This commit is contained in:
Robert Altner 2018-06-05 18:42:55 +02:00
parent b1cd74fdb2
commit ec1e5f64a2
11 changed files with 449 additions and 18 deletions

View file

@ -0,0 +1,62 @@
#include "Field.h"
Field::Field()
{
m_score = 0;
m_gameOver = false;
m_font.loadFromFile("font.ttf");
m_scoreText.setFont(m_font);
m_scoreText.setString(std::to_string(m_score));
m_scoreText.setCharacterSize(32);
m_scoreText.setPosition(5, 5);
m_scoreText.setColor(sf::Color::Black);
for (int y = 0; y < 33; y++)
{
for (int x = 0; x < 33; x++)
{
// Magic numbers and hardcoding is completely acceptable
// Kill me please
// Errors due to this so far: 4
Tile t(sf::Vector2f(TILESIZE, TILESIZE));
t.setFillColor(sf::Color::White);
t.setPosition(sf::Vector2f(x * TILESIZE, y * TILESIZE));
m_field.insert(std::pair<Vector2D, Tile>(Vector2D(x, y), t));
}
}
range = std::uniform_int_distribution<int>(0, 32);
engine.seed(time(NULL));
m_field.find(Vector2D(range(engine), range(engine)))->second.setFillColor(sf::Color::Red);
}
Field::~Field()
{
}
bool Field::IsOnFruit(Vector2D pos)
{
if (m_field.find(pos)->second.getFillColor() == sf::Color::Red)
{
m_field.find(pos)->second.setFillColor(sf::Color::White);
m_field.find(Vector2D(range(engine), range(engine)))->second.setFillColor(sf::Color::Red);
m_score++;
return true;
}
return false;
}
void Field::Render(sf::RenderWindow& window)
{
for (auto it : m_field)
window.draw(it.second);
window.draw(m_scoreText);
}

View file

@ -0,0 +1,33 @@
#pragma once
#include <map>
#include <random>
#include <SFML/Graphics.hpp>
#include "util.h"
typedef sf::RectangleShape Tile;
class Field
{
public:
Field();
~Field();
void Render(sf::RenderWindow& window);
bool IsOnFruit(Vector2D pos);
private:
std::map<Vector2D, Tile> m_field;
Vector2D fruitField;
std::default_random_engine engine;
std::uniform_int_distribution<int> range;
unsigned int m_score;
bool m_gameOver;
sf::Font m_font;
sf::Text m_scoreText;
};

View file

@ -0,0 +1,109 @@
#include "Framework.h"
#include <iostream>
sf::RenderWindow* Framework::window = nullptr; //Set Window object to nullptr. If window is nullptr, the framework was not initialized.
sf::Event Framework::e = sf::Event();
sf::Font Framework::m_font = sf::Font();
sf::Text Framework::m_gameOverText = sf::Text();
Field Framework::m_field = Field();
Snake Framework::m_snake = Snake();
bool Framework::m_gameOver = false;
Framework::~Framework()
{
delete window;
window = nullptr;
}
ErrorType Framework::Initialize(unsigned int width, unsigned int height, std::string title, sf::Uint8 flags)
{
if (window != nullptr)
{
std::cout << "WARNING: Framework has already been initialized." << std::endl;
return WARNING;
}
window = new sf::RenderWindow(sf::VideoMode(width, height), title, flags);
m_font.loadFromFile("font.ttf");
m_gameOverText.setFont(m_font);
m_gameOverText.setString("Game\nOver");
m_gameOverText.setCharacterSize(140);
m_gameOverText.setPosition(100, 200);
m_gameOverText.setColor(sf::Color::Black);
return NONE;
}
ErrorType Framework::Run()
{
if (window == nullptr)
{
std::cout << "ERROR: Framework cannot run before being initialized" << std::endl;
return ERROR;
}
while (window->isOpen())
{
if (Handle() == ERROR) return ERROR;
if(!m_gameOver)
if (Update() == ERROR) return ERROR;
if (Render() == ERROR) return ERROR;
}
return NONE;
}
ErrorType Framework::Handle()
{
while (window->pollEvent(e))
{
switch (e.type)
{
case sf::Event::Closed:
window->close();
break;
case sf::Event::KeyPressed:
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
m_snake.setDirection(Vector2D(0, -1));
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
m_snake.setDirection(Vector2D(-1, 0));
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
m_snake.setDirection(Vector2D(0, 1));
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
m_snake.setDirection(Vector2D(1, 0));
}
}
}
return NONE;
}
ErrorType Framework::Update()
{
if (!m_snake.Update(m_field))
m_gameOver = true;
return NONE;
}
ErrorType Framework::Render()
{
window->clear(sf::Color::Black);
m_field.Render(*window);
m_snake.Render(*window);
if (m_gameOver)
window->draw(m_gameOverText);
window->display();
return NONE;
}

View file

@ -0,0 +1,37 @@
#pragma once
#include <SFML/Graphics.hpp>
#include "Field.h"
#include "Snake.h"
enum ErrorType {
NONE,
WARNING,
ERROR
};
class Framework
{
public:
virtual ~Framework();
static ErrorType Initialize(unsigned int width, unsigned int height, std::string title, sf::Uint8 flags = sf::Style::Default);
static ErrorType Run();
private:
static ErrorType Handle();
static ErrorType Update();
static ErrorType Render();
static sf::RenderWindow* window;
static sf::Event e;
static Field m_field;
static Snake m_snake;
static sf::Font m_font;
static sf::Text m_gameOverText;
static bool m_gameOver;
};

