Time Based Movement?

Started by
9 comments, last by pammatt 19 years, 6 months ago
Can somebody please explain to me what time based movement is and how I would incorporate it into games? I decided to remake my Pong clone since my other game project is going a bit slow but with sounds and a font engine. Last year when I first made it, it was just the ball bouncing back and forth between the paddles and there was no score or anything. Back to my question, how would I use time based movement for the game objects like the paddles and balls? If it helps, I'm using C/C++ with the SDL graphics API.
Advertisement
Achieving Frame Rate Independent Game Movement
I read through that article but it isn't working properly. Here's some source snippets:
	float paddleMovement;			// How far can the paddles move in a second?	float movementValue;			// Value to move each frame	float secondsPerFrame;			// Holds the value for how many seconds have elapsed between frames	float timeDifference;			// How much time has elapsed?	float timer;				// Keeps track of the timevoid CEngine::CalculateTime(){	// Determine how many seconds have elapsed	timeDifference = SDL_GetTicks() - timer;	// The function reads in milliseconds so convert to seconds by dividing by 1000	secondsPerFrame = (float)(timeDifference / 1000.0f);	// Now compute the movement value	movementValue = (float)(paddleMovement * secondsPerFrame);	// Get the new time	timer = (float)SDL_GetTicks();}	if (Engine.keys[SDLK_s] && Player1.GetY() != 400)   	{Player1.AddY((float)1 * Engine.movementValue);}


If I push S, the paddle doesn't move at all. If I take out the multiplication, the paddle moves. So my guess is that somewhere along the lines movementValue is getting assigned to 0. Unless it has to do with my type casting but I kinda doubt that.
*Shameful bump*
first of all, a simple design thing. i notice you are doing the player's movement outside of the player's code (i saw a Change_Y() function). This probably isnt a good idea. you should encapsulate all the player's abilities to inside the player...

secondly, your calculating the time passed in a not-so-good way. i notice you record the time at the bottom, then calculate the difference at the top. first of all, isnt this backwards? wouldnt you want to start the timer at the top, and record the difference at the bottom? otherwise, your just recording how much time since the bottom end of the loop till the top. this is probably 0 MS. hence, why your movement is 0 when you multiply....

anyway, even reversing it isnt a good idea. you should do all time calculations in one place. this is because your OS / game can act funky and the time wont be accurate. (sorry i dont know the exact reason why, i cant describe it in words, but someone here might.) anyway, you should do time-recording in one spot. like this:

previous_time = current_time;current_time  = SDL_GetTicks();time_passed   = (float)(current_time - previous_time) * 0.001f;


this block of code should be at the top of the loop.

why are you changing the Y by 1*movement? whats the 1* there for? anyway, it should look something like this then:

BTW - timer and timeDifference need not be a float. an Uint32 or int would be fine here.
void CEngine::CalculateTime(){previous_time = current_time;current_time  = SDL_GetTicks();time_passed   = (float)(current_time - previous_time) * 0.001f;}


now, in your player movement code.. (move this to inside your player class!!!

if (Engine.keys[SDLK_s] && yPos != 400)   {yPos += (time_passed * paddle_velocity));}


that should work.
FTA, my 2D futuristic action MMORPG
Still no go. Here's my main.cpp file where I have everything:

#include "CEngine.h" int main(int argc, char *argv[]){	int previous_time = 0;	int current_time = 0;	int time_passed = 0;	CEngine Engine;					// Generic engine used throughout game	Engine.Init();					// Initialize everything	// Begin the main game loop	bool done = false;	while (done == false)	{		previous_time = current_time;		current_time  = SDL_GetTicks();		time_passed   = (float)(current_time - previous_time) * 0.001f;		// Check for events		SDL_Event event;    while (SDL_PollEvent(&event))    {      if (event.type == SDL_QUIT)  {done = true;}      if (event.type == SDL_KEYDOWN)      {        if (event.key.keysym.sym == SDLK_ESCAPE) {done = 1;}				if (event.key.keysym.sym == SDLK_p) {Engine.paused = !Engine.paused;}				if (event.key.keysym.sym == SDLK_1 && Engine.menuDrawn) {Engine.menuDrawn = false; Engine.paused = false;} 				if (event.key.keysym.sym == SDLK_2 && Engine.menuDrawn) {done = 1;}      }    }		// Poll key events		Engine.keys = SDL_GetKeyState(NULL);		if (Engine.menuDrawn == false && Engine.paused == false)		{			// Player 1 controls			if (Engine.keys[SDLK_w] && Player1.GetY() != 0)   			{Player1.AddY((time_passed * -2));}			if (Engine.keys[SDLK_s] && Player1.GetY() != 400)   			{Player1.AddY(1);}			// Player 2 controls			if (Engine.keys[SDLK_UP] && Player2.GetY() != 0)   				{Player2.AddY(-1);}			if (Engine.keys[SDLK_DOWN] && Player2.GetY() != 400) 				{Player2.AddY(1);}		}		// Draw everything		Engine.DrawScene();	}	Engine.CleanUp();	return 0;}


I push 's' and it still doesn't move at all. Also, I have two main classes that are in use here. CEngine with does all the game related functions and CSprite which handles all Sprite related functions. When s is pushed, it uses the AddY() function defined in CSprite to change it's position on the Y axis.
hmm. it apears in your code you do

if(s is pushed)
add 1 to y

why is this? you dont even use your time based movement here, so pushing S definetly should move your sprite. this is a problem in the addY() function then...

also, while previous time and current time should be int's, time_passed needs to be a float. this is because most of the time it should be a number less then 1, like 0.4 or something like that.

lastly, i notice where you DO use time based movement to move the sprite, you have it * -2. when doing time based movement, you will want to use numbers much bigger then when you didnt use it. try switching this to -200.
FTA, my 2D futuristic action MMORPG
Sorry about talking about "s" when it was actually "w". I have one last question now. The time-based movement stuff works now but how do I know what values will allow the sprite to move X pixels? time_passed * 200 works fine but how do I know it's moving 200 pixels? time_passed * 100 doesn't work so apparently it doesn't exactly move it 200 pixels, that's just the only acceptable value right now.
thats odd that doing * 100 won't move it. it should move it... maybe its just moving really slow? post the code?
FTA, my 2D futuristic action MMORPG
Well, it moves it very slowly and sometimes it's unevenly moved. Like...it'd jump.

if (Engine.keys[SDLK_w] && Player1.GetY() != 0)
{Player1.AddY((time_passed * -100));}

Same time calculation code as before. I guess for later projects I should just fool around with the numbers until I get what I think is a good speed?

This topic is closed to new replies.

Advertisement