]> Untitled Git - go.git/blob - web/static/go.js
Updated to 1.1.0
[go.git] / web / static / go.js
1 var canvas = document.getElementById("game-canvas");
2 var context = canvas.getContext("2d");
3
4 var backgroundColor = '#F5DEB3';
5 var gridColor = '#8B4513';
6 var boardSize = 19;
7
8 var border = canvas.width / 10;
9 var boardWidth = canvas.width - (border * 2);
10 var boardHeight = canvas.height - (border * 2);
11
12 var cellWidth = boardWidth / (boardSize - 1);
13 var cellHeight = boardHeight / (boardSize - 1);
14
15 var lastX;
16 var lastY;
17
18 /* state of pieces 
19     0: empty
20     1: white
21     2: black
22 */
23
24 var playerStone;
25
26 /* get session ID from URI if included */
27 var session = 0;
28 var queryString = location.search
29 let params = new URLSearchParams(queryString)
30 let url_session = parseInt(params.get("session"))
31
32 if (url_session > 0)
33 {
34     session = url_session
35 }
36 console.log("Session ID: " + url_session)
37
38 var state = [];
39 for (var i = 0; i < boardSize; i++)
40 {
41     state[i] = [];
42     for (var j = 0; j < boardSize; j++)
43     {
44         state[i][j] = 0;
45     }
46 }
47
48 // @connect
49 // Connect to the websocket
50 var socket;
51 const connect = function() {
52     return new Promise((resolve, reject) => {
53         const socketProtocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:')
54         const port = window.location.port;
55         const socketUrl = `${socketProtocol}//${window.location.hostname}:${port}/ws/`
56
57         // Define socket
58         socket = new WebSocket(socketUrl);
59
60         socket.onopen = (e) => {
61             // Resolve the promise - we are connected
62             resolve();
63         }
64
65         socket.onmessage = (msg) => {
66             // Any data from the server can be manipulated here.
67             let parsed = JSON.parse(msg.data);
68             switch (parsed.type) {
69                 case "session":
70                     socket.send(JSON.stringify({
71                         "type":"session",
72                         "data": {
73                             "session":session
74                         }
75                     }));
76                     break;
77                 case "board":
78                     console.log("Setting board state");
79
80                     // lazily clean up board and reinit
81                     for (var i = 0; i < boardSize; i++) {
82                         for (var j = 0; j < boardSize; j++) {
83                             state[i][j] = 0;
84                         }
85                     }
86
87                     // set up board according to db state
88                     parsed.data.forEach( function (move, index) {
89                         state[move.x][move.y] = move.state;
90                     });
91
92                     drawGrid();
93                     break;
94                 case "new":
95                     for (var i = 0; i < boardSize; i++) {
96                         for (var j = 0; j < boardSize; j++) {
97                             state[i][j] = 0;
98                         }
99                     }
100                     drawGrid();
101                 default:
102                     console.log(msg);
103             }
104         }
105
106         socket.onerror = (e) => {
107             // Return an error if any occurs
108             console.log(e);
109             resolve();
110             // Try to connect again
111             connect();
112         }
113     });
114 }
115
116 // @isOpen
117 // check if a websocket is open
118 const isOpen = function(ws) {
119     console.log(ws.readyState);
120     return ws.readyState === ws.OPEN
121 }
122
123
124 // finish grid
125 function drawGrid()
126 {    
127     
128     /* draw board square */
129     context.fillStyle = backgroundColor;
130     context.fillRect(0, 0, canvas.width, canvas.height);
131     
132     /* draw board grid */
133     context.fillStyle = gridColor;
134     for (var i = 0; i < boardSize - 1; i++)
135     {
136         for (var j = 0; j < boardSize - 1; j++)
137         {
138             context.fillRect(
139                 i * cellWidth + border, 
140                 j * cellHeight + border, 
141                 cellWidth - 1, 
142                 cellHeight - 1
143             );
144         }
145     }
146     
147     /* draw quarter marks and center mark on grid */
148     var quarter = Math.floor((boardSize - 1) / 4);
149     var markerSize = 8;
150     var markerMargin = (markerSize / 2) + 0.5;
151     
152     context.fillStyle = backgroundColor;
153     if (!!(boardSize % 2))
154     {
155         context.fillRect(
156             (((boardSize - 1) / 2) * cellWidth) + border - markerMargin, 
157             (((boardSize - 1) / 2) * cellWidth) + border - markerMargin,
158             markerSize, 
159             markerSize
160         );
161     }
162     context.fillRect(
163         (quarter * cellWidth) + border - markerMargin, 
164         (quarter * cellWidth) + border - markerMargin, 
165         markerSize, 
166         markerSize
167     );
168     context.fillRect(
169         (((boardSize - 1) - quarter) * cellWidth) + border - markerMargin, 
170         (quarter * cellWidth) + border - markerMargin, 
171         markerSize, 
172         markerSize
173     );
174     context.fillRect(
175         (((boardSize - 1) - quarter) * cellWidth) + border - markerMargin, 
176         (((boardSize - 1) - quarter) * cellWidth) + border - markerMargin, 
177         markerSize, 
178         markerSize
179     );
180     context.fillRect(
181         (quarter * cellWidth) + border - markerMargin,
182         (((boardSize - 1) - quarter) * cellWidth) + border - markerMargin,
183         markerSize, 
184         markerSize
185     );
186     
187     /* draw text labels for grid */
188     var size = canvas.width / 40;
189     var textSpacing = 10;
190     context.fillStyle = '#000000';
191     context.font = size + "px Arial";
192     
193     for (i = 0; i < boardSize; i++)
194     {
195         context.fillText(
196             (i + 1), textSpacing, 
197             ((canvas.height - border) - (i * cellHeight)) + (size / 3)
198         );
199         context.fillText(
200             (i + 1), canvas.width - (size + textSpacing), 
201             ((canvas.height - border) - (i * cellHeight)) + (size / 3)
202         );
203
204         context.fillText(
205             (String.fromCharCode(97 + i)),
206             (border + (i * cellHeight) + (size / 3)) - (size / 1.5), 
207             textSpacing + size
208         );
209         context.fillText(
210             (String.fromCharCode(97 + i)), 
211             (border + (i * cellHeight) + (size / 3)) - (size / 1.5), 
212             canvas.height - (textSpacing * 2)
213         );
214     }
215
216     drawPieces();
217 }
218
219 function drawPieces() {
220     /* draw pieces */
221     for (var i = 0; i < boardSize; i++)
222     {
223         for (var j = 0; j < boardSize; j++)
224         {
225             switch(state[i][j]) {
226                 case 1:
227                     placeStone(
228                         (i * cellWidth) + border, 
229                         (j * cellWidth) + border, 
230                         'rgba(255, 255, 255, 1)'
231                     );
232                     break;
233                 case 2:
234                     placeStone(
235                         (i * cellWidth) + border, 
236                         (j * cellWidth) + border, 
237                         'rgba(0, 0, 0, 1)'
238                     );
239                     break;
240                 default:
241             }
242         }
243     }
244 }
245
246 canvas.addEventListener('mousedown', function(evt) 
247 {
248     try {
249         // push state change to backend
250         if(isOpen(socket)) {
251             socket.send(JSON.stringify({
252                 "type":"move",
253                 "data": {
254                     "session":session,
255                     "x":lastX,
256                     "y":lastY,
257                     "state":state[lastX][lastY] > 0 ? 0 : playerStone
258                 }
259             }));
260         } else {
261             console.log("Websocket is closed");
262         }
263     } catch(e) {
264         console.log(e);
265     }
266 });
267
268 canvas.addEventListener('mousemove', function(evt) 
269 {
270     var position = getGridPoint(evt);
271
272     if ((position.x != lastX) || (position.y != lastY))
273     {
274         drawGrid();
275         if (
276             ((position.x >=0) && (position.x < boardSize)) && 
277             ((position.y >=0) && (position.y < boardSize))
278         ) {
279             placeStone(
280                 (position.x * cellWidth) + border, 
281                 (position.y * cellWidth) + border, 
282                 'rgba(0, 0, 0, 0.2)'
283             );
284         }
285     }
286     lastX = position.x;
287     lastY = position.y;        
288 });
289
290 function placeStone(x, y, color)
291 {
292     var radius = cellWidth / 2;
293     
294     context.beginPath();
295     context.arc(x, y, radius, 0, 2 * Math.PI, false);
296     context.fillStyle = color;    
297     context.fill();
298     context.lineWidth = 5;
299 }
300
301 function getGridPoint(evt)
302 {
303     var rect = canvas.getBoundingClientRect();
304         
305     var x = Math.round(
306         (evt.clientX-border-rect.left) / (rect.right-2*border-rect.left) * boardWidth
307     );
308     var y = Math.round(
309         (evt.clientY-border-rect.top) / (rect.bottom-2*border-rect.top) * boardHeight
310     );
311     
312     var roundX = Math.round(x / cellWidth);
313     var roundY = Math.round(y / cellHeight);
314     
315     return {
316         x: roundX,
317         y: roundY
318     };
319 }
320
321 // finish
322 document.getElementById("new").onclick = function () {
323     // new game, new session, etc
324     socket.send(JSON.stringify({
325         "type":"new",
326         "data": {
327             "session":session
328         }
329     }));
330 };
331
332 const stones = document.getElementById("stones");
333 playerStone = stones.selectedIndex;
334 stones.onchange = function () {
335     // let player pick stone type
336     playerStone = stones.selectedIndex;
337     console.log(`Player changed stone to ${playerStone}`);
338 };
339
340 connect();