Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Help with sprite movement/collision logic  (Read 3044 times)

0 Members and 1 Guest are viewing this topic.

Jove

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • http://www.jestofevekites.com/
Help with sprite movement/collision logic
« on: March 20, 2011, 11:04:41 am »
I'm having a tough time with my control sprite (ship) occasionally getting stuck on objects it should bounce off of. Now I've completely lost focus and can't see the wood for the trees!

The ship's Y position is fixed and objects in the playfield scroll vertically up and down creating Y movement. X movement is normal stuff.

I know that with the correct chain of events this problem shouldn't occur; I did this 20 years ago on a C64 but my code skills are very rusty.

Collision detection function is good, no problems there. Feel free to ask for that code snippet if it helps. Feel free to correct me anywhere else too!

Thanks,
Mark

Code: [Select]
///////////////////////////////////////////////////////////////////////////////////////////////////
// Control the ship sprite
///////////////////////////////////////////////////////////////////////////////////////////////////

bool collision = ship_collision(ship_X, ship_Y);

// Left & Right
// Neither left or right keys pressed
if (!App.GetInput().IsKeyDown(sf::Key::Left) && (!App.GetInput().IsKeyDown(sf::Key::Right)))
// Wait until speed has decreased to near-zero
if ((xspeed > -20) && (xspeed < 20))
{
xacceleration = 0; // Then cancel acceleration & speed
xspeed = 0;
}
else
// Not zero yet, so force it to slow down
if (xspeed >  0)
xacceleration = -xaccel_factor;
else
xacceleration =  xaccel_factor;


// LEFT
// Check if left key pressed (but not right)
if (App.GetInput().IsKeyDown(sf::Key::Left) && (!App.GetInput().IsKeyDown(sf::Key::Right)))
// Need to set acceleration to LEFT but,
// before changing check we aren't over the side wall
{
if (ship_X >= 20)
// All clear, go left
xacceleration = -xaccel_factor;
else
//bounce off wall
xacceleration = xaccel_factor;
}

// RIGHT
// Check if right key pressed (but not left)
if (App.GetInput().IsKeyDown(sf::Key::Right) && (!App.GetInput().IsKeyDown(sf::Key::Left)))
// Need to set acceleration to RIGHT but,
// before changing check we aren't over the side wall
if (ship_X <= 770)
xacceleration = xaccel_factor;
else
xacceleration = -xaccel_factor;



// Check if ship has reached the side wall
if ((ship_X < 20) || (ship_X > 770))
{
// Invert xspeed
xspeed=-xspeed;
wobble_screen=true;
}


// UPDATE
// Add acceleration to current speed
xspeed += xacceleration;

// Limit speed
if (xspeed > xmaxspeed) xspeed = xmaxspeed;
else
if (xspeed < -xmaxspeed) xspeed = -xmaxspeed;


if (collision == true)
// Invert xspeed
xspeed=-xspeed;




// Up & Down
// Neither up or down keys pressed
if (!App.GetInput().IsKeyDown(sf::Key::Up) && (!App.GetInput().IsKeyDown(sf::Key::Down)))
// Wait until speed has decreased to near-zero
if ((yspeed > -20) && (yspeed < 20))
{
yacceleration = 0; // Then cancel acceleration & speed
yspeed =0;
}
else
// Not zero yet, so force it to slow down only by a smaller factor so it drifts longer
if (yspeed >  0)
yacceleration = -yaccel_factor +25;
else
yacceleration = yaccel_factor -25;


// UP
// Check if up key pressed (but not down)
if (App.GetInput().IsKeyDown(sf::Key::Up) && (!App.GetInput().IsKeyDown(sf::Key::Down)))
// Set acceleration UP
yacceleration = -yaccel_factor;

// DOWN
// Check if down key pressed (but not up)
if (App.GetInput().IsKeyDown(sf::Key::Down) && (!App.GetInput().IsKeyDown(sf::Key::Up)))
// Set acceleration DOWN
yacceleration =  yaccel_factor;


// UPDATE
// Add acceleration to current speed
yspeed += yacceleration;

// Limit speed
if (yspeed > ymaxspeed) yspeed = ymaxspeed;
else
if (yspeed < -ymaxspeed) yspeed = -ymaxspeed;


if (collision == true)
// Invert yspeed
yspeed=-yspeed;



// Update ship position
ship_X += xspeed  * ElapsedTime;
screen_pos += yspeed  * ElapsedTime;

ship_Y = screen_pos + 300;

Ship.SetPosition(ship_X, 300);
{much better code}

Jove

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • http://www.jestofevekites.com/
Help with sprite movement/collision logic
« Reply #1 on: March 20, 2011, 02:04:58 pm »
I just drastically improved this problem.

1) Putting the collision checks right after the "//Add acceleration to current speed" lines (update xspeed / yspeed)

2) Also, saving the previous frame's ship_X and screen_pos (Y, essentially). When the collision is true, restore the previous frame's value.

Seems to work. Kludge?
{much better code}

Gibgezr

  • Newbie
  • *
  • Posts: 33
    • View Profile
Help with sprite movement/collision logic
« Reply #2 on: April 01, 2011, 03:03:51 pm »
A simple improvement to the kludge would be, after a collision is detected,  to loop backwards adjusting the ship position from it's current towards it's old position, on pixel length at a time. Stop the loop when no collision is detected.

Jove

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • http://www.jestofevekites.com/
Help with sprite movement/collision logic
« Reply #3 on: April 01, 2011, 03:21:58 pm »
It's all working and clean now, just a rare 1% occasion where I still get stuck.

So rare it will be hard to nail down, but it's not a big priority.
{much better code}