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