Add generation screen

Finished the UI for the presentation. Probably last commit to this
project, unless I decide to add rectangle squares.
This commit is contained in:
Joscha 2017-06-26 19:06:59 +00:00
parent 5369805616
commit 62e6848dee
7 changed files with 255 additions and 62 deletions

View file

@ -27,7 +27,8 @@ float Control::barMargin = 4;
Control::Control(float winW, float winH, std::string name) : Control::Control(float winW, float winH, std::string name) :
screenSetup(this) screenSetup(this),
screenGenerations(this)
{ {
this->window.create(sf::VideoMode(winW, winH), name); this->window.create(sf::VideoMode(winW, winH), name);
@ -54,6 +55,14 @@ Control::~Control()
} }
sf::Vector2f Control::getSizeWithBar()
{
sf::Vector2f size = sf::Vector2f(this->window.getSize());
size -= sf::Vector2f(0, this->leftText.getCharacterSize() + 2*Control::barMargin);
return size;
}
void Control::interactive() void Control::interactive()
{ {
this->currentScreen = nullptr; this->currentScreen = nullptr;

View file

@ -35,8 +35,10 @@ public:
static float barMargin; static float barMargin;
sf::RenderWindow window; sf::RenderWindow window;
sf::Vector2f getSizeWithBar();
ScreenSetup screenSetup; ScreenSetup screenSetup;
ScreenGenerations screenGenerations;
Control(float winW, float winH, std::string name); // creates a window Control(float winW, float winH, std::string name); // creates a window
~Control(); ~Control();

View file

@ -106,6 +106,12 @@ bool Fitness::loadTarget(std::string filename)
} }
bool Fitness::saveChromosome(std::string filename)
{
return this->chromosome.getTexture().copyToImage().saveToFile(filename);
}
void Fitness::render(const Chromosome& chr) void Fitness::render(const Chromosome& chr)
{ {
this->chromosome.clear(Fitness::backgroundColor); this->chromosome.clear(Fitness::backgroundColor);

View file

@ -13,6 +13,7 @@ public:
Fitness(); Fitness();
bool loadShader(std::string filename); bool loadShader(std::string filename);
bool loadTarget(std::string filename); bool loadTarget(std::string filename);
bool saveChromosome(std::string filename);
void render(const Chromosome& chr); void render(const Chromosome& chr);
unsigned long long compute(); unsigned long long compute();

View file

@ -17,11 +17,7 @@ Screen::~Screen()
// ScreenSetup setup screen // ScreenSetup screen
// const sf::Vector2f ScreenSetup::offset(20, 20);
// const float ScreenSetup::distance = 50;
// const int ScreenSetup::items = 3;
ScreenSetup::ScreenSetup(Control* controlptr) : ScreenSetup::ScreenSetup(Control* controlptr) :
Screen(controlptr), Screen(controlptr),
@ -40,7 +36,6 @@ ScreenSetup::ScreenSetup(Control* controlptr) :
void ScreenSetup::enter() void ScreenSetup::enter()
{ {
std::cout << "ENTERED!" << std::endl;
this->rect.setSize( this->rect.setSize(
sf::Vector2f( sf::Vector2f(
this->control->window.getSize().x, this->control->window.getSize().x,
@ -139,7 +134,7 @@ void ScreenSetup::executeItem(int position)
case 2: break; // spacing placeholder case 2: break; // spacing placeholder
case 3: case 3:
if (Chromosome::isAnyGeneTypeAllowed()) { if (Chromosome::isAnyGeneTypeAllowed()) {
// this->control->switchScreen(Control::screenGenerations); this->control->switchScreen(this->control->screenGenerations);
} else { } else {
this->control->setText("Allow at least one gene type to continue."); this->control->setText("Allow at least one gene type to continue.");
this->warnTimer = sf::seconds(3); this->warnTimer = sf::seconds(3);
@ -186,3 +181,197 @@ void ScreenSetup::drawMenuItem(sf::RenderTarget& target, sf::RenderStates states
this->text.setPosition(position); this->text.setPosition(position);
target.draw(text, states); target.draw(text, states);
} }
// ScreenGenerations screen
ScreenGenerations::ScreenGenerations(Control* controlptr) :
Screen(controlptr)
{
this->targetSprite.setTexture(Control::fitness->target.getTexture());
this->chromoSprite.setTexture(Control::fitness->chromosome.getTexture());
this->currentGeneration = 0;
this->snapshotMode = true; // fullscreen
this->automaticSnapshots = false;
this->manualSnapshotCount = 0;
this->automaticSnapshotCount = 0;
this->lastBestFitness = -1;
std::cout << std::to_string(lastBestFitness) << std::endl;
}
void ScreenGenerations::enter()
{
this->paused = true;
this->updateStatus();
this->updateSpriteSize();
}
void ScreenGenerations::event(sf::Event& event)
{
if (event.type == sf::Event::KeyPressed) {
this->keyPressed(event);
}
}
void ScreenGenerations::update(sf::Time dt)
{
if (!this->paused) {
Control::generation->advance();
++this->currentGeneration;
this->updateStatus();
if (this->automaticSnapshots && Control::generation->individuals[0].fitnessEvaluated) {
unsigned long long fitness = Control::generation->individuals[0].fitness;
if (fitness < this->lastBestFitness) {
std::cout << "Fitness decreased to " << std::to_string(fitness)
<< " -> taking snapshot!" << std::endl;
this->takeSnapshot(false);
this->lastBestFitness = fitness;
}
}
}
}
void ScreenGenerations::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
Control::fitness->render(Control::generation->individuals[0].chromosome);
target.draw(this->targetSprite, states);
target.draw(this->chromoSprite, states);
this->control->drawBar(target, states);
}
void ScreenGenerations::exit()
{
}
void ScreenGenerations::keyPressed(sf::Event& event)
{
switch (event.key.code) {
// close window, stop program
case sf::Keyboard::Q:
this->control->close();
return;
case sf::Keyboard::P:
this->paused = !this->paused;
this->updateStatus();
break;
case sf::Keyboard::M:
this->snapshotMode = !this->snapshotMode;
this->updateStatus();
break;
case sf::Keyboard::S:
this->takeSnapshot(true);
break;
case sf::Keyboard::A:
this->automaticSnapshots = !this->automaticSnapshots;
this->updateStatus();
break;
default: break;
}
}
void ScreenGenerations::updateSpriteSize()
{
sf::Vector2f size = sf::Vector2f(Control::fitness->target.getSize());
sf::Vector2f windowSize = this->control->getSizeWithBar();
float scale;
sf::Vector2f spritePos;
if (2*size.x/size.y > windowSize.x/windowSize.y) {
std::cout << "wider" << std::endl;
// the images are wider than the window
// display is calculated based on width
scale = windowSize.x/(2*size.x);
spritePos.x = 0;
spritePos.y = (windowSize.y - scale*size.y)/2;
} else {
std::cout << "higher" << std::endl;
// the images are higher than the window
// display is calculated based on height
scale = windowSize.y/size.y;
spritePos.x = (windowSize.x - (2*scale*size.x))/2;
spritePos.y = 0;
}
this->targetSprite.setScale(sf::Vector2f(scale, scale));
this->chromoSprite.setScale(sf::Vector2f(scale, scale));
this->targetSprite.setPosition(spritePos);
spritePos.x += scale*size.x;
this->chromoSprite.setPosition(spritePos);
}
void ScreenGenerations::updateStatus()
{
std::string text = "Generation: ";
text += std::to_string(this->currentGeneration);
text += " (Genes: ";
text += std::to_string(Control::generation->individuals[0].chromosome.length());
text += ")";
this->control->setLeftText(text);
text = "[";
text += (this->paused)?"P":"-";
text += (this->automaticSnapshots)?"A":"-";
text += (this->snapshotMode)?"f":"c";
text += "]";
this->control->setRightText(text);
}
void ScreenGenerations::takeSnapshot(bool manual)
{
// name for image file - count
std::string filename;
std::string count;
if (manual) {
filename = "manual_";
count = std::to_string(this->manualSnapshotCount);
++this->manualSnapshotCount;
} else {
filename = "automatic_";
count = std::to_string(this->automaticSnapshotCount);
++this->automaticSnapshotCount;
}
if (count.length() < 5) {
filename += std::string(5 - count.length(), '0');
}
filename += count;
// name for image file - generation and chromosome size
filename += "_gen_";
filename += std::to_string(this->currentGeneration);
filename += "_chr_";
filename += std::to_string(Control::generation->individuals[0].chromosome.length());
filename += ".png";
// actually save snapshot
if (this->snapshotMode) {
// fullscreen
sf::Texture tex;
sf::Vector2u size = this->control->window.getSize();
tex.create(size.x, size.y);
tex.update(this->control->window);
tex.copyToImage().saveToFile(filename);
} else {
// chromosome only
Control::fitness->saveChromosome(filename);
}
}

View file

@ -61,6 +61,33 @@ private:
class ScreenGenerations : public Screen class ScreenGenerations : public Screen
{ {
public:
ScreenGenerations(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();
private:
bool paused;
unsigned int currentGeneration;
bool snapshotMode;
bool automaticSnapshots;
unsigned long long lastBestFitness;
unsigned int manualSnapshotCount;
unsigned int automaticSnapshotCount;
sf::Sprite targetSprite;
sf::Sprite chromoSprite;
void keyPressed(sf::Event& event);
void updateSpriteSize();
void updateStatus();
void takeSnapshot(bool manual);
}; };

View file

@ -8,8 +8,17 @@
#include "Generation.hpp" #include "Generation.hpp"
#include "Control.hpp" #include "Control.hpp"
int main() int main(int argc, char** argv)
{ {
std::string filename;
if (argc != 2) {
std::cout << "u dun goofed" << std::endl;
return 1;
} else {
filename = argv[1];
std::cout << "Using image: " << filename << std::endl;
}
std::minstd_rand randomEngine; std::minstd_rand randomEngine;
randomEngine.seed(time(nullptr)); randomEngine.seed(time(nullptr));
@ -18,16 +27,15 @@ int main()
Generation::re = &randomEngine; Generation::re = &randomEngine;
// Chromosome::allowGeneType(Gene::Circle); // Chromosome::allowGeneType(Gene::Circle);
Chromosome::allowGeneType(Gene::Triangle); // Chromosome::allowGeneType(Gene::Triangle);
Generation::size = 100; Generation::size = 100;
Generation::living = 10; Generation::living = 10;
Generation::crossover = 0.0; Generation::crossover = 0.0;
Fitness fitn; Fitness fitn;
fitn.loadTarget("firefox.png"); // fitn.loadTarget("firefox.png");
// fitn.loadTarget("tom-face.png"); fitn.loadTarget(filename);
// fitn.loadTarget("goldman_sachs.jpg");
fitn.loadShader("compare.glsl"); fitn.loadShader("compare.glsl");
Gene::size = sf::Vector2f(fitn.target.getSize()); Gene::size = sf::Vector2f(fitn.target.getSize());
@ -44,52 +52,3 @@ int main()
con.interactive(); con.interactive();
} }
/*
// Chromosome a;
// for (int i=0; i<1000; ++i) a.mutate();
// Chromosome b(a);
// for (int i=0; i<10; ++i) b.mutate();
// Chromosome c(a);
// Chromosome d(a, b);
// std::cout << a.length() << " | " << b.length() << " | " << c.length() << " | " << d.length() << std::endl;
sf::Sprite ts(fitn.target.getTexture());
sf::Sprite cs(fitn.chromosome.getTexture());
sf::RenderWindow window(sf::VideoMode(winW, winH), "gross");
// window.setMouseCursorVisible(false);
int gencnt = 0;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
// if (event.type == sf::Event::KeyPressed) {
// std::cout << "Trying to advance generation" << std::endl;
// gen.advance();
// std::cout << "Advanced generation" << std::endl;
// }
}
gen.advance();
std::cout << "Generation: " << ++gencnt << " (length: " << gen.individuals[0].chromosome.length() << ")" << std::endl;
// display results
window.clear();
ts.setPosition( 0, 0); window.draw(ts);
fitn.render(gen.individuals[0].chromosome); cs.setPosition(240, 0); window.draw(cs);
fitn.render(gen.individuals[9].chromosome); cs.setPosition(240, 240); window.draw(cs);
// fitn.render(a); cs.setPosition( 0, 0); window.draw(cs);
// fitn.render(b); cs.setPosition(240, 0); window.draw(cs);
// fitn.render(c); cs.setPosition( 0, 240); window.draw(cs);
// fitn.render(d); cs.setPosition(240, 240); window.draw(cs);
window.display();
// std::cout << "Generation finished: " << ++gencnt << " (winner's length: "
// std::cout << genr.individuals[0].chromosome.length() << ")" << std::endl;
}
}
*/