Add states and a setup state to Control

This commit is contained in:
Joscha 2017-06-22 17:43:22 +00:00
parent 121ae73517
commit 5369805616
7 changed files with 400 additions and 13 deletions

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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();
}
*/

View file

@ -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
View 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
View 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
{
};