/************************************************************** * SNAKE SDL + OpenGL Test Game to be ported to UWP * ---------------------------------------------------------- * How to build (mingw mysys): * g++ snake.cpp -o snake -lmingw32 -lSDL2main -lSDL2 -lopengl32 -mwindows * * Controls: * Arrow Keys to move the snake. * ESC or close window to quit. **************************************************************/ #include #include #include #include #include #include static const int GRID_WIDTH = 20; static const int GRID_HEIGHT = 15; static const int WINDOW_SCALE = 32; struct Segment { int x, y; }; enum Direction { UP, DOWN, LEFT, RIGHT }; int main(int argc, char* argv[]) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl; return 1; } SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); int windowWidth = GRID_WIDTH * WINDOW_SCALE; int windowHeight = GRID_HEIGHT * WINDOW_SCALE; SDL_Window* window = SDL_CreateWindow( "Snake (SDL2 + OpenGL)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_OPENGL ); if (!window) { std::cerr << "Failed to create window: " << SDL_GetError() << std::endl; SDL_Quit(); return 1; } SDL_GLContext glContext = SDL_GL_CreateContext(window); if (!glContext) { std::cerr << "Failed to create GL context: " << SDL_GetError() << std::endl; SDL_DestroyWindow(window); SDL_Quit(); return 1; } SDL_GL_SetSwapInterval(1); glViewport(0, 0, windowWidth, windowHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, (GLdouble)windowWidth, (GLdouble)windowHeight, 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.f, 0.f, 0.f, 1.f); std::srand((unsigned int)std::time(nullptr)); std::vector snake; snake.push_back({GRID_WIDTH / 2, GRID_HEIGHT / 2}); Direction dir = RIGHT; int foodX = rand() % GRID_WIDTH; int foodY = rand() % GRID_HEIGHT; const float MOVE_INTERVAL = 0.15f; float timer = 0.0f; bool running = true; Uint32 lastTicks = SDL_GetTicks(); int score = 0; while (running) { SDL_Event e; while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { running = false; } else if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_ESCAPE: running = false; break; case SDLK_UP: if (dir != DOWN) dir = UP; break; case SDLK_DOWN: if (dir != UP) dir = DOWN; break; case SDLK_LEFT: if (dir != RIGHT) dir = LEFT; break; case SDLK_RIGHT: if (dir != LEFT) dir = RIGHT; break; default: break; } } } Uint32 currentTicks = SDL_GetTicks(); float deltaTime = (currentTicks - lastTicks) / 1000.0f; lastTicks = currentTicks; timer += deltaTime; if (timer >= MOVE_INTERVAL) { timer -= MOVE_INTERVAL; Segment head = snake.front(); switch (dir) { case UP: head.y -= 1; break; case DOWN: head.y += 1; break; case LEFT: head.x -= 1; break; case RIGHT: head.x += 1; break; } if (head.x < 0) head.x = GRID_WIDTH - 1; else if (head.x >= GRID_WIDTH) head.x = 0; if (head.y < 0) head.y = GRID_HEIGHT - 1; else if (head.y >= GRID_HEIGHT) head.y = 0; for (size_t i = 0; i < snake.size(); i++) { if (snake[i].x == head.x && snake[i].y == head.y) { std::cout << "Game Over! You ate yourself. Final score: " << score << std::endl; running = false; break; } } if (running) { snake.insert(snake.begin(), head); if (head.x == foodX && head.y == foodY) { score++; foodX = rand() % GRID_WIDTH; foodY = rand() % GRID_HEIGHT; } else { snake.pop_back(); } } } glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_QUADS); float fx = (float)foodX * WINDOW_SCALE; float fy = (float)foodY * WINDOW_SCALE; glVertex2f(fx, fy); glVertex2f(fx + WINDOW_SCALE, fy); glVertex2f(fx + WINDOW_SCALE, fy + WINDOW_SCALE); glVertex2f(fx, fy + WINDOW_SCALE); glEnd(); glColor3f(0.0f, 1.0f, 0.0f); glBegin(GL_QUADS); for (auto &seg : snake) { float sx = (float)seg.x * WINDOW_SCALE; float sy = (float)seg.y * WINDOW_SCALE; glVertex2f(sx, sy); glVertex2f(sx + WINDOW_SCALE, sy); glVertex2f(sx + WINDOW_SCALE, sy + WINDOW_SCALE); glVertex2f(sx, sy + WINDOW_SCALE); } glEnd(); SDL_GL_SwapWindow(window); } SDL_GL_DeleteContext(glContext); SDL_DestroyWindow(window); SDL_Quit(); return 0; }