public void draw() { background( theme.getColor(Types.BACKGROUND)); // Draws background, basically refreshes the screen win.setBackground(theme.getColor(Types.BACKGROUND)); sidePanel.setBackground(theme.getColor(Types.SIDEPANEL1)); for (int i = 0; i < SIM_TICKS; i++) { env.updateAllAgents(); // 'Ticks' for the new frame, sensors sense, networks network and // collisions are checked. env.updateCollisions(); // update the environment with the new collisions env.updateAgentsSight(); // update all the agents to everything they can see in their field // of view handleCollisions(); if (!env.fitnessOnly) { checkDeaths(); } updateUI(); autoSnapshot(); } // move drawn region if (arrowsPressed[0] && !arrowsPressed[1]) offsetY -= moveSpeed * zoomLevel; // UP if (arrowsPressed[1] && !arrowsPressed[0]) offsetY += moveSpeed * zoomLevel; // DOWN if (arrowsPressed[2] && !arrowsPressed[3]) offsetX -= moveSpeed * zoomLevel; // LEFT if (arrowsPressed[3] && !arrowsPressed[2]) offsetX += moveSpeed * zoomLevel; // RIGHT win.draw(); fill(255); text("FrameRate: " + frameRate, 10, 10); // Displays framerate in the top left hand corner text("Mouse X: " + mouseX + "Mouse Y: " + mouseY, 10, 30); text("Fish Generation: " + env.getFishGeneration(), 10, 50); text("Ticks to next fish generation: " + (1000 - (env.getTick() % 1000)), 10, 70); }
private void setupUI() { // Set colors of each element of simulation theme = new UITheme(); theme.setColor(Types.BACKGROUND, color(0)); theme.setColor(Types.SIDEPANEL1, color(50)); theme.setColor(Types.FOOD, color(0, 255, 0)); theme.setColor(Types.FISH, color(255, 127, 0)); theme.setColor(Types.SHARK, color(255, 0, 0)); theme.setColor(Types.WALL, color(255, 255, 0)); theme.setColor(Types.NEURON, color(200)); theme.setColor(Types.NEURON_FIRED, color(0, 255, 0)); // setup main window for UI elements win = new UIWindow(this, 0, 0, screen.width, screen.height); sideTabs = new UITab(this, 250, 0, 250, screen.height); sideTabs.setIsLeft(false); sideTabs.setBackground(50); sideTabs.setFixedBackground(true); sidePanel = sideTabs.addTab("Information"); // new UIWindow(this, 250, 0, 250, screen.height); neatParams = sideTabs.addTab("NEAT Params"); neatParams.setBackground(30); setupNEATParams(); // Simulation draw region UIDrawable sim = new UIDrawable(this, 0, 0, draw_width, draw_height); sim.setBackground(color(255)); sim.setFixedBackground(true); sim.setEventHandler( new UIAction() { public void draw(PApplet canvas) { drawSimulation(canvas); } }); win.addObject(sim); win.addObject(sideTabs); // Buttons to change the current mode btnGroupModes = new UIWindow(this, 0, 0, 250, 150); btnGroupModes.setBackground(30); btnGroupModes.setFixedBackground(true); sidePanel.addObject(btnGroupModes); btnSelectAgent = addModeButton(0, "Select", 2, 118, 255); btnAddFood = addModeButton(1, "Seaweed", 84, 255, 159); btnAddAgent = addModeButton(2, "Agent", 255, 127, 0); btnThrust = addModeButton(3, "Thrust", 0, 231, 125); btnAddWall = addModeButton(4, "Wall", 255, 255, 0); btnGroupModes.selectButton(btnSelectAgent); // Change number of ticks updated each frame sliderTPS = new UISlider(this, 10, 90, 170, 30); sliderTPS.setEventHandler( new UIAction() { public void change(UISlider slider) { SIM_TICKS = (int) (slider.getValue() * SIM_TPS_MAX); lblSimTPS.setText("Ticks: " + SIM_TICKS); } }); sliderTPS.setValue(1.0 / SIM_TPS_MAX); btnGroupModes.addObject(sliderTPS); lblSimTPS = new UILabel(this, 190, 92, "Ticks: " + SIM_TICKS); btnGroupModes.addObject(lblSimTPS); // Statistics window for the currently selected agent winStats = new UIWindow(this, 0, 165, 300, 500); winStats.setBackground(30); winStats.setFixedBackground(true); sidePanel.addObject(winStats); // control to change the selected agents heading agentHeading = new UIVision(this, 25, 270, 200); agentHeading.setTheme(theme); agentHeading.setEventHandler( new UIAction() { public void change(UIAngle ang) { if (selectedAgent != null) { selectedAgent.changeViewHeading(ang.getAngle() - selectedAgent.getViewHeading()); } } }); winStats.addObject(agentHeading); // progress bar of the selected agents current health progHealth = new UIProgress(this, 10, 93, 230, 10); winStats.addObject(progHealth); // sliders to move agents position sliderX = new UISlider(this, 10, 35, 230, 15); sliderX.setEventHandler( new UIAction() { public void change(UISlider slider) { if (selectedAgent != null) { selectedAgent.setX((int) (slider.getValue() * Environment.width)); } } }); winStats.addObject(sliderX); sliderY = new UISlider(this, 10, 60, 230, 15); sliderY.setEventHandler( new UIAction() { public void change(UISlider slider) { if (selectedAgent != null) { selectedAgent.setY((int) (slider.getValue() * Environment.height)); } } }); winStats.addObject(sliderY); // boost agent health back to 100% btnSelectHealth = new UIButton(this, 10, 115, 65, 20, "100%"); btnSelectHealth.setColor(84, 255, 159); btnSelectHealth.setEventHandler( new UIAction() { public void click(UIButton btn) { if (selectedAgent != null) { selectedAgent.updateHealth(1); } } }); winStats.addObject(btnSelectHealth); // thrust selected agent btnSelectThrust = new UIButton(this, 93, 115, 65, 20, "Thrust"); btnSelectThrust.setColor(251, 150, 20); btnSelectThrust.setEventHandler( new UIAction() { public void click(UIButton btn) { if (selectedAgent != null) { selectedAgent.thrust(5); } } }); winStats.addObject(btnSelectThrust); // kill poor agent btnSelectKill = new UIButton(this, 175, 115, 65, 20, "KILL"); btnSelectKill.setColor(210, 50, 50); btnSelectKill.setEventHandler( new UIAction() { public void click(UIButton btn) { if (selectedAgent != null) { // env.removeAgent(selectedAgent); env.scheduledRemove.add(selectedAgent); selectedAgent = null; } } }); winStats.addObject(btnSelectKill); // Toggle focused / tracking mode for selected agent btnToggleFocused = new UIButton(this, 120, 5, 65, 15, (agentFocused ? "Unfocus" : "Focus")); btnToggleFocused.setIsLeft(false); btnToggleFocused.setColor(50, 100, 255); btnToggleFocused.setEventHandler( new UIAction() { public void click(UIButton btn) { agentFocused = !agentFocused; btn.setText(agentFocused ? "Unfocus" : "Focus"); } }); winStats.addObject(btnToggleFocused); // 3D neural network visual UITab bottomWindow = new UITab(this, 0, 300, 250, 300); bottomWindow.setIsTop(false); sidePanel.addObject(bottomWindow); UIWindow tabNeural = bottomWindow.addTab("Network"); UIWindow tabTheme = bottomWindow.addTab("Theme"); tabTheme.setBackground(30); neuralVisual = new UIDrawable3D(this, 0, 0, 250, 250); neuralVisual.setBackground(30); neuralVisual.setFixedBackground(true); tabNeural.addObject(neuralVisual); neuralVisual.setEventHandler( new UIAction() { private float zoom = 0.5f; private int offX = 0; private int offY = 0; boolean arrows[] = new boolean[4]; private boolean rotating = true; public void draw(PApplet canvas) { if (selectedAgent == null) return; if (arrows[0] && !arrows[1]) offY -= moveSpeed / 3; // UP if (arrows[1] && !arrows[0]) offY += moveSpeed / 3; // DOWN MNetwork net = selectedAgent.getNetwork(); noStroke(); pushMatrix(); rotateY(neuralRotation); scale(zoom, zoom, zoom); translate(offX, offY); for (MNeuron n : net.getNeurons()) { // draw the neurons int isFired = (n.isFiring() ? 255 : 60); if (n.getID() >= 3 && n.getID() < 3 + Agent.configNumSegments) fill(theme.getColor(Types.FOOD), isFired); else if (n.getID() >= 3 + Agent.configNumSegments && n.getID() < 3 + Agent.configNumSegments * 2) fill(theme.getColor(Types.WALL), isFired); else if (n.getID() >= 3 + Agent.configNumSegments * 2 && n.getID() < 3 + Agent.configNumSegments * 3) fill(theme.getColor(Types.SHARK), isFired); else if (n.getID() < 3) fill(0, 255, 255, isFired); else fill(theme.getColor(Types.NEURON), isFired); MVec3f vec = n.getCoords(); // clip node if off the display if ((vec.y + offY) * zoom < -135) continue; translate(vec.x, vec.y, vec.z); sphere(3); translate(-vec.x, -vec.y, -vec.z); } for (MSynapse s : net.getSynapses()) { // draw the links between the neurons MNeuron pre = s.getPreNeuron(); MNeuron post = s.getPostNeuron(); MVec3f n1 = pre.getCoords(); MVec3f n2 = post.getCoords(); // clip edge if both nodes above clipping if ((n1.y + offY) * zoom < -135 && (n2.y + offY) * zoom < -135) continue; int isFired = (pre.isFiring() ? 100 : 10); if (pre.getID() >= 3 && pre.getID() < 3 + Agent.configNumSegments) stroke(theme.getColor(Types.FOOD), isFired); else if (pre.getID() >= 3 + Agent.configNumSegments && pre.getID() < 3 + Agent.configNumSegments * 2) stroke(theme.getColor(Types.WALL), isFired); else if (pre.getID() >= 3 + Agent.configNumSegments * 2 && pre.getID() < 3 + Agent.configNumSegments * 3) stroke(theme.getColor(Types.SHARK), isFired); else if (pre.getID() < 3) stroke(0, 255, 255, isFired); else stroke(255, isFired); // partial clipping when one node if above line if ((n1.y + offY) * zoom < -135) { double t = (((-135 / zoom) - offY) - n2.y) / (n1.y - n2.y); int x = (int) ((int) (n2.x + t * (n1.x - n2.x)) / zoom); line( (int) (x), (int) (-135 / zoom) - offY, 0, (int) (n2.x), (int) (n2.y), (int) n2.z); } else if ((n2.y + offY) * zoom < -135) { double t = (((-135.0 / zoom) - offY) - (n1.y)) / (double) ((n2.y - n1.y)); int x = (int) (n1.x + t * (n2.x - n1.x)); line( (int) (n1.x), (int) (n1.y), (int) n1.z, (int) (x), (int) (-135 / zoom) - offY, 0); } else { line((int) n1.x, (int) n1.y, (int) n1.z, (int) n2.x, (int) n2.y, (int) n2.z); } } popMatrix(); if (rotating) neuralRotation -= 0.02; } public boolean mouseWheel(MouseWheelEvent event) { if (!Utilities.isPointInBox( mouseX, mouseY, screen.width - 250, screen.height - 250, 250, 250)) return false; if (zoom > minZoom || event.getWheelRotation() > 0) { zoom = Math.max(minZoom, (zoom + 0.1f * event.getWheelRotation())); } return true; } public boolean mousePressed() { if (!Utilities.isPointInBox( mouseX, mouseY, screen.width - 250, screen.height - 250, 250, 250)) return false; rotating = !rotating; return true; } public boolean keyReleased() { // Hotkeys for buttons if (!Utilities.isPointInBox( mouseX, mouseY, screen.width - 250, screen.height - 250, 250, 250)) return false; switch (keyCode) { case (UP): arrows[0] = false; return true; case (DOWN): arrows[1] = false; return true; case (LEFT): arrows[2] = false; return true; case (RIGHT): arrows[3] = false; return true; } return false; } public boolean keyPressed() { // Hotkeys for buttons if (!Utilities.isPointInBox( mouseX, mouseY, screen.width - 250, screen.height - 250, 250, 250)) return false; switch (keyCode) { case (UP): arrows[0] = true; return true; case (DOWN): arrows[1] = true; return true; case (LEFT): arrows[2] = true; return true; case (RIGHT): arrows[3] = true; return true; } return false; } }); // printout of selected agents stats lblStatTitle = addStatLabel("Selected Agent", 5); lblX = addStatLabel("X", 155); lblY = addStatLabel("X", 170); lblHeading = addStatLabel("X", 185); lblHealth = addStatLabel("X", 200); lblAngle = addStatLabel("X", 215); lblSpeed = addStatLabel("X", 230); // Themes window themeColorWheel = new UIColorWheel(this, 45, 40); themeColorWheel.setEventHandler( new UIAction() { public void change(UIColorWheel wheel) { theme.setColor((Types) themeDrop.getSelected(), wheel.getColor()); } }); tabTheme.addObject(themeColorWheel); themeDrop = new UIDropdown<Types>(this, 25, 10, 200, theme.getKeys()); themeDrop.setEventHandler( new UIAction() { public void change(@SuppressWarnings("rawtypes") UIDropdown drop) { themeColorWheel.setColor(theme.getColor((Types) drop.getSelected())); } }); tabTheme.addObject(themeDrop); // adds mouse scrolling listener to the applet addMouseWheelListener( new MouseWheelListener() { public void mouseWheelMoved(MouseWheelEvent event) { mouseWheel(event); } }); }