From 83ace1f915a60220ef1a4570e0bd5969b68c8dd5 Mon Sep 17 00:00:00 2001 From: moonpower Date: Mon, 3 Feb 2025 20:55:27 +0000 Subject: [PATCH] Upload files to "/" --- snake.cpp | 173 ++++++++++++++++++++++++++++++++++++++++++++ snake_ported.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 snake.cpp create mode 100644 snake_ported.cpp diff --git a/snake.cpp b/snake.cpp new file mode 100644 index 0000000..fb0c056 --- /dev/null +++ b/snake.cpp @@ -0,0 +1,173 @@ +/************************************************************** + * 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; +} diff --git a/snake_ported.cpp b/snake_ported.cpp new file mode 100644 index 0000000..460e0d4 --- /dev/null +++ b/snake_ported.cpp @@ -0,0 +1,185 @@ +/************************************************************** + * SNAKE SDL + OpenGL Test Game to be ported to UWP + * How to build (mingw mysys): + * g++ -shared snake_ported.cpp -o snake_ported.dll \ + -lmingw32 -lSDL2main -lSDL2 -lopengl32 -mwindows + * ---------------------------------------------------------- + **************************************************************/ + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define DLL_EXPORT __declspec(dllexport) +#else +#define DLL_EXPORT +#endif + +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 }; + +extern "C" { + struct ControllerInput { + float left_x; + float left_y; + float right_x; + float right_y; + bool button_a; + bool button_b; + }; + + static float g_left_x = 0.0f; + static float g_left_y = 0.0f; + static Direction g_dir = RIGHT; + static bool g_running = false; + + // Update controller thumbstick values, map them to direction + DLL_EXPORT void update_controller_input(ControllerInput input) { + g_left_x = input.left_x; + g_left_y = input.left_y; + } + + // Forward declaration so external_entry can call it + static int snake_main(); + + // This is the exported entry point that the host app calls + // It calls our internal snake_main() + DLL_EXPORT int external_entry() { + return snake_main(); + } +} + +// The core Snake game logic +static int snake_main() { + //SDL_GL_GetCurrentContext() will be your best friend. + if (!SDL_GL_GetCurrentContext()) { + std::cerr << "No active GL context found. Exiting.\n"; + return -1; + } + + glViewport(0, 0, GRID_WIDTH * WINDOW_SCALE, GRID_HEIGHT * WINDOW_SCALE); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, (double)(GRID_WIDTH * WINDOW_SCALE), + (double)(GRID_HEIGHT * WINDOW_SCALE), 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}); + g_dir = RIGHT; + int foodX = std::rand() % GRID_WIDTH; + int foodY = std::rand() % GRID_HEIGHT; + const float MOVE_INTERVAL = 0.15f; + float timer = 0.0f; + g_running = true; + Uint32 lastTicks = SDL_GetTicks(); + int score = 0; + + while (g_running) { + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + g_running = false; + } else if (e.type == SDL_KEYDOWN) { + switch (e.key.keysym.sym) { + case SDLK_ESCAPE: g_running = false; break; + case SDLK_UP: if (g_dir != DOWN) g_dir = UP; break; + case SDLK_DOWN: if (g_dir != UP) g_dir = DOWN; break; + case SDLK_LEFT: if (g_dir != RIGHT) g_dir = LEFT; break; + case SDLK_RIGHT: if (g_dir != LEFT) g_dir = RIGHT; break; + default: break; + } + } + } + + // handle controller direction via left thumbstick + { + float deadzone = 0.5f; + Direction nextDir = g_dir; + if (g_left_y > deadzone && g_dir != DOWN) nextDir = UP; + if (g_left_y < -deadzone && g_dir != UP) nextDir = DOWN; + if (g_left_x > deadzone && g_dir != LEFT) nextDir = RIGHT; + if (g_left_x < -deadzone && g_dir != RIGHT) nextDir = LEFT; + g_dir = nextDir; + } + + 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 (g_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! Final score: " << score << std::endl; + g_running = false; + break; + } + } + if (g_running) { + snake.insert(snake.begin(), head); + if (head.x == foodX && head.y == foodY) { + score++; + foodX = std::rand() % GRID_WIDTH; + foodY = std::rand() % GRID_HEIGHT; + } else { + snake.pop_back(); + } + } + } + + if (!g_running) break; + + 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(); + + // Since the host created the window & context, we swap via the current window + SDL_GL_SwapWindow(SDL_GL_GetCurrentWindow()); + } + return 0; +}