Speed in game with libgdx - libgdx

I'm making a game using libgdx. For now, every character has a speed, corresponding actually to the number of render the game wait before update the character. For example, if the character has a speed of 15, it will be updated every 15 renders. I'm conscious that this is not how it has to be done.
What is the proper way to do this? I really want to make a speed in %, for example a character will have a speed of 85%.

Use delta.
Gdx.graphics.getDeltaTime() method return secods since last render frame. Usually this value is very small, and it equal 1 / FPS.
#Override
public void render()
{
// limit it with 1/60 sec
float dt = Math.min(Gdx.graphics.getDeltaTime(), 1 / 60f);
// then move your characted according to dt
player.pos = player.pos + player.speed * dt;
// or, you could mute the speed like this:
player.pos = player.pos + player.speed * dt * 0.85;
}

When you calculate you object's next position just multiply it's speed with Gdx.graphics.getDeltaTime(), so the more time has pass since last render the more object will move. Movement speed will be constant, no matter of FPS.
However, simple solutions like this one always come with a catch! If you are i.e. moving a bullet it may happen that too much time has passed since last rendering (specially on mobile device). I.e. half of second, and for that time your bullet moved i.e. 100px and moved trough some target, but since it was never in range of detection (skipped it) target will be missed even it's not suppose to do so - player aimed well.
So, if just moving some object is not what you want, but you need that movement to be in some regular steps better way is not to multiply speed with delta time, but to repeat movement and all calculations (detections and stuff) depending on delta time. I.e.:
You have method move left(), which moves object one step and with that amount of movement everything works well.
Your method should be called 20 times per second (step takes 50mS).
You measured time since last render and it's 100mS, means that your objects need to be moved 2 steps
Don't just multiply it's speed and do one calculation - instead of that repeat whole calculation process 2 times! Call your left() method twice!
If time since last drawing is less then 50mS - then skip calculations and just draw graphics as you did in last frame.
This way you will have separated calculation rate from drawing rate. Calculation rate will be same on all devices, but drawing will depend on devices performance..

Related

Is there a way to have smooth/subpixel motion without turning on smoothing on graphics?

