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.
Related
I need some help with a Java assignment I have, I'm required to build a clone of Pac-Man.
The problem is, I don't know how to draw the movements of the Pac-Man or the Ghosts. I'm thinking I should only draw the walls once, and continiously redraw the characters, but I don't know how I should do it or what methods of drawing I should use.
Generally speaking, it is no good idea not to redraw the complete GUI of any game you write several times each second (the quotient of complete redraws over a second is referred to as the 'frame-rate' of a game). If you do not do this, you might observe weird effects like: The contents look strange if you resize or move the window in case its not displayed in full-screen, there might by weird graphical effects, and, most important, the images of your game-characters won't disappear at their previous positions, if you do not draw the background over them again.
Common approach is to set up a Thread that is not doing anything else but invoking some redraw methods about 60 times each second (60 fps (frames per second) appear fluent to the human eye as our temporal resolution lies in that scale) and to use another Thread that updates the position data of the characters and passes it to the draw-Thread together with the static wall-position-data.
I'm running a game/simulation on JavaFX and when I started it seemed reasonable to add an AnimationTimer to perform the tick updates. My Entity's are composed of a Polygon that holds their shape and position. I added the Polygon's to the scene via a Group and everything renders like magic. However, since it's an simulation, I now want to run millions of ticks with no rendering, to advance to the future and see the results. The problem is, since my Entity's (x,y) positions are inside the Polygon, every time handle() is called in the animation, it seems that the screen is updated.
What is the proper way to split the game loop and render, to be able to call render only after some amount of ticks?
I thought of creating my own MyPolygon class to hold the simulation data, and then when the time comes to draw, create on the fly one Polygon per Entity, but that seems also overkill for me (but maybe I'm wrong).
Also, I'm not sure how to change the ticks per second rate on the AnimationTimer. So I'm not sure it is suited for this specific need.
It seems like a very simple design choice, so there has to be a proper way to do it with JavaFX...
I have a list of game objects that I want to render in libgdx 2D.
In my setup I have two different cameras, one that matches the pixel resolution exactly (for drawing tiled background and fonts) and one that matches the gameboard with a typical viewport of (-0.1, -0.1, 1.2, 1.5).
Now I would like each game object in the list to decide for themselves which camera to use when rendering, which means that the projection matrices for the SpriteBatch may change several times inside the SpriteBatch.begin()...end().
One other solution would be to have two SpriteBatches active at the same time and make the game objects select which spritebatch to render to, and then call End() on them after rendering is finished. Some other questions and posts I've found on the Internets suggest that multiple active SpriteBatches is not a good idea.
What are the pros and cons of these solutions? Is there a better one?
Design wise, thats awful!
I usually have 2 cameras aswell. One for the game objects with low values (12x8 or 15x10), and one for the HUD (attack button, stats, etc) with high values (pixel perfect of my test device). I first draw the game objects, finish the batch, and then I draw the HUD. Just 2 draws. But:
SpriteBatch#setProjectionMatrix
"If this is called inside a Batch.begin()/Batch.end() block, the current batch is flushed to the gpu."
If you set the projection matrix several times inside your render code, that will trigger a lot of batch flushes and negatively (and greatly) affect your performance.
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.
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.