Tic-Tac-Toe

This commit is contained in:
Tobias Berger 2021-11-22 16:40:49 +01:00
parent 19608b3283
commit 647dc39920
3 changed files with 222 additions and 95 deletions

17
.vscode/c_cpp_properties.json vendored Normal file
View file

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/raylib/src/extras"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:\\dev\\tcc\\tcc.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}

40
.vscode/tasks.json vendored
View file

@ -8,25 +8,26 @@
"type": "shell",
"command": "tcc",
"args": [
{ "value": "src/**.c", "quoting": "weak" },
{ "value": "-ooutput.exe", "quoting": "strong" },
{ "value": "-bench", "quoting": "strong" },
{ "value": "-v", "quoting": "strong" },
{ "value": "-b", "quoting": "strong" },
{ "value": "-Iinclude", "quoting": "strong" },
{ "value": "-Iraylib/src", "quoting": "strong" },
{ "value": "-Llib", "quoting": "strong" },
{ "value": "-stdc99", "quoting": "strong" },
{ "value": "-Wall", "quoting": "strong" },
{ "value": "-Werror", "quoting": "strong" },
{ "value": "-Wwrite-strings", "quoting": "strong" },
{ "value": "-lraylib", "quoting": "strong" },
{ "value": "-lopengl32", "quoting": "strong" },
{ "value": "-lgdi32", "quoting": "strong" },
{ "value": "-luser32", "quoting": "strong" },
{ "value": "-lshell32", "quoting": "strong" },
{ "value": "-lwinmm", "quoting": "strong" },
{ "value": "-D__DEBUG", "quoting": "strong" },
{ "value": "src/**.c", "quoting": "weak" },
{ "value": "-ooutput.exe", "quoting": "strong" },
{ "value": "-bench", "quoting": "strong" },
{ "value": "-v", "quoting": "strong" },
{ "value": "-b", "quoting": "strong" },
{ "value": "-Iinclude", "quoting": "strong" },
{ "value": "-Iraylib/src", "quoting": "strong" },
{ "value": "-Iraylib/src/extras", "quoting": "strong" },
{ "value": "-Llib", "quoting": "strong" },
{ "value": "-stdc99", "quoting": "strong" },
{ "value": "-Wall", "quoting": "strong" },
{ "value": "-Werror", "quoting": "strong" },
{ "value": "-Wwrite-strings", "quoting": "strong" },
{ "value": "-lraylib", "quoting": "strong" },
{ "value": "-lopengl32", "quoting": "strong" },
{ "value": "-lgdi32", "quoting": "strong" },
{ "value": "-luser32", "quoting": "strong" },
{ "value": "-lshell32", "quoting": "strong" },
{ "value": "-lwinmm", "quoting": "strong" },
{ "value": "-D__DEBUG", "quoting": "strong" },
],
"group": {
"kind": "build",
@ -44,6 +45,7 @@
{ "value": "-v", "quoting": "strong" },
{ "value": "-Iinclude", "quoting": "strong" },
{ "value": "-Iraylib/src", "quoting": "strong" },
{ "value": "-Iraylib/src/extras", "quoting": "strong" },
{ "value": "-Llib", "quoting": "strong" },
{ "value": "-stdc99", "quoting": "strong" },
{ "value": "-Wall", "quoting": "strong" },

View file

@ -1,116 +1,224 @@
/*******************************************************************************************
*
* raylib [models] example - Heightmap loading and drawing
*
* This example has been created using raylib 1.8 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define FNL_IMPL
#include "FastNoiseLite.h"
// Size of a gameboard pixel
#define SCREEN_SCALE 256
#define HEIGHT_MAP_SIZE 128
#define TOP_OFFSET 40
#define SCREEN_SIZE (SCREEN_SCALE * 3)
#define VIRTUAL_SCREEN_SIZE SCREEN_SIZE / SCREEN_SCALE
typedef enum Player
{
NONE,
RED_PLAYER,
BLUE_PLAYER,
} Player;
Player checkBoard(Player board[9])
{
// horizontal, vertical, and diagonal checks from first cell
if (board[0] != 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] != NONE && (board[1] == board[4] && board[1] == board[7]))
return board[1];
// vertical and diagonal checks from third cell
if (board[2] != 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] != NONE && (board[3] == board[4] && board[3] == board[5]))
return board[3];
// horizontal check from seventh cell
if (board[6] != NONE && (board[6] == board[7] && board[6] == board[8]))
return board[6];
return NONE;
}
void resetBoard(Player board[9])
{
for (unsigned char i = 0; i < 9; i++)
{
board[i] = NONE;
}
}
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
#if defined(__DEBUG)
SetTraceLogLevel(LOG_ALL);
#else
SetTraceLogLevel(LOG_NONE);
#endif
fnl_state fnlState = fnlCreateState();
fnlState.seed = 0;
fnlState.noise_type = FNL_NOISE_CELLULAR;
fnlState.fractal_type = FNL_FRACTAL_PINGPONG;
fnlState.octaves = 3;
fnlState.frequency = 1.0f / 50.0f;
SetConfigFlags(0);
InitWindow(SCREEN_SIZE, SCREEN_SIZE + TOP_OFFSET, "Tic Tac Toe");
InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing");
/* For drawing */
RenderTexture2D target = LoadRenderTexture(VIRTUAL_SCREEN_SIZE, VIRTUAL_SCREEN_SIZE);
// Define our custom camera to look into our 3d world
Camera camera = {{18.0f, 18.0f, 18.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, 45.0f, 0};
Rectangle sourceRec = {0.0f,
0.0f,
(float)VIRTUAL_SCREEN_SIZE,
-(float)VIRTUAL_SCREEN_SIZE};
Rectangle destRec = {0.0f,
(float)(TOP_OFFSET),
SCREEN_SIZE,
SCREEN_SIZE};
Color pixels[HEIGHT_MAP_SIZE * HEIGHT_MAP_SIZE] = {0};
/* For game logic */
Player board[9] = {0};
resetBoard(board);
Player currentPlayer = RED_PLAYER;
for (int x = 0; x < HEIGHT_MAP_SIZE; x++)
{
for (int y = 0; y < HEIGHT_MAP_SIZE; y++)
{
float raw_noise = fnlGetNoise2D(&fnlState, (float)x, (float)y);
float noise = ((raw_noise + 1.0f) / 2.0f) * 255.0f;
unsigned char intensity = (unsigned char)noise;
pixels[x + y * HEIGHT_MAP_SIZE] = (Color){
intensity,
intensity,
intensity,
255,
};
}
}
Image image = {
.data = pixels,
.width = HEIGHT_MAP_SIZE,
.height = HEIGHT_MAP_SIZE,
.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
.mipmaps = 1,
}; // Load heightmap image (RAM)
Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM)
Mesh mesh = GenMeshHeightmap(image, (Vector3){16, 8, 16}); // Generate heightmap mesh (RAM and VRAM)
Model model = LoadModelFromMesh(mesh); // Load model from generated mesh
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 mapPosition = {-8.0f, 0.0f, -8.0f}; // Define model position
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
unsigned char points[3] = {0, 0, 0};
unsigned char turn = 0;
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
//----------------------------------------------------------------------------------
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update camera
//----------------------------------------------------------------------------------
// 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)TOP_OFFSET)) / (float)SCREEN_SCALE);
if (hovered < 0 || hovered >= 9 || board[hovered] != NONE)
{
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
}
else if (board[hovered] == NONE)
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
board[hovered] = currentPlayer;
currentPlayer = (currentPlayer == RED_PLAYER) ? BLUE_PLAYER : RED_PLAYER;
// Cursor doesn't really matter in this frame
Player winner = checkBoard(board);
// Game is over
if (winner != 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 = {0};
switch (board[i])
{
case RED_PLAYER:
color = RED;
break;
case BLUE_PLAYER:
color = BLUE;
break;
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);
ClearBackground(RAYWHITE);
// Draw rendered game texture
DrawTexturePro(target.texture, sourceRec, destRec, (Vector2){0.0f, 0.0f}, 0.0f, WHITE);
BeginMode3D(camera);
#if __DEBUG
DrawFPS(0, TOP_OFFSET);
#endif
DrawModel(model, mapPosition, 1.0f, RED);
// Draw Top Bar
DrawGrid(20, 1.0f);
// Current player in top-left corner
switch (currentPlayer)
{
case RED_PLAYER:
DrawRectangle(0, 0, TOP_OFFSET, TOP_OFFSET, RED);
break;
case BLUE_PLAYER:
DrawRectangle(0, 0, TOP_OFFSET, TOP_OFFSET, BLUE);
break;
}
EndMode3D();
// Scores in top-left, labelled with colored squares
const char *blueScore = TextFormat("%03u", points[2]);
const int blueScoreWidth = MeasureText(blueScore, TOP_OFFSET);
DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE);
DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN);
const char *redScore = TextFormat("%03u %s", points[1], blueScore);
const int redScoreWidth = MeasureText(redScore, TOP_OFFSET);
DrawFPS(10, 10);
const char *scoreboard = TextFormat("%03u %s", points[0], redScore);
const int scoreboardWidth = MeasureText(scoreboard, TOP_OFFSET);
DrawText(scoreboard, SCREEN_SIZE - scoreboardWidth, 0, TOP_OFFSET, WHITE);
DrawRectangle(SCREEN_SIZE - TOP_OFFSET - blueScoreWidth - 2, 0, TOP_OFFSET, TOP_OFFSET, BLUE);
DrawRectangle(SCREEN_SIZE - TOP_OFFSET - redScoreWidth - 2, 0, TOP_OFFSET, TOP_OFFSET, RED);
DrawRectangle(SCREEN_SIZE - TOP_OFFSET - scoreboardWidth - 2, 0, TOP_OFFSET, TOP_OFFSET, WHITE);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------