diff --git a/ConwaysGameOfLife/ConwaysGameOfLife.cpp b/ConwaysGameOfLife/ConwaysGameOfLife.cpp index e989e1e..ad2775a 100644 Binary files a/ConwaysGameOfLife/ConwaysGameOfLife.cpp and b/ConwaysGameOfLife/ConwaysGameOfLife.cpp differ diff --git a/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj b/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj index 3a5e0c2..ea92e88 100644 --- a/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj +++ b/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj @@ -127,10 +127,11 @@ true - Console + Windows true true true + sfml-graphics.lib;sfml-window.lib;sfml-system.lib;%(AdditionalDependencies) @@ -153,13 +154,16 @@ + + + Create Create @@ -167,6 +171,7 @@ Create + diff --git a/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj.filters b/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj.filters index 7cbbfed..c15fbc1 100644 --- a/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj.filters +++ b/ConwaysGameOfLife/ConwaysGameOfLife.vcxproj.filters @@ -27,6 +27,12 @@ Headerdateien + + Headerdateien + + + Headerdateien + @@ -41,5 +47,11 @@ Quelldateien + + Quelldateien + + + Quelldateien + \ No newline at end of file diff --git a/ConwaysGameOfLife/Framework.cpp b/ConwaysGameOfLife/Framework.cpp index 13278f7..77acdee 100644 --- a/ConwaysGameOfLife/Framework.cpp +++ b/ConwaysGameOfLife/Framework.cpp @@ -4,7 +4,8 @@ // Initilaize static variables sf::RenderWindow* Framework::m_window = nullptr; sf::Event Framework::m_event = sf::Event(); -TestRender Framework::m_test = TestRender(); +//TestRender Framework::m_test = TestRender(); +Map Framework::m_map = Map(50, 50, 10); bool Framework::init(unsigned width, unsigned height, const char* title, sf::Uint8 flags) { @@ -75,19 +76,45 @@ bool Framework::run() // Updates screen elements bool Framework::update() { - if (!m_test.update()) return false; +// if (!m_test.update()) return false; + m_map.update(); return true; } // Handles window events bool Framework::handleEvents() { + static float mouseDelta = 0; while (m_window->pollEvent(m_event)) { // On Close Event if (m_event.type == sf::Event::Closed) m_window->close(); + + if (m_event.type == sf::Event::KeyPressed) + { + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Return)) + m_map.changeSimulationState(); + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Add)) + m_map.increaseSpeed(); + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Subtract)) + m_map.decreaseSpeed(); + } } + if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) + { + m_map.mousePos(sf::Mouse::getPosition(*m_window).x, sf::Mouse::getPosition(*m_window).y, true); + } + + if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Right)) + { + m_map.mousePos(sf::Mouse::getPosition(*m_window).x, sf::Mouse::getPosition(*m_window).y, false); + } + + + return true; } @@ -96,7 +123,8 @@ bool Framework::render() { m_window->clear(); - if (!m_test.render(*m_window)) return false; +// if (!m_test.render(*m_window)) return false; + if (!m_map.render(*m_window)) return false; m_window->display(); diff --git a/ConwaysGameOfLife/Framework.h b/ConwaysGameOfLife/Framework.h index 069c17a..5f30106 100644 --- a/ConwaysGameOfLife/Framework.h +++ b/ConwaysGameOfLife/Framework.h @@ -35,7 +35,8 @@ public: private: static sf::RenderWindow* m_window; // A reference to a window object static sf::Event m_event; // The event handling variable of SFML - static TestRender m_test; +// static TestRender m_test; + static Map m_map; // The grid /** Updates the elements on screen diff --git a/ConwaysGameOfLife/Map.cpp b/ConwaysGameOfLife/Map.cpp new file mode 100644 index 0000000..fd99133 --- /dev/null +++ b/ConwaysGameOfLife/Map.cpp @@ -0,0 +1,141 @@ +#include "stdafx.h" +#include "Map.h" + + +Map::Map(unsigned sizeX, unsigned sizeY, unsigned tileSize) +{ + m_zoom = 1.0f; + m_sizeX = sizeX; + m_sizeY = sizeY; + m_simState = false; + steps = 0; + stepDenominator = 100; + + createGrid(sizeX, sizeY); +} + + +Map::~Map() +{ +} + +bool Map::render(sf::RenderWindow& window) +{ + for (auto it : m_grid) + { + it.second->render(window); + } + + return true; +} + +// Create grid +void Map::createGrid(unsigned sizeX, unsigned sizeY) +{ + std::cout << "Creating Grid. Be patient...." << std::endl; + for (int y = 0; y < sizeY; y++) + { + for (int x = 0; x < sizeX; x++) + { + // TODO: Remove Magic Numbers + Tile* t = new Tile(sf::Vector2f((800 /sizeX) * x, (800 / sizeY) * y), sf::Vector2f(800 / sizeX, 800 / sizeY)); + std::pair p(Position(x, y), t); + m_grid.emplace(p); + } + } +} + +// Mouse pos +void Map::mousePos(unsigned x, unsigned y, bool left) +{ + unsigned tileX = floor(x / (800 / m_sizeX)); + unsigned tileY = floor(y / (800 / m_sizeY)); + if (tileX > m_sizeX) tileX = m_sizeX; + if (tileY > m_sizeX) tileY = m_sizeY; + if (tileX < 0) tileX = 0; + if (tileY < 0) tileY = 0; + + if (left) m_grid.find(Position(tileX, tileY))->second->forceStateChange(true); + else m_grid.find(Position(tileX, tileY))->second->forceStateChange(false); +} + +// Simulates +bool Map::update() +{ + if (m_simState && steps % stepDenominator == 0) + { + //std::cout << "Start simulation" << std::endl; + for (auto it : m_grid) + { + // TODO HARDCODED UUGHHHH KILL ME + int neighbours = 0; + if (m_grid.find(Position(it.first.x - 1, it.first.y - 1)) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x - 1, it.first.y - 1))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x , it.first.y - 1)) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x , it.first.y - 1))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x + 1, it.first.y - 1)) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x + 1, it.first.y - 1))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x - 1, it.first.y )) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x - 1, it.first.y ))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x + 1, it.first.y )) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x + 1, it.first.y ))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x - 1, it.first.y + 1)) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x - 1, it.first.y + 1))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x , it.first.y + 1)) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x , it.first.y + 1))->second->getTileState()) neighbours++; + } + + if (m_grid.find(Position(it.first.x + 1, it.first.y + 1)) != m_grid.end()) + { + if (m_grid.find(Position(it.first.x + 1, it.first.y + 1))->second->getTileState()) neighbours++; + } + + //if (it.first.x == 1 && it.first.y == 1) std::cout << neighbours << std::endl; + + if (neighbours < 2) + { + //if (it.first.x == 1 && it.first.y == 1) std::cout << "dying..." << std::endl; + it.second->changeStateTo(false); + } + if (neighbours == 2) it.second->changeStateTo(it.second->getTileState()); + if (neighbours == 3) + { + //if (it.first.x == 1 && it.first.y == 1) std::cout << "reviving..." << std::endl; + it.second->changeStateTo(true); + } + if (neighbours > 3) it.second->changeStateTo(false); + + //if (it.first.x == 1 && it.first.y == 1) std::cout << it.second->getWillChangeState() << std::endl; + } + + for (auto it : m_grid) + { + it.second->applyStateChange(); + //if (it.first.x == 1 && it.first.y == 1) std::cout << it.second->getTileState() << std::endl; + } + //std::cout << "End simulation" << std::endl; + //std::cout << std::endl; + } + steps++; + + return true; +} \ No newline at end of file diff --git a/ConwaysGameOfLife/Map.h b/ConwaysGameOfLife/Map.h new file mode 100644 index 0000000..efdbf70 --- /dev/null +++ b/ConwaysGameOfLife/Map.h @@ -0,0 +1,91 @@ +/** + * Map.h + * Contains the Grid of CGOL and handles the generations + * + * @author Robert Altner + * @version 1.0 +*/ + + +#pragma once + +#include "stdafx.h" +#include "Tile.h" + +struct Position +{ + int x, y; + + Position(int x, int y) + { + this->x = x; + this->y = y; + } + +}; + +inline bool operator <(Position left, Position right) +{ + if (left.y < right.y) return true; + else if (left.y > right.y) return false; + else if (left.y == right.y) + { + if (left.x < right.x) return true; + else return false; + } + else return false; +} + +class Map +{ +public: + Map(unsigned sizeX, unsigned sizeY, unsigned tileSize); + ~Map(); + + /** + Renders Grid and Tiles to the window + + @param window A reference to the window + @return False if an error occured + */ + bool render(sf::RenderWindow& window); + + /** + Simulates + */ + bool update(); + + /** + Gets called when a mouse click was received + + @param x xPos of the Cursor + @param y yPos of the Cursor + */ + void mousePos(unsigned x, unsigned y, bool left); + + void increaseSpeed() { stepDenominator--; if (stepDenominator <= 0) stepDenominator = 1; } + void decreaseSpeed() { stepDenominator++; } + /** + Changes if we should simulate + */ + void changeSimulationState() { m_simState = !m_simState; } + +private: + float m_zoom; + unsigned int m_tileSize; + unsigned m_sizeX, m_sizeY; + bool m_simState; + unsigned steps; + unsigned stepDenominator; + + std::map m_grid; + + /** + Create Grid + + @param sizeX x size of the grid + @param suzeY y size of the grid + */ + void createGrid(unsigned sizeX, unsigned sizeY); +}; + diff --git a/ConwaysGameOfLife/Tile.cpp b/ConwaysGameOfLife/Tile.cpp new file mode 100644 index 0000000..b330f5d --- /dev/null +++ b/ConwaysGameOfLife/Tile.cpp @@ -0,0 +1,35 @@ +#include "stdafx.h" +#include "Tile.h" + + +Tile::Tile(sf::Vector2f position, sf::Vector2f size) +{ + willChangeTo = false; + state = false; + + m_tile.setPosition(position); + m_tile.setSize(size); + m_tile.setFillColor(sf::Color::Black); +} + + +Tile::~Tile() +{ +} + +// Renders Tile +bool Tile::render(sf::RenderWindow& window) +{ + window.draw(m_tile); + return true; +} + +// Change state of cell +void Tile::applyStateChange() +{ + //if(!state) std::cout << state << ", " << willChangeTo << std::endl; + state = willChangeTo; + + if (state == true) m_tile.setFillColor(sf::Color::White); + if (state == false) m_tile.setFillColor(sf::Color::Black); +} \ No newline at end of file diff --git a/ConwaysGameOfLife/Tile.h b/ConwaysGameOfLife/Tile.h new file mode 100644 index 0000000..2268245 --- /dev/null +++ b/ConwaysGameOfLife/Tile.h @@ -0,0 +1,74 @@ +/** + * Tile.h + * Basically a wrapper class for sf::Rextangle but with + * extra features + * + * @author Robert Altner + * @version 1.0 +*/ + +#pragma once + +#include "stdafx.h" + +class Tile +{ +public: + Tile(sf::Vector2f position, sf::Vector2f size); + ~Tile(); + + /** + Returns state of a tile + + @return True if alive, False if dead + */ + bool getTileState() { return state; } + bool getWillChangeState() { return willChangeTo; } + + /** + Sets new size of Tile + + @param size new size + */ + void resize(sf::Vector2f size) { m_tile.setSize(size); } + + /** + Sets new position of Tile + + @param position new position + */ + void reposition(sf::Vector2f position) { m_tile.setPosition(position); } + + /** + Sets a tile either as alive or dead + */ + void applyStateChange(); + + /** + Makes a tile either alive or dead + + @param state New State + */ + void forceStateChange(bool state) { willChangeTo = state; applyStateChange(); } + + /** + Sets willChangeTo + + @param should Should the cell die? + */ + void changeStateTo(bool should) { willChangeTo = should; } + + /** + Renders the Tile + + @param window Reference to window + @return False if an error occured + */ + bool render(sf::RenderWindow& window); + +private: + sf::RectangleShape m_tile; + bool state; //True = alive, False = dead + bool willChangeTo; +}; + diff --git a/ConwaysGameOfLife/stdafx.h b/ConwaysGameOfLife/stdafx.h index c62d895..a7f3a8e 100644 Binary files a/ConwaysGameOfLife/stdafx.h and b/ConwaysGameOfLife/stdafx.h differ