Initial
This commit is contained in:
43
.gitignore
vendored
Normal file
43
.gitignore
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Build directories
|
||||||
|
cmake-build-*/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
CMakeFiles/
|
||||||
|
CMakeCache.txt
|
||||||
|
cmake_install.cmake
|
||||||
|
compile_commands.json
|
||||||
|
Makefile
|
||||||
|
|
||||||
|
# Ninja
|
||||||
|
.ninja_deps
|
||||||
|
.ninja_log
|
||||||
|
|
||||||
|
# CLion / IntelliJ
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Compiled objects
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Raylib generated assets/cache if needed
|
||||||
|
*.rres
|
||||||
35
CMakeLists.txt
Normal file
35
CMakeLists.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
cmake_minimum_required(VERSION 4.2)
|
||||||
|
project(snake)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
add_executable(snake src/main.cpp
|
||||||
|
src/core/App.cpp
|
||||||
|
src/core/App.h
|
||||||
|
src/external/External.cpp
|
||||||
|
src/external/External.h
|
||||||
|
src/core/Game.cpp
|
||||||
|
src/core/Game.h
|
||||||
|
src/external/Config.cpp
|
||||||
|
src/external/Config.h
|
||||||
|
src/external/Time.cpp
|
||||||
|
src/external/Time.h
|
||||||
|
src/core/Board.cpp
|
||||||
|
src/core/Board.h
|
||||||
|
src/core/Renderer.cpp
|
||||||
|
src/core/Renderer.cpp
|
||||||
|
src/core/Renderer.h
|
||||||
|
src/core/Direction.h
|
||||||
|
src/core/Snake.cpp
|
||||||
|
src/core/Snake.h
|
||||||
|
src/core/Direction.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(snake PRIVATE include)
|
||||||
|
|
||||||
|
target_link_directories(snake PRIVATE lib)
|
||||||
|
target_link_libraries(snake PRIVATE
|
||||||
|
raylib
|
||||||
|
X11
|
||||||
|
)
|
||||||
|
|
||||||
1743
include/raylib.h
Normal file
1743
include/raylib.h
Normal file
File diff suppressed because it is too large
Load Diff
3139
include/raymath.h
Normal file
3139
include/raymath.h
Normal file
File diff suppressed because it is too large
Load Diff
63
src/core/App.cpp
Normal file
63
src/core/App.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
|
||||||
|
#include <raylib.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
App::App() {
|
||||||
|
m_external = new External();
|
||||||
|
m_game = new Game(
|
||||||
|
config()->getSizeX(),
|
||||||
|
config()->getSizeY(),
|
||||||
|
m_external
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
App::~App() {
|
||||||
|
delete m_game;
|
||||||
|
delete m_external;
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::run(int argc, char **argv) {
|
||||||
|
this->init();
|
||||||
|
this->runLoop();
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::init() {
|
||||||
|
const int sizeField = config()->getSizeField();
|
||||||
|
const int sizeX = config()->getSizeX();
|
||||||
|
const int sizeY = config()->getSizeY();
|
||||||
|
|
||||||
|
InitWindow(sizeX * sizeField, sizeY * sizeField, "Snake");
|
||||||
|
|
||||||
|
time()->reset();
|
||||||
|
|
||||||
|
std::srand(std::time(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::close() {
|
||||||
|
CloseWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::runLoop() {
|
||||||
|
while (!WindowShouldClose()) {
|
||||||
|
m_game->update(time()->getDeltaTime());
|
||||||
|
m_game->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Config * App::config() const {
|
||||||
|
return m_external->getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
Time * App::time() const {
|
||||||
|
return m_external->getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
Game * App::game() const {
|
||||||
|
return m_game;
|
||||||
|
}
|
||||||
36
src/core/App.h
Normal file
36
src/core/App.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_APP_H
|
||||||
|
#define SNAKE_APP_H
|
||||||
|
#include "Game.h"
|
||||||
|
#include "../external/External.h"
|
||||||
|
|
||||||
|
class App {
|
||||||
|
public:
|
||||||
|
App();
|
||||||
|
~App();
|
||||||
|
|
||||||
|
void run(int argc, char **argv);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void runLoop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] Game *game() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Config *config() const;
|
||||||
|
[[nodiscard]] Time *time() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Game* m_game;
|
||||||
|
|
||||||
|
External* m_external;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_APP_H
|
||||||
137
src/core/Board.cpp
Normal file
137
src/core/Board.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Board.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "raymath.h"
|
||||||
|
|
||||||
|
Board::Board(const int sizeX, const int sizeY, External *external)
|
||||||
|
: m_sizeX(sizeX), m_sizeY(sizeY), m_external(external)
|
||||||
|
{
|
||||||
|
m_fieldsMatrix = new Field * [m_sizeY];
|
||||||
|
for (int i = 0; i < m_sizeY; i++) {
|
||||||
|
m_fieldsMatrix[i] = new Field[m_sizeX];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_snake = new Snake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Board::~Board() {
|
||||||
|
for (int i = 0; i < m_sizeY; i++) {
|
||||||
|
delete[] m_fieldsMatrix[i];
|
||||||
|
}
|
||||||
|
delete[] m_fieldsMatrix;
|
||||||
|
|
||||||
|
delete m_snake;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::reset() {
|
||||||
|
clear();
|
||||||
|
initSnake();
|
||||||
|
putAppleOnRandomPlace();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::clear() {
|
||||||
|
for (int i = 0; i<m_sizeY; i++) {
|
||||||
|
for (int j = 0; j<m_sizeX; j++) {
|
||||||
|
m_fieldsMatrix[i][j] = Field::Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_appleX = 0;
|
||||||
|
m_appleY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::initSnake() {
|
||||||
|
|
||||||
|
const int initSize = 3;
|
||||||
|
|
||||||
|
int x = std::rand() % (m_sizeX - initSize * 2) + initSize;
|
||||||
|
int y = std::rand() % (m_sizeY - initSize * 2) + initSize;
|
||||||
|
Vector2 headPosition = {static_cast<float>(x), static_cast<float>(y)};
|
||||||
|
|
||||||
|
auto direction = static_cast<Direction>(std::rand() % 4);
|
||||||
|
|
||||||
|
m_snake->init(headPosition, initSize, direction);
|
||||||
|
|
||||||
|
setField(headPosition, Field::Head);
|
||||||
|
|
||||||
|
Vector2 tailPosition = headPosition;
|
||||||
|
Vector2 directionVector = DirectionUnitVector(DirectionInvert(direction));
|
||||||
|
|
||||||
|
for (int i = 1; i < initSize; i++) {
|
||||||
|
tailPosition = Vector2Add(tailPosition, directionVector);
|
||||||
|
setField(tailPosition, Field::Tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::moveSnake(Direction direction) {
|
||||||
|
const Vector2 oldHeadPosition = m_snake->getHeadPosition();
|
||||||
|
m_snake->move(direction);
|
||||||
|
const Vector2 newHeadPosition = m_snake->getHeadPosition();
|
||||||
|
|
||||||
|
Field bumpedField = getField(newHeadPosition);
|
||||||
|
if (bumpedField == Field::Apple) {
|
||||||
|
putAppleOnRandomPlace();
|
||||||
|
}
|
||||||
|
else if (bumpedField == Field::Tail) {
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
else if (isPositionOutside(newHeadPosition)) {
|
||||||
|
exit(-2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Vector2 lastInTailPosition = m_snake->removeLastFromTail();
|
||||||
|
setField(lastInTailPosition, Field::Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
setField(oldHeadPosition, Field::Tail);
|
||||||
|
setField(newHeadPosition, Field::Head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::putAppleOnRandomPlace() {
|
||||||
|
int x, y;
|
||||||
|
do {
|
||||||
|
x = std::rand() % m_sizeX;
|
||||||
|
y = std::rand() % m_sizeY;
|
||||||
|
}
|
||||||
|
while (m_fieldsMatrix[y][x] != Field::Empty);
|
||||||
|
|
||||||
|
repositionApple(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::repositionApple(int x, int y) {
|
||||||
|
if (m_fieldsMatrix[m_appleY][m_appleX] == Field::Apple) {
|
||||||
|
m_fieldsMatrix[m_appleY][m_appleX] = Field::Empty;
|
||||||
|
}
|
||||||
|
m_appleX = x;
|
||||||
|
m_appleY = y;
|
||||||
|
m_fieldsMatrix[y][x] = Field::Apple;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field ** Board::getFields() const {
|
||||||
|
return m_fieldsMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::swapFields(const int x1, const int y1, const int x2, const int y2) const {
|
||||||
|
const auto tempField = m_fieldsMatrix[y1][x1];
|
||||||
|
m_fieldsMatrix[y1][x1] = m_fieldsMatrix[y2][x2];
|
||||||
|
m_fieldsMatrix[y2][x2] = tempField;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field Board::getField(const Vector2 position) const {
|
||||||
|
return m_fieldsMatrix[static_cast<int>(position.y)][static_cast<int>(position.x)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::setField(const Vector2 position, const Field field) const {
|
||||||
|
m_fieldsMatrix[static_cast<int>(position.y)][static_cast<int>(position.x)] = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Board::isPositionOutside(Vector2 position) const {
|
||||||
|
return position.y < 0 || position.y >= m_sizeY
|
||||||
|
|| position.x < 0 || position.x >= m_sizeX;
|
||||||
|
}
|
||||||
57
src/core/Board.h
Normal file
57
src/core/Board.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_BOARD_H
|
||||||
|
#define SNAKE_BOARD_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Direction.h"
|
||||||
|
#include "Snake.h"
|
||||||
|
#include "../external/External.h"
|
||||||
|
|
||||||
|
enum Field {
|
||||||
|
Empty = 0,
|
||||||
|
Head = 1,
|
||||||
|
Tail = 2,
|
||||||
|
Apple = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
class Board {
|
||||||
|
public:
|
||||||
|
Board(int sizeX, int sizeY, External *external);
|
||||||
|
~Board();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void reset();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Snake
|
||||||
|
void initSnake();
|
||||||
|
void moveSnake(Direction direction);
|
||||||
|
|
||||||
|
// Apple
|
||||||
|
void putAppleOnRandomPlace();
|
||||||
|
void repositionApple(int x, int y);
|
||||||
|
|
||||||
|
// Fields
|
||||||
|
Field ** getFields() const;
|
||||||
|
void swapFields(int x1, int y1, int x2, int y2) const;
|
||||||
|
Field getField(Vector2 position) const;
|
||||||
|
void setField(Vector2 position, Field field) const;
|
||||||
|
bool isPositionOutside(Vector2 position) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_sizeX, m_sizeY;
|
||||||
|
Field ** m_fieldsMatrix;
|
||||||
|
|
||||||
|
Snake *m_snake;
|
||||||
|
|
||||||
|
int m_appleX = 0, m_appleY = 0;
|
||||||
|
|
||||||
|
External *m_external;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_BOARD_H
|
||||||
50
src/core/Direction.cpp
Normal file
50
src/core/Direction.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 10/05/2026.
|
||||||
|
//
|
||||||
|
#include "Direction.h"
|
||||||
|
|
||||||
|
Vector2 DirectionUnitVector(Direction direction) {
|
||||||
|
switch (direction) {
|
||||||
|
case Right:
|
||||||
|
return {1, 0};
|
||||||
|
break;
|
||||||
|
case Up:
|
||||||
|
return {0, -1};
|
||||||
|
break;
|
||||||
|
case Left:
|
||||||
|
return {-1, 0};
|
||||||
|
break;
|
||||||
|
case Down:
|
||||||
|
return {0, 1};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
Direction DirectionInvert(Direction direction) {
|
||||||
|
const int directionNumber = direction;
|
||||||
|
return static_cast<Direction>((directionNumber + 2) % 4); // Rotate 180 deg
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Direction> DirectionFrom2VectorsInLine(Vector2 first, Vector2 second) {
|
||||||
|
|
||||||
|
if (first.x == second.x) {
|
||||||
|
if (first.y > second.y) {
|
||||||
|
return Direction::Up;
|
||||||
|
}
|
||||||
|
if (first.y < second.y) {
|
||||||
|
return Direction::Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (first.y == second.y) {
|
||||||
|
if (first.x > second.x) {
|
||||||
|
return Direction::Left;
|
||||||
|
}
|
||||||
|
if (first.x < second.x) {
|
||||||
|
return Direction::Right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
22
src/core/Direction.h
Normal file
22
src/core/Direction.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_DIRECTION_H
|
||||||
|
#define SNAKE_DIRECTION_H
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
Right = 0,
|
||||||
|
Up = 1,
|
||||||
|
Left = 2,
|
||||||
|
Down = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector2 DirectionUnitVector(Direction direction);
|
||||||
|
Direction DirectionInvert(Direction direction);
|
||||||
|
std::optional<Direction> DirectionFrom2VectorsInLine(Vector2 first, Vector2 second);
|
||||||
|
|
||||||
|
#endif //SNAKE_DIRECTION_H
|
||||||
70
src/core/Game.cpp
Normal file
70
src/core/Game.cpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
|
||||||
|
Game::Game(const int sizeX, const int sizeY, External *external)
|
||||||
|
: m_sizeX(sizeX), m_sizeY(sizeY), m_external(external)
|
||||||
|
{
|
||||||
|
m_board = new Board(m_sizeX, m_sizeY, external);
|
||||||
|
m_board->reset();
|
||||||
|
|
||||||
|
m_currentDirection = Direction::Left;
|
||||||
|
|
||||||
|
m_turnTime = m_external->getConfig()->getTurnTimeSeconds();
|
||||||
|
m_timeElapsedSinceLastTurn = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::~Game() {
|
||||||
|
delete m_board;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::update(double deltaTime) {
|
||||||
|
m_timeElapsedSinceLastTurn += deltaTime;
|
||||||
|
catchInput();
|
||||||
|
if (checkTurnPassed()) {
|
||||||
|
// m_board->putAppleOnRandomPlace();
|
||||||
|
m_board->moveSnake(m_currentDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::render() {
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(WHITE);
|
||||||
|
|
||||||
|
int sizeField = m_external->getConfig()->getSizeField();
|
||||||
|
m_renderer.renderFields(m_board->getFields(), m_sizeX, m_sizeY, sizeField);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::catchInput() {
|
||||||
|
switch (GetKeyPressed()) {
|
||||||
|
case KEY_RIGHT:
|
||||||
|
m_currentDirection = Direction::Right;
|
||||||
|
return;
|
||||||
|
case KEY_UP:
|
||||||
|
m_currentDirection = Direction::Up;
|
||||||
|
return;
|
||||||
|
case KEY_LEFT:
|
||||||
|
m_currentDirection = Direction::Left;
|
||||||
|
return;
|
||||||
|
case KEY_DOWN:
|
||||||
|
m_currentDirection = Direction::Down;
|
||||||
|
return;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Game::checkTurnPassed() {
|
||||||
|
if (m_timeElapsedSinceLastTurn > m_turnTime) {
|
||||||
|
m_timeElapsedSinceLastTurn = 0.0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
42
src/core/Game.h
Normal file
42
src/core/Game.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_GAME_H
|
||||||
|
#define SNAKE_GAME_H
|
||||||
|
#include "Direction.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "../external/External.h"
|
||||||
|
|
||||||
|
class Game {
|
||||||
|
public:
|
||||||
|
Game(int sizeX, int sizeY, External *external);
|
||||||
|
~Game();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void update(double deltaTime);
|
||||||
|
void render();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void catchInput();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool checkTurnPassed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_sizeX, m_sizeY;
|
||||||
|
|
||||||
|
Direction m_currentDirection;
|
||||||
|
|
||||||
|
double m_turnTime;
|
||||||
|
double m_timeElapsedSinceLastTurn;
|
||||||
|
|
||||||
|
Board *m_board;
|
||||||
|
|
||||||
|
Renderer m_renderer;
|
||||||
|
|
||||||
|
External *m_external;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_GAME_H
|
||||||
39
src/core/Renderer.cpp
Normal file
39
src/core/Renderer.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Renderer.h"
|
||||||
|
|
||||||
|
void Renderer::renderFields(Field **fieldsMatrix, int sizeX, int sizeY, int sizeField) {
|
||||||
|
for (int i = 0; i < sizeY; i++) {
|
||||||
|
for (int j = 0; j < sizeX; j++) {
|
||||||
|
int x = j * sizeField;
|
||||||
|
int y = i * sizeField;
|
||||||
|
renderField(x, y, fieldsMatrix[i][j], sizeField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::renderField(int x, int y, Field field, int sizeField) {
|
||||||
|
int pad = 1;
|
||||||
|
DrawRectangle(x+pad, y+pad, sizeField-2*pad, sizeField-2*pad, getFieldColor(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Renderer::getFieldColor(const Field field) {
|
||||||
|
auto color = GRAY;
|
||||||
|
switch (field) {
|
||||||
|
case Empty:
|
||||||
|
color = WHITE;
|
||||||
|
break;
|
||||||
|
case Head:
|
||||||
|
color = DARKGREEN;
|
||||||
|
break;
|
||||||
|
case Tail:
|
||||||
|
color = GREEN;
|
||||||
|
break;
|
||||||
|
case Apple:
|
||||||
|
color = RED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
22
src/core/Renderer.h
Normal file
22
src/core/Renderer.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_RENDERER_H
|
||||||
|
#define SNAKE_RENDERER_H
|
||||||
|
#include "Board.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Renderer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
void renderFields(Field ** fieldsMatrix, int sizeX, int sizeY, int sizeField);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void renderField(int x, int y, Field field, int sizeField);
|
||||||
|
static Color getFieldColor(Field field);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_RENDERER_H
|
||||||
69
src/core/Snake.cpp
Normal file
69
src/core/Snake.cpp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 10/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Snake.h"
|
||||||
|
|
||||||
|
#include <raymath.h>
|
||||||
|
|
||||||
|
Snake::Snake()
|
||||||
|
: m_size(0), m_head({0, 0})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Snake::init(Vector2 head, int size, Direction initialDirection) {
|
||||||
|
m_tail.clear();
|
||||||
|
m_head = head;
|
||||||
|
m_size = size;
|
||||||
|
expandTail(DirectionInvert(initialDirection), size-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Snake::move(Direction direction) {
|
||||||
|
std::optional<Direction> currentDirection = getCurrentDirection();
|
||||||
|
|
||||||
|
if (currentDirection.has_value() && currentDirection.value() == DirectionInvert(direction)) {
|
||||||
|
direction = currentDirection.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_size++;
|
||||||
|
m_tail.push_front(m_head);
|
||||||
|
|
||||||
|
Vector2 directionVector = DirectionUnitVector(direction);
|
||||||
|
m_head = Vector2Add(m_head, directionVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Direction> Snake::getCurrentDirection() const {
|
||||||
|
if (m_tail.empty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return DirectionFrom2VectorsInLine(m_tail.front(), m_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Snake::getHeadPosition() {
|
||||||
|
return m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Snake::removeLastFromTail() {
|
||||||
|
Vector2 lastInTail = m_tail.back();
|
||||||
|
m_tail.pop_back();
|
||||||
|
m_size--;
|
||||||
|
return lastInTail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Snake::expandTail(const Direction direction, const int count) {
|
||||||
|
const Vector2 directionVector = DirectionUnitVector(direction);
|
||||||
|
|
||||||
|
Vector2 lastInTail = getLastInTail();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
lastInTail = Vector2Add(lastInTail, directionVector);
|
||||||
|
m_tail.push_back(lastInTail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Snake::getLastInTail() const {
|
||||||
|
if (m_tail.empty()) {
|
||||||
|
return m_head;
|
||||||
|
}
|
||||||
|
return m_tail.back();
|
||||||
|
}
|
||||||
44
src/core/Snake.h
Normal file
44
src/core/Snake.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 10/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_SNAKE_H
|
||||||
|
#define SNAKE_SNAKE_H
|
||||||
|
#include <optional>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include "Direction.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Snake {
|
||||||
|
public:
|
||||||
|
Snake();
|
||||||
|
|
||||||
|
void init(Vector2 head, int size, Direction initialDirection);
|
||||||
|
|
||||||
|
// Movement
|
||||||
|
public:
|
||||||
|
void move(Direction direction);
|
||||||
|
private:
|
||||||
|
[[nodiscard]] std::optional<Direction> getCurrentDirection() const;
|
||||||
|
|
||||||
|
// Head
|
||||||
|
public:
|
||||||
|
Vector2 getHeadPosition();
|
||||||
|
|
||||||
|
// Tail
|
||||||
|
public:
|
||||||
|
Vector2 removeLastFromTail();
|
||||||
|
private:
|
||||||
|
void expandTail(Direction direction, int count);
|
||||||
|
[[nodiscard]] Vector2 getLastInTail() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_size;
|
||||||
|
Vector2 m_head;
|
||||||
|
std::deque<Vector2> m_tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_SNAKE_H
|
||||||
21
src/external/Config.cpp
vendored
Normal file
21
src/external/Config.cpp
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
int Config::getSizeX() {
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::getSizeY() {
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::getSizeField() {
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Config::getTurnTimeSeconds() {
|
||||||
|
return 0.2;
|
||||||
|
}
|
||||||
18
src/external/Config.h
vendored
Normal file
18
src/external/Config.h
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_CONFIG_H
|
||||||
|
#define SNAKE_CONFIG_H
|
||||||
|
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
public:
|
||||||
|
int getSizeX();
|
||||||
|
int getSizeY();
|
||||||
|
int getSizeField();
|
||||||
|
double getTurnTimeSeconds();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_CONFIG_H
|
||||||
23
src/external/External.cpp
vendored
Normal file
23
src/external/External.cpp
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "External.h"
|
||||||
|
|
||||||
|
External::External() {
|
||||||
|
m_config = new Config();
|
||||||
|
m_time = new Time();
|
||||||
|
}
|
||||||
|
|
||||||
|
External::~External() {
|
||||||
|
delete m_config;
|
||||||
|
delete m_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
Config * External::getConfig() const {
|
||||||
|
return m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time * External::getTime() const {
|
||||||
|
return m_time;
|
||||||
|
}
|
||||||
24
src/external/External.h
vendored
Normal file
24
src/external/External.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_EXTERNAL_H
|
||||||
|
#define SNAKE_EXTERNAL_H
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Time.h"
|
||||||
|
|
||||||
|
class External {
|
||||||
|
public:
|
||||||
|
External();
|
||||||
|
~External();
|
||||||
|
|
||||||
|
Config* getConfig() const;
|
||||||
|
Time* getTime() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Config *m_config;
|
||||||
|
Time *m_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_EXTERNAL_H
|
||||||
29
src/external/Time.cpp
vendored
Normal file
29
src/external/Time.cpp
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Time.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
Time::Time() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Time::reset() {
|
||||||
|
m_previousCurrentTime = getCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Time::getDeltaTime() {
|
||||||
|
timeAliased now = getCurrentTime();
|
||||||
|
|
||||||
|
auto secondsElapsed = now - m_previousCurrentTime;
|
||||||
|
|
||||||
|
m_previousCurrentTime = now;
|
||||||
|
|
||||||
|
return secondsElapsed.count() / 1000000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeAliased Time::getCurrentTime() {
|
||||||
|
return std::chrono::system_clock::now();
|
||||||
|
}
|
||||||
29
src/external/Time.h
vendored
Normal file
29
src/external/Time.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by stewki on 09/05/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SNAKE_TIME_H
|
||||||
|
#define SNAKE_TIME_H
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
typedef std::chrono::time_point<std::chrono::system_clock> timeAliased;
|
||||||
|
|
||||||
|
class Time {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Time();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
double getDeltaTime();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static timeAliased getCurrentTime();
|
||||||
|
|
||||||
|
private:
|
||||||
|
timeAliased m_previousCurrentTime;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SNAKE_TIME_H
|
||||||
10
src/main.cpp
Normal file
10
src/main.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
#include "core/App.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
App app;
|
||||||
|
app.run(argc, argv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user