Add states and a setup state to Control
This commit is contained in:
parent
121ae73517
commit
5369805616
7 changed files with 400 additions and 13 deletions
2
Makefile
2
Makefile
|
|
@ -9,7 +9,7 @@ SOURCEFILES = cpp
|
|||
SRCDIR = src
|
||||
TMPDIR = build
|
||||
TARGET = gross
|
||||
FILES = Genes Chromosome Fitness Generation Control main
|
||||
FILES = Genes Chromosome Fitness Generation Screens Control main
|
||||
|
||||
#SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES))
|
||||
OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(FILES))
|
||||
|
|
|
|||
|
|
@ -16,12 +16,23 @@ void Chromosome::allowGeneType(Gene::GeneType gt, bool allowed)
|
|||
}
|
||||
|
||||
|
||||
void Chromosome::toggleGeneType(Gene::GeneType gt)
|
||||
{
|
||||
Chromosome::allowGeneType(gt, !Chromosome::isGeneTypeAllowed(gt));
|
||||
}
|
||||
|
||||
bool Chromosome::isGeneTypeAllowed(Gene::GeneType gt)
|
||||
{
|
||||
return Chromosome::allowedGeneTypes.find(gt) != Chromosome::allowedGeneTypes.end();
|
||||
}
|
||||
|
||||
|
||||
bool Chromosome::isAnyGeneTypeAllowed()
|
||||
{
|
||||
return !Chromosome::allowedGeneTypes.empty();
|
||||
}
|
||||
|
||||
|
||||
Chromosome::Chromosome()
|
||||
{
|
||||
// empty so you can choose between crossover and creating a new chromosome
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ public:
|
|||
static std::minstd_rand* re;
|
||||
|
||||
static void allowGeneType(Gene::GeneType gt, bool allowed=true);
|
||||
static void toggleGeneType(Gene::GeneType gt);
|
||||
static bool isGeneTypeAllowed(Gene::GeneType gt);
|
||||
static bool isAnyGeneTypeAllowed();
|
||||
|
||||
Chromosome(); // create empty chromosome
|
||||
Chromosome(const Chromosome& father, const Chromosome& mother); // crossover
|
||||
|
|
|
|||
124
src/Control.cpp
124
src/Control.cpp
|
|
@ -2,18 +2,40 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
* Setup:
|
||||
* - current item
|
||||
* - circles
|
||||
* - triangles
|
||||
* - spheres
|
||||
* - max number limited?
|
||||
*
|
||||
* Generations:
|
||||
* - paused
|
||||
* - save image
|
||||
* - display mode
|
||||
* - saving?
|
||||
*
|
||||
* StepThrough:
|
||||
* - which step am I at? -> enums
|
||||
*/
|
||||
|
||||
Fitness* Control::fitness;
|
||||
Generation* Control::generation;
|
||||
|
||||
float Control::barMargin = 4;
|
||||
|
||||
|
||||
Control::Control(float winW, float winH, std::string name)
|
||||
Control::Control(float winW, float winH, std::string name) :
|
||||
screenSetup(this)
|
||||
{
|
||||
this->window.create(sf::VideoMode(winW, winH), name);
|
||||
|
||||
this->targetSprite.setTexture(Control::fitness->target.getTexture());
|
||||
this->chromosomeSprite.setTexture(Control::fitness->chromosome.getTexture());
|
||||
// this->targetSprite.setTexture(Control::fitness->target.getTexture());
|
||||
// this->chromosomeSprite.setTexture(Control::fitness->chromosome.getTexture());
|
||||
|
||||
// this->currentScreen = &this->screenSetup;
|
||||
// this->nextScreen = this->currentScreen;
|
||||
|
||||
this->leftText.setCharacterSize(20);
|
||||
this->leftText.setFillColor(sf::Color::Black);
|
||||
|
|
@ -34,17 +56,52 @@ Control::~Control()
|
|||
|
||||
void Control::interactive()
|
||||
{
|
||||
this->currentScreen = nullptr;
|
||||
this->switchScreen(this->screenSetup);
|
||||
|
||||
std::cout << "Starting interactive loop" << std::endl;
|
||||
sf::Clock clock;
|
||||
while (this->window.isOpen()) {
|
||||
sf::Event event;
|
||||
while (this->window.pollEvent(event)) {
|
||||
if (this->currentScreen != this->nextScreen) {
|
||||
if (this->currentScreen != nullptr) this->currentScreen->exit();
|
||||
if (this->nextScreen == nullptr) {
|
||||
std::cout << "Switched to null screen; window closed" << std::endl;
|
||||
window.close();
|
||||
continue;
|
||||
}
|
||||
this->currentScreen = this->nextScreen;
|
||||
this->currentScreen->enter();
|
||||
}
|
||||
|
||||
this->window.clear();
|
||||
this->window.draw(this->bar);
|
||||
this->window.draw(this->rightText);
|
||||
this->window.draw(this->leftText);
|
||||
// handle window events
|
||||
sf::Event event;
|
||||
while (this->window.pollEvent(event)) {
|
||||
this->currentScreen->event(event);
|
||||
}
|
||||
|
||||
// update screen
|
||||
this->currentScreen->update(clock.restart());
|
||||
|
||||
// draw screen
|
||||
this->window.clear(sf::Color::White);
|
||||
this->window.draw(*this->currentScreen);
|
||||
this->window.display();
|
||||
}
|
||||
|
||||
std::cout << "Interactive loop stopped; window closed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void Control::switchScreen(Screen& newScreen)
|
||||
{
|
||||
std::cout << "Switched screens" << std::endl;
|
||||
this->nextScreen = &newScreen;
|
||||
}
|
||||
|
||||
|
||||
void Control::close()
|
||||
{
|
||||
this->nextScreen = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -53,6 +110,8 @@ void Control::setFont(const sf::Font& font)
|
|||
this->leftText.setFont(font);
|
||||
this->rightText.setFont(font);
|
||||
|
||||
this->screenSetup.setFont(font);
|
||||
|
||||
this->updateBar();
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +132,15 @@ void Control::setRightText(const std::string& text)
|
|||
}
|
||||
|
||||
|
||||
void Control::setText(const std::string& left, const std::string& right)
|
||||
{
|
||||
this->leftText.setString(left);
|
||||
this->rightText.setString(right);
|
||||
|
||||
this->updateBar();
|
||||
}
|
||||
|
||||
|
||||
void Control::updateBar()
|
||||
{
|
||||
// update bar size and position
|
||||
|
|
@ -122,3 +190,41 @@ void Control::updateBar()
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Control::drawBar(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
target.draw(this->bar, states);
|
||||
target.draw(this->rightText, states);
|
||||
target.draw(this->leftText, states);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void Control::modeGenerations()
|
||||
{
|
||||
// handle window events
|
||||
sf::Event event;
|
||||
while (this->window.pollEvent(event)) {
|
||||
// window closed
|
||||
if (event.type == sf::Event::Closed) {
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// key pressed
|
||||
if (event.type == sf::Event::KeyPressed) {
|
||||
if (event.key.code == sf::Keyboard::Q) {
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->window.clear();
|
||||
this->window.draw(this->bar);
|
||||
this->window.draw(this->rightText);
|
||||
this->window.draw(this->leftText);
|
||||
this->window.display();
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "Chromosome.hpp"
|
||||
#include "Fitness.hpp"
|
||||
#include "Generation.hpp"
|
||||
#include "Screens.hpp"
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -33,20 +34,29 @@ public:
|
|||
|
||||
static float barMargin;
|
||||
|
||||
sf::RenderWindow window;
|
||||
|
||||
ScreenSetup screenSetup;
|
||||
|
||||
Control(float winW, float winH, std::string name); // creates a window
|
||||
~Control();
|
||||
|
||||
void interactive();
|
||||
|
||||
void switchScreen(Screen& newScreen);
|
||||
void close();
|
||||
|
||||
void setFont(const sf::Font& font);
|
||||
void setLeftText(const std::string& text);
|
||||
void setRightText(const std::string& text);
|
||||
void setText(const std::string& leftText, const std::string& rightText="");
|
||||
|
||||
void drawBar(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
|
||||
private:
|
||||
sf::RenderWindow window;
|
||||
|
||||
sf::Sprite targetSprite;
|
||||
sf::Sprite chromosomeSprite;
|
||||
Screen* currentScreen;
|
||||
Screen* nextScreen;
|
||||
|
||||
sf::RectangleShape bar;
|
||||
sf::Text leftText;
|
||||
|
|
|
|||
188
src/Screens.cpp
Normal file
188
src/Screens.cpp
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
#include "Screens.hpp"
|
||||
|
||||
#include "Control.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// Screen base class
|
||||
Screen::Screen(Control* controlptr)
|
||||
{
|
||||
this->control = controlptr;
|
||||
}
|
||||
|
||||
|
||||
Screen::~Screen()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ScreenSetup setup screen
|
||||
// const sf::Vector2f ScreenSetup::offset(20, 20);
|
||||
// const float ScreenSetup::distance = 50;
|
||||
// const int ScreenSetup::items = 3;
|
||||
|
||||
|
||||
ScreenSetup::ScreenSetup(Control* controlptr) :
|
||||
Screen(controlptr),
|
||||
offset(20, 20),
|
||||
distance(30),
|
||||
items(4)
|
||||
{
|
||||
this->selection = 0;
|
||||
|
||||
this->text.setCharacterSize(20);
|
||||
this->text.setFillColor(sf::Color::Black);
|
||||
|
||||
this->rect.setFillColor(sf::Color::Yellow);
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::enter()
|
||||
{
|
||||
std::cout << "ENTERED!" << std::endl;
|
||||
this->rect.setSize(
|
||||
sf::Vector2f(
|
||||
this->control->window.getSize().x,
|
||||
30
|
||||
)
|
||||
);
|
||||
|
||||
this->selectItem(0);
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::event(sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed) {
|
||||
this->keyPressed(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::update(sf::Time dt)
|
||||
{
|
||||
if (this->warnTimer > sf::Time::Zero) {
|
||||
this->warnTimer -= dt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
this->drawMenu(target, states);
|
||||
|
||||
if (this->warnTimer > sf::Time::Zero) {
|
||||
this->control->drawBar(target, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::exit()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::setFont(const sf::Font& font)
|
||||
{
|
||||
this->text.setFont(font);
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::keyPressed(sf::Event& event)
|
||||
{
|
||||
switch (event.key.code) {
|
||||
// close window, stop program
|
||||
case sf::Keyboard::Q:
|
||||
this->control->close();
|
||||
return;
|
||||
|
||||
// move selection up in menu
|
||||
case sf::Keyboard::Up:
|
||||
if (event.key.shift) this->selectItem(0);
|
||||
else this->selectItem(this->selection - 1);
|
||||
break;
|
||||
|
||||
// move selection down in menu
|
||||
case sf::Keyboard::Down:
|
||||
if (event.key.shift) this->selectItem(this->items - 1);
|
||||
else this->selectItem(this->selection + 1);
|
||||
break;
|
||||
|
||||
// select current item and perform action
|
||||
case sf::Keyboard::Return:
|
||||
this->executeItem(this->selection);
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::selectItem(int position)
|
||||
{
|
||||
// kinda ugly, just to get the same % behaviour as in python
|
||||
this->selection = ((position%this->items) + this->items)%this->items;
|
||||
this->rect.setPosition(
|
||||
sf::Vector2f(
|
||||
0,
|
||||
this->offset.y + this->distance*this->selection
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::executeItem(int position)
|
||||
{
|
||||
switch (position) {
|
||||
case 0: Chromosome::toggleGeneType(Gene::Circle); break;
|
||||
case 1: Chromosome::toggleGeneType(Gene::Triangle); break;
|
||||
case 2: break; // spacing placeholder
|
||||
case 3:
|
||||
if (Chromosome::isAnyGeneTypeAllowed()) {
|
||||
// this->control->switchScreen(Control::screenGenerations);
|
||||
} else {
|
||||
this->control->setText("Allow at least one gene type to continue.");
|
||||
this->warnTimer = sf::seconds(3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::drawMenu(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
target.draw(this->rect);
|
||||
|
||||
sf::Vector2f position = this->offset;
|
||||
|
||||
this->drawMenuItem(
|
||||
target, states, position, "Circle genes: ",
|
||||
Chromosome::isGeneTypeAllowed(Gene::Circle)?"x":" "
|
||||
);
|
||||
position.y += this->distance;
|
||||
|
||||
this->drawMenuItem(
|
||||
target, states, position, "Triangle genes:",
|
||||
Chromosome::isGeneTypeAllowed(Gene::Triangle)?"x":" "
|
||||
);
|
||||
position.y += 2*this->distance;
|
||||
|
||||
this->drawMenuItem(
|
||||
target, states, position, "Continue"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void ScreenSetup::drawMenuItem(sf::RenderTarget& target, sf::RenderStates states,
|
||||
sf::Vector2f position, std::string name, std::string choice) const
|
||||
{
|
||||
if (choice != "") {
|
||||
name += " [";
|
||||
name += choice;
|
||||
name += "]";
|
||||
}
|
||||
|
||||
this->text.setString(name);
|
||||
this->text.setPosition(position);
|
||||
target.draw(text, states);
|
||||
}
|
||||
70
src/Screens.hpp
Normal file
70
src/Screens.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/System.hpp>
|
||||
|
||||
class Control;
|
||||
|
||||
|
||||
|
||||
class Screen : public sf::Drawable
|
||||
{
|
||||
public:
|
||||
Screen(Control* controlptr);
|
||||
virtual ~Screen();
|
||||
|
||||
virtual void enter() =0;
|
||||
virtual void event(sf::Event& event) =0;
|
||||
virtual void update(sf::Time dt) =0;
|
||||
// virtual void draw() const =0;
|
||||
virtual void exit() =0;
|
||||
|
||||
protected:
|
||||
Control* control;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ScreenSetup : public Screen
|
||||
{
|
||||
public:
|
||||
ScreenSetup(Control* controlptr);
|
||||
|
||||
virtual void enter();
|
||||
virtual void event(sf::Event& event);
|
||||
virtual void update(sf::Time dt);
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
virtual void exit();
|
||||
|
||||
void setFont(const sf::Font& font);
|
||||
|
||||
private:
|
||||
sf::Vector2f offset;
|
||||
float distance;
|
||||
int items;
|
||||
|
||||
int selection;
|
||||
mutable sf::Text text;
|
||||
sf::RectangleShape rect;
|
||||
|
||||
sf::Time warnTimer;
|
||||
|
||||
void keyPressed(sf::Event& event);
|
||||
void selectItem(int position);
|
||||
void executeItem(int position);
|
||||
void drawMenu(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
void drawMenuItem(sf::RenderTarget& target, sf::RenderStates states, sf::Vector2f position,
|
||||
std::string name, std::string choice="") const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ScreenGenerations : public Screen
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ScreenStepThrough : public Screen
|
||||
{
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue