10
« on: April 01, 2011, 03:35:20 pm »
Here is how I am currently handling a lot of my input; this is a simple example, not perfect code by any means:
void Game::DoInput(void)
{
if(App->GetInput().IsKeyDown(sf::Key::Left)) turn_left = true;
else turn_left = false;
if(App->GetInput().IsKeyDown(sf::Key::Right)) turn_right = true;
else turn_right = false;
if(App->GetInput().IsKeyDown(sf::Key::Up)) thrust = true;
else thrust = false;
if(App->GetInput().IsKeyDown(sf::Key::Space)) fire = true;
else fire = false;
}
void Game::DoPhysics(float time_passed)
{
if(turn_left) theShip.angle += TURN_SPEED * time_passed;
if(turn_right) theShip.angle -= TURN_SPEED * time_passed;
if(fire) theShip.Shoot();
if(thrust) theShip.Thrust(time_passed);
theShip.Update(time_passed);
theAsteroid.Update(time_passed);
//slow down the ship a bit
for(int partialseconds_passed = time_passed * 10000.f;partialseconds_passed >= 0; --partialseconds_passed)
theShip.motion *= 0.99999;
//collision detection
if(theShip.CheckShotCollision(&theAsteroid))
{
//reset the asteroid
float rand_angle = rand()%360;
rand_angle /= 57.2957795f; //convert from degrees to radians
theAsteroid.motion.x = -sin(rand_angle);
theAsteroid.motion.y = -cos(rand_angle);
theAsteroid.motion *= ASTEROID_SPEED;
theAsteroid.pos.x = 30;
theAsteroid.pos.y = 30;
}
}
void Game::DrawLevel(void)
{
App->Clear();
theShipSprite->SetRotation(theShip.angle * 57.2957795f);
theShipSprite->SetPosition(theShip.pos.x, theShip.pos.y);
App->Draw(*theShipSprite);
theAsteroidSprite->SetPosition(theAsteroid.pos.x, theAsteroid.pos.y);
App->Draw(*theAsteroidSprite);
for(int i = 0; i < theShip.shots.size(); ++i)
{
theShotsSprite->SetPosition(theShip.shots[i]->pos.x, theShip.shots[i]->pos.y);
App->Draw(*theShotsSprite);
}
}
The Game::Run() function DOES NOT CHANGE from the one I posted before; nothing is added to it's event handling loop. If I was tracking mouse movement, I would probably add that into the event loop of Game::Run(), just because it's simple.
So, with the code above, my Game::Logic playstate looks like:
case PLAY1:
{
DoInput();
DoPhysics(time_passed);
DrawLevel();
}
break;
By doing things this way, I can easily have totally different DoInput() functions for different game states, like DoInputPlay2() etc., if they are required. Also, I have followed the cardinal rule of application/game programming by following the CONTROL/MODEL/VIEW paradigm, and seperating my CONTROL (inputs) from my MODEL (physics and rules) from my VIEW (rendering). That's why the DoInput() function only sets flag variables but doesn't act on them, and the DoPhysics() function doesn't know anything about any input events, it just acts on these flag variables that allow the CONTROLLER to communicate to the MODEL "what the player wishes to do". Keeping the three parts of the program compartmentalized like this is very important for large projects, in my experience.
Looking at the above (quickly-written) code, I would improve it by making a Ship::Turn() function, among other things. Anyway, I hope this is helpful.