Slick2D game speed changing - java

I created a game using Swing, and it was a bit unreliable, so I started remaking it using Slick2D game engine and I have encountered issues.
The background of the game rolls across the screen at a certain about of pixels each time the update method is called. This keeps speeding up and slowing down, so the background will move very fast, and then very slow, and keeps fluctuating.
I have tried * by delta (which monitors the refresh rate, I think!) on my value which moves the background, but as this wont give me an exact value I can use to reset the background to the left hand side (2 background move from right to left. left hand one goes to the right at -800 pixels).
What is causing this and how do I overcome it?
Thanks

Here's some reading for you (there's a gamedev-specific StackExchange site, BTW):
https://gamedev.stackexchange.com/questions/6825/time-based-movement-vs-frame-rate-based-movement
https://gamedev.stackexchange.com/questions/1589/fixed-time-step-vs-variable-time-step
One of the most important points in these articles is that things move at a certain rate OVER TIME, not over a certain number of frames. Since frame rates can unpredictably change, time-based and frame-based movement don't wind up being equivalent to one another.
And here's some explanation...
So, your computer and OS are multithreaded, and thus, you can never know what's happening outside your app, and what the overall load is on the machine. Because of this, even when you're in full-screen mode you aren't getting exclusive access to the CPU. So, that's one factor to why things speed up and slow down.
The delta's purpose in Slick2D is to allow you to deal with this speed up/slow down, and allow your app to change its frame rate dynamically so that the perceived movement on the screen doesn't change due to the load on your machine. The delta is not the monitor the refresh rate (which is constant); the delta is the number of milliseconds that have passed since the last call to update.
So how do you use this delta properly? Let's say your background is supposed to move at a rate of 100px/sec. If the delta (on a given call to update) is 33 milliseconds, then the amount you should move your background on this update is 100*(33/1000.0) = 0.033 - so you would move your background by 0.033 pixels. This might seem weird, and you may wonder what the point is of moving <1 pixel, but stick with me.
First, the reason you have to divide it by 1000.0 instead of 1000, is because you want the movement of the delta to give you a floating point number.
You'll notice that the 2D graphics stuff in Slick2D uses float values to track the placement of things. That's because if the delta tells you to move something by 0.033 pixels, you need to move it by 0.033: not 0, and not 1 pixels. Sub-pixel movement is critical to smoothing out the increase/decrease in frame rates as well, because the cumulative effect over several sub-pixel movements is that, when the moment is right, all those little movements add up to a whole pixel, and it's perfectly smooth, resulting in the correct overall movement rate.
You may think that, since your screen resolves images to a given pixel, and not sub-pixel elements, that it doesn't matter if you do sub-pixel movement, but if you convert all your movement tracking to floats, you'll see that the effect you're observing largely goes away.

Related

Smooth movement Opengl ES 2.0

I'm building a very simple "game" for Android using Opengl ES 2.0. The gameplay consists in a moving point which accelerates or decelerates based on user input.
Of course the space covered by the point in a single frame depends on the amount of time elapsed from last frame, so to calculate this space i multiply the speed of the point and this amount of time.
I also have a camera which moves according to my point, but I flip x and y axis in order to make the camera follow the point.
My problem is that the point (and the camera) doesn't move smoothly. By the way I don't get why, since FPS are always 60 or at least 55 (I check them through an external app).
If I use always the same amount of time between a frame and the next all is smooth.
By the way, in order to understand what is wrong I built a very simple FPS counter and I log FPS (or elapsed time) through Log.d. Here I noticed that values vary between 45 and 80 FPS. Now, I think that if I could lock this value to a maximum of 60 (which is most smartphones screen refresh rate), then the movement would be way more smooth.
So my question is: how can I avoid my app draws a frame before 0.0166 seconds elapsed from last frame?
Thanks for reading and sorry for my english!
Here I noticed that values vary between 45 and 80 FPS.
The graphics subsystem will return a buffer to the application as soon as one is available, so with triple buffering the frame time measured on the CPU can be a little unpredictable as the application is not running tightly locked with the compositor and CPU time can move about due to CPU frequency changes.
In general the display update will be capped at 60 FPS but because your animation is based on the elapsed frame time you are seeing on at the API level (which is decoupled from the actual display update) you are animating each frame as if it were 45 FPS or 80 FPS which isn't what actually appears on screen.
If you know you are close to 60 FPS, I'd try something like averaging the elapsed time over the last 3 frames, and using that timestep as your animation update rate. This should remove most of the jitter caused by buffer skid, at the expense of a little latency to reacting to large workload changes.

