Tic-Tac-Toe
This commit is contained in:
parent
19608b3283
commit
647dc39920
3 changed files with 222 additions and 95 deletions
17
.vscode/c_cpp_properties.json
vendored
Normal file
17
.vscode/c_cpp_properties.json
vendored
Normal 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
|
||||
}
|
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
|
@ -15,6 +15,7 @@
|
|||
{ "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" },
|
||||
|
@ -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" },
|
||||
|
|
260
src/main.c
260
src/main.c
|
@ -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
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
Reference in a new issue