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
|
SRCDIR = src
|
||||||
TMPDIR = build
|
TMPDIR = build
|
||||||
TARGET = gross
|
TARGET = gross
|
||||||
FILES = Genes Chromosome Fitness Generation Control main
|
FILES = Genes Chromosome Fitness Generation Screens Control main
|
||||||
|
|
||||||
#SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES))
|
#SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES))
|
||||||
OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(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)
|
bool Chromosome::isGeneTypeAllowed(Gene::GeneType gt)
|
||||||
{
|
{
|
||||||
return Chromosome::allowedGeneTypes.find(gt) != Chromosome::allowedGeneTypes.end();
|
return Chromosome::allowedGeneTypes.find(gt) != Chromosome::allowedGeneTypes.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Chromosome::isAnyGeneTypeAllowed()
|
||||||
|
{
|
||||||
|
return !Chromosome::allowedGeneTypes.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Chromosome::Chromosome()
|
Chromosome::Chromosome()
|
||||||
{
|
{
|
||||||
// empty so you can choose between crossover and creating a new chromosome
|
// empty so you can choose between crossover and creating a new chromosome
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ public:
|
||||||
static std::minstd_rand* re;
|
static std::minstd_rand* re;
|
||||||
|
|
||||||
static void allowGeneType(Gene::GeneType gt, bool allowed=true);
|
static void allowGeneType(Gene::GeneType gt, bool allowed=true);
|
||||||
|
static void toggleGeneType(Gene::GeneType gt);
|
||||||
static bool isGeneTypeAllowed(Gene::GeneType gt);
|
static bool isGeneTypeAllowed(Gene::GeneType gt);
|
||||||
|
static bool isAnyGeneTypeAllowed();
|
||||||
|
|
||||||
Chromosome(); // create empty chromosome
|
Chromosome(); // create empty chromosome
|
||||||
Chromosome(const Chromosome& father, const Chromosome& mother); // crossover
|
Chromosome(const Chromosome& father, const Chromosome& mother); // crossover
|
||||||
|
|
|
||||||
124
src/Control.cpp
124
src/Control.cpp
|
|
@ -2,18 +2,40 @@
|
||||||
|
|
||||||
#include <iostream>
|
#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;
|
Fitness* Control::fitness;
|
||||||
Generation* Control::generation;
|
Generation* Control::generation;
|
||||||
|
|
||||||
float Control::barMargin = 4;
|
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->window.create(sf::VideoMode(winW, winH), name);
|
||||||
|
|
||||||
this->targetSprite.setTexture(Control::fitness->target.getTexture());
|
// this->targetSprite.setTexture(Control::fitness->target.getTexture());
|
||||||
this->chromosomeSprite.setTexture(Control::fitness->chromosome.getTexture());
|
// this->chromosomeSprite.setTexture(Control::fitness->chromosome.getTexture());
|
||||||
|
|
||||||
|
// this->currentScreen = &this->screenSetup;
|
||||||
|
// this->nextScreen = this->currentScreen;
|
||||||
|
|
||||||
this->leftText.setCharacterSize(20);
|
this->leftText.setCharacterSize(20);
|
||||||
this->leftText.setFillColor(sf::Color::Black);
|
this->leftText.setFillColor(sf::Color::Black);
|
||||||
|
|
@ -34,17 +56,52 @@ Control::~Control()
|
||||||
|
|
||||||
void Control::interactive()
|
void Control::interactive()
|
||||||
{
|
{
|
||||||
|
this->currentScreen = nullptr;
|
||||||
|
this->switchScreen(this->screenSetup);
|
||||||
|
|
||||||
|
std::cout << "Starting interactive loop" << std::endl;
|
||||||
|
sf::Clock clock;
|
||||||
while (this->window.isOpen()) {
|
while (this->window.isOpen()) {
|
||||||
sf::Event event;
|
if (this->currentScreen != this->nextScreen) {
|
||||||
while (this->window.pollEvent(event)) {
|
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();
|
// handle window events
|
||||||
this->window.draw(this->bar);
|
sf::Event event;
|
||||||
this->window.draw(this->rightText);
|
while (this->window.pollEvent(event)) {
|
||||||
this->window.draw(this->leftText);
|
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();
|
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->leftText.setFont(font);
|
||||||
this->rightText.setFont(font);
|
this->rightText.setFont(font);
|
||||||
|
|
||||||
|
this->screenSetup.setFont(font);
|
||||||
|
|
||||||
this->updateBar();
|
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()
|
void Control::updateBar()
|
||||||
{
|
{
|
||||||
// update bar size and position
|
// 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 "Chromosome.hpp"
|
||||||
#include "Fitness.hpp"
|
#include "Fitness.hpp"
|
||||||
#include "Generation.hpp"
|
#include "Generation.hpp"
|
||||||
|
#include "Screens.hpp"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -33,20 +34,29 @@ public:
|
||||||
|
|
||||||
static float barMargin;
|
static float barMargin;
|
||||||
|
|
||||||
|
sf::RenderWindow window;
|
||||||
|
|
||||||
|
ScreenSetup screenSetup;
|
||||||
|
|
||||||
Control(float winW, float winH, std::string name); // creates a window
|
Control(float winW, float winH, std::string name); // creates a window
|
||||||
~Control();
|
~Control();
|
||||||
|
|
||||||
void interactive();
|
void interactive();
|
||||||
|
|
||||||
|
void switchScreen(Screen& newScreen);
|
||||||
|
void close();
|
||||||
|
|
||||||
void setFont(const sf::Font& font);
|
void setFont(const sf::Font& font);
|
||||||
void setLeftText(const std::string& text);
|
void setLeftText(const std::string& text);
|
||||||
void setRightText(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:
|
private:
|
||||||
sf::RenderWindow window;
|
|
||||||
|
|
||||||
sf::Sprite targetSprite;
|
Screen* currentScreen;
|
||||||
sf::Sprite chromosomeSprite;
|
Screen* nextScreen;
|
||||||
|
|
||||||
sf::RectangleShape bar;
|
sf::RectangleShape bar;
|
||||||
sf::Text leftText;
|
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