background information
I've been in recent development of a game using LWJGL and I was curious as to how many frames per second I could get from running the game without using the Display.sync(60) function (Which limits fps to 60). Upon commenting out the code, I stumbled upon the game speed updating at 9000 some fps, which, in turn, made the game tick run 9 thousand times per second.
question
How should I implement a game timer to prevent the fps creating issues with how fast the game actually runs? I am aware I need to separate the two timers, but how/which way is the most efficient of going about doing so (in java)?
TheCodingUniverse offers a great tutorial here: http://thecodinguniverse.com/lwjgl-frame-rate-independent-movement/
However, the basic answer is that you move the frame by saving the last System.currentTime() and then compare it to this System.currentTime(). Then when moving it would be like object.move(x * delta, y * delta);
To quote from the above link,
// Under the class definition
private static long lastFrame;
private static long getTime() {
return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
private static double getDelta() {
long currentTime = getTime();
double delta = (double) currentTime - (double) lastFrame;
lastFrame = getTime();
return delta;
}
// In initialization code
lastFrame = getTime();
// In game loop
long delta = getDelta();
movement_x += dx * delta;
I hope that helps :).
Related
So I am trying to make a Physics Simulation, which aims to simulate a missile going off a long distance away, (for my example I have used 1.6km) and I have a AA weapon at this 1.6km distance; when the missile is launched, due to maths I have worked out when I need to release the AA weapon to hit the missile. So cool the maths all checks out, and I am 99% certain mathematically this should work; but the error seems to occur in the animation stage, and I feel this is something to do with how I am handling gravity.
The issue is instead of the flight path of the missile following a lovely parabola, it is instead taking a path consisting of many different linear functions (hence the Eulerian integration speculation(Source: http://natureofcode.com/book/chapter-5-physics-libraries/)); and I believe the reason for this is to do with my scale. I am using a scale of 1 pixel = 1 meter. The image updates every 60 seconds, so I am saying every cycle, take the vertical velocity - (9.81 / 60) and then update the position by (Vertical velocity / 60). The problem is, it only wants to round to the nearest pixel, so in the first 2 seconds or so, it only wants to have the vertical position change at 4 pixels per cycle, and then it goes to 5, then 6... This causes the flight path (when the missile was launched at 200m/s at 50 degrees and the AA launched at 70degrees with the same speed) to look like:
If anyone knows how I can fix this issue to turn the inaccurate linear representation into a nice parabolic one that was still accurate to the time, (the time after launch is about 3 seconds for this). If anyone has any suggestions and/or solutions, or if you are able to explain why this is happening and don't mind spending a little time explaining it to me to get a better understanding of the problem, that would be greatly appreciated! If you require any more information to help you help me, then just leave a comment and I will provide you with any info. The relevant pieces of code are:
public void gravity(){
for (int i = 0; i < rockets.size(); i++){
if(timeToStart <= milliSecondTimer){
rockets.get(1).fired = true;
//Trail of other rocket
if (milliSecondTimer > 0.1 * count){
rockets.add(new Ball(rockets.get(1).x - 20 ,rockets.get(1).y - HEIGHT + 100,5,0,0,false));
}
}
if(rockets.get(i).fired){
rockets.get(i).vSpeed -= 9.81 / 60;
rockets.get(i).move(0, (int) (rockets.get(i).vSpeed / 60));
rockets.get(i).move(1, (int) (rockets.get(i).hSpeed / 60));
} else if (timeToStart==1110){
//function to work out the time displacment
derr(1);
}
//For the trail
if (milliSecondTimer > 0.1 * count){
rockets.add(new Ball(rockets.get(0).x - 20 ,rockets.get(0).y - HEIGHT + 100,5,0,0,false));
count++;
}
}
}
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame("App Name");
Rockets app = new Rockets();
frame.setSize((int)(WIDTH * SCALER),(int)(HEIGHT * SCALER));
frame.add(app);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.requestFocus();
long lastLoopTime = System.nanoTime();
int fps = 0, lastFpsTime = 0, count = 1;
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
//Game Loop
while(true){
long now = System.nanoTime();
long updateLength = now - lastLoopTime;
lastLoopTime = now;
delta = updateLength / ((double)OPTIMAL_TIME);
lastFpsTime += updateLength;
fps++;
if (lastFpsTime > 100000000 * count){
milliSecondTimer += 0.1;
count++;
}
if (lastFpsTime >= 1000000000){
System.out.println("(FPS: "+fps+")");
lastFpsTime = 0;
fps = 0;
count = 1;
}
loopsGone++;
app.repaint();
Thread.sleep( (lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 );
}
}
Thank you,
Sam
Perhaps you can change your x and y rocket coordinates to a float (I'm assuming they are int right now). And then when you are drawing, that is when you add the (int) cast. For instance,
rockets.get(i).move(0, (int) (rockets.get(i).vSpeed / 60));
Should not have an int cast.
Also, you're going to want to change
(rockets.get(i).vSpeed / 60));
to
(rockets.get(i).vSpeed / 60.0));
You want your position to retain precision, which it's not doing currently with the int cast. This is what using a float would achieve.
It doesn't look like scale is the issue. It would be an issue if you are trying to draw a parabola on an image that is, say, 10 x 10 pixels.
Could you post your rocket class? I'd like to run this, looks interesting.
Thanks for accepting my answer. Here is another issue I saw.
For much better precision in position, you will want to update your position function much more frequent, meaning more than once every time you repaint. This is how my game loop looks.
public void run() {
long lastTime=System.nanoTime();
final double amountOfTicks=60.0;
double ns=1000000000/amountOfTicks;
double delta=0;
int updates=0;
int frames=0;
long timer=System.currentTimeMillis();
while (running) {
long now=System.nanoTime();
delta +=(now-lastTime) / ns;
lastTime=now;
if (delta>1) {
update(); <--- this is where your gravity() method belongs
delta--;
updates++;
}
render(); <---- this will be your repaint method
frames++;
if (System.currentTimeMillis()-timer>1000) {
timer+=1000;
currUpdates=updates;
currFrames=frames;
updates=0;
frames=0;
}
}
}
What it does is updates spaceship positions once every millisecond, but only renders in 60 fps.
I have a (simple) game engine; and in game loop i have a "deltaTime" variable. (The time since last frame, in seconds) The deltaTime variable is exactly as id expect.
However, even though the deltaTime is fine, i cant transform an entity's position accurately. It works fine under very low FPS, but as it get higher (15<) it breaks down, and doesn't work. The object goes very, very slowly. The faster the FPS, the slower it goes. I even tried limiting the FPS to 120.
Ive been able to find the suspected troubled code area here:
curEntity.pos.y+= curEntity.velocity.y * deltaTime;
pos.y, velocity.y, and deltaTime are all floats.
Whats the deal here? How can i fix this?
If your interested, here is the code that gets the deltaTime:
long now = System.nanoTime();
deltaTime= (now - lastTime) / 1000000000f;
lastTime=now;
// Its worth noting, i'm trying to do what Unity does;
also, i have tried chaning the pos.y, velocity.y, and deltaTime to doubles
After messing around with it for awhile i found out the answer:
I had the delta-Time since the last loop pass, not the last physics update.
Here (if anyone cares) is the answer:
while(running){
long now = System.nanoTime();
//HERE IS WHERE THE DELTA TIME CODE WAS LAST
tickDelta += (now - lastTime) / nsPerTick;
frameDelta += (now - lastTime) / nsPerFrame;
lastTime=now;
if(tickDelta>=1){
//THIS IS WHERE IT SHOULD BE
//GETS THE TIME SINCE LAST TICK
deltaTime= (now - deltaTimeTimer) / 1000000000f;
deltaTimeTimer=now;
ticks++; Tick(); tickDelta=0;
}
if(frameDelta>=1){frames++; Render(); frameDelta=0;}
if(System.currentTimeMillis() - Timer >= 1){Timer+=1000; System.out.println("FPS: "+frames+"; TPS: "+ticks +"; deltaTime: "+deltaTime); ticks=0;frames=0;}
try{Thread.sleep(5);} catch(Exception err){} //TODO: Remove
//System.out.println(deltaTime);
}
}
So, I am working on making a 2D game in Java, and I really don't have too much experience with Java. I currently use a very simple loop using a swing timer running every 10ms or so that looks something like:
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
However, I need something more practical for obvious reasons. These reasons include the fact that more lag means less FPS AND slower movement/other updating.
I found the following code in a tutorial for a 3D Java game here. It would begin running when the program starts, and I understand enough to know it would work. However, I do not fully understand it: (tick() is the updater, render() renders the screen)
long currenttime;
long previoustime = System.nanoTime();
long passedtime;
int frames = 0;
double unprocessedseconds = 0;
double secondspertick = 1 / 60.0;
int tickcount = 0;
boolean ticked = false;
while (gameIsRunning) {
currenttime = System.nanoTime();
passedtime = currenttime - previoustime;
previoustime = currenttime;
unprocessedseconds += passedtime / 1000000000.0;
while (unprocessedseconds > secondspertick) {
tick();
unprocessedseconds -= secondspertick;
ticked = true;
tickcount++;
System.out.println(tickcount);
if (tickcount % 60 == 0) {
System.out.println(frames + " FPS");
previoustime += 1000;
frames = 0;
}
}
if (ticked) {
render();
frames++;
}
render();
frames++;
}
This code was not explained in the tutorial I found it in. Could someone please break this down and explain it?
I have also looked here for ideas, and the final piece of code on that page with a render thread and an update thread makes a lot of sense to me.
Which method should I use? One of the above, or something totally different? Also, you can probably tell that this is my first question here on stackoverflow.
Thanks in advance,
Josh
tick() is probably updating the game object's physical properties (position, velocity, etc.) tick() is called multiple times each update because some simulations can't handle too large a timestep without becoming unstable.
There's a popular article online which explains why this is the case, and why using a fixed timestep is the proper procedure. Check it out.
Each update the game is advanced in 1/60th second (so 60 frames a second) increments. This is repeated until there's less than 1/60th a second remaining in the aggregate. Aggregate is just a fancy word for sum.
Then a snapshot of the game's current state is rendered to the screen.
I won't get too deep into it, but really this code should be inerpolating each object's position by the remaining time in the aggregate during render().
long currenttime;
long previoustime = System.nanoTime();
long passedtime;
int frames = 0;
//this is an aggregate, games usually step in fixed units of time.
//this is usually because physics simulations can't handle too large of time steps.
double unprocessedseconds = 0;
double secondspertick = 1 / 60.0;
int tickcount = 0;
boolean ticked = false;
while (gameIsRunning) {
//get elapsed nano seconds from the epoch (january 1st, 1970)
currenttime = System.nanoTime();
//take difference of current time in nanos and previous time in nanos
passedtime = currenttime - previoustime;
previoustime = currenttime;
//divide to get the elapsed time in seconds.
unprocessedseconds += passedtime / 1000000000.0;
while (unprocessedseconds > secondspertick) {
tick();
unprocessedseconds -= secondspertick;
ticked = true;
tickcount++;
System.out.println(tickcount);
if (tickcount % 60 == 0) {
System.out.println(frames + " FPS");
previoustime += 1000;
frames = 0;
}
}
if (ticked) {
render();
frames++;
}
render();
frames++;
}
Good luck Josh.
Edit:
I have no experience with games using one thread for updates, and one for rendering. I can't give advice on those for that reason. If you have little or no experience with multithreading I'd avoid it as only complex games are likely to require this approach, and multithreading will add a multitude of issues you probably don't want to deal with.
Multithreaded game engines will consume more memory between rendering and updating than a single threaded game, or will wind up being depend on one another anyway. This is because the two threads can't manipulate the same data simultaneously. Therefor the only way for the two threads to operate is with synchronization on those data structures, or by the update thread suppling the render thread with immutable data to render.
Writing a multithreaded game engine would be a good introduction to threading. It could teach you quite a lot. Depends on what you want to get out of this.
If you are making a 2D game I feel even more confident that you will not need one thread for updating and one for rendering.
If you really want to pursue this, here's the approach I'd take.
You don't need more than a while loop to control rendering.
The way I do my engines is just as explained before, I multi-thread. Basically, if you split the job of processing and drawing the game into two segments it becomes quicker at the expense of more resources in use. I do a little something like this:
public class Engine implements Runnable {
//Sets classes
Engine tick = new Engine(true);
Engine render = new Engine(false);
Thread tickThread = new Thread(tick);
Thread renderThread = new Thread(render);
boolean job;
boolean isRunning = false;
long sleepTime = 5L;
public Engine(boolean job) {
//Sets what the thread does
this.job = job;
}
public static void startEngine() {
//Starts Engine
isRunning = true;
tickThread.start();
renderThread.start();
}
public void tick() {
//Process things
}
public void render() {
//Draw things
}
public void run() {
//Do engine base things
while(isRunning) {
if(job) {
tick();
} else {
render();
}
Thread.sleep(sleepTime);
}
}
}
This is by no means advanced. This is just an example of what a simple multi-thread game engine would be like. Honestly, I used this exact code when I was starting off making games. This could be used but some adjustments should be made depending on what you use it for. What I mean is that lets say you have an object that's moving and its being rendered at the same time. If the objects position is 50 and increasing and the render method is drawing it then the object could go to 51 then 52 before being rendered again. Normally, the processing is faster than the drawing. Another example: Lets say you have an ArrayList and are constantly removing and adding objects to it. Sometimes you can remove an object just as the render method is about to draw it and cause a null pointer exception because it's trying to draw something that doesn't exist. (I used "if(object.get(i) != null)" and worked around it that way)
I hope this helped at least a little (two years later, lol) and helped you get a basis of what multi-threading is like (if you didn't already).
I'm making a basic 2D game, yet I'm having problems with lag. The character on the game moves fine, yet sometimes slows right down, mainly when near an enemy. The enemy is not causing the lag though, as I've had 50 of them on the screen at once and it runs fine.
I've done the timing almost identically to how it's done in the Killer Game Programming in Java book, yet it doesn't seem to work too well. The FPS also seems to change a lot, which it shouldn't, because it should always take 15ms to complete an update-render-paint-sleep cycle, can anyone explain this?
Also, I think it lags more when my computer is doing things in the background (antivirus scanning, etc.), although I can run the game at about 550FPS while it's running other programs, so I don't think it's my computer.
Here's how I do the timing:
int waitTime = 1000 / 65; //65 being the desired FPS
while(running){
if(!loading){
gameUpdate();
gameRender();
gamePaint();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = waitTime - (timeDiff / 1000000L);
if(sleepTime > 0){
try{
mainThread.sleep(sleepTime);
} catch(InterruptedException ie){}
}
else{
sleepSkipped++;
if(sleepSkipped == maxSleepSkipped){
Thread.yield();
sleepSkipped = 0;
}
}
fpsTime += (System.nanoTime() - beforeTime) / 1000000;
fps++;
if(fpsTime > 1000){
System.out.println("FPS: " + fps);
fps = 0;
fpsTime = 0;
}
beforeTime = System.nanoTime();
}
}
I think your problem is similar to one very recently Weird behavior in Thread.sleep()
I see that in your loop you add the sleeptime to your timer, meaning it keeps increasing (lowering fps) until it becomes so large that substracting the waittime from it gives a negative number, making your loop go into the one that yields the thread where it adds to the skipcount and yields when the count is high enough.
As arynaq suggested, it was a problem with the enemy collision detection. Every cycle through the loop made each enemy call quite a few methods, however I have now removed and relocated many of the method calls, which has completely fixed the lag problem. Thank you, arynaq.
I'm writing a fairly simple 2D multiplayer-over-network game. Right now, I find it nearly impossible for myself to create a stable loop. By stable I mean such kind of loop inside which certain calculations are done and which is repeated over strict periods of time (let's say, every 25 ms, that's what I'm fighting for right now). I haven't faced many severe hindrances this far except for this one.
In this game, several threads are running, both in server and client applications, assigned to various tasks. Let's take for example engine thread in my server application. In this thread, I try to create game loop using Thread.sleep, trying to take in account time taken by game calculations. Here's my loop, placed within run() method. Tick() function is payload of the loop. It simply contains ordered calls to other methods doing constant game updating.
long engFPS = 40;
long frameDur = 1000 / engFPS;
long lastFrameTime;
long nextFrame;
<...>
while(true)
{
lastFrameTime = System.currentTimeMillis();
nextFrame = lastFrameTime + frameDur;
Tick();
if(nextFrame - System.currentTimeMillis() > 0)
{
try
{
Thread.sleep(nextFrame - System.currentTimeMillis());
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
The major problem is that Thread.sleep just loves to betray your expectations about how much it will sleep. It can easily put thread to rest for much longer or much shorter time, especially on some machines with Windows XP (I've tested it myself, WinXP gives really nasty results compared to Win7 and other OS). I've poked around internets quite a lot, and result was disappointing. It seems to be fault of the thread scheduler of the OS we're running on, and its so-called granularity. As far as I understood, this scheduler constantly, over certain amount of time, checks demands of every thread in system, in particular, puts/awakes them from sleep. When re-checking time is low, like 1ms, things may seem smooth. Although, it is said that WinXP has granularity as high as 10 or 15 ms. I've also read that not only Java programmers, but those using other languages face this problem as well.
Knowing this, it seems almost impossible to make a stable, sturdy, reliable game engine. Nevertheless, they're everywhere.
I'm highly wondering by which means this problem can be fought or circumvented. Could someone more experienced give me a hint on this?
Don't rely on the OS or any timer mechanism to wake your thread or invoke some callback at a precise point in time or after a precise delay. It's just not going to happen.
The way to deal with this is instead of setting a sleep/callback/poll interval and then assuming that the interval is kept with a high degree of precision, keep track of the amount of time that has elapsed since the previous iteration and use that to determine what the current state should be. Pass this amount through to anything that updates state based upon the current "frame" (really you should design your engine in a way that the internal components don't know or care about anything as concrete as a frame; so that instead there is just state that moves fluidly through time, and when a new frame needs to be sent for rendering a snapshot of this state is used).
So for example, you might do:
long maxWorkingTimePerFrame = 1000 / FRAMES_PER_SECOND; //this is optional
lastStartTime = System.currentTimeMillis();
while(true)
{
long elapsedTime = System.currentTimeMillis() - lastStartTime;
lastStartTime = System.currentTimeMillis();
Tick(elapsedTime);
//enforcing a maximum framerate here is optional...you don't need to sleep the thread
long processingTimeForCurrentFrame = System.currentTimeMillis() - lastStartTime;
if(processingTimeForCurrentFrame < maxWorkingTimePerFrame)
{
try
{
Thread.sleep(maxWorkingTimePerFrame - processingTimeForCurrentFrame);
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
Also note that you can get greater timer granularity by using System.nanoTime() in place of System.currentTimeMillis().
You may getter better results with
LockSupport.parkNanos(long nanos)
altho it complicates the code a bit compared to sleep()
maybe this helps you.
its from david brackeen's bock developing games in java
and calculates average granularity to fake a more fluent framerate:
link
public class TimeSmoothie {
/**
How often to recalc the frame rate
*/
protected static final long FRAME_RATE_RECALC_PERIOD = 500;
/**
Don't allow the elapsed time between frames to be more than 100 ms
*/
protected static final long MAX_ELAPSED_TIME = 100;
/**
Take the average of the last few samples during the last 100ms
*/
protected static final long AVERAGE_PERIOD = 100;
protected static final int NUM_SAMPLES_BITS = 6; // 64 samples
protected static final int NUM_SAMPLES = 1 << NUM_SAMPLES_BITS;
protected static final int NUM_SAMPLES_MASK = NUM_SAMPLES - 1;
protected long[] samples;
protected int numSamples = 0;
protected int firstIndex = 0;
// for calculating frame rate
protected int numFrames = 0;
protected long startTime;
protected float frameRate;
public TimeSmoothie() {
samples = new long[NUM_SAMPLES];
}
/**
Adds the specified time sample and returns the average
of all the recorded time samples.
*/
public long getTime(long elapsedTime) {
addSample(elapsedTime);
return getAverage();
}
/**
Adds a time sample.
*/
public void addSample(long elapsedTime) {
numFrames++;
// cap the time
elapsedTime = Math.min(elapsedTime, MAX_ELAPSED_TIME);
// add the sample to the list
samples[(firstIndex + numSamples) & NUM_SAMPLES_MASK] =
elapsedTime;
if (numSamples == samples.length) {
firstIndex = (firstIndex + 1) & NUM_SAMPLES_MASK;
}
else {
numSamples++;
}
}
/**
Gets the average of the recorded time samples.
*/
public long getAverage() {
long sum = 0;
for (int i=numSamples-1; i>=0; i--) {
sum+=samples[(firstIndex + i) & NUM_SAMPLES_MASK];
// if the average period is already reached, go ahead and return
// the average.
if (sum >= AVERAGE_PERIOD) {
Math.round((double)sum / (numSamples-i));
}
}
return Math.round((double)sum / numSamples);
}
/**
Gets the frame rate (number of calls to getTime() or
addSample() in real time). The frame rate is recalculated
every 500ms.
*/
public float getFrameRate() {
long currTime = System.currentTimeMillis();
// calculate the frame rate every 500 milliseconds
if (currTime > startTime + FRAME_RATE_RECALC_PERIOD) {
frameRate = (float)numFrames * 1000 /
(currTime - startTime);
startTime = currTime;
numFrames = 0;
}
return frameRate;
}
}