Skip to content

Commit

Permalink
Merge branch 'master' into readme-edits
Browse files Browse the repository at this point in the history
  • Loading branch information
m516 authored Mar 10, 2017
2 parents 178b486 + 71c7aab commit b276213
Show file tree
Hide file tree
Showing 23 changed files with 1,420 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
17 changes: 17 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Snake 1</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
11 changes: 11 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SnakeApp

This project is an application that allows users to program a snake and compete against other snakes on the web. It serves as a client to ThePowerRule's SnakeServer application. Although two test snakes are provided, it is up to users to program intelligent snakes that can compete in online arenas.
Installation instructions:
1. Install EGit.
Expand All @@ -16,4 +17,4 @@ Now you should be able to select Clone URI or Existing Local Repository. Hit Cl
In the URI text box type "https://github.com/ThePowerRule/SnakeApp/" and click next.
Select the master branch and hit next.
Create a directory to store your new project.
You're done!
You're done!
2 changes: 2 additions & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/application/
/gui/
Binary file added bin/gui/GUI.class
Binary file not shown.
Binary file added bin/gui/GUIController.class
Binary file not shown.
74 changes: 74 additions & 0 deletions bin/gui/GUILayout.fxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.effect.Reflection?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.paint.LinearGradient?>
<?import javafx.scene.paint.Stop?>
<?import javafx.scene.text.Font?>

<AnchorPane fx:id="windowPane" maxHeight="512.0" maxWidth="640.0" minHeight="512.0" minWidth="640.0" prefHeight="512.0" prefWidth="640.0" scaleShape="false" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.GUIController">
<children>
<AnchorPane fx:id="arenaPane" minHeight="384.0" minWidth="384.0" prefHeight="512.0" prefWidth="384.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="256.0" AnchorPane.topAnchor="0.0">
<children>
<Canvas fx:id="arena" height="384.0" width="384.0" AnchorPane.bottomAnchor="256.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Canvas fx:id="arenaInfo" height="128.0" layoutY="384.0" width="384.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="384.0" />
</children>
</AnchorPane>
<AnchorPane fx:id="infoPane" layoutX="396.0" prefHeight="512.0" AnchorPane.rightAnchor="0.0">
<children>
<Label fx:id="textName" contentDisplay="CENTER" graphicTextGap="0.0" prefHeight="36.0" prefWidth="256.0" text="Snake Name" textAlignment="CENTER" textOverrun="WORD_ELLIPSIS" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<font>
<Font name="Eurostile Bold" size="32.0" />
</font>
<effect>
<Reflection fraction="0.53" topOffset="-10.0" topOpacity="1.0" />
</effect>
<textFill>
<LinearGradient cycleMethod="REFLECT" endX="0.5095238095238095" endY="1.0" startX="0.5285714285714286">
<stops>
<Stop color="#616b75" />
<Stop color="#0d0c11" offset="0.9923371647509578" />
<Stop color="#0d0c11" offset="1.0" />
</stops>
</LinearGradient>
</textFill>
</Label>
<LineChart fx:id="statusGraph" layoutX="42.0" layoutY="46.0" prefHeight="196.0" prefWidth="128.0" AnchorPane.leftAnchor="42.0" AnchorPane.topAnchor="46.0">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" tickLabelRotation="-14.0" />
</yAxis>
</LineChart>
<Label fx:id="textWins" layoutY="65.0" prefHeight="17.0" prefWidth="74.0" text="Wins: 1" AnchorPane.leftAnchor="0.0">
<font>
<Font name="Eurostile Bold" size="16.0" />
</font>
</Label>
<Label fx:id="textLosses" layoutY="82.0" prefHeight="17.0" prefWidth="74.0" text="Losses: 1" AnchorPane.leftAnchor="0.0" />
<Label fx:id="textStatus" layoutY="135.0" prefHeight="17.0" prefWidth="74.0" text="Top 15%" AnchorPane.leftAnchor="0.0">
<font>
<Font name="Eurostile Bold" size="16.0" />
</font>
</Label>
<Button fx:id="buttonServer" layoutX="177.0" layoutY="460.0" mnemonicParsing="false" onAction="#buttonGoPressed" prefHeight="24.0" prefWidth="35.0" text="Go!" AnchorPane.leftAnchor="177.0" />
<TableView fx:id="listSnakes" editable="true" layoutX="28.0" layoutY="241.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.leftAnchor="28.0">
<columns>
<TableColumn fx:id="mySnakes" prefWidth="199.0" text="My snakes" />
</columns>
</TableView>
<TextField fx:id="textfieldServer" layoutX="14.0" layoutY="460.0" onAction="#serverAddressEntered" prefHeight="25.0" prefWidth="163.0" promptText="Go to server" text="127.0.0.1" />
</children>
</AnchorPane>
</children>
</AnchorPane>
1 change: 1 addition & 0 deletions bin/gui/application.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
12 changes: 12 additions & 0 deletions src/application/AppConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package application;

