cubemaster21
|
 |
«
Posted
2013-01-16 00:38:36 » |
|
I've been trying to make a movement equation without much luck. I might just be over complicating it, but I'm not sure why it's not working. On my brother's computer, it runs much too slow (His computer is wicked fast.). And on mine, it runs just right. Here's my movement equation that I've got. Any criticism is also welcome. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public void move(int delta){ xCollision = false; yCollision = false; pastX = x; pastY = y; velocity.y += (G_ACCELERATION * delta)/1000.0; x += (velocity.x * delta)/1000.0; collisionBox = new CollisionBox(x, y, sprite.getWidth(),sprite.getHeight()); if(doesCollideOnX()){ x = pastX; velocity.x = 0.0; xCollision = true; } y += (velocity.y * delta)/1000.0; collisionBox = new CollisionBox(x, y, sprite.getWidth(),sprite.getHeight()); if(doesCollideOnY()){ y = pastY; velocity.y = 0.0; yCollision = true; } collisionBox = new CollisionBox(x, y, sprite.getWidth(),sprite.getHeight()); } |
If it helps any, the main specs on my computer are 2.1ghz Core 2 duo CPU, 4gb RAM, and 256mb on board video memory.
|
|
|
|
Agro
|
 |
«
Reply #1 - Posted
2013-01-16 00:41:34 » |
|
You need to keep a constant frame rate. I see delta in there somewhere, are you using delta timing?
|
|
|
|
cubemaster21
|
 |
«
Reply #2 - Posted
2013-01-16 00:43:07 » |
|
Yeah, i'm using delta timing.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
Vladiedoo
|
 |
«
Reply #3 - Posted
2013-01-16 00:44:52 » |
|
Maybe his computer runs so fast that the program reads delta as "0".
EDIT: A quick "System.out.println(delta);" will show.
EDIT2: Ah I read too fast, sorry.
|
|
|
|
|
cubemaster21
|
 |
«
Reply #4 - Posted
2013-01-16 00:46:39 » |
|
Well, it does move, and i've monitored the delta as 1 on his computer.
|
|
|
|
Ultroman
|
 |
«
Reply #5 - Posted
2013-01-16 00:49:57 » |
|
Probably a rounding-error somewhere, or you haven't capped your deltaTime.
|
- Jonas
|
|
|
cubemaster21
|
 |
«
Reply #6 - Posted
2013-01-16 00:54:43 » |
|
I cannot say that I've capped my deltaTime. What do you suggest would be a good cap?
|
|
|
|
Ultroman
|
 |
«
Reply #7 - Posted
2013-01-16 00:59:51 » |
|
Depends. Are you using libgdx or some other library? If so, you shouldn't have these problems, and you shouldn't need to implement a cap. deltaTime should probably not be 1. It should be a float. My deltaTime, using libgdx is something like 0.000165532564577 (taken from memory, not an actual case). Which deltaTime do you get on your own computer vs his?
|
- Jonas
|
|
|
cubemaster21
|
 |
«
Reply #8 - Posted
2013-01-16 01:02:58 » |
|
Well, I'm using my own engine, and all the delta is measured in milliseconds. For his computer, he gets 1ms as his delta. I usually get around 5ms on mine.
|
|
|
|
Ultroman
|
 |
«
Reply #9 - Posted
2013-01-16 01:06:36 » |
|
Please yield code snippet where you calculate deltaTime and apply it to something.
|
- Jonas
|
|
|
Games published by our own members! Check 'em out!
|
|
Best Username Ever
|
 |
«
Reply #10 - Posted
2013-01-16 01:08:35 » |
|
It seems like you did not do serious debugging. The problem is most likely your game loop, but we can only make wild guesses at what the problem might be.
Note that if you have a delta of 1.999 milliseconds that scraps the remainder after rounding, then you will not have consistent movement and will move slower at that rate than 1.000000001 rounded to 1.
|
|
|
|
|
HeroesGraveDev
|
 |
«
Reply #11 - Posted
2013-01-16 01:10:19 » |
|
Velocity movement with deltas is complicated.
It means that if loop A runs twice as fast as loop B, and the velocity increment is 0.5.
loop A delta = 1 loop B delta = 2
tick 1 A speed = 0.5 dist = 0.5 B speed = 1.0 dist = 2.0
tick 2 (still tick 1 for loop B) A speed = 1.0 dist = 1.5 B speed = 1.0 dist = 2.0
tick 3 (tick 2 for loop B) A speed = 1.5 dist = 3.0 B speed = 2.0 dist = 6.0
etc.
You need to work out a way to fix this or switch to a fixed timestep.
|
|
|
|
cubemaster21
|
 |
