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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org