public class AppConfig {
public static void addSnakes(){
SnakeManager.addSnake(new TestSnake());
SnakeManager.addSnake(new TestSnake());
SnakeManager.addSnake(new TestSnake());
SnakeManager.addSnake(new TestSnake());
SnakeManager.addSnake(new TestSnake());
System.out.println("AddSnake called");
}
}
29 changes: 29 additions & 0 deletions src/application/AppManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package application;
import java.util.HashMap;
import java.util.Map;
import gui.*;

public class AppManager{
private static AppManager currentAppManager;
private Map<Class<?>,String> snakeTypes = new HashMap<Class<?>, String>();
//private static GUIController controller = new GUIController();
private AppManager(){
}
private void init(){
//Initialize and configure the snake.
AppConfig.addSnakes();
System.out.println("AppManager Initialized!");
}
public static void main(String[] args) {
currentAppManager = new AppManager();
currentAppManager.init();
//Launch GUI
GUI.run();
}
public void addSnakeType(Class<?> snakeClass, String snakeName) {
snakeTypes.put(snakeClass, snakeName);
}
public static AppManager getCurrentAppManager() {
return currentAppManager;
}
}
164 changes: 164 additions & 0 deletions src/application/Arena.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//TODO Add functionality for multiple snakes
package application;
import javafx.application.Platform;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;