«
Reply #12 - Posted
2013-01-16 01:13:47 » |
|
You need to work out a way to fix...
That's what I've been trying to do, and that's the reason I posted here. Please yield code snippet where you calculate deltaTime and apply it to something.
As for the game loop, you'll probably all think it to be atrocious, but here you go, copy and pasted straight from my engine. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| log("Starting Toasted Engine..."); boolean successfulShutdown = true; Screen.setTransform(backupTransform); long lastTime = System.nanoTime(); double unprocessedSecond = 0; int frames = 0; boolean ticked = false; splashTimer.start(); while (running) { long currentTime = System.nanoTime(); long deltaTime = currentTime - lastTime; lastTime = currentTime; unprocessedSecond += deltaTime / 1000000000.0; while (unprocessedSecond > secondsPerTick) {
unprocessedSecond -= secondsPerTick; ticked = true; tickCount++; if (tickCount % 60 == 0) { FPS = frames; lastTime += 1000; frames = 0; if (printFPS) log(Integer.toString(FPS)); }
}
if (ticked) { delta = (int) (deltaTime / 1000000); if(!splashTimer.isDone() && showCustomStaticSplash){ splash(delta); Screen.add(customStaticSplash, 0, 0, Screen.getScreenWidth(), Screen.getScreenHeight()); Screen.drawToWindow(); continue; } if(updateTimers) for (Timer t : timers) t.update(delta); for (EngineLoop el : methods) el.doProcesses(delta); AffineTransform preRender = Screen.getGraphicalTransform(); for (RenderLoop rl : renderLoops){ rl.render(); Screen.setTransform(preRender); } if (renderDebug) { Font.RenderText("FPS:" + FPS, 0, 0, 1, debugColor); Font.RenderText("Delta:" + delta, 0,Font.getCharHeight() + 2, 1, debugColor); Font.RenderText("Tick:" + tickCount, 0, 2 * (Font.getCharHeight() + 2), 1, debugColor); Font.RenderText("Render loops:" + renderLoops.size(), 0,3 * (Font.getCharHeight() + 2), 1,debugColor); Font.RenderText("Logic loops:" + methods.size(), 0,4 * (Font.getCharHeight() + 2), 1,debugColor); Font.RenderText("Timers:" + timers.size(), 0, 5 * (Font.getCharHeight() + 2),1, debugColor); } frames++; Screen.drawToWindow();
long timeTaken = System.currentTimeMillis(); long sleepTime = period - timeTaken; try { Thread.sleep(sleepTime); } catch (Exception e) { } }
} |
|
|
|
|
Ultroman
|
 |
«
Reply #13 - Posted
2013-01-16 01:18:08 » |
|
Off the bat: long lastTime = System.nanoTime(); should be changed to long lastTime = 0;
Otherwise your first update will run with a deltaTime of 0.
|
- Jonas
|
|
|
Ultroman
|
 |
«
Reply #14 - Posted
2013-01-16 01:25:33 » |
|
These variables are weird. timeTaken is not actually set to the time taken to render the frame, and period is, for us, undefined. Please elaborate.
long timeTaken = System.currentTimeMillis(); long sleepTime = period - timeTaken;
|
- Jonas
|
|
|
cubemaster21
|
 |
«
Reply #15 - Posted
2013-01-16 01:28:36 » |
|
These variables are weird. timeTaken is not actually set to the time taken to render the frame, and period is, for us, undefined. Please elaborate.
long timeTaken = System.currentTimeMillis(); long sleepTime = period - timeTaken;
I've been using this loop since I started programming, I got it from a youtube tutorial. I'm not quite sure of what's going on there. I should probably just remove it
|
|
|
|
Ultroman
|
 |
«
Reply #16 - Posted
2013-01-16 01:29:33 » |
|
No no no, you have to sleep (or yield) between updates!
|
- Jonas
|
|
|
cubemaster21
|
 |
«
Reply #17 - Posted
2013-01-16 01:32:34 » |
|
No no no, you have to sleep (or yield) between updates!
Yeah, idk what I was thinking. Btw, the period variable is equal to 30. At this point, I'm thinking I might need to rewrite my engine....
|
|
|
|
Ultroman
|
 |
«
Reply #18 - Posted
2013-01-16 01:33:00 » |
|
What is period set to? It seems to me, that you'd have to change long timeTaken = System.currentTimeMillis(); to long timeTaken = System.currentTimeMillis()-lastTime;
But I don't think this'll help your problem.
|
- Jonas
|
|
|
Ultroman
|
 |
«
Reply #19 - Posted
2013-01-16 01:34:53 » |
|
You can easily implement another gameLoop, without having to change all your update-code. I do think you have to simplify/rethink your time-handling.
|
- Jonas
|
|
|
cubemaster21
|
 |
