Libgdx intermittent jitter when interpolating from previous position to current physics body position - libgdx

I recently separated my render timestep from the physics timestep. Physics is running at 20hz and the client interpolates the sprite position from the previous position to the current physics position every render call. I'm using a technique from Gaffer on Games: Fix Your Timetep!. This code is in the render(delta) call.
if (delta > 0.25f) delta = 0.25f;
accumulator += delta;
while (accumulator >= physicsStep) {
update(physicsStep);
accumulator -= physicsStep;
}
interpolate(accumulator / physicsStep);
renderWorld();
This is update(physicsStep)
prevPosition.set(position);
physPosition.add(velocity.cpy().scl(physicsStep));
bounds.setCenter(physPosition);
This is interpolate(alpha)
position.set(prevPosition).lerp(physPosition, alpha);
It renders smoothly most of the time, but as I said everyone once and a while the character will start to jitter. It becomes smooth again after a while. Any ideas on how to deal with this?
I've been messing with it and the jitter is being caused by the interpolation "slowing down" right before it reaches the target position (current physics position). It doesn't slow down when it runs smoothly, only when it jitters.

Related

How to collision detect objects with vx and vy?

I've been trying to find out how to block the player from moving the correct way. However, the way I've been doing now, stops the player from moving at all.
I want the player to stop moving horizontally if it touches the side of the block's collisionArea, and if it touches the top or bottom of the block's collisionArea, I want it to stop moving vertically only. So that way you can still move up and down when you touch the side, and side to side when you touch top or botttom. Thanks.
if (player.collisionArea.hitTestObject(block.collisionArea))
{
player.y -= vy;
player.x -= vx;
}
Your basic approach is to move your object, test if the current position hits your obstacle, then move it back if it does. This could be adapted to separate out the x and y axis quite easily (reduced code for clarity):
player.x += vx;
if(player.hitTestObject(block)){
player.x -= vx;
}
player.y += vy;
if(player.hitTestObject(block)){
player.y -= vy;
}
However, there are potential problems with this. First of all, DisplayObject/x and y round their values to "twips", so your addition and subtraction of vx and vy will not necessarily result in the object landing back in the original position exactly. This can produce problems with objects getting stuck in walls and such. Sound strange? Try this:
var s:Sprite = new Sprite();
s.x = 1.1925;
trace(s.x); // 1.15
So, to avoid this, you can store the position separately instead of relying on the DisplayObject x and y property.
var oldPosition:Point = new Point(player.x, player.y);
player.x += vx;
if(player.hitTestObject(block)){
player.x = oldPosition.x;
}
player.y += vy;
if(player.hitTestObject(block)){
player.y = oldPosition.y;
}
Second, I thought I would just mention that while hitTestObject() is a convenient API to check the intersection of two display object bounding rectangles, in my experience when you mix it with movement and collision response it starts to break down, because it relies on the state of the display, which is subject to oddities like the twips rounding, and inflexible with timing (you can't, for example, project all your movements, then check collisions, since you need to move your display object to get a valid result from hitTestObject()). The better way IMO is to make collision detection purely math based, for example circle intersection/distance checks. All that hitTestObject() is really doing is Rectangle/intersects() based on display objects bounds anyway. Pure math based collision detection is more work to setup, but more flexible and in my experience more predictable. Just a thought for the future, perhaps!
First of all, this question is very genuine - Just for the next time, make sure you clarify the background of your question (i.e I`m making a game with an actionscript 2d graphics, blah blah blah).
Anyhow, I'll copy you a part of a code i written back in the day when i was into developing javascript games. Since i dont know how your objects are arranged, i`ll modify it in a way that'll just introduce the general algorithm.
// player: a class that holds an array of moves, and other relevant information. Varys on your program.
var optimizePosition = function (player) {
//after each time the player attempts to move, i check if he touches of the blocks. if he does, i move him back.
foreach(Block block in blocks)// replace this with an iterator for all the blocks
{
if (player.x-block.x < 32 || player.y-block.y < 32 ) // if player is touching a block:
undoLastMove(getLastMove(player),player);
}
// a little extra: always good to check if he's going out of the screen in the same function:
if(player.x > canvas.width - 64 || player.y > canvas.height - 64)
undoLastMove(getLastMove(player),player);
}
and each time the player moves, i call the function:
optimizePosition(player);
The content of undoLastMove(player) will contain the code you written above.

AS3 What causes lag with side scrollers?

I've been programming a side scroller based on a tutorial found in a book. My friend did the same, and his is working perfectly.
I've only really changed a few variable names around (I've also done animations differently) but for some reason, when my character is moving, there is a large amount of lag.
HOwever the lag is only present when there are 'walls' on the stage. When I scroll past them, the lag goes away, then returns.
Walls and Floors both use the same code (they are both assigned as 'floorObjects' variables) and use the same collision code, however I cannot figure out why there is lag involved.
From where the character starts (about 60x) if the character goes left, there is a HUGE amount of lag. If I go right, there isn't too much lag, until the screen starts to scroll.
The lag from going left I believe may have something to do with the program being preventing from scrolling off the map etc. But I can't figure out why there is lag when trying to move right.
I've listed the Scroll code, and the main loop, if need be I can upload the collisions code, and any help would be greatly appreciated.
Scroll code;
public function scrollGame()
{
var stagePosition:Number = gameLevel.x + player.mc.x;
var rightEdge:Number = stage.stageWidth - edgeDistance;
var leftEdge:Number = edgeDistance;
//Scroll the GameLevel to the Left if player moves right
if(stagePosition > rightEdge)
{
gameLevel.x -= (stagePosition - rightEdge);
//Prevent the game scrolling off the stage
if (gameLevel.x < -(gameLevel.width-stage.stageWidth))
gameLevel.x = -(gameLevel.width-stage.stageWidth);
}
//Scroll the GameLevel to the right if player moves left
if(stagePosition < leftEdge)
{
gameLevel.x += (leftEdge - stagePosition);
//Prevent the game scrolling off the stage
if(gameLevel.x > 0)
gameLevel.x = 0;
}
}
Main Loop:
public function gameLoop(e:Event)
{
//Get Time Difference
if(lastTime == 0) lastTime = getTimer();
var timeDiff:int = getTimer() - lastTime;
lastTime += timeDiff;
//Game Cycle tasks
//Only perform if in play mode
if(gameMode == "play")
{
moveCharacter(player, timeDiff);
moveEnemies(timeDiff);
checkCollisions();
scrollGame();
}
}
UPDATE:
So I "profiled" it, most of the time is being spent either in the MoveCharacter() function, using the gotoAndStop() command. So I removed that, and it made no difference, still lagging. I then removed the enemies also, still lagging. But turning quality down to low has somehow fixed it (though at a poor quality now ) Any ideas as to what is causing the lag and how to fix it?
this is from the flash university book isn't it?
The code is fine.
I know what will lag your flash game.
This is a guess though, and I do get this error some times.
Make sure your images are optimized!
If they're imported from photo shop or illustratro then flash will have to deal with those complicate vector points.
Use .png for transparent images, bitmaps don't hurt either.

Infinite horizontal scroll at constant speed in AS3 using TweenLite

I need to do an endless horizontal scroll of elements within a parent MovieClip.
No matter what ever method I try, an element of 'drift' occurs and eventually the elements start to overlap.
I've tried using relative recursive tweening for each element according
but this method seems prone to quite a bit of error after repeated starts and stops.
//CODE START
function doScroll():void {
TweenLite.to(this, .25, {x:"20", ease:Linear.easeNone,onUpdate:checkPos,onComplete:doScroll});
}
//CODE END
I've reverted to doing absolute tweens to a predefined position using a contant speed. This seems to be more accurate but still some 'drift' occurs.
//CODE START
//_dest is predefined
var speed:Number = 500;
var dist:Number = this.x - _dest;
var distAbs:Number = dist < 0 ? -dist : dist;
//kludge to get constant velocity by recalculating time every frame
_time = distAbs / speed;
TweenLite.to(this, _time, {x:_dest, ease:Linear.easeNone,onComplete:reset});
//CODE END
Thought this should be very simple.
Can anyone point me to any possible tutorials or make any suggestions?
Any help appreciated.
Solution/Discussion at http://forums.greensock.com/viewtopic.php?f=1&t=6800
(warning: this is gonna require a rather lengthy explanation...)
It's a logic problem in your code. In your onUpdate, you were running conditional logic such that if the x position is beyond 980, it kills the tween and moves x back to -980 and starts things over. You're doing that for each individual item, each of which begins at a different position. That initial position affects when it crosses that threshold, thus when they reposition, the offsets are different.
For example, let's say item1 starts at an x position of 0 and item2 starts at 490 and both start moving at 400 pixels per second and your frame rate is 60, thus they'll move 6.66666 pixels per frame. Item1 will take 147 frames to hit 980. However, item2 will take 74 frames (actually 73.5, but there's no such thing as a half-frame) to cross the 980 threshold, but when it does so it will be at an x position of 983.333333. At that point it jumps back to -980 due to your conditional logic, but notice that it traveled an EXTRA 3.333333 pixels. You intended Item1 and item2 to travel at the exact same velocities and they do during the tween, but your onUpdate logic is misaligning them on the reposition such that in the end, some are traveling more than others which affects their overall velocity.
Another issue has to do with the fact that Flash rounds x/y coordinates of DisplayObjects to the nearest 0.05. So when you do your manual reposition (wrap), small rounding errors creep in. For example, let's say TweenLite sets the exact x value to 980.799. Flash will actually round that to 980.75. Then when you reposition it like this.x -= 980 and then tween it, the value would have just lost almost 0.05 pixels on that round. Do that many times and it can add up to a half-pixel or whole pixel (or more). All your items are crossing the threshold at slightly different spots, thus the rounding errors aren't the same, thus you start seeing slight variances in the spacing. Again, this is NOT an issue with the tweening engine. You'll see that the engine itself sets the values correctly, but Flash rounds them internally when applied to DisplayObjects.
A solution was posted at http://forums.greensock.com/viewtopic.php?f=1&t=6800 that includes an FLA and support files.
As others have suggested, I'd recommend having a single chunk of code that manages ALL the items that you're aligning/scrolling. It would lay things out from a single reference point so that everything lines up perfectly every time. You could tween a getter/setter that applies the logic. I use that technique all the time and it works great. You can see a smaller-scale example in the code I attached in the above URL (the scrollX getter/setter in ItemBase.as)
If you will be tweening all background elements at the same rate indefinitely on a single dimension - why not use a Timer and bypass tweening libraries entirely?

Help with velocity vectors

I have a velocity vector that is V(233, 188).
It makes an object moves toward the right-bottom side of the screen in 300 pixels per second when the origin is V(0, 0).
When the position of the object is, for instance, (592, 334), I set the velocity vector to V(294, 55) but the object does not start moving toward that direction... It keeps moving the same direction, but it seems that it makes a small curve of 10 degrees...
What I'm doing is:
objectLocation += velocity * elapsedTime;
What am I doing wrong?
The difference between (233,188) and (294,55) is not that much, in the grand scheme of things. To verify your code is working, try a vector such as (200,-200). That will cause it to actually bounce off the point in the y-direction.
If that code works, then it's just your values that aren't working.

How do I apply gravity to my bouncing ball application?

I've written a fairly simple java application that allows you to drag your mouse and based on the length of the mouse drag you did, it will shoot a ball in that direction, bouncing off walls as it goes.
Here is a quick screenshot:
alt text http://img222.imageshack.us/img222/3179/ballbouncemf9.png
Each one of the circles on the screen is a Ball object. The balls movement is broken down into an x and y vector;
public class Ball {
public int xPos;
public int yPos;
public int xVector;
public int yVector;
public Ball(int xPos, int yPos, int xVector, int yVector) {
this.xPos = xPos;
this.yPos = yPos;
this.xVector = xVector;
this.yVector = yVector;
}
public void step()
{
posX += xVector;
posY += yVector;
checkCollisions();
}
public void checkCollisions()
{
// Check if we have collided with a wall
// If we have, take the negative of the appropriate vector
// Depending on which wall you hit
}
public void draw()
{
// draw our circle at it's position
}
}
This works great. All the balls bounce around and around from wall to wall.
However, I have decided that I want to be able to include the effects of gravity. I know that objects accelerate toward the earth at 9.8m/s but I don't directly know how this should translate into code. I realize that the yVector will be affected but my experimentation with this didn't have the desired effect I wanted.
Ideally, I would like to be able to add some gravity effect to this program and also allow the balls to bounce a few times before settling to the "ground."
How can I create this bouncing-elastic, gravity effect? How must I manipulate the speed vectors of the ball on each step? What must be done when it hits the "ground" so that I can allow it to bounce up again, but somewhat shorter then the previous time?
Any help is appreciated in pointing me in the right direction.
Thanks you for the comments everyone! It already is working great!
In my step() I am adding a gravity constant to my yVector like people suggested and this is my checkCollision():
public void checkCollision()
{
if (posX - radius < 0) // Left Wall?
{
posX = radius; // Place ball against edge
xVector = -(xVector * friction);
}
else if (posX + radius > rightBound) // Right Wall?
{
posX = rightBound - radius; // Place ball against edge
xVector = -(xVector * friction);
}
// Same for posY and yVector here.
}
However, the balls will continue to slide around/roll on the floor. I assume this is because I am simply taking a percentage (90%) of their vectors each bounce and it is never truly zero. Should I add in a check that if the xVector becomes a certain absolute value I should just change it to zero?
What you have to do is constantly subtract a small constant (something that represents your 9.8 m/s) from your yVector. When the ball is going down (yVector is already negative), this would make it go faster. When it's going up (yVector is positive) it would slow it down.
This would not account for friction, so the things should bounce pretty much for ever.
edit1:
To account for friction, whenever it reverses (and you reverse the sign), lower the absolute number a little. Like if it hits at yVector=-500, when you reverse the sign, make it +480 instead of +500. You should probably do the same thing to xVector to stop it from bouncing side-to-side.
edit2:
Also, if you want it to react to "air friction", reduce both vectors by a very small amount every adjustment.
edit3:
About the thing rolling around on the bottom forever--Depending on how high your numbers are, it could be one of two things. Either your numbers are large and it just seems to take forever to finish, or you are rounding and your Vectors are always 5 or something. (90% of 5 is 4.5, so it may round up to 5).
I'd print out a debug statement and see what the Vector numbers are like. If they go to somewhere around 5 and just stay there, then you can use a function that truncates your fraction to 4 instead of rounding back to 5. If it keeps on going down and eventually stops, then you might have to raise your friction coefficient.
If you can't find an easy "rounding" function, you could use (0.9 * Vector) - 1, subtracting 1 from your existing equation should do the same thing.
When the balls are all rolling around on the ground, yes, check to see if the velocity is below a certain minimum value and, if so, set it to zero. If you look at the physics behind this type of idealized motion and compare with what happens in the real world, you'll see that a single equation cannot be used to account for the fact that a real ball stops moving.
BTW, what you're doing is called the Euler method for numerical integration. It goes like this:
Start with the kinematic equations of motion:
x(t) = x0 + vx*t + 0.5*axt^2
y(t) = y0 + vyt + 0.5*ayt^2
vx(t) = vx0 + axt
vy(t) = vy0 + ay*t
Where x and y are position, vx and vy are velocity, ax and ay are acceleration, and t is time. x0, y0, vx0, and vy0 are the initial values.
This describes the motion of an object in the absence of any outside force.
Now apply gravity: ay = -9.8 m/s^2
To this point, there's no need to do anything tricky. We can solve for the position of each ball using this equation for any time.
Now add air friction: Since it's a spherical ball, we can assume it has a coefficient of friction c. There are typically two choices for how to model the air friction. It can be proportional to the velocity or to the square of velocity. Let's use the square:
ax = -cvx^2
ay = -cvy^2 - 9.8
Because the acceleration is now dependent on the velocity, which is not constant, we must integrate. This is bad, because there's no way to solve this by hand. We'll have to integrate numerically.
We take discrete time steps, dt. For Euler's method, we simply replace all occurances of t in the above equations with dt, and use the value from the previous timestep in place of the initial values, x0, y0, etc. So now our equations look like this (in pseudocode):
// Save previous values
xold = x;
yold = y;
vxold = vx;
vyold = vy;
// Update acceleration
ax = -cvxold^2;
ay = -cvyold^2 - 9.8;
// Update velocity
vx = vxold + axdt;
vy = vyold + aydt;
// Update position
x = xold + vxold*dt + 0.5*axdt^2;
y = yold + vyolddt + 0.5*ay*dt^2;
This is an approximation, so it won't be exactly correct, but it'll look OK. The problem is that for bigger timesteps, the error increases, so if we want to accurately model how a real ball would move, we'd have to use very tiny values for dt, which would cause problems with accuracy on a computer. To solve that, there are more complicated techniques. But if you just want to see behavior that looks like gravity and friction at the same time, then Euler's method is ok.
Every time slice you have to apply the effects of gravity by accelerating the ball in teh y downwards direction. As Bill K suggested, that's as simple as making a subtraction from your "yVector". When the ball hits the bottom, yVector = -yVector, so now it's moving upwards but still accelarating downwards. If you want to make the balls eventually stop bouncing, you need to make the collisions slightly inelastic, basically by removing some speed in the y-up direction, possibly by instead of "yVector = -yVector", make it "yVector = -0.9 * yVector".
public void step()
{
posX += xVector;
posY += yVector;
yVector += g //some constant representing 9.8
checkCollisions();
}
in checkCollisions(), you should invert and multiply yVector by a number between 0 and 1 when it bounces on the ground. This should give you the desired effect
It's a ballistic movement. So you got a linear movement on x-axis and an uniform accelerated movement on y-axis.
The basic idea is that the y-axis will follow the equation:
y = y0 + v0 * t + (0.5)*a*t^2
Or, in C code, for example:
float speed = 10.0f, acceleration = -9.8f, y = [whatever position];
y += speed*t + 0.5f*acceleration*t^2;
Where here I use tiem parametrization. But you could use Torricelli:
v = sqrt(v0^2 + 2*acceleration*(y-y0));
And, on this model, you must maintain the last values of v and y.
Finally, I've done something similar using the first model with dt (time's differential) being fixed at 1/60 second (60 FPS).
Well, both models give good real-like results, but sqrt(), for example, is expensive.
You really want to simulate what gravity does - all it does is create force that acts over time to change the velocity of an object. Every time you take a step, you change the velocity of your ball a little bit in order to "pull" it towards the bottom of the widget.
In order to deal with the no-friction / bouncing ball settles issue, you need to make the "ground" collision exert a different effect than just strict reflection - it should remove some amount of energy from the ball, making it bounce back at a smaller velocity after it hits the ground than it would otherwise.
Another thing that you generally want to do in these types of bouncy visualizations is give the ground some sideways friction as well, so that when it's hitting the ground all the time, it will eventually roll to a stop.
I agree with what "Bill K" said, and would add that if you want them to "settle" you will need to reduce the x and y vectors over time (apply resistance). This will have to be a very small amount at a time, so you may have to change your vectors from int to a floating point type, or only reduce them by 1 every few seconds.
What you want to do is change the values of xVector and yVector to simulate gravity and friction. This is really pretty simple to do. (Need to change all of your variables to floats. When it comes time to draw, just round the floats.)
In your step function, after updating the ball's position, you should do something like this:
yVector *= 0.95;
xVector *= 0.95;
yVector -= 2.0;
This scales the X and Y speed down slightly, allowing your balls to eventually stop moving, and then applies a constant downward "acceleration" to the Y value, which will accumulate faster than the "slowdown" and cause the balls to fall.
This is an approximation of what you really want to do. What you really want is to keep a vector representing the acceleration of your balls. Every step you would then dot product that vector with a constant gravity vector to slightly change the ball's acceleration. But I think that my be more complex than you want to get, unless you're looking for a more realistic physics simulation.
What must be done when it hits the
"ground" so that I can allow it to
bounce up again
If you assume a perfect collision (ie all the energy is conserved) all you have to do reverse the sign of one of the velocity scalar depending on which wall was hit.
For example if the ball hits the right or left walls revese the x scalar component and leave the the y scalar component the same:
this.xVector = -this.xVector;
If the ball hits the top or bottom walls reverse the y scalar component and leave the x scalar component the same:
this.yVector = -this.yVector;
but somewhat shorter then the previous
time?
In this scenario some of the energy will be lost in the collision with the wall so just add in a loss factor to take of some of the velocity each time the wall is hit:
double loss_factor = 0.99;
this.xVector = -(loss_factor * this.xVector);
this.yVector = -(loss_factor * this.yVector;