OLD | NEW |
| (Empty) |
1 // Copyright 2011 (c) The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @file | |
7 * The JavaScript user interface of the Hex game. Maintains the | |
8 * basic board state (red,blue,clear) and communicates with the nexe | |
9 * AI program. | |
10 */ | |
11 | |
12 // Provide the HexGame namespace | |
13 HexGame = {}; | |
14 | |
15 HexGame.LEFT_OFFSET = 100; | |
16 HexGame.TOP_OFFSET = 50; | |
17 HexGame.HEX_SIZE = 50; | |
18 HexGame.HALF_HEX_SIZE = HexGame.HEX_SIZE / 2; | |
19 HexGame.Cos60 = 0.50; | |
20 HexGame.Sin60 = 0.866025403784439; | |
21 HexGame.WHITE = 'rgb(255,255,255)'; | |
22 var X_DELTA = HexGame.HEX_SIZE * HexGame.Cos60; | |
23 var Y_DELTA = HexGame.HEX_SIZE * HexGame.Sin60; | |
24 var Y_HEX_SIZE = 2 * Y_DELTA; | |
25 var X_HEX_SIZE = 2 * X_DELTA + HexGame.HALF_HEX_SIZE; | |
26 | |
27 var canvas; | |
28 var canvasBk; | |
29 var hexTurnColor; | |
30 var ctx; | |
31 var ctxBk; | |
32 var x = 75; | |
33 var y = 50; | |
34 var WIDTH = 900; | |
35 var HEIGHT = 800; | |
36 | |
37 var maxRows = 8; // how many 'rows' of hexes | |
38 var redColor = 'rgb(255,182,193)'; | |
39 | |
40 var received_game_loop_ready = false; | |
41 var whoseTurn = 'R'; // turn in 'B' or 'R' | |
42 var gameWinner = ''; // set when we get a winner | |
43 var turnNumber = 1; | |
44 var lastUserColumn = 0; | |
45 var lastUserRow = 0; | |
46 | |
47 // global variable for the board (2D array of hexagons). | |
48 // theBoard also maintains state information about what is | |
49 // currently happening / expected in the UI. | |
50 var theBoard; | |
51 | |
52 function handleMessage(message_event) { | |
53 console.log('handleMessage RECVD[' + message_event.data + ']'); | |
54 | |
55 var result = message_event.data; | |
56 if (result == "INVALIDMOVE") { | |
57 alert('The last move ' + lastUserColumn + ':' + lastUserRow + ' was NOT vali
d'); | |
58 hexTurnColor = Board.HexType.RED; | |
59 whoseTurn = 'R'; | |
60 } else if (result == "COMPUTERWINS") { | |
61 gameWinner = 'The computer won'; | |
62 alert('Sorry, the Computer won the game!'); | |
63 updateHtmlField('Turn', gameWinner); | |
64 } else if (result == "USERWINS") { | |
65 gameWinner = 'The user won'; | |
66 alert('Congratulations, you won the game!'); | |
67 updateHtmlField('Turn', gameWinner); | |
68 } else if (result.indexOf("COMPUTERMOVE:") != -1) { | |
69 console.log('RECIEVED COMPUTER MOVE ' + result + ' whoseTurn=' + | |
70 whoseTurn + ' hexTurnColor=' + hexTurnColor); | |
71 colon_char = result.indexOf(":"); | |
72 result = result.substring(colon_char+1); | |
73 var moveArray = result.split(','); | |
74 var col = parseInt(moveArray[0]); | |
75 var row = parseInt(moveArray[1]); | |
76 | |
77 var colorAtHex = theBoard.getHex(col, row); | |
78 if (colorAtHex == Board.HexType.RED) { | |
79 alert('ERROR: Computer is trying to go to ' + col + ':' + row + ' which is
already ' + colorAtHex); | |
80 return; | |
81 } | |
82 if (colorAtHex == Board.HexType.BLUE) { | |
83 // Sometimes happens when computer wins...because final move is | |
84 // sent to make sure that it does get drawn | |
85 return; | |
86 } | |
87 | |
88 console.log('Setting hex ' + col + ':' + row + ' to ' + hexTurnColor); | |
89 theBoard.setHex(col, row, hexTurnColor); | |
90 console.log('SetHex, whoseTurn was ' + whoseTurn); | |
91 if (hexTurnColor == Board.HexType.RED) { | |
92 hexTurnColor = Board.HexType.BLUE; | |
93 whoseTurn = 'B'; | |
94 } else { | |
95 hexTurnColor = Board.HexType.RED; | |
96 whoseTurn = 'R'; | |
97 turnNumber++; //after a blue move, bump turn number | |
98 } | |
99 console.log('whoseTurn now is ' + whoseTurn); | |
100 theBoard.initDraw(ctxBk); | |
101 } else if (result.indexOf("GAME_LOOP_READY") != -1) { | |
102 console.log('RECEIVED READY: ' + result); | |
103 received_game_loop_ready = true; | |
104 } else { | |
105 console.log('DID NOT HANDLE ' + result); | |
106 } | |
107 } | |
108 | |
109 function clearContext(theContext) { | |
110 theContext.beginPath(); | |
111 theContext.clearRect(0, 0, canvas.width, canvas.height); | |
112 theContext.closePath(); | |
113 } | |
114 | |
115 // Convert an xCoord to a column | |
116 function xToColumn(xCoord) { | |
117 // TODO: handle the 'pointy parts' of a hex | |
118 var column = Math.floor((xCoord - HexGame.LEFT_OFFSET) / X_HEX_SIZE); | |
119 return column; | |
120 } | |
121 | |
122 // Convert a column, yCoord to a row | |
123 function yToRow(column, yCoord) { | |
124 // TODO: handle the 'pointy parts' of a hex | |
125 var columnTop = yCoord - 30; | |
126 if (column % 2 == 1) { | |
127 columnTop -= Y_DELTA; | |
128 } | |
129 var row = Math.floor(columnTop / Y_HEX_SIZE); | |
130 var rowFloat = columnTop / Y_HEX_SIZE; | |
131 | |
132 var columnWithMaxRows = Math.floor(theBoard.columns_ / 2) + 1; // column with
max number of rows | |
133 // var adjusted column for layout | |
134 var columnsFromCenter = Math.floor(Math.abs(columnWithMaxRows - column)); | |
135 console.log('columnsFromCenter='+columnsFromCenter); | |
136 var numRows = Math.abs(columnWithMaxRows - columnsFromCenter); | |
137 var firstRow = Math.floor((theBoard.rows_ - numRows) / 2); | |
138 if (column%2==1) { firstRow--; } | |
139 | |
140 var adjusted_row = row - firstRow - 1; | |
141 return adjusted_row; | |
142 } | |
143 | |
144 // note: Uses ctx.fillColor to fill | |
145 function drawHex(ctx, column, row, logicalColumn, logicalRow, isLastRow, color)
{ | |
146 | |
147 ctx.fillStyle = color; | |
148 | |
149 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * column; | |
150 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * row; | |
151 if (column % 2 == 1) y += Y_DELTA; | |
152 y += HexGame.HALF_HEX_SIZE; | |
153 ctx.beginPath(); | |
154 ctx.moveTo(x, y); | |
155 var lineThickness = ctx.lineThickness; | |
156 var lineWidth = ctx.lineWidth; | |
157 x += X_DELTA; | |
158 y += Y_DELTA; | |
159 ctx.lineTo(x, y); | |
160 x += HexGame.HEX_SIZE; | |
161 ctx.lineTo(x, y); | |
162 x += X_DELTA; | |
163 y -= Y_DELTA; | |
164 ctx.lineTo(x, y); | |
165 x -= X_DELTA; | |
166 y -= Y_DELTA; | |
167 ctx.lineTo(x, y); | |
168 x -= HexGame.HEX_SIZE; | |
169 ctx.lineTo(x, y); | |
170 x -= X_DELTA; | |
171 y += Y_DELTA; | |
172 ctx.lineTo(x, y); | |
173 ctx.stroke(); | |
174 ctx.fill(); // fill hex with the color set before calling HexGame (red,blue) | |
175 ctx.closePath(); | |
176 | |
177 /*** Experimental code to draw circles instead of a filled hex -- use this if | |
178 you comment out the ctx.fill() call a few lines above. | |
179 | |
180 if (color != HexGame.WHITE) { | |
181 var midx = HexGame.LEFT_OFFSET + X_HEX_SIZE * column + X_HEX_SIZE/1.4; | |
182 var midy = HexGame.TOP_OFFSET + Y_HEX_SIZE * row + Y_HEX_SIZE/3; | |
183 if (column % 2 == 1) midy += Y_DELTA; | |
184 ctx.beginPath(); | |
185 ctx.arc( midx, midy, X_HEX_SIZE/3, Y_HEX_SIZE/3, true); | |
186 ctx.closePath(); | |
187 ctx.fill(); | |
188 } | |
189 ***/ | |
190 | |
191 ctx.lineThickness = lineThickness; | |
192 | |
193 var showAlerts = false; | |
194 // if this is an edge...add an extra line topLeft,bottomRight = blue; topRig
ht,bottomLeft = red | |
195 // FIXME -- hardcoded to 11 being middle, etc. | |
196 var strokeStyle = ctx.strokeStyle; | |
197 if (logicalRow==1 && logicalColumn >= 1 && logicalColumn < 11 ) { | |
198 if(showAlerts) {alert('top left');} | |
199 // then the two 'top left' segments should be blue | |
200 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * column; | |
201 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * row; | |
202 if (column % 2 == 1) y += Y_DELTA; | |
203 y += HexGame.HALF_HEX_SIZE; | |
204 ctx.strokeStyle = 'rgb(0,0,255)'; | |
205 ctx.lineWidth = 12; | |
206 ctx.beginPath(); | |
207 ctx.moveTo(x, y); | |
208 x += X_DELTA; | |
209 y -= Y_DELTA; | |
210 ctx.lineTo(x, y); | |
211 x += HexGame.HEX_SIZE; | |
212 ctx.lineTo(x, y); | |
213 ctx.stroke(); | |
214 ctx.closePath(); | |
215 if(showAlerts) {alert('done TL');} | |
216 } | |
217 if (logicalRow==1 && logicalColumn >= 11 && logicalColumn <= 21) { | |
218 // then the two 'top right' segments should be red | |
219 if(showAlerts) {alert('top right');} | |
220 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * column + X_DELTA; | |
221 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * row - Y_DELTA; | |
222 if (column % 2 == 1) y += Y_DELTA; | |
223 y += HexGame.HALF_HEX_SIZE; | |
224 ctx.strokeStyle = 'rgb(255,0,0)'; | |
225 ctx.lineWidth = 12; | |
226 ctx.beginPath(); | |
227 ctx.moveTo(x, y); | |
228 x += HexGame.HEX_SIZE; | |
229 ctx.lineTo(x, y); | |
230 x += X_DELTA; | |
231 y += Y_DELTA | |
232 ctx.lineTo(x, y); | |
233 ctx.stroke(); | |
234 ctx.closePath(); | |
235 if(showAlerts) {alert('done TR');} | |
236 } | |
237 if (logicalRow == logicalColumn) { | |
238 // then it is a BOTTOM hex | |
239 //then the two 'bottom left' hexes need to be RED | |
240 if(showAlerts) {alert('bottom left');} | |
241 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * column; | |
242 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * row; | |
243 if (column % 2 == 1) y += Y_DELTA; | |
244 y += HexGame.HALF_HEX_SIZE; | |
245 ctx.strokeStyle = 'rgb(255,0,0)'; | |
246 ctx.lineWidth = 12; | |
247 ctx.beginPath(); | |
248 ctx.moveTo(x, y); | |
249 x += X_DELTA; | |
250 y += Y_DELTA; | |
251 ctx.lineTo(x, y); | |
252 x += HexGame.HEX_SIZE; | |
253 ctx.lineTo(x, y); | |
254 ctx.stroke(); | |
255 ctx.closePath(); | |
256 if(showAlerts) {alert('done BL');} | |
257 } | |
258 if (logicalRow + logicalColumn == 22 && logicalColumn > 11 && isLastRow) { | |
259 // then the two 'bottom right' segments should be BLUE | |
260 if(showAlerts) {alert('bottom right' + ' isLastRow=' + isLastRow + ' logic
alRow=' + logicalRow + ' logicalColumn=' + logicalColumn);} | |
261 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * (column-1) + X_DELTA * 2 + HexG
ame.HEX_SIZE; | |
262 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * row + Y_DELTA; // + HexGame.Y_HE
X_SIZE; | |
263 if (column % 2 == 1) y += Y_DELTA; | |
264 y += HexGame.HALF_HEX_SIZE; | |
265 ctx.strokeStyle = 'rgb(0,0,255)'; | |
266 ctx.lineWidth = 12; // WHY 16 and not 12 | |
267 ctx.beginPath(); | |
268 ctx.moveTo(x, y); | |
269 x += HexGame.HEX_SIZE; | |
270 ctx.lineTo(x, y); | |
271 x += X_DELTA; | |
272 y -= Y_DELTA | |
273 ctx.lineTo(x, y); | |
274 ctx.stroke(); | |
275 ctx.closePath(); | |
276 if(showAlerts) {alert('done bottom right');} | |
277 } | |
278 if (logicalColumn == 11 && logicalRow == 1) { | |
279 // ONE more little segment on top | |
280 if(showAlerts) {alert('top small');} | |
281 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * column; | |
282 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * row; | |
283 if (column % 2 == 1) y += Y_DELTA; | |
284 y += HexGame.HALF_HEX_SIZE; | |
285 ctx.strokeStyle = 'rgb(0,0,255)'; | |
286 ctx.lineWidth = 12; | |
287 ctx.beginPath(); | |
288 ctx.moveTo(x, y); | |
289 x += X_DELTA; | |
290 y -= Y_DELTA; | |
291 ctx.lineTo(x, y); | |
292 ctx.stroke(); | |
293 ctx.closePath(); | |
294 if(showAlerts) {alert('done top small');} | |
295 } | |
296 if (logicalColumn == 11 && logicalRow == 11) { | |
297 if(showAlerts) {alert('11 && 11');} | |
298 // ONE more little segment bottomright | |
299 var x = HexGame.LEFT_OFFSET + X_HEX_SIZE * column + X_HEX_SIZE; | |
300 var y = HexGame.TOP_OFFSET + Y_HEX_SIZE * (row) + Y_DELTA * 2; | |
301 y += HexGame.HALF_HEX_SIZE; | |
302 ctx.strokeStyle = 'rgb(0,0,255)'; | |
303 ctx.lineWidth = 12; | |
304 ctx.beginPath(); | |
305 ctx.moveTo(x, y); | |
306 x += X_DELTA; | |
307 y -= Y_DELTA; | |
308 ctx.lineTo(x, y); | |
309 ctx.stroke(); | |
310 ctx.closePath(); | |
311 if(showAlerts) {alert('done 11x11');} | |
312 } | |
313 ctx.lineThickness = lineThickness; | |
314 ctx.lineWidth = lineWidth; | |
315 ctx.strokeStyle = strokeStyle; | |
316 } | |
317 | |
318 /** | |
319 * Constructor for the Board: columns and rows of hexagons. | |
320 * hexColumn_ is a 2d array of the type of hexagon at each location. | |
321 */ | |
322 function Board(columns, rows) { | |
323 console.log('Creating Board ' + columns + ' x ' + rows); | |
324 this.columns_ = columns; | |
325 this.rows_ = rows; | |
326 this.hexColumn_ = new Array(); | |
327 for (var i = 1; i <= columns; ++i) { | |
328 this.hexColumn_[i] = new Array(); | |
329 for (var j = 1; j <= rows; ++j) { | |
330 this.hexColumn_[i][j] = Board.HexType.CLEAR; | |
331 } | |
332 } | |
333 this.turnState_ = 0; | |
334 } | |
335 | |
336 /** | |
337 * The values used for Board status to hex types. | |
338 */ | |
339 Board.HexType = { | |
340 CLEAR: 0, | |
341 RED: 1, | |
342 BLUE: 2 | |
343 }; | |
344 | |
345 Board.TurnState = { | |
346 MOVING: 0, | |
347 ATTACKING: 1, | |
348 }; | |
349 | |
350 | |
351 Board.prototype.setHex = function(column, row, hexType) { | |
352 console.log('setHex column=' + column + ' row=' + row + ' hexType=' + hexType)
; | |
353 this.hexColumn_[column][row] = hexType; | |
354 }; | |
355 Board.prototype.getHex = function(column, row) { | |
356 if (this.hexColumn_[column] == undefined || | |
357 this.hexColumn_[column][row] == undefined) { | |
358 return Board.HexType.CLEAR; | |
359 } | |
360 var value = this.hexColumn_[column][row]; | |
361 if (value == undefined || value == null) | |
362 return Board.HexType.CLEAR; | |
363 return this.hexColumn_[column][row]; | |
364 }; | |
365 Board.prototype.postMsg = function() { | |
366 if (!naclModule) { | |
367 console.log('No NaCl module'); | |
368 return; | |
369 } | |
370 var stringData = 'POST_BOARD ' + this.columns_ + | |
371 ' ' + this.rows_ + ' '; | |
372 for (i = 0; i < this.columns_; ++i) { | |
373 for (j = 0; j < this.rows_; ++j) { | |
374 var hexType = this.hexColumn_[i][j]; | |
375 stringData = stringData + hexType + ' '; | |
376 } | |
377 } | |
378 console.log('naclModule=' + naclModule + ' stringData: ' + stringData); | |
379 var result = naclModule.postMessage(stringData); | |
380 console.log('result = ' + result); | |
381 }; | |
382 | |
383 // | |
384 // If rows = 21, then max is 11 (21/2+1). | |
385 // For column = 0, firstRow is 5, lastRow is 5 | |
386 // For column = 1, firstRow is 4, lastRow is 5 | |
387 // For column = 2, firstRow is 4, lastRow is 6 | |
388 // For column = 11, firstRow is 0, lastRow is 11 | |
389 // For column = 12, firstRow is 0, lastRow is 10 | |
390 // | |
391 Board.prototype.initDraw = function(ctx) { | |
392 this.turnState = Board.TurnState.MOVING; | |
393 console.log('this.columns_: ' + this.columns_ + ' this.rows_:' + this.rows_); | |
394 var drawThisHex; | |
395 var fillColor; | |
396 | |
397 ctx.globalCompositeOperation = 'source-over'; | |
398 var columnWithMaxRows = Math.floor(this.columns_ / 2) + 1; // column with max
number of rows | |
399 for (i = 0; i <= this.columns_; ++i) { | |
400 | |
401 var columnsFromCenter = Math.floor(Math.abs(columnWithMaxRows - i)); | |
402 var numRows = Math.abs(columnWithMaxRows - columnsFromCenter); | |
403 var firstRow = Math.floor((this.rows_ - numRows) / 2); | |
404 if (i%2 == 0) { | |
405 firstRow++; | |
406 } | |
407 var lastRow = firstRow + numRows; | |
408 | |
409 for (j = 0; j <= this.rows_; ++j) { | |
410 fillColor = 'rgb(255,255,255)'; | |
411 drawThisHex = false; | |
412 if (j > firstRow && j <= lastRow) { | |
413 drawThisHex = true; | |
414 } | |
415 if (drawThisHex == false) { | |
416 fillColor = 'rgb(255,0,0)'; | |
417 } else { | |
418 var hexRow = j - firstRow; | |
419 var hexColumn = i + 1; | |
420 var adjCol = i; | |
421 var adjRow = hexRow; | |
422 // adjCol and adjRow are 1-based column-row from the game/user POV | |
423 var colorAtHex = this.getHex(adjCol, adjRow); | |
424 if (colorAtHex == Board.HexType.RED) { | |
425 ctx.strokeStyle = 'rgb(255,0,0)'; | |
426 fillColor = 'rgb(255,0,0)'; | |
427 } else if (colorAtHex == Board.HexType.BLUE) { | |
428 ctx.strokeStyle = 'rgb(0,0,255)'; // FIXME, use a constant for EACH
color | |
429 fillColor = 'rgb(0,0,255)'; | |
430 } else { | |
431 // if no one has the hex, then it's clear | |
432 ctx.strokeStyle = 'rgb(0,0,0)'; | |
433 } | |
434 } | |
435 // ctx.fillStyle = fillColor; | |
436 if(drawThisHex) { | |
437 drawHex(ctx, i, j, adjCol, adjRow, j == lastRow, fillColor); | |
438 } | |
439 } | |
440 } | |
441 | |
442 console.log('WhoseTurn=' + whoseTurn + ' turnNumber=' + turnNumber); | |
443 if (gameWinner != '') { | |
444 updateHtmlField('Turn', gameWinner); | |
445 } else { | |
446 updateHtmlField('Turn', 'TURN: ' + whoseTurn); | |
447 } | |
448 updateHtmlField('TurnNumber', 'Turn: Number: ' + turnNumber); | |
449 updateHtmlField('status_field', 'UPDATED'); | |
450 }; | |
451 | |
452 function InitHexGame() { | |
453 canvas = document.getElementById('canvas'); | |
454 canvasBk = document.getElementById('canvasBk'); | |
455 | |
456 ctx = canvas.getContext('2d'); | |
457 ctxBk = canvasBk.getContext('2d'); | |
458 | |
459 theBoard = new Board(21, 11); | |
460 theBoard.initDraw(ctxBk); | |
461 | |
462 hexTurnColor = Board.HexType.RED; | |
463 } | |
464 | |
465 function hexMouseDownHandler(e) { | |
466 var x = e.offsetX; | |
467 var y = e.offsetY; | |
468 var columnClicked = xToColumn(x); | |
469 var rowClicked = yToRow(columnClicked, y); | |
470 console.log(' hexMouseDownHandler: ' + columnClicked + ':' + rowClicked); | |
471 if (received_game_loop_ready == false) { | |
472 // then we are waiting for the game loop in the nexe to ge up and | |
473 // running...wait | |
474 alert('Sorry, the AI is still getting ready'); | |
475 return; | |
476 } | |
477 if (columnClicked <= 0 || rowClicked <= 0) { | |
478 return; | |
479 } | |
480 if (gameWinner != '') { | |
481 alert('Sorry, the game is over -- ' + gameWinner); | |
482 return; | |
483 } | |
484 if (whoseTurn == 'B') { | |
485 alert("Sorry, it's the computer's turn -- be patient!"); | |
486 return; | |
487 } | |
488 | |
489 // see if the hex has a color | |
490 var colorAtHex = theBoard.getHex(columnClicked, rowClicked); | |
491 console.log('colorAtHex = ' + colorAtHex + ' RED=' + Board.HexType.RED + ' CLE
AR=' + Board.HexType.CLEAR); | |
492 if (colorAtHex == Board.HexType.CLEAR) { | |
493 // then set it to the new color. | |
494 theBoard.setHex(columnClicked, rowClicked, hexTurnColor); | |
495 var stringData = 'USERMOVE ' + columnClicked + ':' + rowClicked; | |
496 console.log('setting hex ' + columnClicked + ':' + rowClicked + ' to ' + hex
TurnColor); | |
497 console.log(' In hexMouseDownHandler, hexTurnColor=' + hexTurnColor + ' whos
eTurn=' + whoseTurn); | |
498 if (hexTurnColor == Board.HexType.RED) { | |
499 hexTurnColor = Board.HexType.BLUE; | |
500 whoseTurn = 'B'; | |
501 } else { | |
502 hexTurnColor = Board.HexType.RED; | |
503 turnNumber++; //after a blue move, bump turn number | |
504 whoseTurn = 'R'; | |
505 } | |
506 theBoard.initDraw(ctxBk); | |
507 | |
508 lastUserColumn = columnClicked; | |
509 lastUserRow = rowClicked; | |
510 // BEFORE we call postMessage, we need to set our own state! | |
511 naclModule.postMessage(stringData); | |
512 | |
513 } else { | |
514 alert('The hex was NOT clear'); | |
515 } | |
516 } | |
517 | |
518 // Remove |element| from |array| | |
519 function removeElementFromArray(element, array) { | |
520 var index = array.indexOf(element); | |
521 if (index != -1) { | |
522 array.splice(index, 1); // Remove it if we found it | |
523 } | |
524 } | |
525 | |
526 InitHexGame(); | |
527 canvas.onmousedown = hexMouseDownHandler; | |
OLD | NEW |