blob: 86d1b3c5027177825a49c86d386d55e21e940a4a [file] [log] [blame]
刘洪青6266f992017-05-15 21:21:03 +08001<?xml version="1.0" encoding="UTF-8"?>
2<!--
3 Licensed to the Apache Software Foundation (ASF) under one or more
4 contributor license agreements. See the NOTICE file distributed with
5 this work for additional information regarding copyright ownership.
6 The ASF licenses this file to You under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with
8 the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17-->
18<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
19<head>
20 <title>Apache Tomcat WebSocket Examples: Multiplayer Snake</title>
21 <style type="text/css"><![CDATA[
22 #playground {
23 width: 640px;
24 height: 480px;
25 background-color: #000;
26 }
27
28 #console-container {
29 float: left;
30 margin-left: 15px;
31 width: 300px;
32 }
33
34 #console {
35 border: 1px solid #CCCCCC;
36 border-right-color: #999999;
37 border-bottom-color: #999999;
38 height: 480px;
39 overflow-y: scroll;
40 padding-left: 5px;
41 padding-right: 5px;
42 width: 100%;
43 }
44
45 #console p {
46 padding: 0;
47 margin: 0;
48 }
49 ]]></style>
50</head>
51<body>
52 <div class="noscript"><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
53 Javascript and reload this page!</h2></div>
54 <div style="float: left">
55 <canvas id="playground" width="640" height="480"/>
56 </div>
57 <div id="console-container">
58 <div id="console"/>
59 </div>
60 <script type="application/javascript"><![CDATA[
61
62 var Game = {};
63
64 Game.fps = 30;
65 Game.socket = null;
66 Game.nextFrame = null;
67 Game.interval = null;
68 Game.direction = 'none';
69 Game.gridSize = 10;
70
71 function Snake() {
72 this.snakeBody = [];
73 this.color = null;
74 }
75
76 Snake.prototype.draw = function(context) {
77 for (var id in this.snakeBody) {
78 context.fillStyle = this.color;
79 context.fillRect(this.snakeBody[id].x, this.snakeBody[id].y, Game.gridSize, Game.gridSize);
80 }
81 };
82
83 Game.initialize = function() {
84 this.entities = [];
85 canvas = document.getElementById('playground');
86 if (!canvas.getContext) {
87 Console.log('Error: 2d canvas not supported by this browser.');
88 return;
89 }
90 this.context = canvas.getContext('2d');
91 window.addEventListener('keydown', function (e) {
92 var code = e.keyCode;
93 if (code > 36 && code < 41) {
94 switch (code) {
95 case 37:
96 if (Game.direction != 'east') Game.setDirection('west');
97 break;
98 case 38:
99 if (Game.direction != 'south') Game.setDirection('north');
100 break;
101 case 39:
102 if (Game.direction != 'west') Game.setDirection('east');
103 break;
104 case 40:
105 if (Game.direction != 'north') Game.setDirection('south');
106 break;
107 }
108 }
109 }, false);
110 if (window.location.protocol == 'http:') {
111 Game.connect('ws://' + window.location.host + '/examples/websocket/snake');
112 } else {
113 Game.connect('wss://' + window.location.host + '/examples/websocket/snake');
114 }
115 };
116
117 Game.setDirection = function(direction) {
118 Game.direction = direction;
119 Game.socket.send(direction);
120 Console.log('Sent: Direction ' + direction);
121 };
122
123 Game.startGameLoop = function() {
124 if (window.webkitRequestAnimationFrame) {
125 Game.nextFrame = function () {
126 webkitRequestAnimationFrame(Game.run);
127 };
128 } else if (window.mozRequestAnimationFrame) {
129 Game.nextFrame = function () {
130 mozRequestAnimationFrame(Game.run);
131 };
132 } else {
133 Game.interval = setInterval(Game.run, 1000 / Game.fps);
134 }
135 if (Game.nextFrame != null) {
136 Game.nextFrame();
137 }
138 };
139
140 Game.stopGameLoop = function () {
141 Game.nextFrame = null;
142 if (Game.interval != null) {
143 clearInterval(Game.interval);
144 }
145 };
146
147 Game.draw = function() {
148 this.context.clearRect(0, 0, 640, 480);
149 for (var id in this.entities) {
150 this.entities[id].draw(this.context);
151 }
152 };
153
154 Game.addSnake = function(id, color) {
155 Game.entities[id] = new Snake();
156 Game.entities[id].color = color;
157 };
158
159 Game.updateSnake = function(id, snakeBody) {
160 if (typeof Game.entities[id] != "undefined") {
161 Game.entities[id].snakeBody = snakeBody;
162 }
163 };
164
165 Game.removeSnake = function(id) {
166 Game.entities[id] = null;
167 // Force GC.
168 delete Game.entities[id];
169 };
170
171 Game.run = (function() {
172 var skipTicks = 1000 / Game.fps, nextGameTick = (new Date).getTime();
173
174 return function() {
175 while ((new Date).getTime() > nextGameTick) {
176 nextGameTick += skipTicks;
177 }
178 Game.draw();
179 if (Game.nextFrame != null) {
180 Game.nextFrame();
181 }
182 };
183 })();
184
185 Game.connect = (function(host) {
186 if ('WebSocket' in window) {
187 Game.socket = new WebSocket(host);
188 } else if ('MozWebSocket' in window) {
189 Game.socket = new MozWebSocket(host);
190 } else {
191 Console.log('Error: WebSocket is not supported by this browser.');
192 return;
193 }
194
195 Game.socket.onopen = function () {
196 // Socket open.. start the game loop.
197 Console.log('Info: WebSocket connection opened.');
198 Console.log('Info: Press an arrow key to begin.');
199 Game.startGameLoop();
200 setInterval(function() {
201 // Prevent server read timeout.
202 Game.socket.send('ping');
203 }, 5000);
204 };
205
206 Game.socket.onclose = function () {
207 Console.log('Info: WebSocket closed.');
208 Game.stopGameLoop();
209 };
210
211 Game.socket.onmessage = function (message) {
212 // _Potential_ security hole, consider using json lib to parse data in production.
213 var packet = eval('(' + message.data + ')');
214 switch (packet.type) {
215 case 'update':
216 for (var i = 0; i < packet.data.length; i++) {
217 Game.updateSnake(packet.data[i].id, packet.data[i].body);
218 }
219 break;
220 case 'join':
221 for (var j = 0; j < packet.data.length; j++) {
222 Game.addSnake(packet.data[j].id, packet.data[j].color);
223 }
224 break;
225 case 'leave':
226 Game.removeSnake(packet.id);
227 break;
228 case 'dead':
229 Console.log('Info: Your snake is dead, bad luck!');
230 Game.direction = 'none';
231 break;
232 case 'kill':
233 Console.log('Info: Head shot!');
234 break;
235 }
236 };
237 });
238
239 var Console = {};
240
241 Console.log = (function(message) {
242 var console = document.getElementById('console');
243 var p = document.createElement('p');
244 p.style.wordWrap = 'break-word';
245 p.innerHTML = message;
246 console.appendChild(p);
247 while (console.childNodes.length > 25) {
248 console.removeChild(console.firstChild);
249 }
250 console.scrollTop = console.scrollHeight;
251 });
252
253 Game.initialize();
254
255
256 document.addEventListener("DOMContentLoaded", function() {
257 // Remove elements with "noscript" class - <noscript> is not allowed in XHTML
258 var noscripts = document.getElementsByClassName("noscript");
259 for (var i = 0; i < noscripts.length; i++) {
260 noscripts[i].parentNode.removeChild(noscripts[i]);
261 }
262 }, false);
263
264 ]]></script>
265</body>
266</html>