public class Arena{
/*
* Arenas are composed of byte arrays which represent what occupies each cell in the array
* ERR - Dark grey - no data retrieved or bad data given for this cell
* EMPTY - Black - this cell is unoccupied
* WALL - White - this cell is a wall block
* FRUIT - Magenta - this cell is occupied by a fruit
* SNAKE - snake-specific - this cell is occupied by a snake segment
*/
public static final byte ERR = 0, EMPTY = 1, WALL = 2, FRUIT = 3;
/*
* Commands from the server to the arena are sent with these keys
* ERR - bad message to server, followed by a command number, which
* requests the client application to repeat the command
* ARENA_CONFIG - requests the client to resize the arena to the x_size and y_size
* ARENA_DISPLAY - the updated arena, followed by all of the pixels
* END - An end of a command
*/
public static final int END = -2, ARENA_CONFIG = -3, ARENA_DISPLAY = -4, SNAKE_CONFIG = -6;
private static volatile byte[][] arena;
private static int xSize, ySize;
public static Arena instance = new Arena();
static Color[] snakeColors;
private static GraphicsContext graphics;
static Color bkg;
private static Canvas canvas;
private Arena(){
}
public static int getXSize() {
return xSize;
}
public static int getYSize() {
return ySize;
}
/**Initializes a new arena
* Snakes must not call this method or ANY OTHER MUTATOR METHODS in this class!
* It will throw errors in the application and will not change anything in the server.
*/
public static void init(int new_x_size, int new_y_size, int numSnakes){
arena = new byte[new_x_size][new_y_size];
xSize = new_x_size;
ySize = new_y_size;
for (int i = 0; i < arena.length; i++) {
for (int j = 0; j < arena[i].length; j++) {
arena[i][j] = ERR;
}
}
snakeColors = new Color[numSnakes+1];
for(int i = 0; i <= numSnakes; i ++){
snakeColors[i] = Color.hsb(360.0*(float)i/(float)numSnakes, 1f, 1f);
}
}
public static void setBlock(int x, int y, byte type){
arena[x][y] = type;
}
public static int getBlock(int x, int y){
return arena[x][y];
}
public static void setCanvas(Canvas newCanvas){
canvas = newCanvas;
graphics = canvas.getGraphicsContext2D();
}

public synchronized void repaint(){
Platform.runLater(() -> {
int snakeID = SnakeManager.getSnake(0).getID()-1 - FRUIT;
if(snakeID > 0){
bkg = snakeColors[snakeID].darker().darker();
}
else{
bkg = Color.BLACK;
}
graphics.setFill(bkg);
graphics.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
for(int i = 0; i < arena.length; i ++){
byte[] column = arena[i];
Paint c;
for (int j = 0; j < column.length; j++) {
byte cell = arena[i][j];
switch(cell){
case EMPTY:
if(bkg==null)
c = Color.BLACK;
else c = bkg;
break;
case WALL:
c = Color.LIGHTGRAY;
break;
case FRUIT:
c = Color.MAGENTA;
break;
default:
if(cell < snakeColors.length+FRUIT && cell > FRUIT){
c = snakeColors[cell-FRUIT-1];
}
else c = Color.DARKGRAY;
break;
}
drawCell(i,j,c);
}

}
});
}

void drawCell(int x, int y, Paint c){
int blockWidth = (int) (canvas.getWidth()/arena.length);
int blockHeight = (int) (canvas.getHeight()/arena[0].length);
//Rectangle rect = new Rectangle(x*blockWidth, y*blockHeight, blockWidth, blockHeight);
graphics.setFill(Color.web(c.toString()));
graphics.fillRect(x*blockWidth, y*blockHeight, blockWidth, blockHeight);
}
/**
* Returns a constructed rectangle at a certain position in the arena.
* This method is depreciated because all of the cells are drawn directly on the Arena canvas
* @param x - the x-coordinate of the cell in the arena
* @param y - the y-coordinate of the cell in the arena
* @param p - the color/gradient/texture of the cell
* @return a rectangle to be displayed on the Arena canvas
*/
@Deprecated
Rectangle getCell(int x, int y, Paint p){
int blockWidth = (int) (canvas.getWidth()/arena.length);
int blockHeight = (int) (canvas.getHeight()/arena[0].length);
Rectangle r = new Rectangle(x*blockWidth, y*blockHeight, blockWidth, blockHeight);
r.setFill(p);
return r;
}
public synchronized static boolean retrieveCommand(int commandType, Integer[] command){
try{
switch(commandType){
case ARENA_CONFIG:
Console.addText("Arena configured");
init(command[0], command[1], command[2]);
break;
case ARENA_DISPLAY:
for(int i = 0; i < command.length; i ++){
int num = command[i];
int y = i%ySize, x = i/ySize;
setBlock(x,y,(byte)num);
}
instance.repaint();
break;
default:
return false;
}
}
catch(Exception e){
e.printStackTrace();
return false;
}
return true;
}
}

31 changes: 31 additions & 0 deletions src/application/Console.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package application;

public class Console{
//private static String[] lines = new String[64];
//private static int numLines = 0;
//private static TextArea gui = new TextArea("Welcome!");
public static void init() {
//gui.setEditable(false);
//lines = new String[64];
//numLines = 0;
}
public static void addText(String str) {
/*
numLines ++;
if(numLines == lines.length) {
for(int i = 0; i < lines.length-1; i ++) {
lines[i] = lines[i+1];
}
numLines--;
}
lines[numLines] = str;
String strings = "";
for(int i = numLines; i >= 0; i --){
String s = lines[i];
if(s != null) strings += s + "\n";
}
gui.setText(strings);
*/
System.out.println(str);
}
}
Loading

0 comments on commit b276213

Please sign in to comment.