How to reset coordinate if crosses float limits in an infinite running game in libgdx

I am new to the world of libgdx, I am developing an infinite running game. I am curious to know if a player is running for several hours and its position keeps on changing lets says its x value is increasing countinously, then what happens if position crosses float max limits. Some of the discussion suggests that we need to reset the coordinates after certain moments of time http://answers.unity3d.com/questions/491411/best-practices-for-endless-runner-type-games.html. But I am not sure how to achieve this in libgdx.
Whatever method you have of keeping the level "infinite" (without actually using up "infinite" memory), is where you can tie in "resetting" your character and level's position most conveniently.
In many cases, your character doesn't even need to "actually" be moving - the level can just be moving past him to the left.. similar to how people use a treadmill to run, but actually they stay in place. Destroy the pieces that move off-screen to the left and keep them coming on the right.
Alternatively, the character might be running along and at some convenient point you can move the entire level and the character back to the origin with nobody the wiser. It just has to happen "all at once", without physics methods of movements, and for every position you store. On slower devices, depending on the number of objects you have to move, this could result in a long single frame of lag... so use with caution.

Best Timer Designs for Java2D video games

I am building a Java2D video game with multiple sprites updating on the screen at once, and was looking for feedback with regard to best way to handle updates via use of Timers.
I was looking for feedback on best way to handle Timer design that would update locations of each Sprite. Currently, the way I have been doing it, is I have one Timer. When it expires, I update the position of each Sprite. I only ever Update Sprite location by 1 pixel, to keep motion smooth. If something was to update slower that then rest of the Sprite, I update it's position say on every 3 or 5th call of a getImage() call (used to get the current icon image of the sprite).
Now with this approach, all updates are dependent on the main timer, and the Sprites sort of update in relation to each other. So if I wanted to speed up the game, I just update the refresh rate of the main timer.
However, I don't know if this is the best approach. Would it be better to put each object on it's own timer, but would that cause other issues? Maybe cause problems for the main paint() method?
Was just looking for feedback on a good design technique for this.
It is possible to keep using one timer while having perfectly smooth animations despite different animation and movement speeds between different sprites. The way to do is by changing your animation and movement of sprites from a tick based approach (move x many pixels per update) to a time based approach (move x many pixels per how much time has elapsed since the last update).
This would mean your Sprite class (or whatever you have), has floating point x and y positions, as well as floating point x and y velocities. To change the speed of a certain sprite, you would change the velocity (which would be pixels/drawingUnitsEtc per millisecond/nanosecond), and won't be limited by how fast you can make the timer run.
However, I don't know if this is the best approach. Would it be better to put each object on it's own timer, but would that cause other issues?
Well if you did use a timer per Sprite that used a different speed, you would run into overhead problems if the timers ran on their own thread, and if the timers were executed on the same thread then you are technically updating your Sprites based on how much time has elapsed but just moving the velocity constant to an integer.
You would also run into a problem of how you can ensure the Timer consistently returns. With separate timers, imagine that there may be two sprites that are walking next to each other in game which want to update at 10ms, but one of them is running at 11ms due to a laggy timer, eventually one will run into the back of the other and turn around and mess up your level design or some other game mechanic. Another one is that they could be two Sprites of the same kind but now one is now an animation frame ahead of the other while that didn't hold true for the first few seconds that you saw them. With a single timer that updates all sprites that operate together you'll get those consistent results.
Assuming you're using java.util.timer's schedule method.
You could use the scheduleAtFixedRate method for cleaner looking code.
Only use one instance of Timer and attach all sprites to it, this keeps all sprites running on the same thread because then you eliminate all forms of concurrent modification, using a new thread for each sprite is way overkill as the threads will be running as fast as possible and maxing out the computer.
You could also simply make something along the lines of a SpriteManager class which extends Thread so that you don't even need to use timer, all sprites will be running as fast as possible but on one thread, it wont put too much load on the cpu but it worth it. Professionally, movement falls under physics so a game would have some physics thread that handles all updates to everything.
You could get even more detailed in the physics thread by realising that throughout the course of gameplay the amount of objects on the thread will change therefore will update less frequently making everything slower (even if it is microseconds). To keep everything running smoothly you can delta scale. Delta scaling simply takes the time it took last frame as a hint to how fast the thread is running and scales the speed of objects up or down appropriately - this is how (most) games don't run slower when the frame rate drops, instead, they look like they jumped to where it would be at that point in time.

