mirror of
https://github.com/fazo96/AIrium.git
synced 2025-01-25 11:54: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.g2d.BitmapFont;
|
||||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
|
import logic.Creature;
|
||||||
import logic.Element;
|
import logic.Element;
|
||||||
import logic.World;
|
import logic.World;
|
||||||
|
|
||||||
public class Game extends ApplicationAdapter {
|
public class Game extends ApplicationAdapter {
|
||||||
|
|
||||||
private static Game game;
|
private static Game game;
|
||||||
ShapeRenderer shaper;
|
ShapeRenderer renderer, overlayRenderer;
|
||||||
private World world;
|
private World world;
|
||||||
private float cameraSpeed = 15;
|
private float cameraSpeed = 15;
|
||||||
private BitmapFont font;
|
private BitmapFont font;
|
||||||
@ -22,8 +23,10 @@ public class Game extends ApplicationAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void create() {
|
public void create() {
|
||||||
game = this;
|
game = this;
|
||||||
shaper = new ShapeRenderer();
|
renderer = new ShapeRenderer();
|
||||||
shaper.setAutoShapeType(true);
|
renderer.setAutoShapeType(true);
|
||||||
|
overlayRenderer = new ShapeRenderer();
|
||||||
|
overlayRenderer.setAutoShapeType(true);
|
||||||
font = new BitmapFont();
|
font = new BitmapFont();
|
||||||
Thread worldThread = new Thread(world);
|
Thread worldThread = new Thread(world);
|
||||||
worldThread.setName("Worker");
|
worldThread.setName("Worker");
|
||||||
@ -42,22 +45,22 @@ public class Game extends ApplicationAdapter {
|
|||||||
world.newGen(false);
|
world.newGen(false);
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
|
||||||
shaper.translate(-cameraSpeed, 0, 0);
|
renderer.translate(-cameraSpeed, 0, 0);
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
|
||||||
shaper.translate(cameraSpeed, 0, 0);
|
renderer.translate(cameraSpeed, 0, 0);
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
|
||||||
shaper.translate(0, -cameraSpeed, 0);
|
renderer.translate(0, -cameraSpeed, 0);
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
|
||||||
shaper.translate(0, cameraSpeed, 0);
|
renderer.translate(0, cameraSpeed, 0);
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyJustPressed(Input.Keys.PLUS)) {
|
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)) {
|
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)) {
|
if (Gdx.input.isKeyJustPressed(Input.Keys.P)) {
|
||||||
paused = !paused;
|
paused = !paused;
|
||||||
@ -69,15 +72,23 @@ public class Game extends ApplicationAdapter {
|
|||||||
world.setFpsLimit(60);
|
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
|
// Draw
|
||||||
Gdx.gl.glClearColor(0, 0, 0, 1);
|
Gdx.gl.glClearColor(0, 0, 0, 1);
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
shaper.setColor(1, 1, 1, 1);
|
renderer.begin(ShapeRenderer.ShapeType.Line);
|
||||||
shaper.begin(ShapeRenderer.ShapeType.Line);
|
|
||||||
try {
|
try {
|
||||||
for (Element e : world.getElements()) {
|
for (Element e : world.getElements()) {
|
||||||
try {
|
try {
|
||||||
e.render(shaper);
|
e.render(renderer);
|
||||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||||
// No idea why it happens, but it's rendering so meh
|
// No idea why it happens, but it's rendering so meh
|
||||||
//Log.log(Log.ERROR, ex+"");
|
//Log.log(Log.ERROR, ex+"");
|
||||||
@ -85,10 +96,21 @@ public class Game extends ApplicationAdapter {
|
|||||||
}
|
}
|
||||||
} catch (ConcurrentModificationException ex) {
|
} 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
|
// draw borders
|
||||||
shaper.rect(0, 0, world.getWidth(), world.getHeight());
|
renderer.rect(0, 0, world.getWidth(), world.getHeight());
|
||||||
shaper.end();
|
renderer.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
public World getWorld() {
|
public World getWorld() {
|
||||||
|
@ -24,7 +24,7 @@ public class Vegetable extends Element {
|
|||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
setSize(getSize()-decayRate);
|
setSize(getSize()-decayRate);
|
||||||
if (getSize() <= 0) {
|
if (getSize() <= 2) {
|
||||||
Game.get().getWorld().getDeadPlants().add(this);
|
Game.get().getWorld().getDeadPlants().add(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import com.mygdx.game.Game;
|
|||||||
import com.mygdx.game.Log;
|
import com.mygdx.game.Log;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -22,6 +23,7 @@ public class World implements Runnable {
|
|||||||
private final int width, height, nPlants, creatPerGen;
|
private final int width, height, nPlants, creatPerGen;
|
||||||
private int generation = 1;
|
private int generation = 1;
|
||||||
private int fpsLimit = 60, fps = 0;
|
private int fpsLimit = 60, fps = 0;
|
||||||
|
private Creature selected;
|
||||||
private final ArrayList<Element> elements;
|
private final ArrayList<Element> elements;
|
||||||
private final ArrayList<Element> toAdd;
|
private final ArrayList<Element> toAdd;
|
||||||
private final ArrayList<Creature> creatures;
|
private final ArrayList<Creature> creatures;
|
||||||
@ -42,6 +44,7 @@ public class World implements Runnable {
|
|||||||
deadPlants = new ArrayList();
|
deadPlants = new ArrayList();
|
||||||
graveyard = new ArrayList();
|
graveyard = new ArrayList();
|
||||||
fpsListeners = new ArrayList();
|
fpsListeners = new ArrayList();
|
||||||
|
selected = null;
|
||||||
newGen(true);
|
newGen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +99,10 @@ public class World implements Runnable {
|
|||||||
}
|
}
|
||||||
toAdd.clear();
|
toAdd.clear();
|
||||||
elements.removeAll(graveyard);
|
elements.removeAll(graveyard);
|
||||||
|
if (selected != null && graveyard.contains(selected)) {
|
||||||
|
selected = null;
|
||||||
|
Log.log(Log.INFO, "Cleared selection");
|
||||||
|
}
|
||||||
elements.removeAll(deadPlants);
|
elements.removeAll(deadPlants);
|
||||||
plants.removeAll(deadPlants);
|
plants.removeAll(deadPlants);
|
||||||
deadPlants.clear();
|
deadPlants.clear();
|
||||||
@ -116,6 +123,10 @@ public class World implements Runnable {
|
|||||||
elements.removeAll(creatures);
|
elements.removeAll(creatures);
|
||||||
graveyard.addAll(creatures);
|
graveyard.addAll(creatures);
|
||||||
creatures.clear();
|
creatures.clear();
|
||||||
|
if (selected != null) {
|
||||||
|
selected = null;
|
||||||
|
Log.log(Log.INFO, "Cleared selection");
|
||||||
|
}
|
||||||
Comparator creatureComp = new Comparator<Creature>() {
|
Comparator creatureComp = new Comparator<Creature>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -212,6 +223,19 @@ public class World implements Runnable {
|
|||||||
public abstract void fpsChanged(int newValue);
|
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() {
|
private void spawnVegetable() {
|
||||||
spawn(false, null);
|
spawn(false, null);
|
||||||
}
|
}
|
||||||
@ -276,4 +300,12 @@ public class World implements Runnable {
|
|||||||
return fps;
|
return fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Creature getSelectedCreature() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectCreature(Creature selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package logic.neural;
|
package logic.neural;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
import com.mygdx.game.Log;
|
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
|
* Give some input to the brain
|
||||||
*
|
*
|
||||||
|
@ -55,11 +55,12 @@ public class Neuron {
|
|||||||
if (isInputNeuron) {
|
if (isInputNeuron) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
if(cache.hasCachedOutput()) return cache.getCachedOutput();
|
||||||
float a = bias * -1; // activation
|
float a = bias * -1; // activation
|
||||||
for (int i = 0; i < weights.length; i++) {
|
for (int i = 0; i < weights.length; i++) {
|
||||||
if (cache.has(i)) {
|
if (cache.has(i)) {
|
||||||
try {
|
try {
|
||||||
return cache.get(i);
|
a += cache.get(i);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// This should never happen
|
// This should never happen
|
||||||
Logger.getLogger(Neuron.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Neuron.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
@ -82,6 +83,23 @@ public class Neuron {
|
|||||||
return mutatedWeights;
|
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) {
|
public void setOutput(float output) {
|
||||||
isInputNeuron = true;
|
isInputNeuron = true;
|
||||||
this.output = output;
|
this.output = output;
|
||||||
|
@ -8,6 +8,8 @@ package logic.neural;
|
|||||||
public class NeuronCache {
|
public class NeuronCache {
|
||||||
|
|
||||||
private float[] cache;
|
private float[] cache;
|
||||||
|
private float cachedOutput;
|
||||||
|
private boolean cachedOutputValid;
|
||||||
private boolean[] validity;
|
private boolean[] validity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,6 +59,18 @@ public class NeuronCache {
|
|||||||
return validity[index];
|
return validity[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getCachedOutput() {
|
||||||
|
return cachedOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasCachedOutput() {
|
||||||
|
return cachedOutputValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCachedOutput(float cachedOutput) {
|
||||||
|
this.cachedOutput = cachedOutput;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears cache.
|
* Clears cache.
|
||||||
*/
|
*/
|
||||||
@ -64,5 +78,7 @@ public class NeuronCache {
|
|||||||
for (int i = 0; i < cache.length; i++) {
|
for (int i = 0; i < cache.length; i++) {
|
||||||
validity[i] = false;
|
validity[i] = false;
|
||||||
}
|
}
|
||||||
|
cachedOutputValid = false;
|
||||||
|
cachedOutput = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user