I’m writing Snake in C++, using OpenGL and GLFW. I’m trying to implement a feature where the game exits, when the snakes head crashes into its body.
Here are the move() and CrashCheck() functions of the Snake class that I wrote.
x_pos is a floating point array that stores the x_coordinate of a segment of the snake body. y_pos does the same with the y_coordinate. length is the number of body segments in the snake, and increases when the snake eats food(not yet implemented). x_speed and y_speed store the speeds of the segments along the axis. The snake can never move along both the axes simultaneously; Also, float MAX_S = 0.00075;. I’ve included my draw() function as well. And Fix_Snake_x and Fix_Snake_y are functions that realign the segments of the snake (because they kept separating and causing havoc with the game). I know it’s a stupid way to correct the problem, so if you can suggest fixes in the move() function, that would helpful.
void draw(float win_aspect)
{
for(int a = 0; a < length; a++)
{
Fix_Snake_y();
glBegin(GL_QUADS);
glColor3f(1.0,0.0,0.0);
glVertex2f(x_pos[a],y_pos[a]);
glVertex2f((x_pos[a]+0.05),y_pos[a]);
glVertex2f((x_pos[a]+0.05),y_pos[a]-0.05);
glVertex2f(x_pos[a],y_pos[a] - 0.05);
glEnd();
Fix_Snake_x();
}
}
void move()
{
for(int a = length ; a >= 0; a--)
{
if(a > 0)
{
if(x_pos[a] >= x_pos[a-1] && x_speed[a] < 0)
{
x_pos[a] += -MAX_S;
Fix_Snake_y();
Fix_Snake_x();
if(x_pos[a] <= x_pos[a - 1])
{
x_speed [a] = 0;
if(y_pos[a] <= y_pos[a-1])
{
y_speed[a] = MAX_S;
}
else
{
y_speed[a] = -MAX_S;
}
}
}
if(x_pos[a] <= x_pos[a-1] && x_speed[a] > 0)
{
x_pos[a] += MAX_S;
Fix_Snake_y();
Fix_Snake_x();
if(x_pos[a] >= x_pos[a - 1])
{
x_speed [a] = 0;
if(y_pos[a] <= y_pos[a-1])
{
y_speed[a] = MAX_S;
}
else
{
y_speed[a] = -MAX_S;
}
}
}
if(y_pos[a] <= y_pos[a-1] && y_speed[a] > 0)
{
y_pos[a] += MAX_S;
Fix_Snake_y();
Fix_Snake_x();
if(y_pos[a] >= y_pos[a-1])
{
y_speed[a] = 0;
if(x_pos[a] >= x_pos[a-1])
{
x_speed[a] = -MAX_S;
}
if(x_pos[a] <= x_pos[a-1])
{
x_speed[a] = MAX_S;
}
}
}
if(y_pos[a] >= y_pos[a-1] && y_speed[a] < 0)
{
y_pos[a] += -MAX_S;
Fix_Snake_y();
Fix_Snake_x();
if(y_pos[a] <= y_pos[a-1])
{
y_speed[a] = 0;
if(x_pos[a] >= x_pos[a-1])
{
x_speed[a] = -MAX_S;
}
if(x_pos[a] <= x_pos[a-1])
{
x_speed[a] = MAX_S;
}
}
}
}
if(a == 0)
{
x_pos[0] += x_speed[0];
y_pos[0] += y_speed[0];
Fix_Snake_y();
Fix_Snake_x();
}
CrashCheck();
}
}
void CrashCheck()
{
for(int a = 1; a < length; a++)
{
if(y_speed[0] > 0 && y_speed[a] == 0)
{
if(x_pos[0] < x_pos[a] && x_pos[0] < x_pos[a] + 0.05)
{
if(y_pos[0] < y_pos[a] && y_pos[0] > y_pos[a] - 0.05)
{
exit(0);
}
}
}
else if(y_speed[0] < 0 && y_speed[a] == 0)
{
if(x_pos[0] > x_pos[a] && x_pos[0] < x_pos[a] + 0.05)
{
if(y_pos[0] < y_pos[a] && y_pos[0] > y_pos[a] - 0.05)
{
exit(0);
}
}
}
}
}
void Fix_Snake_x()
{
for(int a = 1; a<length; a++)
{
if(a > 0)
{
if(x_pos[a] <= x_pos[a-1] - 0.05)
{
x_pos[a] = x_pos[a-1] - 0.05;
}
if(x_pos[a] >= x_pos[a -1] + 0.05)
{
x_pos[a] = x_pos[a-1] + 0.05;
}
}
}
}
void Fix_Snake_y()
{
for(int a = 1; a < length; a++)
{
if(a > 0)
{
if(y_pos[a] <= y_pos[a-1] - 0.05)
{
y_pos[a] = y_pos[a-1] - 0.05;
}
if(y_pos[a] >= y_pos[a-1] + 0.05)
{
y_pos[a] = y_pos[a-1] + 0.05;
}
}
}
}
Edit:
New move function
for(int a = 0; a < length; a++)
{
if(a > 0)
{
if(x_speed[a] < 0 && x_pos[a] >= x_pos[a-1])
{
x_pos[a] += x_speed[a];
if(x_pos[a] == x_pos[a-1])
{
y_speed[a] = y_speed[a-1];
x_speed[a] = 0;
continue;
}
}
if(x_speed[a] > 0 && x_pos[a] <= x_pos[a-1])
{
x_pos[a] += x_speed[a];
if(x_pos[a] == x_pos[a-1])
{
y_speed[a] = y_speed[a-1];
x_speed[a] = 0;
continue;
}
}
if(y_speed[a] > 0 && y_pos[a] <= y_pos[a-1])
{
y_pos[a] += y_speed[a];
if(y_pos[a] == y_pos[a-1])
{
x_speed[a] = x_speed[a-1];
y_speed[a] = 0;
}
}
if(y_speed[a] < 0 && y_pos[a] >= y_pos[a-1])
{
y_pos[a] += y_speed[a];
if(y_pos[a] == y_pos[a-1])
{
x_speed[a] = x_speed[a-1];
y_speed[a] = 0;
}
}
}
else
{
x_pos[0] += x_speed[0];
y_pos[0] += y_speed[0];
}
}
Is causing a few problems. The snake breaks it there are too many simultaneous turns. Only the first two blocks remain in motion
If I were you, I would store a
std::setwith all the invalid coordinates that the snake can’t go to. That would include:Then for each move of the snake, considering the x/y speed(s) I would first try to
InsertLocationintoCInvalidPlaces, if that returnstruethen I can step there, iffalsethen the snake’s just about to hit a wall, the border or it’s own body and the “game” can finish. Here’s the code for that:What you will have to do additionally is :
CInvalidPlacesit’s tail usingRemoveLocationCInvalidPlacesthe extra segment.If need be, you can find in the following places extra information about an
stl::set:HTH,
JP