Issue with LWJGL Display

I am currently in the process of making a tile based 2D platformer using lwjgl. I have a character that is able to run and jump all around the map. I have run into a strange problem when moving the window. When I move the window the game will freeze which isn't a big deal because when you let go it unfreezes, but after it unfreezes my character will end up moving down a number of tiles based on how long you hold the window or move the window for. Is there anything i should know about the library and the display, or do you need to see the code for the window initialization or the physics and collision detection? I have no idea why the movement of the window would have anything to do with the players position!
Solution:
After quite a lot of thought and attempts to fix the problem, I had realized that i am using a delta in my update methods, because delta is calculated by the time between each update, because the game freezes when the window is "moved" or "grabbed" the delta value becomes very large in a short period of time causing the player or object to be moved a very large amount at once. To fix this i simply put a limit on the delta value that gets passed into my update methods so that the player would not be able to move 10+ tiles at a time.

Bodies overlapping in 2D Physics simulation (Java)

I made a program in Java where circles can bounce into each other and gravitate towards each other.
For the most part (few circles on the screen), there are no noticeable bugs. The problem starts to happen when there is a large amount of circles on screen. Sometimes, the circles will overlap if it gets too crowded. It's as if the weight of all the other circles are crushing the circles together, causing them to overlap. Of course, there program doesn't know anything about how much a circle weighs, so it's not really crushing. Most likely, the piece of logic that handles resolving collisions is not able to handle crowded situations.
Circles are stored in an array, and each circle goes through the array using a for loop, comparing itself to the other circles. If the distance between the center of this circle and the center of the other circle is less than the sum of their radii, then the circles are colliding. The velocities of both circles are updated using an equation for collisions.
I think the problem occurs because if a circle is surrounded, it might receive an updated velocity into the circle behind it, while the circle behind it also receives an updated velocity into the former circle. In other words, the two circles get told to move toward each other, even though they are already touching. Once they overlap this way, I don't know why they don't undo their overlap.
I've tried restoring touching scenario if they are overlapping by finding the distance they are overlapped, then moving them apart from each other; each moves half the overlap distance apart. This doesn't change the circle's velocity, only their position.
This still doesn't solve the problem. If the circle is surrounded, and it overlaps with one of it's neighboring circles, its position is changed so they aren't overlapping, but this new position may cause it to overlap with another circle. Same problem.
If there was no gravity pushing the circles together, they would eventually spread out and resolve their overlapping issues, but the gravity prevents this from happening.
Further information:
Gravity is not taken into account when calculating new velocities after a collision.
Sounds like your hunches about what is causing the problem are correct in both cases.
Unfortunately, there's no easy way to fix this issue - it pretty much means rewriting your whole collision detection & resolution code from scratch. You have to work out the exact timing of the first collision, update everything only that far, resolve the collision (do your velocity update) then work out the exact timing of the next collision, then repeat...
Writing a good physics engine is hard, there's a good reason that there are many textbooks on the market about this subject!
The cheap 'fix' for your problem is to reduce the time interval for updates - e.g. instead of updating the physics in 33ms steps (~30fps), try updating in 16ms steps (~60fps). This won't prevent the problem, but it will make it much less likely to occur. Halving the time step will also double the time the processor has to spend doing physics updates!
If you use the cheap fix, the time step which will work best for you will be determined by how frequently collisions occur - more collisions means smaller time steps. How frequently collisions occur basically depends on how fast the circles tend to move and their population density (how much of a given area is filled by circles).
UPDATE: A little more info on the 'proper' approach.
The update would go something like this:
Start updating a frame. Let's say we want to update as far as time tF.
For every pair of circles, work out when you would expect a collision to occur (ignoring all the other circles). Let's call this time tC.
Find the smallest value of tC. Let's say this is for the collision between circles A and B, and let's call that collision cAB.
If tC <= tF, update all of the circles up to time tC. Otherwise, go to step 6.
Resolve collision cAB. Go back to step 2!
Update all the circles to time tF.
As you might imagine, this can get quite complicated. Step 2 can be quite tricky (and coputationally expensive) for non-circular objects (especially once you include things like angular momentum, etc.) although there are a lot of tricks you can do here to speed it up. It's also basically impossible to know how many times you'll be looping between steps 2 and 5.
Like I said, doing good physics simulation is hard. Doing it in real-time is even harder!

Categories

Resources