I'm creating this 2D, pixel art game. When the camera follows the player (it uses easing), on the final approach, the position gets several subpixel adjustments.
If I have smoothing ON (on my graphic assets), the graphics look good (sharp. it's pixel art) but the subpixel motion is jerky/jumpy.
If I have smoothing OFF, the subpixel motion is smooth, but the pixel art graphics look blurry.
I'm using Flash player v21. I've tried this with Starling and with Flash's display list.
You have a pixelated object that is moving in increments of less than the pixel size, but you don't want to restrict your mathematical easing to integers, or even worse, factors of 8 or what have you. The solution I am using in my project for this exact issue is posted below (I just got it working last week!)
Concept
create a driver that is controlled by the easing using floating point numbers.
Allow this driver to then control where the actual display object is rendered. We can use a constraint to only allow the display object to render on your chosen resolution.
Code Example
// you'll put these lines or equivalent in the correct spots for your particular needs.
// SCALE_UP will be your resolution control. If your pixels are 4 pixels wide, use 4.
const SCALE_UP: int = 4;
var d:CharacterDriver = new CharacterDriver();
var c:Character = new Character();
c._driver = d; // I've found it useful to be able to reference the driver
d._drives = c; // or the thing the driver drives via the linked object.
// you don't have to do this.
then when you are ready to do your easing of the driver:
function yourEase(c:Character, d:CharacterDriver):void{
c.x = Math.ceil(d.x - Math.ceil(d.x)%SCALE_UP);//this converts a floating point number into a factor of SCALE_UP
c.y = Math.ceil(d.y - Math.ceil(d.y)%SCALE_UP);
Now this will make your character move around 4 pixels at a time, but still be able to experience easing!
The bit with the modulo (%) operator is the key. For instance, 102-102%4 = 100. 103-103%4 = 100. 104-104%4 = 104.
In case anyone is confused by that, look at what 102%4 does: 4 goes into 102 25 times with a remainder of 2. so 102%4 = 2. Then 102 - 2 = 100.
In your case, since the "camera" is following the player (i.e. the background is moving, right?) then you really need to apply drivers to everything in the background instead, but it is basically the same idea.
Hope this helps.
since you specifically mentioned the "final approach" i think your problem comes from the fact that the easing equations puts your graphics at fractional coordinates, especially while getting closer to the target, but you should also notice it during the rest of the animation.
depending on the easing "engine" that you're using you should be able to set a "round values" flag, so all the coordinates set will be integer values and not fractional
if that's not possible, find a way in your display objects to round the x and y values every time they change

How to lock FPS with requestAnimationFrame?

I used script from Paul Irish
https://gist.github.com/paulirish/1579671
to create animation loop inside html site.
It works although it's faster in fullscreen mode than in browser window.
Also, I observed different speeds depending on canvas size and depending on browser I use.
Question: How can I ensure stable frame rate using the script?
Code is available here (Beginning WebGL, chapter 1 by Brian Danchilla):
https://github.com/bdanchilla/beginningwebgl/blob/master/01/2D_movement.html
Something like this should work. If the time delta between two frames is shorter than your FPS limit, the update function returns and waits for the next frame. But this will only limit the updates from happening too quickly; like emackey said, there's always the possibility the update loop will run more slowly.
var updateId,
previousDelta = 0,
fpsLimit = 30;
function update(currentDelta) {
updateId = requestAnimationFrame(update);
var delta = currentDelta - previousDelta;
if (fpsLimit && delta < 1000 / fpsLimit) {
return;
}
/* your code here */
previousDelta = currentDelta;
}
To embellish what #emackey said,
The short answer is you can't. You could ask the computer to do an infinite amount of work each frame. I can't promise to do that work in a finite amount of time.
On top of that each computer has a different amount of power. A cheap integrated GPU has much less power than a high end graphics card. An intel i3 is much slower than an i7.
You also mentioned changing the canvas size. Drawing a 300x150 canvas is only 45000 pixels worth of work. Drawing a 1920x1080 canvas would be 2,073,600 pixels of work or 46x more work
The best you can do is do the least amount of work possible, and or remove features on slow hardware either automatically or by user choice. Most games do this. They graphics setting options where the user can choose resolution, texture res, anti-alising levels and all kinds of other things.
That said, you can try to do your computations so things in your app move at a consistent speed relative to time. The framerate might slower on a slow machine or with a larger canvas but the distance something moves per second will remain the same.
You can do this by using the time value passed into requestAnimationFrame
function render(time) {
// time is time in milliseconds since the page was loaded
...do work...
requestAnimationFrame(render);
}
requestAnimationFrame(render);
For example here is NON framerate independent animation
function render(time) {
xPosition = xPosition + velocity;
...
requestAnimationFrame(render);
}
requestAnimationFrame(render);
and here is frame rate independent animation
var then = 0;
function render(time) {
var timeInSeconds = time * 0.001;
var deltaTimeInSeconds = timeInSeconds - then;
then = timeInSeconds;
xPosition = xPosition + velocityInUnitsPerSecond * deltaTimeInSeconds;
...
requestAnimationFrame(render);
}
requestAnimationFrame(render);
Note: The time passed into requestAnimationFrame is higher resolution than Date.now()
Here's an article on it with animations
You can't enforce a stable frame rate directly. Your page is not the only app running on the user's platform, and platform capabilities vary widely. requestAnimationFrame runs as fast as it can, not exceeding the display update interval on the target device, but potentially much slower depending on available CPU, GPU, memory, and other limitations.
The standard practice here is to measure the amount of time that has elapsed since the previous animation frame, typically with Date.now(), and each frame advance the animation by that amount of time. To the human eye, this makes the resulting animation run at a consistent speed, even if the frame rate is highly variable.
For example, sites such as Shadertoy and GLSL Sandbox run full-screen GLSL shaders and pass in a uniform called time (or iGlobalTime), which is a float representing the number of seconds elapsed since the shader started. This time value increases at irregular intervals depending on how long each animation frame took to render, but the result is that the float appears to count upwards at a stable 1.0 per second. In this way, shader playback based on this time value can appear consistent.

Blur show effect - html5 canvas

I want to create a blur show effect like : http://www.flasheff.com/patternsshowcase/ (FESBlur).
I've tried to use http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html using setInterval and changing the radius of the effect on each "frame", but if I set the interval delay to a lower value(increase the effect's speed), it doesn't runs smooth ( I think it's beacuse it uses imageData, and changes the value of every pixel).
Do you have any ideea about how I could make that effect to run fast enough? (about 1 second from max blur to non-blur)
Thanks,
Gabriel
I'm no expert at any of this, but some very obvious things come to mind:
Method 1: Buffering. Buffering is probably the single most effective way to stop stutters. If you could delay the initiation of the animation by .25 seconds before actually outputting it, you could probably get half of the calculations done before the animation even starts.
Method 2: Caching. The time that a blur takes to process usually grows as the radius of the blur grows. Let's say you have 20 frames in your animation. If you can cache frame 5, 10, 15, and 20 (unblurred image) then you can get frames 1-4 from blurring 5 with a small radius, and you'll get frame 5 for free, then you can get frames 6-9 from blurring 10 with a small radius, and you'll get frame 10 for free, and so on.
Method 3: Interpolation/Blending of Coarse Blurs. Blending two images should be quicker than blurring one image. If you make your animation 21 frames (1-21), then you should be able to calculate frames 1, 5, 9, 13, 17, and 21. Those frames would be free, and you'd the other frames by blending them: frame 2 (F2) would be 75% F1 and 25% F5, F3 would be 50% F1 and 50% F5, and so on.
My guess is that this would take a decent amount of tinkering on your part. None of these are going to fix your problem by simply changing a parameter or two to some magic numbers.
Realize this, however: javascript doesn't really get to pick and choose when it will or will not get the attention of the processor, and it's not exactly high on the processor's list of priorities. If the processor decides to go on vacation for 1/10th of a second, there's probably nothing that you can do to stop the stutter.
Use requestAnimFrame instead of setInterval. More info on http://paulirish.com/2011/requestanimationframe-for-smart-animating/
I tested this with faster blur reduction on my FF5 and it seems to perform fine.
(function animloop(){
blurImage();
requestAnimFrame(animloop);
})();
function blurImage(){
stackBlurImage( "image1", "output", amount, true );
amount=amount-4;
}

