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 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 #pragma once
#include <vector>
#include <Util.h> #include <Util.h>
#include <Player.h>
#include <GameConfig.h>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp> #include <SFML/Audio.hpp>
#include <imgui-SFML.h> #include <imgui-SFML.h>
#include <imgui.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 class Game
{ {
public: public:
@ -38,6 +16,8 @@ public:
void run(); void run();
bool init();
private: private:
void imgui(); void imgui();
@ -57,19 +37,26 @@ private:
void scoreSystem(); void scoreSystem();
void failState();
private: private:
GameConfig config;
sf::Clock clock; sf::Clock clock;
sf::RenderWindow window; sf::RenderWindow window;
sf::Font font; sf::Font font;
sf::Text lives;
sf::Text score; sf::Text score;
Player player; sf::SoundBuffer failSoundBuffer;
// mostly used for imgui sf::RectangleShape tempRect;
int framerate{};
float volume{}; //sf::Sound failSound;
Player player{};
size_t frameCount{};
bool useImgui; 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) 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") , font("assets/fonts/ChakraPetch-Regular.ttf")
, lives(font)
, score(font) , score(font)
, volume(10)
, useImgui(useImgui_in) , 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)}); tempRect.setSize({config.gridSize, config.gridSize});
score.setPosition({10, static_cast<float>(window.getSize().y - 80)}); 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; std::string inputBuff;
while(configFile >> 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; return true;
@ -131,18 +173,83 @@ void Game::input()
void Game::collision() 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() 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() void Game::imgui()
{ {
ImGui::SetNextWindowCollapsed(false, ImGuiCond_Once); ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once);
ImGui::SetNextWindowSize({490,375}, ImGuiCond_Once); ImGui::SetNextWindowSize({490,375}, ImGuiCond_Once);
ImGui::SetNextWindowPos({26,29}, ImGuiCond_Once); ImGui::SetNextWindowPos({26,29}, ImGuiCond_Once);
if(!ImGui::Begin("menu")) if(!ImGui::Begin("menu"))
@ -156,7 +263,7 @@ void Game::imgui()
ImGui::Text("R: reset game"); ImGui::Text("R: reset game");
ImGui::Unindent(); 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(); 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)); score.setString("Score: " + std::to_string(player.score));
window.draw(lives);
window.draw(score); window.draw(score);
ImGui::SFML::Render(window); 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() void Game::run()
{ {
while(window.isOpen()) while(window.isOpen())
{ {
ImGui::SFML::Update(window, clock.restart()); ImGui::SFML::Update(window, clock.restart());
frameCount++;
input(); input();
movement(); if (!fail)
{
movement();
collision(); collision();
soundSystem(); soundSystem();
scoreSystem(); scoreSystem();
}
else
{
failState();
}
imgui(); 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; useImgui = false;
} }
} }
Game game(useImgui); Game game(useImgui);
game.run(); game.run();