View file

@ -0,0 +1,66 @@
#include "Snake.h"
#include <iostream>
Snake::Snake()
{
for (int i = 0; i < 3; i++)
{
m_snake.push_back(SnakePiece(Vector2D(16, 16)));
}
m_direction = Vector2D(1, 0);
m_clock.restart();
}
Snake::~Snake()
{
}
bool Snake::Update(Field& field)
{
if (m_clock.getElapsedTime().asMilliseconds() >= 250)
{
m_snake.pop_back();
Vector2D v = m_snake.begin()->position + m_direction;
m_snake.insert(m_snake.begin(), v);
if (m_snake.begin()->position.x > 32 ||
m_snake.begin()->position.x < 0 ||
m_snake.begin()->position.y > 32 ||
m_snake.begin()->position.y < 0)
{
return false;
}
auto it = m_snake.begin();
it++;
while (it != m_snake.end())
{
if (m_snake.begin()->position == it->position)
return false;
it++;
}
if (field.IsOnFruit(m_snake.begin()->position))
{
std::cout << "Score!" << std::endl;
m_snake.insert(m_snake.end(), m_snake.back());
}
m_clock.restart();
}
return true;
}
void Snake::Render(sf::RenderWindow& window)
{
for (auto it : m_snake)
{
window.draw(it.tile);
}
}

View file

@ -0,0 +1,27 @@
#pragma once
#include <vector>
#include <SFML/Graphics.hpp>
#include "util.h"
#include "Field.h"
typedef sf::RectangleShape Tile;
class Snake
{
public:
Snake();
virtual ~Snake();
void Render(sf::RenderWindow& window);
bool Update(Field& field);
void setDirection(Vector2D dir) { m_direction = dir; }
private:
std::vector<SnakePiece> m_snake;
Vector2D m_direction;
sf::Clock m_clock;
};

View file

@ -29,7 +29,7 @@
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
@ -142,11 +142,20 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Field.cpp" />
<ClCompile Include="Framework.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Snake.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClInclude Include="Field.h" />
<ClInclude Include="Framework.h" />
<ClInclude Include="Snake.h" />
<ClInclude Include="util.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\sfml-system.redist.2.4.2.0\build\native\sfml-system.redist.targets" Condition="Exists('..\packages\sfml-system.redist.2.4.2.0\build\native\sfml-system.redist.targets')" /> <Import Project="..\packages\sfml-system.redist.2.4.2.0\build\native\sfml-system.redist.targets" Condition="Exists('..\packages\sfml-system.redist.2.4.2.0\build\native\sfml-system.redist.targets')" />

View file

@ -18,8 +18,31 @@
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Framework.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Snake.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Field.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClInclude Include="Framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Snake.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Field.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project> </Project>

Binary file not shown.

View file

@ -1,23 +1,10 @@
#include <SFML/Graphics.hpp> #include "Framework.h"
int main() int main()
{ {
sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(800, 800), "SnakePlusPlus v1.0", sf::Style::None | sf::Style::Close);
sf::Event e;
while (window->isOpen()) Framework::Initialize(WIDTH, HEIGHT, "SnakePlusPlus v1.0", sf::Style::Close);
{ Framework::Run();
while (window->pollEvent(e))
{
switch (e.type)
{
case sf::Event::Closed:
window->close();
}
}
window->clear(); return 0;
window->display();
}
} }

View file

@ -0,0 +1,78 @@
#pragma once
#include <SFML/Graphics.hpp>
#define WIDTH 825
#define HEIGHT 825
#define TILESIZE 25
#define TPR WIDTH / TILESIZE
#define TPC HEIGHT / TILESIZE
// My own Vector2 class because sf::Vector2f does not have a < operator
struct Vector2D {
Vector2D(){}
Vector2D(float x, float y) :
x(x),
y(y)
{}
float x;
float y;
friend bool operator<(const Vector2D& lhs, const Vector2D& rhs)
{
if (lhs.y < rhs.y)
return true;
else if (lhs.y > rhs.y)
return false;
else if (lhs.x < rhs.x)
return true;
else
return false;
}
friend bool operator==(const Vector2D& lhs, const Vector2D& rhs)
{
if (lhs.x == rhs.x && lhs.y == rhs.y)
return true;
return false;
}
Vector2D& operator=(const Vector2D& rhs)
{
x = rhs.x;
y = rhs.y;
return *this;
}
Vector2D& operator+=(const Vector2D& rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
friend Vector2D& operator+(const Vector2D& lhs, const Vector2D& rhs)
{
return Vector2D(lhs.x + rhs.x, lhs.y + rhs.y);
}
};
struct SnakePiece
{
SnakePiece(Vector2D position)
{
this->position = Vector2D(position.x, position.y);
tile.setSize(sf::Vector2f(TILESIZE, TILESIZE));
tile.setPosition(TILESIZE * position.x, TILESIZE * position.y); // "I will redo this properly without magic numbers"
// i did it!
tile.setFillColor(sf::Color::Black);
}
Vector2D position;
sf::RectangleShape tile;
};