«
Reply #20 - Posted
2013-01-16 01:39:05 » |
|
Yeah, a new game loop seems to be in order... Thanks for the help guys. Ultroman, which would you recommend? Fixed or variable time step?
|
|
|
|
Ultroman
|
 |
«
Reply #21 - Posted
2013-01-16 01:57:10 » |
|
You have a lot of stuff about unprocessedSeconds and ticking. It seems like a mix of methods, and it gets very confusing. It seems weird to me that you'd ever get deltatimings of 1 and 5. I'm running my game at 60fps using a variable timestep loop, and my deltatimings are usually around 16.0. I only update each frame, because I don't need any more than that. If I need to do any collision-detection more precisely (so bullets don't go through something in a single frame), I simply divide the deltaTime by a factor in my bullet collision-code, and check the progression and collisions for the bullet each iteration of the divided time. This run-through of gameloops may help you, although the fixed timestep implementation is a bit confusing. I'd go with the variable timestep loop, but read through that article, and see which one is the best for your situation.
|
- Jonas
|
|
|
Ultroman
|
 |
«
Reply #22 - Posted
2013-01-16 03:07:01 » |
|
This is what I use: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| private volatile boolean running = false; private int desiredFPS = 60; private int fps = 0; private int frames = 0; private long totalTime = 0L; private long sleepTime = 0L; private long deltaTime = 0L; private long lastUpdateTime = 0L; private long currentUpdateTime = 0L; private long endLoopTime = 0L; private long maxDelta = 17 * (long)1e6, desiredDelta = Math.round((double)1000000000L / desiredFPS);
public void run() { currentUpdateTime = System.nanoTime(); while (running) { currentUpdateTime = System.nanoTime();
updateTimersForFPScounter();
deltaTime = currentUpdateTime - lastUpdateTime; lastUpdateTime = currentUpdateTime; while(deltaTime > 0) { long delta = deltaTime > maxDelta ? maxDelta : deltaTime; updateGameLogic(delta); deltaTime -= delta; }
do{ do{ Graphics2D g = (Graphics2D)s.getBufferStrategy().getDrawGraphics(); draw(g); g.dispose(); }while(s.getBufferStrategy().contentsRestored()); s.getBufferStrategy().show(); }while(s.getBufferStrategy().contentsLost());
endLoopTime = System.nanoTime(); sleepTime = desiredDelta - (endLoopTime - currentUpdateTime);
long diff; if(sleepTime>0){ while((diff = System.nanoTime()-endLoopTime) < getSleepTime()) { if(diff < getSleepTime()*0.8) try { Thread.sleep(1); } catch(Exception exc) {} else Thread.yield(); } } }
if(!s.isWindowedMode())s.restoreScreen();
System.exit(-1); }
private void updateTimersForFPScounter() { totalTime += currentUpdateTime - lastUpdateTime; frames++;
if( totalTime >= 1000000000) { totalTime = 0; setFps(frames); frames = 0; } } |
|
- Jonas
|
|
|
cubemaster21
|
 |
«
Reply #23 - Posted
2013-01-16 03:19:55 » |
|
Yeah, that's A LOT better than the monstrosity that I posted, do you mind if I use it?
|
|
|
|
Sparky83
|
 |
«
Reply #24 - Posted
2013-01-16 09:35:07 » |
|
Off the bat: long lastTime = System.nanoTime(); should be changed to long lastTime = 0;
Otherwise your first update will run with a deltaTime of 0.
What is the problem with that? Wouldn't it be more of a problem if you set lastTime to 0 and then have uncontrollable delta in the first frame? Because you never know the relative starting point of the time measuring of nanotime(). I prefer having no movement or change in the first frame. Why should that be a problem at all?
|
|
|
|
|
Ultroman
|
 |
«
Reply #25 - Posted
2013-01-16 20:05:27 » |
|
Yeah, that's A LOT better than the monstrosity that I posted, do you mind if I use it?
Not at all  Off the bat: long lastTime = System.nanoTime(); should be changed to long lastTime = 0;
Otherwise your first update will run with a deltaTime of 0.
What is the problem with that? Wouldn't it be more of a problem if you set lastTime to 0 and then have uncontrollable delta in the first frame? Because you never know the relative starting point of the time measuring of nanotime(). I prefer having no movement or change in the first frame. Why should that be a problem at all? If the timings of lastTime and the deltaTime you use later to update before the first frame, you will get a little bit of remainder from their differences, which I would define as an abnormal deltaTime for a frame. Better to ensure that it updates a correct amount of time.
|
- Jonas
|
|
|
|