Rules can be created from the UI Game can be stopped/started from the UI Current level can be reset (Load from file again) Added "Game" target and main file TODO (A lot): - Unit tests - Fully functionnal UI - Win conditions - Level background - Level switching/progression - Interesting and varied rules - Multi-scale pathfinding - etc
202 lines
5.5 KiB
C++
202 lines
5.5 KiB
C++
#include <memory>
|
|
|
|
//
|
|
// Created by trotfunky on 06/06/19.
|
|
//
|
|
|
|
#include "Game.h"
|
|
|
|
|
|
Game::Game(std::vector<std::string>& levels, std::vector<std::string>& textures) : levelFiles(std::move(levels)),
|
|
textureFiles(std::move(textures)), running(false), ruleCount(0)
|
|
{
|
|
loadTextures();
|
|
}
|
|
|
|
void Game::loadLevel(int levelID)
|
|
{
|
|
// TODO : Reset rules when reseting level
|
|
running = false;
|
|
|
|
pugi::xml_document document;
|
|
pugi::xml_parse_result result = document.load_file((pro_maat::levelFolder+levelFiles.at(levelID)).c_str());
|
|
|
|
if(!result)
|
|
{
|
|
pro_maat::errorWindow(result.description());
|
|
}
|
|
|
|
currentLevel = std::make_unique<Level>(document,textures,levelID);
|
|
}
|
|
|
|
void Game::loadTextures()
|
|
{
|
|
textures.reserve(textureFiles.size());
|
|
for(const std::string& filePath : textureFiles)
|
|
{
|
|
textures.emplace_back(std::make_unique<sf::Texture>());
|
|
textures.back()->loadFromFile(pro_maat::textureFolder+filePath);
|
|
}
|
|
}
|
|
|
|
void Game::runGame()
|
|
{
|
|
sf::RenderWindow window(sf::VideoMode(1280,1024),"Project Maat");
|
|
|
|
sf::Clock clock;
|
|
|
|
tgui::Gui gui(window);
|
|
addWidgets(gui);
|
|
|
|
while (window.isOpen())
|
|
{
|
|
sf::Event event;
|
|
while (window.pollEvent(event))
|
|
{
|
|
if (event.type == sf::Event::Closed)
|
|
{
|
|
window.close();
|
|
}
|
|
|
|
gui.handleEvent(event);
|
|
}
|
|
if (running && clock.getElapsedTime().asMilliseconds() >= 200)
|
|
{
|
|
currentLevel->runStep();
|
|
clock.restart();
|
|
}
|
|
window.clear(sf::Color::White);
|
|
// TODO : Consider drawing in a sf::RenderTexture to allow positioning the level at a fixed position ?
|
|
currentLevel->render(window);
|
|
gui.draw();
|
|
window.display();
|
|
}
|
|
}
|
|
|
|
void Game::addWidgets(tgui::Gui& gui)
|
|
{
|
|
tgui::Button::Ptr button = tgui::Button::create("Start");
|
|
button->setSize("10%","5%");
|
|
button->setPosition("89%","94%");
|
|
button->connect("pressed",&Game::setRunning,this,true,std::ref(gui));
|
|
gui.add(button,"start");
|
|
|
|
// TODO : Use clone/copy ?
|
|
button = tgui::Button::create("Stop");
|
|
button->setSize("10%","5%");
|
|
button->setPosition("79%","94%");
|
|
button->connect("pressed",&Game::setRunning,this,false,std::ref(gui));
|
|
gui.add(button,"stop");
|
|
|
|
button = tgui::Button::create("Reset");
|
|
button->setSize("10%","5%");
|
|
button->setPosition("69%","94%");
|
|
button->connect("pressed",&Game::loadLevel,this,currentLevel->getLevelID());
|
|
gui.add(button,"reset");
|
|
|
|
button = tgui::Button::create("Add a new rule");
|
|
button->setSize("10%","5%");
|
|
button->setPosition("89%","6%");
|
|
button->connect("pressed",&Game::addRule,this,std::ref(gui));
|
|
gui.add(button,"add");
|
|
}
|
|
|
|
Game::operator bool() const
|
|
{
|
|
return (currentLevel ? true : false);
|
|
}
|
|
|
|
//
|
|
// Widget callbacks
|
|
//
|
|
|
|
void Game::setRunning(bool newState, tgui::Gui& gui)
|
|
{
|
|
running = newState;
|
|
|
|
// TODO : Iterate over all rules
|
|
|
|
auto affectedTypeCombo = gui.get<tgui::ComboBox>("AffectedType0");
|
|
if(!affectedTypeCombo) return;
|
|
auto targetTypeCombo = gui.get<tgui::ComboBox>("TargetType0");
|
|
if(!targetTypeCombo) return;
|
|
auto actionCombo = gui.get<tgui::ComboBox>("Action0");
|
|
if(!actionCombo) return;
|
|
|
|
// If the rule is complete only
|
|
if(!affectedTypeCombo->getSelectedItem().isEmpty() &&
|
|
!targetTypeCombo->getSelectedItem().isEmpty() &&
|
|
!actionCombo->getSelectedItem().isEmpty())
|
|
{
|
|
currentLevel->addRule(Entity::entityTypeLookup.at(affectedTypeCombo->getSelectedItem()),
|
|
Entity::stateLookup.at(actionCombo->getSelectedItem()),
|
|
Entity::entityTypeLookup.at(targetTypeCombo->getSelectedItem()));
|
|
}
|
|
|
|
}
|
|
|
|
void Game::addRule(tgui::Gui& gui)
|
|
{
|
|
if(ruleCount >= pro_maat::maxRules) return;
|
|
|
|
// To update names with indexes
|
|
std::stringstream string;
|
|
|
|
|
|
tgui::ComboBox::Ptr combo = tgui::ComboBox::create();
|
|
combo->addItem("Citizen");
|
|
combo->addItem("Noble");
|
|
combo->setPosition("85%","5%");
|
|
|
|
// TODO : Move height according to number of rules
|
|
// Keep the proportions while moving
|
|
// sf::Vector2f tempPos = combo->getPosition();
|
|
// tempPos.y += tempPos.y*2*ruleCount;
|
|
// combo->setPosition(tempPos);
|
|
combo->setSize("5%","2%");
|
|
|
|
string << "AffectedType" << ruleCount;
|
|
gui.add(combo,string.str());
|
|
string.str("");
|
|
|
|
// TODO : Use clone/copy ?
|
|
combo = tgui::ComboBox::create();
|
|
combo->addItem("Citizen");
|
|
combo->addItem("Noble");
|
|
combo->addItem("House");
|
|
combo->setSize("5%","2%");
|
|
combo->setPosition("95%","5%");
|
|
|
|
// Keep the proportions while moving
|
|
// tempPos = combo->getPosition();
|
|
// tempPos.y += tempPos.y*2*ruleCount;
|
|
// combo->setPosition(tempPos);
|
|
|
|
string << "TargetType" << ruleCount;
|
|
gui.add(combo,string.str());
|
|
string.str("");
|
|
|
|
combo = tgui::ComboBox::create();
|
|
combo->addItem("Seek");
|
|
combo->addItem("Flee");
|
|
combo->setSize("4%","2%");
|
|
combo->setPosition("90.5%","5%");
|
|
|
|
// Keep the proportions while moving
|
|
// tempPos = combo->getPosition();
|
|
// tempPos.y += tempPos.y*2*ruleCount;
|
|
// combo->setPosition(tempPos);
|
|
|
|
string << "Action" << ruleCount;
|
|
gui.add(combo,string.str());
|
|
string.str("");
|
|
|
|
// TODO : Move the button down with each rule then hide it
|
|
// TODO : Hide button when max rules hit
|
|
// FIXME : Cannot hide ?
|
|
gui.get<tgui::Button>("add")->setSize("0%","0%");
|
|
gui.get<tgui::Button>("add")->setTextSize(0);
|
|
gui.get<tgui::Button>("add")->setPosition("-10%","-10%");
|
|
|
|
ruleCount++;
|
|
}
|