initial implementation

-implemented basic movement
This commit is contained in:
Joseph Aquino 2025-12-19 11:40:38 -05:00
parent de9b81cf26
commit a3d6742d98
7 changed files with 249 additions and 64 deletions

View File

@ -1,4 +1,11 @@
framerate 60
playerColor 1 1 1
tickRate 60
playerHeadColor 1 1 1
playerBodyColor 1 1 1
headGridStartPos 10 10
gridSize 50

View File

@ -1,36 +1,14 @@
#pragma once
#include <vector>
#include <Util.h>
#include <Player.h>
#include <GameConfig.h>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <imgui-SFML.h>
#include <imgui.h>
class SnakeNode
{
};
struct Player
{
Player() = default;
Player(sf::Vector2i gridPos_in);
sf::Vector2i gridPos{};
sf::Vector2i previousGridPos{};
sf::Vector2f windowPos{};
int score{};
int lives{3};
bool left{false};
bool right{false};
bool up{false};
bool down{false};
};
class Game
{
public:
@ -38,6 +16,8 @@ public:
void run();
bool init();
private:
void imgui();
@ -57,19 +37,26 @@ private:
void scoreSystem();
void failState();
private:
GameConfig config;
sf::Clock clock;
sf::RenderWindow window;
sf::Font font;
sf::Text lives;
sf::Text score;
Player player;
sf::SoundBuffer failSoundBuffer;
// mostly used for imgui
int framerate{};
float volume{};
sf::RectangleShape tempRect;
//sf::Sound failSound;
Player player{};
size_t frameCount{};
bool useImgui;
static constexpr unsigned int numPhysicsUpdates{4};
bool fail;
bool running{true};
};

13
include/GameConfig.h Normal file
View File

@ -0,0 +1,13 @@
#include <Util.h>
#include <SFML/Graphics.hpp>
struct GameConfig
{
float volume{10};
int tickRate{};
int framerate{};
Color playerHeadColor;
Color playerBodyColor;
sf::Vector2i headGridStartPos;
float gridSize;
};

38
include/Player.h Normal file
View File

@ -0,0 +1,38 @@
#include <SFML/Graphics.hpp>
#include <Util.h>
enum class Direction
{
up,
down,
left,
right
};
struct SnakeNode
{
SnakeNode(sf::Vector2i gridPos_in, sf::Color color_in = sf::Color::White);
sf::Vector2f windowPos{};
sf::Vector2i gridPos{};
sf::Vector2i previousGridPos{};
Color color{};
};
struct Player
{
Player() = default;
SnakeNode& head();
std::vector<SnakeNode> body;
int score{};
Direction facing{Direction::up};
Direction inputBuffer{};
bool left{false};
bool right{false};
bool up{false};
bool down{false};
};

View File

