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