Skip to content

Instantly share code, notes, and snippets.

@8q
Created April 8, 2018 15:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 8q/9dbaf37c5a72d59fadc08d0a6a9a7674 to your computer and use it in GitHub Desktop.
Save 8q/9dbaf37c5a72d59fadc08d0a6a9a7674 to your computer and use it in GitHub Desktop.
mischan.png[83x100], takagiya.png[80x80]
import java.util.List;
import java.util.Iterator;
import java.util.Arrays;
Stage stage;
Population population;
int LIFE_TIME = 400;
float MUTATION_RATE = 0.025;
int POPULATION_NUM = 20;
int _lifetimeCounter = 0;
void setup()
{
size(1280, 720);
noStroke();
stage = new Stage();
population = new Population();
}
void draw()
{
displayInfo();
stage.draw();
if (_lifetimeCounter < LIFE_TIME)
{
population.run();
population.updateFitness();
population.draw();
_lifetimeCounter++;
} else
{
DNA bestDNA = population.bestDNA();
println(bestDNA.fitness);
if(bestDNA.isFinished())
{
noLoop();
bestDNA.player.draw();
return;
}
_lifetimeCounter = 0;
population.selection();
population.generate();
}
}
void displayInfo()
{
fill(0);
rect(0, 640, 1280, 80);
fill(255, 255, 0);
textFont (createFont("MS Gothic", 48, true));
textSize(48);
text("" + (population.generations + 1) + "世代", 10, 695);
textSize(24);
text((_lifetimeCounter) + "/" + LIFE_TIME, 300, 697);
}
class Population
{
DNA[] dnas = new DNA[POPULATION_NUM];
List<DNA> matingPool = new ArrayList<DNA>();
int generations = 0;
Population()
{
for (int i = 0; i < dnas.length; i++)
{
dnas[i] = new DNA();
}
}
void run()
{
for (DNA dna : dnas)
{
dna.run();
}
}
void draw()
{
for (DNA dna : dnas)
{
dna.player.draw();
}
}
void updateFitness()
{
for (DNA dna : dnas)
{
dna.updateFitness();
}
}
DNA bestDNA()
{
int pos = 0;
float maxFitness = 0;
for (int i = 0; i < dnas.length; i++)
{
if (dnas[i].fitness > maxFitness)
{
maxFitness = dnas[i].fitness;
pos = i;
}
}
return dnas[pos];
}
void selection()
{
matingPool.clear();
float maxFitness = bestDNA().fitness;
for (int i = 0; i < dnas.length; i++)
{
float fitness = map(dnas[i].fitness, 0, maxFitness, 0, 1);
int n = int(fitness * 100);
for (int j = 0; j < n; j++)
{
matingPool.add(dnas[i]);
}
}
}
void generate()
{
for (int i = 0; i < dnas.length; i++)
{
int a = int(random(matingPool.size()));
int b = int(random(matingPool.size()));
DNA partnerA = matingPool.get(a);
DNA partnerB = matingPool.get(b);
DNA child = partnerA.crossover(partnerB);
child.mutate();
dnas[i] = child;
}
generations++;
}
}
class DNA
{
char[] genes;
Player player = new Player();
float fitness = 0;
DNA()
{
genes = new char[LIFE_TIME];
for (int i = 0; i < genes.length; i++)
{
genes[i] = (char)random(0, 4);
}
}
boolean isFinished()
{
return fitness > 0.00011;
}
void run()
{
if(isFinished()) return;
switch(genes[_lifetimeCounter])
{
case 0:
player.move(15, 0);
break;
case 1:
player.move(0, 15);
break;
case 2:
player.move(-15, 0);
break;
case 3:
player.move(0, -15);
break;
}
}
float updateFitness()
{
float newFitness = pow(1 / (PVector.dist(new PVector(stage.target.x, stage.target.y), new PVector(player.x, player.y))), 2);
return fitness = fitness < newFitness ? newFitness : fitness;
}
DNA crossover(DNA partner)
{
DNA child = new DNA();
int midpoint = int(random(genes.length));
for (int i = 0; i < genes.length; i++)
{
if (i > midpoint)
child.genes[i] = genes[i];
else
child.genes[i] = partner.genes[i];
}
return child;
}
void mutate()
{
for (int i = 0; i < genes.length; i++)
{
if (random(1.0) < MUTATION_RATE)
{
genes[i] = (char)random(0, 4);
}
}
}
}
class Player
{
PImage img = loadImage("image/mischan.png");
int x = 1180, y = 540, w = 50, h = 60;
void draw()
{
image(img, x, y, w, h);
}
void move(int dx, int dy)
{
if (!stage.isWall(x + dx, y + dy) && !stage.isWall(x + dx + w, y + dy)
&& !stage.isWall(x + dx, y + dy + h) && !stage.isWall(x + dx + w, y + dy + h)
&& x + dx >= 0 && x + dx + w <= 1280
&& y + dy >= 0 && y + dy + h <= 640)
{
x += dx;
y += dy;
}
}
}
class Stage
{
class Target
{
int x = 0, y = 0, w = 100, h = 100;
PImage img = loadImage("image/takagiya.png");
void draw()
{
fill(220, 20, 60);
rect(x, y, w, h);
image(img, x + w * 0.1, y + h * 0.1, w * 0.8, w * 0.8);
}
}
class Wall
{
int x, y, w, h;
Wall(int x, int y, int w, int h)
{
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
void draw()
{
fill(210, 105, 30);
rect(x, y, w, h);
}
boolean isContain(int x, int y)
{
return x >= this.x && x <= this.x + w && y >= this.y && y <= this.y + h;
}
}
Target target = new Target();
Wall[] walls =
{
new Wall(1010, 120, 110, 410),
new Wall(540, 0, 300, 380),
new Wall(600, 510, 180, 130),
new Wall(100, 440, 330, 200),
new Wall(150, 220, 220, 110),
new Wall(260, 110, 110, 110),
};
void draw()
{
fill(80, 200, 80);
rect(0, 0, 1280, 640);
for (Wall wall : walls)
{
wall.draw();
}
target.draw();
}
boolean isWall(int x, int y)
{
for (Wall wall : walls)
{
if (wall.isContain(x, y))
return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment