egg
This commit is contained in:
parent
1a1a73ea9f
commit
95f105fd96
9 changed files with 252 additions and 236 deletions
8
.vscode/tasks.json
vendored
8
.vscode/tasks.json
vendored
|
@ -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" },
|
||||
|
|
9
.vscode/workspace.code-workspace
vendored
9
.vscode/workspace.code-workspace
vendored
|
@ -8,5 +8,14 @@
|
|||
"recommendations": [
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"*.lock": "yarnlock",
|
||||
"*.m": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"raylib.h": "c",
|
||||
"math.h": "c"
|
||||
}
|
||||
}
|
||||
}
|
33
include/rogue.h
Normal file
33
include/rogue.h
Normal file
|
@ -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;
|
28
src/draw.c
Normal file
28
src/draw.c
Normal file
|
@ -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();
|
||||
}
|
118
src/engine.c
Normal file
118
src/engine.c
Normal file
|
@ -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
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
21
src/main.c
Normal file
21
src/main.c
Normal file
|
@ -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;
|
||||
}
|
232
src/main.cpp
232
src/main.cpp
|
@ -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;
|
||||
}
|
27
src/map.c
Normal file
27
src/map.c
Normal file
|
@ -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);
|
||||
}
|
12
src/player.c
Normal file
12
src/player.c
Normal file
|
@ -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;
|
||||
}
|
Reference in a new issue