@ -12,22 +12,36 @@
Game::Game(bool useImgui_in)
: window({sf::VideoMode({ 1920u, 1080u }), "project-breakout"})
: config()
, window({sf::VideoMode({ 1920u, 1080u }), "project-snake"})
, font("assets/fonts/ChakraPetch-Regular.ttf")
, lives(font)
, score(font)
, volume(10)
, useImgui(useImgui_in)
{
if (!ImGui::SFML::Init(window))
{
std::cout << "ERROR: Could not open window\n";
return;
}
if (!ImGui::SFML::Init(window)) return;
if (!parseConfigFile())
{
std::cout << "ERROR: Could not parse config file\n";
window.close();
return;
}
if (!parseConfigFile()) return;
player.body.reserve(100);
player.body.emplace_back(config.headGridStartPos);
player.head().windowPos.x = player.head().gridPos.x * config.gridSize;
player.head().windowPos.y = player.head().gridPos.y * config.gridSize;
lives.setPosition({10, static_cast<float>(window.getSize().y - 40)});
score.setPosition({10, static_cast<float>(window.getSize().y - 80)});
tempRect.setSize({config.gridSize, config.gridSize});
tempRect.setOutlineThickness(5);
window.setFramerateLimit(framerate);
score.setPosition({10, static_cast<float>(window.getSize().y - 40)});
window.setFramerateLimit(config.framerate);
}
@ -44,7 +58,35 @@ bool Game::parseConfigFile()
std::string inputBuff;
while(configFile >> inputBuff)
{
if (inputBuff == "framerate")
{
configFile >> config.framerate;
}
if (inputBuff == "tickRate")
{
configFile >> config.tickRate;
}
if (inputBuff == "playerHeadColor")
{
configFile >> config.playerHeadColor.r >> config.playerHeadColor.g >> config.playerHeadColor.b;
}
if (inputBuff == "playerBodyColor")
{
configFile >> config.playerBodyColor.r >> config.playerBodyColor.g >> config.playerBodyColor.b;
}
if (inputBuff == "headGridStartPos")
{
configFile >> config.headGridStartPos.x >> config.headGridStartPos.y;
}
if (inputBuff == "gridSize")
{
configFile >> config.gridSize;
}
}
return true;
@ -131,18 +173,83 @@ void Game::input()
void Game::collision()
{
const size_t limit = player.body.size();
for (size_t i = 1; i < limit; i++)
{
if (player.head().gridPos == player.body.at(i).gridPos)
{
fail = true;
//failSound.play();
return;
}
}
}
void Game::movement()
{
if (player.left and !player.right and (player.facing == Direction::up or player.facing == Direction::down))
{
player.inputBuffer = Direction::left;
}
if (player.right and !player.left and (player.facing == Direction::up or player.facing == Direction::down))
{
player.inputBuffer = Direction::right;
}
if (player.up and !player.down and (player.facing == Direction::left or player.facing == Direction::right))
{
player.inputBuffer = Direction::up;
}
if (player.down and !player.up and (player.facing == Direction::left or player.facing == Direction::right))
{
player.inputBuffer = Direction::down;
}
if (frameCount % config.tickRate != 0) return;
switch (player.inputBuffer)
{
case Direction::up:
player.head().previousGridPos = player.head().gridPos;
player.head().gridPos += sf::Vector2i{ 0, -1 };
player.facing = Direction::up;
// std::cout << "up\n";
break;
case Direction::down:
player.head().previousGridPos = player.head().gridPos;
player.head().gridPos += sf::Vector2i{ 0, 1 };
player.facing = Direction::down;
// std::cout << "down\n";
break;
case Direction::left:
player.head().previousGridPos = player.head().gridPos;
player.head().gridPos += sf::Vector2i{ -1, 0 };
player.facing = Direction::left;
// std::cout << "left\n";
break;
case Direction::right:
player.head().previousGridPos = player.head().gridPos;
player.head().gridPos += sf::Vector2i{ 1, 0 };
player.facing = Direction::right;
// std::cout << "right\n";
break;
}
player.head().windowPos.x = player.head().gridPos.x * config.gridSize;
player.head().windowPos.y = player.head().gridPos.y * config.gridSize;
}
void Game::imgui()
{
ImGui::SetNextWindowCollapsed(false, ImGuiCond_Once);
ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once);
ImGui::SetNextWindowSize({490,375}, ImGuiCond_Once);
ImGui::SetNextWindowPos({26,29}, ImGuiCond_Once);
if(!ImGui::Begin("menu"))
@ -156,7 +263,7 @@ void Game::imgui()
ImGui::Text("R: reset game");
ImGui::Unindent();
if (ImGui::SliderFloat("Game Volume", &volume, 0, 100, "%.1f"))
if (ImGui::SliderFloat("Game Volume", &config.volume, 0, 100, "%.1f"))
{
}
@ -169,10 +276,15 @@ void Game::render()
{
window.clear();
lives.setString("Lives: " + std::to_string(player.lives));
for (auto& node : player.body)
{
tempRect.setFillColor(node.color.sfml());
tempRect.setPosition(node.windowPos);
window.draw(tempRect);
}
score.setString("Score: " + std::to_string(player.score));
window.draw(lives);
window.draw(score);
ImGui::SFML::Render(window);
@ -195,21 +307,39 @@ void Game::resetGame()
}
void Game::failState()
{
// if (failSound.getStatus() == sf::Sound::Status::Stopped)
// {
// resetGame();
// return;
// }
}
void Game::run()
{
while(window.isOpen())
{
ImGui::SFML::Update(window, clock.restart());
frameCount++;
input();
movement();
if (!fail)
{
movement();
collision();
collision();
soundSystem();
soundSystem();
scoreSystem();
scoreSystem();
}
else
{
failState();
}
imgui();

11
src/Player.cpp Normal file
View File

@ -0,0 +1,11 @@
#include <Player.h>
SnakeNode::SnakeNode(sf::Vector2i gridPos_in, sf::Color color_in)
: gridPos(gridPos_in)
, color(color_in)
{ }
SnakeNode& Player::head()
{
return body[0];
}

View File

@ -11,7 +11,6 @@ int main(int argc, char* argv[])
useImgui = false;
}
}
Game game(useImgui);
game.run();