I'm starting to develop a game in libgdx, and I'm wondering what the best practice is for the following situation. There are two things that I'm trying to do at the moment: move a menu (sprite) into place, and pan the camera to the player sprite. My idea to accomplish these things is to have an 'action_stack' ArrayList in the render() function. The ArrayList would contain 'Action' instances. Each Action instance would have a step() function, which would be over-ridden. In the render() function, I would iterate through action_stack, and fire each elements' step() function. So, to accomplish moving the menu into place, I would create the class:
public class MenuAnim1 implements Action {
private int targetX;
private int targetY;
private Sprite menu;
public MenuAnim1() {
//set initial sprite and position
}
public Step() (
//move this.menu towards targetX and targetY
//draw the sprite
//if not at target position, do nothing
//if at target position, remove this object from action_stack
}
}
...and put an instance into the action_stack:
MenuAnim1 menuAnim1 = new MenuAnim1();
action_stack.add(menuAnim1);
Sorry if my Java is bad, I'm not super familiar with it. Anyways, my question is: is this even good practice? What do people normally do? Is there a better way to do what I'm describing above?
I have never used Actions, but your idea is good. If you want them to be time dependant (and thus fps independant), be sure to use the time that has passed since the last frame to the current, also known as delta or deltaTime. You can get it like this:
Gdx.graphics.getDeltaTime();
so, to make your action move the sprite, for example, to the right, this would do the trick:
speed = 10; //It will move 10 units per second.
delta = Gdx.graphics.getDeltaTime();
menu.translateX(speed*delta);
(Sprite#translateX)
Related
I create little sprites of sheeps on the top of my screen, then they should go down and after crossing bottom line they disappear. Problem is that when they are going across the screen it is very noticable that sometimes they lag. For milliseconds but its possible to see it. It happens absolutely randomly. They change their position with Gdx.graphics.getDeltaTime();
public void update (float deltaTime) {
updateMotionX(deltaTime);
updateMotionY(deltaTime);
// Move to new position
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
}
Here is the code of spawing them:
private Sheep spawnSheep(){
Sheep sheep = new Sheep();
sheep.dimension.set(dimension);
// select random cloud image
sheep.setRegion(regSheeps.random());
// position
Vector2 pos = new Vector2();
pos.x = -0.19f; // position after end of level
pos.y = 5;
sheep.position.set(pos);
//speed
Vector2 speed = new Vector2();
speed.y = 3.5f;
sheep.terminalVelocity.set(speed);
speed.y *= -1;
sheep.velocity.set(speed);
return sheep;
}
Maybe somebody already had that problem, i have no idea why it happens,
The lagging is most likely caused by garbage collection because you're continuously allocating memory within your game loop.
You want to avoid calling new whenever possible in the game loop, and if you do call new you want to reuse those objects whenever possible.
Look at pools in libgdx
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Pool.html
If you're returning an object from a method, such as a Vector2, then create a static instance and reuse that object for return values. Be aware that this is not thread safe and calling the method again will overwrite the value from the first call.
If I was you I'd search for any instances of the word 'new' in your code, and make sure none of them are called frequently within the game loop. You also want to be aware of calling methods that will create instances of objects. Simple things like converting an integer to a string will waste memory, as well as more obvious things like creating a copy of an array.
You should find this useful for tracking memory allocation.
https://visualvm.java.net/
I have 2 classes; A and B.
A is the character class, it contains every character detail (position...)
B is the class which get the A class and render. I need to create another object when I touch the screen. I got it, the class seems containing the new values but it doesn't renderize them.
for (A a: aa) {
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.setColor(Color.RED);
shapeRenderer.circle(a.getBoundingCircle().x, a.getBoundingCircle().y, a.getBoundingCircle().radius);
shapeRenderer.end();
}
is recommended use best names.
are you sure a.getBoundingCircle() cotains the correct data, and are you sure had objects A in aa and your program join inside the for?
and i dont look b
Ok, your problem is the new values dont be renderized.
Two options:
You not are running the loop for render the objects.
Your new values are out of the screen.
When you get the position of the touch events you get the screenx and the screeny, not the game camera coordenates, and you need convert it with unproject.
For example:
Vector3 touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
touchPos now is in the game coordenates.
I'm using LibGDX for my Android app. I need to move and orient 3D object(ModelInstance) along a spline.In my case it's CatmullRomSpline. I got the movement working but having problem with orienting the ModelInstance along the spline.
My Code:
public void update() {
float t = SPEED * Gdx.graphics.getDeltaTime();
elapsedTime = elapsedTime + SPEED * Gdx.graphics.getDeltaTime();
//Movement
catmull.valueAt(value, elapsedTime);
myObject3d.transform.setTranslation(value);
//Rotation
derivative = catmull.derivativeAt(derivative, t);
derivative = derivative.nor();
//Tried to bring object into default position before rotating
//Vector.X - is the default direction of my Object - facing right
//myObject3d.transform.rotate(Vector3.X, Vector3.X);
myObject3d.transform.rotate(derivative, Vector3.X);
}
The Matrix4#rotate method has two arguments, base and target. In your case the base vector should be Vector3.X, while the target is derivative. You need to swap the arguments for this. Also, the Matrix4#rotate method post-multiplies the rotation on top the existing rotation. Or in other words: this will accumulate the absolute rotation on every call. You probably want to use the Matrix4#setToRotation method instead, which resets the rotation on every call (clears the matrix).
myObject3d.transform.setToRotation(Vector3.X, derivative);
myObject3d.transform.setTranslation(value);
While this probably will work in most cases, you might get unexpected results depending on the path. Like said, there are infinite possible rotations that will result in this direction. Therefor it's better to use two additional vectors to specify the up (Y) and right (Z) vector.
right.set(Vector3.Y).crs(derivative).nor();
up.set(right).crs(derivative).nor();
myObject3d.transform.set(derivative, up, right, position).rotate(Vector3.X, 180);
Here the cross product is used to calculate the right and up vectors, where it is assumed that Vector3.Y is usually close to the up vector. Then the Matrix4#set method is used to set the matrix to reflect these values. The first argument specifies the "new" X-axis, the second the "new" Y-axis, the third the "new" Z-axis and the last argument specifies the translation (location).
Here's a working example: https://gist.github.com/xoppa/7558c0c75e9534795e9f
Although unrelated, keep in mind that path.valueAt method uses 0 <= t <= 1. Or in other words, t (elapsedTime in your code) should not be below 0 or above 1.
I have a custom view with an added method named moveView which changes the location of the view by a X pixels in Y direction when invoked. Now I want to have 6 of these views spread all over the screen and be in constant movement.
What I have:
Handler (I need it for UI updates?)
ApplyMoveRunnable (implements Runnable. Constructor receives custom View, amount of pixels to move, and direction in which it will move)
6 Threads (one for each view)
6 MoveCalcRunnable (one for each thread. implements Runnable)
What I tried:
I tried creating my 6 views and then 6 Threads. Each of these threads' MoveCalcRunnable call the moveView() method within their respective views. This moveView() method calculates the amount of pixels the view will move and the direction in which it will move and sends this information to the ApplyMoveRunnable and then calls the handler.post(applyMoveRunnable).
Simply put, what happens is this:
Instantiate ApplyMoveRunnable applyMoveRunnable
Instantiate Handler handler.
Instantiate 6 MoveCalcRunnable's.
Create 6 threads, one for each view, each holding a MoveCalcRunnable.
Start all threads.
When I run this, at first I see my 6 views, but then one moves and nothing else happens.
Here's the run() method for each of my MoveCalcRunnable:
#Override
public void run() {
Log.e(tag, "Thread locking directionAmountRunnable.");
synchronized (applyMoveRunnable) {
Log.e(tag, "Moving view.");
myView.moveView();
}
}
Can anyone help me get this to work? Or suggest a better, simpler, and/or more efficient way of doing this?
On developing a painting canvas application in android, i need to track all the points and have to redraw it in another canvas. Now i am able to track all the points, but don't know how to synchronize the point drawing in case of draw and redraw ie the user should redraw the points at the same time gap as in the draw. How can i achieve this?
Not sure if this is the sort of answer you are looking for but I would record the events with a sort of timestamp, really a time difference to the next point. Something like:
class Point {
int x;
int y;
long deltaTime;
}
Its up to you how precise you want to be with the timing. Second to millisecond precision should be good enough. You could interpret deltaTime as either the time until this point should be drawn or the time until the next point should be drawn (I'm going to use the latter in my example).
A few reasons to use a deltaTime instead of a direct timestamp is that it lets you check for really long pauses and you are going to have to compute the delta time anyways in playback. Also using it as a long should give you enough room for really lengthy pauses and lets you use the Handler class which accepts a long integer for the number of milliseconds to wait before executing.
public class Redrawer implements Handler.callback {
LinkedList<Point> points; //List of point objects describing your drawing
Handler handler = new Handler(this); //Probably should place this in class initialization code
static final int MSG_DRAW_NEXT = 0;
public void begin(){
//Do any prep work here and then we can cheat and mimic a message call
//Without a delay specified it will be called ASAP but on another
//thread
handler.sendEmptyMessage(MSG_DRAW_NEXT);
}
public boolean handleMessage(Message msg){
//If you use the handler for other things you will want to
//branch off depending on msg.what
Point p = points.remove(); //returns the first element, and removes it from the list
drawPoint(p);
if (!points.isEmpty())
handler.sendEmptyMessageDelayed(MSG_DRAW_NEXT, p.deltaTime);
public void drawPoint(Point p){
//Canvas drawing code here
//something like canvas.drawPixel(p.x, p.y, SOMECOLOR);
//too lazy to look up the details right now
//also since this is called on another thread you might want to use
//view.postInvalidate
}
This code is far from complete or bullet-proof. Namely you will need to possibly pause or restart the redrawing at a later time because the user switched activities or got a phone call, etc. I also didn't implement the details of where or how you get the canvas object (I figure you have that part down by now). Also you probably want to keep track of the previous point so you can make a rectangle to send to View.postInvalidate as redrawing a small portion of the screen is much faster than redrawing it all. Lastly I didn't implement any clean-up, the handler and points list will need to be destroyed as needed.
There are probably several different approaches to this, some probably better than this. If you're worried about long pauses between touch events simply add a check for the deltaTime if its greater than say 10 seconds, then just override it to 10 seconds. Ex. handler.sendEmptyMessage(MSG_DRAW_NEXT, Math.min(p.deltaTime, 100000)); I'd suggest using a constant instead of a hard coded number however.
Hope this helps