Author: markt
Date: Tue Mar 6 22:21:11 2012
New Revision: 1297760
URL: http://svn.apache.org/viewvc?rev=1297760&view=rev
Log:
Fix collision bug (steering into your own snake now kills the snake)
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/Snake.java
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/SnakeWebSocketServlet.java
tomcat/trunk/webapps/examples/websocket/snake.html
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/Snake.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/Snake.java?rev=1297760&r1=1297759&r2=1297760&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/Snake.java
(original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/Snake.java
Tue Mar 6 22:21:11 2012
@@ -21,19 +21,20 @@ import java.nio.CharBuffer;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
-import java.util.Iterator;
import org.apache.catalina.websocket.WsOutbound;
public class Snake {
- private static final int DEFAULT_LENGTH = 6;
+ private static final int DEFAULT_LENGTH = 5;
private final int id;
private final WsOutbound outbound;
private Direction direction;
- private Deque<Location> locations = new ArrayDeque<Location>();
+ private int length = DEFAULT_LENGTH;
+ private Location head;
+ private Deque<Location> tail = new ArrayDeque<Location>();
private String hexColor;
public Snake(int id, WsOutbound outbound) {
@@ -45,14 +46,12 @@ public class Snake {
private void resetState() {
this.direction = Direction.NONE;
- this.locations.clear();
- Location startLocation = SnakeWebSocketServlet.getRandomLocation();
- for (int i = 0; i < DEFAULT_LENGTH; i++) {
- locations.add(startLocation);
- }
+ this.head = SnakeWebSocketServlet.getRandomLocation();
+ this.tail.clear();
+ this.length = DEFAULT_LENGTH;
}
- private void kill() {
+ private synchronized void kill() {
resetState();
try {
CharBuffer response = CharBuffer.wrap("{'type': 'dead'}");
@@ -62,8 +61,8 @@ public class Snake {
}
}
- private void reward() {
- grow();
+ private synchronized void reward() {
+ length++;
try {
CharBuffer response = CharBuffer.wrap("{'type': 'kill'}");
outbound.writeTextMessage(response);
@@ -73,8 +72,7 @@ public class Snake {
}
public synchronized void update(Collection<Snake> snakes) {
- Location firstLocation = locations.getFirst();
- Location nextLocation = firstLocation.getAdjacentLocation(direction);
+ Location nextLocation = head.getAdjacentLocation(direction);
if (nextLocation.x >= SnakeWebSocketServlet.PLAYFIELD_WIDTH) {
nextLocation.x = 0;
}
@@ -87,42 +85,40 @@ public class Snake {
if (nextLocation.y < 0) {
nextLocation.y = SnakeWebSocketServlet.PLAYFIELD_HEIGHT;
}
- locations.addFirst(nextLocation);
- locations.removeLast();
+ if (direction != Direction.NONE) {
+ tail.addFirst(head);
+ if (tail.size() > length) {
+ tail.removeLast();
+ }
+ head = nextLocation;
+ }
for (Snake snake : snakes) {
- if (snake.getId() != getId() &&
- colliding(snake.getHeadLocation())) {
- snake.kill();
- reward();
+ if (snake.getTail().contains(head)) {
+ kill();
+ if (id != snake.id) {
+ snake.reward();
+ }
}
}
}
- private void grow() {
- Location lastLocation = locations.getLast();
- Location newLocation = new Location(lastLocation.x, lastLocation.y);
- locations.add(newLocation);
- }
-
- private boolean colliding(Location location) {
- return direction != Direction.NONE && locations.contains(location);
+ public synchronized Collection<Location> getTail() {
+ return tail;
}
- public void setDirection(Direction direction) {
+ public synchronized void setDirection(Direction direction) {
this.direction = direction;
}
public synchronized String getLocationsJson() {
StringBuilder sb = new StringBuilder();
- for (Iterator<Location> iterator = locations.iterator();
- iterator.hasNext();) {
- Location location = iterator.next();
+ sb.append(String.format("{x: %d, y: %d}",
+ Integer.valueOf(head.x), Integer.valueOf(head.y)));
+ for (Location location : tail) {
+ sb.append(',');
sb.append(String.format("{x: %d, y: %d}",
Integer.valueOf(location.x), Integer.valueOf(location.y)));
- if (iterator.hasNext()) {
- sb.append(',');
- }
}
return String.format("{'id':%d,'body':[%s]}",
Integer.valueOf(id), sb.toString());
@@ -135,8 +131,4 @@ public class Snake {
public String getHexColor() {
return hexColor;
}
-
- public synchronized Location getHeadLocation() {
- return locations.getFirst();
- }
}
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/SnakeWebSocketServlet.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/SnakeWebSocketServlet.java?rev=1297760&r1=1297759&r2=1297760&view=diff
==============================================================================
---
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/SnakeWebSocketServlet.java
(original)
+++
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/SnakeWebSocketServlet.java
Tue Mar 6 22:21:11 2012
@@ -101,6 +101,7 @@ public class SnakeWebSocketServlet exten
CharBuffer response = CharBuffer.wrap(message);
connection.getWsOutbound().writeTextMessage(response);
} catch (IOException ignore) {
+ // Ignore
}
}
}
@@ -196,13 +197,13 @@ public class SnakeWebSocketServlet exten
@Override
protected void onTextMessage(CharBuffer charBuffer) throws IOException
{
String message = charBuffer.toString();
- if ("left".equals(message)) {
+ if ("west".equals(message)) {
snake.setDirection(Direction.WEST);
- } else if ("up".equals(message)) {
+ } else if ("north".equals(message)) {
snake.setDirection(Direction.NORTH);
- } else if ("right".equals(message)) {
+ } else if ("east".equals(message)) {
snake.setDirection(Direction.EAST);
- } else if ("down".equals(message)) {
+ } else if ("south".equals(message)) {
snake.setDirection(Direction.SOUTH);
}
}
Modified: tomcat/trunk/webapps/examples/websocket/snake.html
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/websocket/snake.html?rev=1297760&r1=1297759&r2=1297760&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/websocket/snake.html (original)
+++ tomcat/trunk/webapps/examples/websocket/snake.html Tue Mar 6 22:21:11 2012
@@ -67,6 +67,7 @@
Game.socket = null;
Game.nextFrame = null;
Game.interval = null;
+ Game.direction = 'none';
Game.gridSize = 10;
function Snake() {
@@ -94,24 +95,29 @@
if (code > 36 && code < 41) {
switch (code) {
case 37:
- Game.socket.send('left');
+ if (Game.direction != 'east')
Game.setDirection('west');
break;
case 38:
- Game.socket.send('up');
+ if (Game.direction != 'south')
Game.setDirection('north');
break;
case 39:
- Game.socket.send('right');
+ if (Game.direction != 'west')
Game.setDirection('east');
break;
case 40:
- Game.socket.send('down');
+ if (Game.direction != 'north')
Game.setDirection('south');
break;
}
- Console.log('Sent: keyCode ' + code);
}
}, false);
Game.connect('ws://' + window.location.host +
'/examples/websocket/snake');
};
+ Game.setDirection = function(direction) {
+ Game.direction = direction;
+ Game.socket.send(direction);
+ Console.log('Sent: Direction ' + direction);
+ };
+
Game.startGameLoop = function() {
if (window.webkitRequestAnimationFrame) {
Game.nextFrame = function () {
@@ -156,7 +162,8 @@
Game.removeSnake = function(id) {
Game.entities[id] = null;
- delete Game.entities[id]; // force GC
+ // Force GC.
+ delete Game.entities[id];
};
Game.run = (function() {
@@ -184,12 +191,13 @@
}
Game.socket.onopen = function () {
- // Socket initialised.. start the game loop
+ // Socket open.. start the game loop.
Console.log('Info: WebSocket connection opened.');
Console.log('Info: Press an arrow key to begin.');
Game.startGameLoop();
setInterval(function() {
- Game.socket.send('ping'); // prevent server read timeout
+ // Prevent server read timeout.
+ Game.socket.send('ping');
}, 5000);
};
@@ -199,7 +207,8 @@
};
Game.socket.onmessage = function (message) {
- var packet = eval('(' + message.data + ')'); // Consider using
json lib to parse data.
+ // _Potential_ security hole, consider using json lib to parse
data in production.
+ var packet = eval('(' + message.data + ')');
switch (packet.type) {
case 'update':
for (var i = 0; i < packet.data.length; i++) {
@@ -216,6 +225,7 @@
break;
case 'dead':
Console.log('Info: Your snake is dead, bad luck!');
+ Game.direction = 'none';
break;
case 'kill':
Console.log('Info: Head shot!');
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]