Actionscript collisions: solving exceptions and strange cases

I have created a collision class to detect collisions using pixels. In my class I've also developed some functions for determining the collsion angle. Based on this I created some examples:
http://megaswf.com/serve/25437/
http://megaswf.com/serve/25436/
(Space to change gravity, right/left to give some speed to the ball.)
As you will probably notice, there are strange things that happen:
When the ball speed is very low
When the direction of the ball is
almost tangent to the obstacle.
collision http://img514.imageshack.us/img514/4059/colisao.png
The above image shows how I calculate the collision angle.
I call the red dots the keypoints. I search for a maximum number of keypoints (normally 4). If I find more then 2 keypoints, I choose the 2 farthest ones (as shown in one of the blue objects). Thats how I then find the normal angle to where in the surface the object collided. I don't know if this is an obsolete way of doing things.
based on that angle, I rotate the speed vector to do the bouncing.
The piece of code to do the maths is here:
static public function newSpeedVector(speedX: Number, speedY: Number, normalAngle: Number): Object{
var vector_angle: Number = Math.atan2(speedY, speedX) * (180/Math.PI);
var rotating_angle: Number = (2*(normalAngle - vector_angle) + 180) % 360;
var cos_ang: Number = Math.cos(rotating_angle/DEGREES_OF_1RAD);
var sin_ang: Number = Math.sin(rotating_angle/DEGREES_OF_1RAD);
var final_speedX: Number = speedX * cos_ang - speedY * sin_ang;
var final_speedY: Number = speedX * sin_ang + speedY * cos_ang;
return {x_speed: final_speedX, y_speed: final_speedY};
}
This is how the new speed vector is calculated...
My question is, has anyone faced this kind of problem or has some idea on how to avoid this from happening?
Without seeing your code, this is the best I can provide.
Collision physics should have some velocity threshold that is considered "stopped". That is, once the velocity gets small enough you should explicitly mark an object as stopped and exempt it from your collision code. This will help stabilize slow moving objects. Trial and error is required for a good threshold.
When a collision happens, it is important to at least attempt to correct any inter-penetration. This is most likely the reason why tangent collisions are behaving strangely. Attempt to move the colliding object away from what it hit in a reasonable manner.
Your method of determining the normal should work fine. Game physics is all about cheating (cheating in a way that still looks good). I take it rotation and friction isn't a part of what you're going for?
Try this. You have the contact normal. When you detect a collision, calculate the penetration depth and move your object along the normal so that is isn't penetrating anymore. You can use the two points you have already calculated to get one point of penetration, you'll need to calculate the other though. For circles it's easy (center point + radius in direction of normal). There are more complex ways of going about this but see if the simple method works well for you.
I have read and recommend this book: Game Physics Engine Development
I did something a little like that and got a similar problem.
What I did is that when the pixels from the bouncing object (a ball in your case) overlap with the pixels from the obstacle, you need to move the ball out of the obstacle so that they are not overlapping.
Say the ball is rolling on the obstacle, before your render the ball again you need to move it back by the amount of 'overlap'. If you know at what angle the ball hit the obstable just move it out along that angle.
You also need to add some damping otherwise the ball will never stop. Take a (very) small value, if the ball velocity is bellow that value, set the velocity to 0.
You can try one more thing, which I think is very effective.
You can make functions such as getNextX() and getNextY()(Which of course give their position coordinated after the next update) in your game objects and Check collision on objects based on their next position instead of their current position.
This way, the objects will never overlap, you'll know when they are about collide and apply your after collision physics gracefully!

