From 95f105fd964f5825e65fd7a61e78572c310753e6 Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Mon, 29 Nov 2021 16:43:21 +0100 Subject: [PATCH] egg --- .vscode/tasks.json | 8 +- .vscode/workspace.code-workspace | 9 ++ include/rogue.h | 33 +++++ src/draw.c | 28 ++++ src/engine.c | 118 ++++++++++++++++ src/main.c | 21 +++ src/main.cpp | 232 ------------------------------- src/map.c | 27 ++++ src/player.c | 12 ++ 9 files changed, 252 insertions(+), 236 deletions(-) create mode 100644 include/rogue.h create mode 100644 src/draw.c create mode 100644 src/engine.c create mode 100644 src/main.c delete mode 100644 src/main.cpp create mode 100644 src/map.c create mode 100644 src/player.c diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b06625b..419ec5b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,7 +8,7 @@ "type": "shell", "command": "gcc", "args": [ - { "value": "src/**.cpp", "quoting": "weak" }, + { "value": "src/**.c", "quoting": "weak" }, { "value": "-ooutput.exe", "quoting": "strong" }, { "value": "-Og", "quoting": "strong" }, { "value": "-g", "quoting": "strong" }, @@ -16,7 +16,7 @@ { "value": "-Iraylib/src", "quoting": "strong" }, { "value": "-Iraylib/src/extras", "quoting": "strong" }, { "value": "-Llib", "quoting": "strong" }, - { "value": "-std=c++2a", "quoting": "strong" }, + { "value": "-std=c17", "quoting": "strong" }, { "value": "-Werror", "quoting": "strong" }, { "value": "-Wall", "quoting": "strong" }, { "value": "-Wextra", "quoting": "strong" }, @@ -42,7 +42,7 @@ "type": "shell", "command": "gcc", "args": [ - { "value": "src/**.cpp", "quoting": "weak" }, + { "value": "src/**.c", "quoting": "weak" }, { "value": "-ooutput.exe", "quoting": "strong" }, { "value": "-Ofast", "quoting": "strong" }, { "value": "-Iinclude", "quoting": "strong" }, @@ -50,7 +50,7 @@ { "value": "-Iraylib/src/extras", "quoting": "strong" }, { "value": "-Llib", "quoting": "strong" }, { "value": "-std=c++2a", "quoting": "strong" }, - { "value": "-Werror", "quoting": "strong" }, + { "value": "-Werro17 "quoting": "strong" }, { "value": "-Wall", "quoting": "strong" }, { "value": "-Wextra", "quoting": "strong" }, { "value": "-Wno-missing-field-initializers", "quoting": "strong" }, diff --git a/.vscode/workspace.code-workspace b/.vscode/workspace.code-workspace index e759b54..09875e9 100644 --- a/.vscode/workspace.code-workspace +++ b/.vscode/workspace.code-workspace @@ -8,5 +8,14 @@ "recommendations": [ "ms-vscode.cpptools" ] + }, + "settings": { + "files.associations": { + "*.lock": "yarnlock", + "*.m": "cpp", + "cstdlib": "cpp", + "raylib.h": "c", + "math.h": "c" + } } } \ No newline at end of file diff --git a/include/rogue.h b/include/rogue.h new file mode 100644 index 0000000..f75460e --- /dev/null +++ b/include/rogue.h @@ -0,0 +1,33 @@ +#include "raylib.h" + +typedef struct Vector2i +{ + int x; + int y; +} Vector2i; + +typedef struct Entity +{ + Vector2i position; + Color color; +} Entity; + +typedef struct Tile +{ + bool walkable; + Color color; +} Tile; + +Entity *createPlayer(Vector2i start_position); +Tile **createMapTiles(); +void freeMapTiles(Tile **map_tiles); +void renderEverything(RenderTexture2D target); + +void initGame(); +void mainLoop(); +void endGame(); + +extern unsigned int const MAP_HEIGHT; +extern unsigned int const MAP_WIDTH; +extern Entity *player; +extern Tile **map; \ No newline at end of file diff --git a/src/draw.c b/src/draw.c new file mode 100644 index 0000000..f4dda0c --- /dev/null +++ b/src/draw.c @@ -0,0 +1,28 @@ +#include "raylib.h" +#include "rogue.h" + +void drawMap(Tile **map) +{ + for (unsigned int x = 0; x < MAP_WIDTH; x++) + { + for (unsigned int y = 0; y < MAP_HEIGHT; y++) + { + DrawPixel(x, y, map[x][y].color); + } + } +} + +void drawEntity(Entity *entity) +{ + DrawPixel(entity->position.x, entity->position.y, entity->color); +} + +void renderEverything(RenderTexture2D target) +{ + BeginTextureMode(target); + { + drawMap(map); + drawEntity(player); + } + EndTextureMode(); +} \ No newline at end of file diff --git a/src/engine.c b/src/engine.c new file mode 100644 index 0000000..ba27be0 --- /dev/null +++ b/src/engine.c @@ -0,0 +1,118 @@ +#include "raylib.h" +#include "rogue.h" + +static int const PIXEL_SCALE = 10; +static int const VIRTUAL_SCREEN_WIDTH = 80; +static int const VIRTUAL_SCREEN_HEIGHT = 45; + +const unsigned int MAP_HEIGHT = VIRTUAL_SCREEN_HEIGHT; +const unsigned int MAP_WIDTH = VIRTUAL_SCREEN_WIDTH; + +static int const REAL_SCREEN_WIDTH = VIRTUAL_SCREEN_WIDTH * PIXEL_SCALE; +static int const REAL_SCREEN_HEIGHT = VIRTUAL_SCREEN_HEIGHT * PIXEL_SCALE; + +static Rectangle const virtualScreenRect = {0.0f, 0.0f, (float)VIRTUAL_SCREEN_WIDTH, -(float)VIRTUAL_SCREEN_HEIGHT}; +static Rectangle const realScreenRect = {0.0f, 0.0f, (float)REAL_SCREEN_WIDTH, (float)REAL_SCREEN_HEIGHT}; + +RenderTexture2D virtualScreen; + +void initGame() +{ + // Initialization + //-------------------------------------------------------------------------------------- +#if defined(__DEBUG) + SetTraceLogLevel(LOG_ALL); +#else + SetTraceLogLevel(LOG_NONE); +#endif + SetConfigFlags(0); + InitWindow(REAL_SCREEN_WIDTH, REAL_SCREEN_HEIGHT, "TODO: Add a title"); + + virtualScreen = LoadRenderTexture(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT); + + player = createPlayer((Vector2i){VIRTUAL_SCREEN_WIDTH / 2, VIRTUAL_SCREEN_HEIGHT / 2}); + map = createMapTiles(); + + // SetTargetFPS(60); // Set our game to run at 60 frames-per-second +} + +void update() +{ + // Update + //---------------------------------------------------------------------------------- + + if (IsKeyPressed(KEY_RIGHT)) + { + player->position.x++; + } + if (IsKeyPressed(KEY_LEFT)) + { + player->position.x--; + } + if (IsKeyPressed(KEY_UP)) + { + player->position.y--; + } + if (IsKeyPressed(KEY_DOWN)) + { + player->position.y++; + } +} + +void draw() +{ + // Draw + //---------------------------------------------------------------------------------- + BeginTextureMode(virtualScreen); + { + ClearBackground(BLACK); + + DrawPixel(player->position.x, player->position.y, player->color); + + /* + for (unsigned int x = 0; x < VIRTUAL_SCREEN_WIDTH; x++) + { + for (unsigned int y = 0; y < VIRTUAL_SCREEN_HEIGHT; y++) + { + const unsigned char r = (unsigned char)floorf((float)x / (float)VIRTUAL_SCREEN_WIDTH * 255.0f); + const unsigned char b = (unsigned char)floorf((float)y / (float)VIRTUAL_SCREEN_HEIGHT * 255.0f); + const unsigned char g = 255 - (r + b) / 2; + const unsigned char a = 255; + + DrawPixel(x, y, (Color){r, g, b, a}); + } + } + */ + } + EndTextureMode(); + + BeginDrawing(); + { + ClearBackground(BLACK); + // Draw rendered game texture + DrawTexturePro(virtualScreen.texture, virtualScreenRect, realScreenRect, (Vector2){0.0f, 0.0f}, 0.0f, WHITE); + + // Draw GUI here + //-------------------------------------------------------------------------------------- +#if __DEBUG + DrawFPS(0, 0); +#endif + } + EndDrawing(); +} + +void mainLoop() +{ + update(); + draw(); +} + +void endGame() +{ + // De-Initialization + //-------------------------------------------------------------------------------------- + MemFree(player); + freeMapTiles(map); + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d818ae2 --- /dev/null +++ b/src/main.c @@ -0,0 +1,21 @@ +#include "raylib.h" +#include "math.h" +#include "rogue.h" + +Entity *player; +Tile **map; + +int main(void) +{ + initGame(); + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + mainLoop(); + } + + endGame(); + + return 0; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index ce31f47..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,232 +0,0 @@ -#include "raylib.h" -#include "raymath.h" -#include "monogram.ttf.h" - -enum class Player -{ - NONE, - RED_PLAYER, - BLUE_PLAYER, -}; - -Player checkBoard(Player board[9]) -{ - // horizontal, vertical, and diagonal checks from first cell - if (board[0] != Player::NONE && ((board[0] == board[1] && board[0] == board[2]) || (board[0] == board[3] && board[0] == board[6]) || (board[0] == board[4] && board[0] == board[8]))) - return board[0]; - - // vertical check from second cell - if (board[1] != Player::NONE && (board[1] == board[4] && board[1] == board[7])) - return board[1]; - - // vertical and diagonal checks from third cell - if (board[2] != Player::NONE && ((board[2] == board[5] && board[2] == board[8]) || (board[2] == board[4] && board[2] == board[6]))) - return board[2]; - - // horizontal check from fourth cell - if (board[3] != Player::NONE && (board[3] == board[4] && board[3] == board[5])) - return board[3]; - - // horizontal check from seventh cell - if (board[6] != Player::NONE && (board[6] == board[7] && board[6] == board[8])) - return board[6]; - - return Player::NONE; -} - -void resetBoard(Player board[9]) -{ - for (unsigned char i = 0; i < 9; i++) - { - board[i] = Player::NONE; - } -} - -int main(void) -{ - // Size of a gameboard pixel - static const int SCREEN_SCALE = 256; - static const int TOPBAR_HEIGHT = 40; - static const int VIRTUAL_SCREEN_SIZE = 3; - static const int SCREEN_SIZE = VIRTUAL_SCREEN_SIZE * SCREEN_SCALE; - - static const float TEXT_SPACING = 2.0f; - - // Initialization - //-------------------------------------------------------------------------------------- -#if defined(__DEBUG) - SetTraceLogLevel(LOG_ALL); -#else - SetTraceLogLevel(LOG_NONE); -#endif - - SetConfigFlags(0); - InitWindow(SCREEN_SIZE, SCREEN_SIZE + TOPBAR_HEIGHT, "Tic Tac Toe"); - - static const int fontChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' '}; - Font monogramFont = LoadFontFromMemory(".ttf", monogramFontBytes, sizeof(monogramFontBytes), TOPBAR_HEIGHT, (int *)fontChars, sizeof(fontChars)); - - /* For drawing */ - RenderTexture2D target = LoadRenderTexture(VIRTUAL_SCREEN_SIZE, VIRTUAL_SCREEN_SIZE); - - Rectangle sourceRec = {0.0f, - 0.0f, - (float)VIRTUAL_SCREEN_SIZE, - -(float)VIRTUAL_SCREEN_SIZE}; - Rectangle destRec = {0.0f, - (float)(TOPBAR_HEIGHT), - SCREEN_SIZE, - SCREEN_SIZE}; - - /* For game logic */ - Player board[9]; - resetBoard(board); - Player currentPlayer = Player::RED_PLAYER; - - unsigned char points[3] = {0, 0, 0}; - unsigned char turn = 0; - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - //---------------------------------------------------------------------------------- - // Update - //---------------------------------------------------------------------------------- - - // Toggle borderless - if (IsKeyPressed(KEY_F1)) - { - if (IsWindowState(FLAG_WINDOW_UNDECORATED)) - { - ClearWindowState(FLAG_WINDOW_UNDECORATED); - } - else - { - SetWindowState(FLAG_WINDOW_UNDECORATED); - } - } - - Vector2 mousePos = GetMousePosition(); - // Floor instead of trunc to check negative values for out-of-bounds check for cursor - char hovered = (char)floorf(mousePos.x / (float)SCREEN_SCALE) + 3 * (char)floorf((mousePos.y - ((float)TOPBAR_HEIGHT)) / (float)SCREEN_SCALE); - - if (hovered < 0 || hovered >= 9 || board[(unsigned char)hovered] != Player::NONE) - { - SetMouseCursor(MOUSE_CURSOR_DEFAULT); - } - else if (board[(unsigned char)hovered] == Player::NONE) - { - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - { - board[(unsigned char)hovered] = currentPlayer; - currentPlayer = (currentPlayer == Player::RED_PLAYER) ? Player::BLUE_PLAYER : Player::RED_PLAYER; - // Cursor doesn't really matter in this frame - - Player winner = checkBoard(board); - - // Game is over - if (winner != Player::NONE || (++turn) >= 9) - { - TraceLog(LOG_INFO, TextFormat("Winner: %d", winner)); - points[(int)winner]++; - resetBoard(board); - turn = 0; - } - } - else - { - SetMouseCursor(MOUSE_CURSOR_POINTING_HAND); - } - } - - //---------------------------------------------------------------------------------- - // Draw - //---------------------------------------------------------------------------------- - - BeginTextureMode(target); - { - ClearBackground(WHITE); - - for (unsigned char i = 0; i < 9; i++) - { - Color color; - - switch (board[i]) - { - case Player::RED_PLAYER: - color = RED; - break; - case Player::BLUE_PLAYER: - color = BLUE; - break; - case Player::NONE: - default: - color = WHITE; - break; - } - - const unsigned char x = i % 3; - const unsigned char y = i / 3; - DrawPixel(x, y, color); - - if (i == hovered) - { - DrawPixel(x, y, Color{255, 255, 255, 128}); - } - } - } - EndTextureMode(); - - BeginDrawing(); - { - ClearBackground(BLACK); - - // Draw rendered game texture - DrawTexturePro(target.texture, sourceRec, destRec, Vector2{0.0f, 0.0f}, 0.0f, WHITE); - -#if __DEBUG - DrawFPS(0, TOPBAR_HEIGHT); -#endif - - // Draw Top Bar - - // Current player in top-left corner - switch (currentPlayer) - { - case Player::RED_PLAYER: - DrawRectangle(0, 0, TOPBAR_HEIGHT, TOPBAR_HEIGHT, RED); - break; - case Player::BLUE_PLAYER: - DrawRectangle(0, 0, TOPBAR_HEIGHT, TOPBAR_HEIGHT, BLUE); - break; - default: - break; - } - - // Scores in top-left, labelled with colored squares - const char *blueScore = TextFormat("%03u ", points[2]); - const int blueScoreWidth = (int)MeasureTextEx(monogramFont, blueScore, TOPBAR_HEIGHT, TEXT_SPACING).x; - - const char *redScore = TextFormat("%03u %s", points[1], blueScore); - const int redScoreWidth = (int)MeasureTextEx(monogramFont, redScore, TOPBAR_HEIGHT, TEXT_SPACING).x; - - const char *scoreboard = TextFormat("%03u %s", points[0], redScore); - const int scoreboardWidth = (int)MeasureTextEx(monogramFont, scoreboard, TOPBAR_HEIGHT, TEXT_SPACING).x; - - DrawTextEx(monogramFont, scoreboard, Vector2{(float)SCREEN_SIZE - scoreboardWidth, 0}, TOPBAR_HEIGHT, TEXT_SPACING, WHITE); - - DrawRectangle(SCREEN_SIZE - TOPBAR_HEIGHT - blueScoreWidth - 2, 0, TOPBAR_HEIGHT, TOPBAR_HEIGHT, BLUE); - DrawRectangle(SCREEN_SIZE - TOPBAR_HEIGHT - redScoreWidth - 2, 0, TOPBAR_HEIGHT, TOPBAR_HEIGHT, RED); - DrawRectangle(SCREEN_SIZE - TOPBAR_HEIGHT - scoreboardWidth - 2, 0, TOPBAR_HEIGHT, TOPBAR_HEIGHT, WHITE); - } - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000..73c5c04 --- /dev/null +++ b/src/map.c @@ -0,0 +1,27 @@ +#include "rogue.h" + +Tile **createMapTiles() +{ + Tile **tiles = MemAlloc(sizeof(Tile *) * MAP_WIDTH); + + for (unsigned int x = 0; x < MAP_WIDTH; x++) + { + tiles[x] = MemAlloc(sizeof(Tile) * MAP_HEIGHT); + for (unsigned int y = 0; y < MAP_HEIGHT; y++) + { + tiles[x][y].color = WHITE; + tiles[x][y].walkable = false; + } + } + + return tiles; +} + +void freeMapTiles(Tile **map_tiles) +{ + for (unsigned int x = 0; x < MAP_WIDTH; x++) + { + MemFree(map_tiles[x]); + } + MemFree(map_tiles); +} diff --git a/src/player.c b/src/player.c new file mode 100644 index 0000000..02aa8b3 --- /dev/null +++ b/src/player.c @@ -0,0 +1,12 @@ +#include "rogue.h" +#include "raylib.h" + +Entity *createPlayer(Vector2i const start_position) +{ + Entity *const newPlayer = MemAlloc(sizeof(Entity)); + + newPlayer->position = start_position; + newPlayer->color = DARKBLUE; + + return newPlayer; +}