mirror of
https://github.com/fazo96/AIrium.git
synced 2025-01-10 09:34:20 +01:00
fixed bugs, implemented brain rendering and creature selection (broken for now)
This commit is contained in:
parent
75146638bf
commit
124087d381
@ -7,13 +7,14 @@ import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import logic.Creature;
|
||||
import logic.Element;
|
||||
import logic.World;
|
||||
|
||||
public class Game extends ApplicationAdapter {
|
||||
|
||||
private static Game game;
|
||||
ShapeRenderer shaper;
|
||||
ShapeRenderer renderer, overlayRenderer;
|
||||
private World world;
|
||||
private float cameraSpeed = 15;
|
||||
private BitmapFont font;
|
||||
@ -22,8 +23,10 @@ public class Game extends ApplicationAdapter {
|
||||
@Override
|
||||
public void create() {
|
||||
game = this;
|
||||
shaper = new ShapeRenderer();
|
||||
shaper.setAutoShapeType(true);
|
||||
renderer = new ShapeRenderer();
|
||||
renderer.setAutoShapeType(true);
|
||||
overlayRenderer = new ShapeRenderer();
|
||||
overlayRenderer.setAutoShapeType(true);
|
||||
font = new BitmapFont();
|
||||
Thread worldThread = new Thread(world);
|
||||
worldThread.setName("Worker");
|
||||
@ -42,22 +45,22 @@ public class Game extends ApplicationAdapter {
|
||||
world.newGen(false);
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
|
||||
shaper.translate(-cameraSpeed, 0, 0);
|
||||
renderer.translate(-cameraSpeed, 0, 0);
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
|
||||
shaper.translate(cameraSpeed, 0, 0);
|
||||
renderer.translate(cameraSpeed, 0, 0);
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
|
||||
shaper.translate(0, -cameraSpeed, 0);
|
||||
renderer.translate(0, -cameraSpeed, 0);
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
|
||||
shaper.translate(0, cameraSpeed, 0);
|
||||
renderer.translate(0, cameraSpeed, 0);
|
||||
}
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.PLUS)) {
|
||||
shaper.scale(0.5f, 0.5f, 1);
|
||||
renderer.scale(0.5f, 0.5f, 1);
|
||||
}
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.MINUS)) {
|
||||
shaper.scale(1.5f, 1.5f, 1);
|
||||
renderer.scale(1.5f, 1.5f, 1);
|
||||
}
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.P)) {
|
||||
paused = !paused;
|
||||
@ -69,15 +72,23 @@ public class Game extends ApplicationAdapter {
|
||||
world.setFpsLimit(60);
|
||||
}
|
||||
}
|
||||
if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
|
||||
renderer.translate(Gdx.input.getDeltaX(), Gdx.input.getDeltaY() * -1, 0);
|
||||
}
|
||||
/*
|
||||
// Broken for now
|
||||
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
|
||||
// TODO: project coordinates to world
|
||||
world.selectCreatureAt(Gdx.input.getX(), Gdx.input.getY());
|
||||
}*/
|
||||
// Draw
|
||||
Gdx.gl.glClearColor(0, 0, 0, 1);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
shaper.setColor(1, 1, 1, 1);
|
||||
shaper.begin(ShapeRenderer.ShapeType.Line);
|
||||
renderer.begin(ShapeRenderer.ShapeType.Line);
|
||||
try {
|
||||
for (Element e : world.getElements()) {
|
||||
try {
|
||||
e.render(shaper);
|
||||
e.render(renderer);
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
// No idea why it happens, but it's rendering so meh
|
||||
//Log.log(Log.ERROR, ex+"");
|
||||
@ -85,10 +96,21 @@ public class Game extends ApplicationAdapter {
|
||||
}
|
||||
} catch (ConcurrentModificationException ex) {
|
||||
}
|
||||
shaper.setColor(0.3f, 0.3f, 0.3f, 1);
|
||||
if (world.getSelectedCreature() != null) {
|
||||
// There is a selection
|
||||
Creature c = world.getSelectedCreature();
|
||||
renderer.setColor(1, 1, 1, 1);
|
||||
// Draw selection rectangle
|
||||
renderer.rect(c.getX() - c.getSize() / 2, c.getY() - c.getSize() / 2, c.getX() + c.getSize() / 2, c.getY() + c.getSize() / 2);
|
||||
// Draw brain
|
||||
overlayRenderer.begin();
|
||||
c.getBrain().render(overlayRenderer);
|
||||
overlayRenderer.end();
|
||||
}
|
||||
renderer.setColor(0.3f, 0.3f, 0.3f, 1);
|
||||
// draw borders
|
||||
shaper.rect(0, 0, world.getWidth(), world.getHeight());
|
||||
shaper.end();
|
||||
renderer.rect(0, 0, world.getWidth(), world.getHeight());
|
||||
renderer.end();
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
|
@ -24,7 +24,7 @@ public class Vegetable extends Element {
|
||||
@Override
|
||||
public void update() {
|
||||
setSize(getSize()-decayRate);
|
||||
if (getSize() <= 0) {
|
||||
if (getSize() <= 2) {
|
||||
Game.get().getWorld().getDeadPlants().add(this);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import com.mygdx.game.Game;
|
||||
import com.mygdx.game.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@ -22,6 +23,7 @@ public class World implements Runnable {
|
||||
private final int width, height, nPlants, creatPerGen;
|
||||
private int generation = 1;
|
||||
private int fpsLimit = 60, fps = 0;
|
||||
private Creature selected;
|
||||
private final ArrayList<Element> elements;
|
||||
private final ArrayList<Element> toAdd;
|
||||
private final ArrayList<Creature> creatures;
|
||||
@ -42,6 +44,7 @@ public class World implements Runnable {
|
||||
deadPlants = new ArrayList();
|
||||
graveyard = new ArrayList();
|
||||
fpsListeners = new ArrayList();
|
||||
selected = null;
|
||||
newGen(true);
|
||||
}
|
||||
|
||||
@ -96,6 +99,10 @@ public class World implements Runnable {
|
||||
}
|
||||
toAdd.clear();
|
||||
elements.removeAll(graveyard);
|
||||
if (selected != null && graveyard.contains(selected)) {
|
||||
selected = null;
|
||||
Log.log(Log.INFO, "Cleared selection");
|
||||
}
|
||||
elements.removeAll(deadPlants);
|
||||
plants.removeAll(deadPlants);
|
||||
deadPlants.clear();
|
||||
@ -116,6 +123,10 @@ public class World implements Runnable {
|
||||
elements.removeAll(creatures);
|
||||
graveyard.addAll(creatures);
|
||||
creatures.clear();
|
||||
if (selected != null) {
|
||||
selected = null;
|
||||
Log.log(Log.INFO, "Cleared selection");
|
||||
}
|
||||
Comparator creatureComp = new Comparator<Creature>() {
|
||||
|
||||
@Override
|
||||
@ -212,6 +223,19 @@ public class World implements Runnable {
|
||||
public abstract void fpsChanged(int newValue);
|
||||
}
|
||||
|
||||
public void selectCreatureAt(int x, int y) {
|
||||
selected = null; // Clear selection
|
||||
try {
|
||||
for (Creature c : creatures) {
|
||||
if (c.overlaps(x, y)) {
|
||||
selected = c;
|
||||
Log.log(Log.INFO, "Selected a creature");
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentModificationException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnVegetable() {
|
||||
spawn(false, null);
|
||||
}
|
||||
@ -276,4 +300,12 @@ public class World implements Runnable {
|
||||
return fps;
|
||||
}
|
||||
|
||||
public Creature getSelectedCreature() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void selectCreature(Creature selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package logic.neural;
|
||||
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.mygdx.game.Log;
|
||||
|
||||
/**
|
||||
@ -81,6 +82,39 @@ public class Brain {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw this brain's status.
|
||||
*
|
||||
* @param s the ShapeRenderer to use for the drawing
|
||||
*/
|
||||
public void render(ShapeRenderer s) {
|
||||
s.set(ShapeRenderer.ShapeType.Filled);
|
||||
int neuronHeight = 0;
|
||||
for (Neuron[] ns : neurons) {
|
||||
if (ns.length > neuronHeight) {
|
||||
neuronHeight = ns.length;
|
||||
}
|
||||
}
|
||||
s.rect(0, 0, neurons.length * 50, neuronHeight * 30);
|
||||
for (int i = 0; i < neurons.length; i++) {
|
||||
//s.set(ShapeRenderer.ShapeType.Line);
|
||||
for (int j = 0; j < neurons[i].length; j++) {
|
||||
// get neuron result first so cache system can kick in and save some calculations
|
||||
float nr = neurons[i][j].compute();
|
||||
// Draw neuron links
|
||||
float[] links = neurons[i][j].getInputs();
|
||||
for (int f = 0; f < links.length; f++) {
|
||||
s.setColor(links[f], links[f], links[f], 1);
|
||||
s.line(i * 50, j * 30, (i - 1) * 50, f * 30);
|
||||
}
|
||||
// Draw neuron
|
||||
s.setColor(1 - nr, nr, 0, 1);
|
||||
s.set(ShapeRenderer.ShapeType.Filled);
|
||||
s.circle(i * 50, j * 30, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give some input to the brain
|
||||
*
|
||||
|
@ -55,11 +55,12 @@ public class Neuron {
|
||||
if (isInputNeuron) {
|
||||
return output;
|
||||
}
|
||||
if(cache.hasCachedOutput()) return cache.getCachedOutput();
|
||||
float a = bias * -1; // activation
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
if (cache.has(i)) {
|
||||
try {
|
||||
return cache.get(i);
|
||||
a += cache.get(i);
|
||||
} catch (Exception ex) {
|
||||
// This should never happen
|
||||
Logger.getLogger(Neuron.class.getName()).log(Level.SEVERE, null, ex);
|
||||
@ -82,6 +83,23 @@ public class Neuron {
|
||||
return mutatedWeights;
|
||||
}
|
||||
|
||||
public float[] getInputs() {
|
||||
float inputs[] = new float[weights.length];
|
||||
for (int i = 0; i < inputs.length; i++) {
|
||||
if (cache.has(i)) {
|
||||
try {
|
||||
inputs[i] = cache.get(i);
|
||||
} catch (Exception ex) {
|
||||
// Shouldnt happen
|
||||
Logger.getLogger(Neuron.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else {
|
||||
inputs[i] = 0;
|
||||
}
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
public void setOutput(float output) {
|
||||
isInputNeuron = true;
|
||||
this.output = output;
|
||||
|
@ -8,6 +8,8 @@ package logic.neural;
|
||||
public class NeuronCache {
|
||||
|
||||
private float[] cache;
|
||||
private float cachedOutput;
|
||||
private boolean cachedOutputValid;
|
||||
private boolean[] validity;
|
||||
|
||||
/**
|
||||
@ -57,6 +59,18 @@ public class NeuronCache {
|
||||
return validity[index];
|
||||
}
|
||||
|
||||
public float getCachedOutput() {
|
||||
return cachedOutput;
|
||||
}
|
||||
|
||||
public boolean hasCachedOutput() {
|
||||
return cachedOutputValid;
|
||||
}
|
||||
|
||||
public void setCachedOutput(float cachedOutput) {
|
||||
this.cachedOutput = cachedOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears cache.
|
||||
*/
|
||||
@ -64,5 +78,7 @@ public class NeuronCache {
|
||||
for (int i = 0; i < cache.length; i++) {
|
||||
validity[i] = false;
|
||||
}
|
||||
cachedOutputValid = false;
|
||||
cachedOutput = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user