I am just starting out trying to make games in C++. I have some experience with the language but I have never made games or used SDL too much. As a start I took a motion tutorial from http://lazyfoo.net/SDL_tutorials/ and made it into a two player game where random red dots appear and the players race to collect 10. It has collision detection and such which I figure out how to do. After doing this I'm trying to expand it into snakes now not just dots. However I am having problems get the snakes to move correctly. I was able to hack it together somewhat but when changing direction from say right to up the whole snake flips at once instead of moving a section at a time. I think I am missing something conceptually about this. I could do it on a matrix but I dont want to restrict motion to a square matrix
snake.cpp
Snake::Snake()
{
pieces.push_back(Dot());
headX = pieces.at(0).getX();
headY = pieces.at(0).getY();
length = 1;
};
void Snake::show()
{
int curX;
int curY;
for( int i =0; i < length; i++)
{
curX = pieces.at(i).getX();
curY = pieces.at(i).getY();
apply_surface( curX, curY, dot, screen );
}
};
void Snake::handle_input()
{
pieces.at(0).handle_input(0);
for( int i =1; i < length; i++)
{
int xVel = pieces.at(i-1).getXVelocity();
int yVel = pieces.at(i-1).getYVelocity();
if(yVel < 0 && xVel ==0)
pieces.at(i-1).setDirection(0);
if(yVel > 0 && xVel ==0)
pieces.at(i-1).setDirection(1);
if(yVel == 0 && xVel < 0)
pieces.at(i-1).setDirection(2);
if(yVel == 0 && xVel >0)
pieces.at(i-1).setDirection(3);
}
};
void Snake::move()
{
pieces.at(0).move();
int previous_x;
int previous_y;
int previous_xVel;
int previous_yVel;
for( int i=1; i < length; i++)
{
previous_x = pieces.at(i-1).getX();
previous_y = pieces.at(i-1).getY();
previous_xVel = pieces.at(i-1).getXVelocity();
previous_yVel = pieces.at(i-1).getYVelocity();
if(previous_xVel != 0 || previous_yVel != 0)
{
pieces.at(i).setX(previous_x-(2*previous_xVel));
pieces.at(i).setY(previous_y-(2*previous_yVel));
}
else
{
if(pieces.at(i-1).getDirection() == 0)
{
pieces.at(i).setX(previous_x);
pieces.at(i).setY(previous_y+(DOT_HEIGHT));
}
else if(pieces.at(i-1).getDirection() ==1)
{
pieces.at(i).setX(previous_x);
pieces.at(i).setY(previous_y-(DOT_HEIGHT));
}
else if(pieces.at(i-1).getDirection() ==2)
{
pieces.at(i).setX(previous_x+DOT_WIDTH);
pieces.at(i).setY(previous_y);
}
else if(pieces.at(i-1).getDirection() ==3)
{
pieces.at(i).setX(previous_x-DOT_WIDTH);
pieces.at(i).setY(previous_y);
}
else
{
pieces.at(i).setX(previous_x-(DOT_WIDTH));
pieces.at(i).setY(previous_y-(DOT_HEIGHT));
}
}
pieces.at(i).setXVelocity(previous_xVel);
pieces.at(i).setYVelocity(previous_yVel);
}
};
Dot Snake::getHead()
{
return pieces.at(0);
};
void Snake::addToSnake()
{
int x = pieces.at(length-1).getX();
int y = pieces.at(length-1).getY();
int xv = pieces.at(length-1).getXVelocity();
int yv = pieces.at(length-1).getYVelocity();
pieces.push_back(Dot(x-DOT_WIDTH,y,xv,yv));
length++;
};dot.cpp
Dot::Dot()
{
//Initialize the offsets
x = 0;
y = 0;
//Initialize the velocity
xVel = 0;
yVel = 0;
radius = DOT_WIDTH/2;
}
Dot::Dot(int xStart, int yStart)
{
//Initialize the offsets
x = xStart;
y = yStart;
//Initialize the velocity
xVel = 0;
yVel = 0;
radius = DOT_WIDTH/2;
}
Dot::Dot(int xStart, int yStart, int xvel, int yvel)
{
//Initialize the offsets
x = xStart;
y = yStart;
//Initialize the velocity
xVel = xvel;
yVel = yvel;
radius = DOT_WIDTH/2;
}
void Dot::handle_input(int player)
{
if(player == 0)
{
//If a key was pressed
if( event.type == SDL_KEYDOWN )
{
//Adjust the velocity
switch( event.key.keysym.sym )
{
case SDLK_UP: yVel -= DOT_HEIGHT / 2; break;
case SDLK_DOWN: yVel += DOT_HEIGHT / 2; break;
case SDLK_LEFT: xVel -= DOT_WIDTH / 2; break;
case SDLK_RIGHT: xVel += DOT_WIDTH / 2; break;
}
}
//If a key was released
else if( event.type == SDL_KEYUP )
{
//Adjust the velocity
switch( event.key.keysym.sym )
{
case SDLK_UP: yVel += DOT_HEIGHT / 2; break;
case SDLK_DOWN: yVel -= DOT_HEIGHT / 2; break;
case SDLK_LEFT: xVel += DOT_WIDTH / 2; break;
case SDLK_RIGHT: xVel -= DOT_WIDTH / 2; break;
}
}
}
//other color stuff ommitted
}
void Dot::move()
{
//Move the dot left or right
x+=xVel;
//If the dot went too far to the left or right
if(x + DOT_WIDTH > SCREEN_WIDTH)
x = 0;
if(x < 0)
x = SCREEN_WIDTH-DOT_WIDTH;
//Move the dot up or down
y += yVel;
//If the dot went too far up or down
if(y + DOT_HEIGHT > SCREEN_HEIGHT)
y = 0;
if(y < 0)
y = SCREEN_HEIGHT-DOT_HEIGHT;
}
void Dot::move(int x_velocity, int y_velocity)
{
//Move the dot left or right
xVel = x_velocity;
x+=x_velocity;
//If the dot went too far to the left or right
if(x + DOT_WIDTH > SCREEN_WIDTH)
x = 0;
if(x < 0)
x = SCREEN_WIDTH-DOT_WIDTH;
//Move the dot up or down
yVel = y_velocity;
y += y_velocity;
//If the dot went too far up or down
if(y + DOT_HEIGHT > SCREEN_HEIGHT)
y = 0;
if(y < 0)
y = SCREEN_HEIGHT-DOT_HEIGHT;
}
void Dot::show(int color)
{
//Show the dot
if(color == 0)
apply_surface( x, y, dot, screen );
else
apply_surface( x, y, blueDot, screen );
}
main.cpp
int main( int argc, char* args[] )
{
//declarations are ommited
//While the user hasn't quit
while( quit == false )
{
if(gameState == 0)
{
//Start the frame timer
fps.start();
//While there's events to handle
while( SDL_PollEvent( &event ) )
{
//Handle events for the dot
snake1.handle_input();
dotTwo.handle_input(1);
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}
}
//collison
vector<smallDot> temp = pointDots;
for(unsigned int i = 0; i < temp.size();i++)
{
if(temp.at(i).checkCollision(snake1.getHead()))
{
temp.erase(temp.begin()+i);
snake1.addToSnake();
player1score += DOT_VALUE;
}
}
pointDots = temp;
temp.clear();
temp = pointDots;
for(unsigned int i = 0; i < temp.size();i++)
{
if(temp.at(i).checkCollision(dotTwo))
{
temp.erase(temp.begin()+i);
player2score += DOT_VALUE;
}
}
pointDots = temp;
temp.clear();
//status
//Move the dot
snake1.move();
dotTwo.move();
//Add point dot
dotsTimer.update();
if(dotsTimer.check())
{
pointDots.push_back(smallDot());
}
//Fill the screen white
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );
displayScores(player1score,player2score);
//Show the dot on the screen
for (unsigned int i = 0; i < pointDots.size(); i++)
{
//if (pointDots.at(i) == NULL)
// continue; // skip NULL objects
pointDots.at(i).show();
}
snake1.show();
dotTwo.show(1);
//Update the screen
if( SDL_Flip( screen ) == -1 )
return 1;
if( gameOver(player1score,player2score))
gameState = 1;
//Cap the frame rate
}
else if (gameState == 1)
{
//stuff for winner omitted for length
SDL_Flip(screen);
}
}
//Clean up
clean_up();
return 0;
}I had to omit stuff for length but the full code and everything if you would like to look at it all is at https://github.com/b...st/Snake%20Game along with all the other file and the visual studio solution
Any help or advice will be greatly appreciated






