I learn C++ on example game "Snake".
Do not scold from code, i begin programmers. Better help, and specify on errors.
#include <GL/freeglut.h>
#include <iostream>
#include <string>
#include <list>
#include <ctime>
using namespace std;
bool dirSnake = true;
int lives = 3;
int score = 0;
const int gameFieldSize = 20;
int fieldWidth = 260;
int fieldHeight = 260;
struct Color3f
{
float r = 0.5f;
float g = 0.5f;
float b = 0.5f;
};
struct Vector2i
{
int x, y;
};
Vector2i snakeDir{ 1, 0 };
list<Vector2i> snake;
Vector2i food;
void drawText(float x, float y, string text)
{
glColor3f(1.0f, 1.0f, 1.0f);
glRasterPos2f(x, y);
glutBitmapString(GLUT_BITMAP_8_BY_13, (const unsigned char*)text.c_str());
}
void drawSquare(int x, int y, int size, Color3f color)
{
const float padding = 0.1f;
glColor3f(color.r, color.g, color.b);
glBegin(GL_QUADS);
glVertex2f(x + padding, y + padding);
glVertex2f(x + size - padding, y + padding);
glVertex2f(x + size - padding, y + size - padding);
glVertex2f(x + padding, y + size - padding);
glEnd();
}
void drawFood()
{
Color3f foodColor;
foodColor.r = 0.0f;
foodColor.g = 0.5f;
foodColor.b = 0.5f;
drawSquare(food.x, food.y, 1, foodColor);
}
void drawSnake()
{
Color3f snakeColor;
snakeColor.r = 0.0f;
snakeColor.g = 1.0f;
snakeColor.b = 0.0f;
for (auto const& cell : snake)
{
drawSquare(cell.x, cell.y, 1, snakeColor);
}
}
void drawRectangle(float x, float y, float width, float height)
{
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width, y + height);
glVertex2f(x, y + height);
glEnd();
}
void draw()
{
glClear(GL_COLOR_BUFFER_BIT);
drawText(0, 19, "Score: " + to_string(score));
drawText(15, 19, "Lives: " + to_string(lives));
if (score >= 10)
{
drawText(gameFieldSize / 3, gameFieldSize / 2, "You win the game");
}
if (dirSnake == false)
{
drawText(gameFieldSize / 3, gameFieldSize / 2, "You lose the game");
}
drawFood();
drawSnake();
glutSwapBuffers();
}
int getRandomInt(int max)
{
srand(time(0));
return rand() % max;
return 0;
}
void update(int value)
{
if (score >= 10)
{
dirSnake = false;
}
if (dirSnake)
{
Vector2i newPos;
int xHead = snake.front().x;
int yHead = snake.front().y;
if (xHead >= gameFieldSize)
{
snake.front().x = -1;
}
else if (xHead == -1)
{
snake.front().x = gameFieldSize;
}
else if (yHead >= gameFieldSize)
{
snake.front().y = -1;
}
else if (yHead == -1)
{
snake.front().y = gameFieldSize;
}
newPos.x = snake.front().x + snakeDir.x;
newPos.y = snake.front().y + snakeDir.y;
snake.push_front(newPos);
snake.pop_back();
for (auto it = ++snake.begin(); it != snake.end(); ++it)
{
int snakeX = (*it).x;
int snakeY = (*it).y;
if (newPos.x == snakeX && newPos.y == snakeY)
{
dirSnake = false;
cout << "Warning" << endl;
}
}
if (xHead == food.x && yHead == food.y)
{
score++;
Vector2i cell = { food.x, food.y };
snake.push_back(cell);
// Generate a new food
food.x = getRandomInt(gameFieldSize);
food.y = getRandomInt(gameFieldSize);
}
glutTimerFunc(150, update, 0);
glutPostRedisplay();
}
}
void specialKeyHandler(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
if (snakeDir.y == 0) {
snakeDir.x = 0;
snakeDir.y = 1;
}
break;
case GLUT_KEY_LEFT:
if (snakeDir.x == 0) {
snakeDir.x = -1;
snakeDir.y = 0;
}
break;
case GLUT_KEY_DOWN:
if (snakeDir.y == 0) {
snakeDir.x = 0;
snakeDir.y = -1;
}
break;
case GLUT_KEY_RIGHT:
if (snakeDir.x == 0) {
snakeDir.x = 1;
snakeDir.y = 0;
}
break;
}
}
void normalKeyHandler(unsigned char key, int x, int y)
{
switch (key)
{
case 'w':
if (snakeDir.y == 0) {
snakeDir.x = 0;
snakeDir.y = 1;
}
break;
case 'a':
if (snakeDir.x == 0) {
snakeDir.x = -1;
snakeDir.y = 0;
}
break;
case 's':
if (snakeDir.y == 0) {
snakeDir.x = 0;
snakeDir.y = -1;
}
break;
case 'd':
if (snakeDir.x == 0) {
snakeDir.x = 1;
snakeDir.y = 0;
}
break;
default:
cout << "This key is not used: " << key << endl;
break;
}
}
void setNewCoordSystem(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, gameFieldSize, 0.0f, gameFieldSize, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(fieldWidth, fieldHeight);
glutCreateWindow("Snake");
glutDisplayFunc(draw);
glutTimerFunc(250, update, 0);
glutKeyboardFunc(normalKeyHandler);
glutSpecialFunc(specialKeyHandler);
setNewCoordSystem(fieldWidth, fieldHeight);
Vector2i head = { 4, 1 };
snake.push_back(head);
glutMainLoop();
return 0;
}