Best practices: ENTER_FRAME vs. Timer

I'm creating a Flash game which is based on the old Pacman and I'm not sure which is the best way to control the animation.
As I understand it these type of games were originally dependent on a game loop which ran faster or slower depending on the CPU, which is why I imagine that the most similar to use would be the ENTER_FRAME event.
This however presents the problem of having to have a specific frame rate and changing it later is out of the question, not to mention being limited to very few different "speeds" (see below). An example could be that the sprite has to move 12 pixels before the next move is determined. If the speed is then 4 pixels per frame, the math is quite simple:
[...]
public var stepCount:uint = 0;
[...]
function enterFrameHandler(e:Event):void
{
if(stepCount==0) {
//Some code to evaluate next move. Let's say it evaluates to MOVE RIGHT
}
if(MOVE_RIGHT)
{
x += 4;
}
stepCount++;
if(stepCount > 2)
{
stepCount = 0; //Now ready to evaluate direction again.
}
}
This all works fine, but let's say that I want the sprite to move 5 pixels per frame. Then the number of frames before making the next evaluation would not compute. The stepSize would have to be a multiple of 12, which limits the different possible speeds (1,2,3,4 and 6 pixels per frame).
This is why I attempted to base the movement on a Timer instead, which I also managed to get to work, but the movement was somewhat erratic and it seemed like the Timer was using far more memory than the ENTER_FRAME event. Instead of an even movement the Timer made the sprite slow down and speed up and slow down again.
Another possible solution could be the Tween class, but it seems extravagant.
Does anyone have experience with what works best in other games?
Morten Twellmann
You have several separate issues here. Your first question is, should you execute your game loop in a frame event or a timer event? The answer is easy - you should do it in a frame event. The reason is that regardless of how you move your characters, the screen is updated precisely once per frame. So any time you're calling your game loop more than once per frame you're wasting CPU, and any time you call it less than once per frame, you're sacrificing visual quality. So this one is easy, don't bother with timer events at all.
The next question is whether your game's movement should be tied to frames or miliseconds, and the answer is that it depends on the game. Ask yourself this: suppose that some user is playing your game, and their spaceship (or whatever) is flying along at a given speed. Suddenly, the user's anti-virus package does something heavy, and the CPU spike causes Flash to stop updating for one second. Once the spike is over, do you want the spaceship to continue moving from where it was when the spike started? Or do you want it to jump forwards to where it would be if it had continued moving during the spike? If you want the former, you should tie your movement to frames; if you want the latter, you should tie it to miliseconds. But which one is best depends on how you want your game to work.
The final question is, how exactly should you move the characters in your game? Based on what you wrote, I'd do it as follows. For frame-based movement (i.e. the first approach described earlier):
// the ship moves 25 pixels per second
var shipSpeed:Number = 25;
// the number of seconds per frame, based on the published framerate
var frameTime:Number = 1 / stage.frameRate;
// game loop called each frame:
function gameLoop() {
// ...
playerShip.x += shipSpeed * frameTime;
// ....
}
This way, the ship's movement on screen is constant, regardless of what framerate you publish your SWF at. Using a higher framerate simply makes the movement smoother. Likewise, to tie your movement to time instead of frames, simply change "frameTime" in the code above to refer to the time elapsed since the previous frame, as described in Allan's answer.
Yes frame rates will vary depending on CPU amongst other things. Therefore you need to take this into account with your game loop. What I like to do is get the time difference between the current frame and the old frame and use that value in my calculations. So if it happens that there is a delay the larger difference value will then make up for the fact less frames ran.
var _previousTime:Number;
//gameLoop is the function called on ENTER_FRAME
public function gameLoop(e:Event):void
{
var currentTime:Number = getTimer();
var difference:Number = currentTime - _previousTime;
_previousTime = currentTime;
//use difference variable with calculations involving movement
}