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

Reply via email to