summaryrefslogtreecommitdiff
path: root/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'index.html')
-rw-r--r--index.html302
1 files changed, 302 insertions, 0 deletions
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..8624e20
--- /dev/null
+++ b/index.html
@@ -0,0 +1,302 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CaptureGo</title>
+<script src="/socket.io/socket.io.js"></script>
+<script>
+var CELL_WID=25,STONE_SIZE=0.4*CELL_WID;
+
+var cvs=null,ctx=null;
+var myId=null,myName=null;
+var currentGame=null,currentOther=null,winningPlayer=null;
+var GS_WAIT=0,GS_TURN=1,GS_FINISH=2;
+var gameState=GS_WAIT;
+const socket=io();
+
+function setStatus(str){
+ document.getElementById("status").innerHTML=str;
+}
+
+function setGameStatus(str){
+ document.getElementById("game_status").innerHTML=str;
+}
+
+function interfaceSwitch(cont){
+ document.getElementById("cont_connect").classList.add("invisible");
+ document.getElementById("cont_game").classList.add("invisible");
+ document.getElementById("cont_"+cont).classList.remove("invisible");
+}
+
+function getPlayersList(){
+ socket.emit("list_players",function(list){
+ var sel=document.getElementById("other_player_select");
+ sel.innerHTML="";
+ for(var i=0;i<list.length;i++){
+ if(list[i].id==myId)continue;
+ var option=document.createElement("option");
+ option.value=list[i].id;
+ option.appendChild(document.createTextNode(list[i].name));
+ sel.appendChild(option);
+ }
+ });
+}
+
+function initConnect(){
+ setStatus("Connecting...");
+
+ socket.on("connect",function(){
+ socket.emit("my_info",function(p){
+ myId=p.id; myName=p.name;
+ document.getElementById("info").innerHTML="ID: "+myId+"<br>Name: "+myName;
+ setStatus("Connected.");
+ interfaceSwitch("connect");
+ getPlayersList();
+ });
+ });
+
+ socket.on("disconnect",function(){
+ location.href=location.href;
+ });
+
+ socket.on("err",function(err){
+ alert(err);
+ });
+
+ socket.on("player_list_change",getPlayersList);
+
+ socket.on("game_create",function(game){
+ if(currentGame){
+ socket.emit("leave_game",game.id);
+ return;
+ }
+ currentGame=game;
+ if(game.players[0].id==myId)currentOther=game.players[1];
+ else currentOther=game.players[0];
+ interfaceSwitch("game");
+ document.getElementById("game_header").innerHTML="Game with "+currentOther.name;
+ setGameStatus("Preparing");
+ var colourString=game.players[0].id==myId?"black":"white";
+ document.getElementById("colour_note").innerHTML="You are playing "+colourString+".";
+ winningPlayer=null;
+ redrawBoard();
+ });
+
+ socket.on("game_leave",function(g,p){
+ if(g.id!=currentGame.id)return;
+ currentGame=g;
+ socket.emit("leave_game",g.id);
+ interfaceGameState(GS_FINISH);
+ });
+
+ socket.on("game_turn",function(g){
+ if(g.id!=currentGame.id)return;
+ currentGame=g;
+ redrawBoard();
+ interfaceGameState(GS_TURN);
+ });
+
+ socket.on("game_other_turn",function(g){
+ if(g.id!=currentGame.id)return;
+ currentGame=g;
+ redrawBoard();
+ interfaceGameState(GS_WAIT);
+ });
+
+ socket.on("game_win",function(g,p){
+ if(g.id!=currentGame.id)return;
+ currentGame=g;
+ winningPlayer=p;
+ redrawBoard();
+ interfaceGameState(GS_FINISH);
+ });
+}
+
+function boardX(idx){
+ return (~~(idx%currentGame.size)+0.5)*CELL_WID;
+}
+
+function boardY(idx){
+ return (~~(idx/currentGame.size)+0.5)*CELL_WID;
+}
+
+function redrawBoard(){
+ if(currentGame==null){
+ interfaceSwitch("connect");
+ return;
+ }
+
+ var G=currentGame;
+ var bsz=G.size*CELL_WID;
+
+ if(cvs.width!=bsz||cvs.height!=bsz){cvs.width=bsz; cvs.height=bsz;}
+
+ ctx.fillStyle="rgb(224,177,92)";
+ ctx.fillRect(0,0,cvs.width,cvs.height);
+ ctx.strokeStyle="rgb(0,0,0)";
+ ctx.beginPath();
+ for(var i=0;i<G.size;i++){
+ ctx.moveTo(boardX(i),boardY(0));
+ ctx.lineTo(boardX(i),boardY(G.size*G.size-1));
+ ctx.moveTo(boardX(0),boardY(G.size*i));
+ ctx.lineTo(boardX(G.size*G.size-1),boardY(G.size*i));
+ }
+ ctx.stroke();
+
+ var dots=[];
+ if(G.size==9)dots=[2*9+2,6*9+2,2*9+6,6*9+6];
+ if(G.size==13)dots=[3*13+3,3*13+9,9*13+3,9*13+9,6*13+6];
+ if(G.size==19)dots=[3*19+3,3*19+9,3*19+15,9*19+3,9*19+9,9*19+15,15*19+3,15*19+9,15*19+15];
+ ctx.fillStyle="rgb(0,0,0)";
+ ctx.beginPath();
+ for(var i=0;i<dots.length;i++){
+ ctx.moveTo(boardX(dots[i])+2.2,boardY(dots[i]));
+ ctx.arc(boardX(dots[i]),boardY(dots[i]),2.2,0,2*Math.PI,true);
+ }
+ ctx.fill();
+
+ for(var i=0;i<G.size*G.size;i++){
+ if(G.board[i]==1)ctx.fillStyle="rgb(0,0,0)";
+ else if(G.board[i]==-1)ctx.fillStyle="rgb(255,255,255)";
+ else continue;
+ ctx.beginPath();
+ ctx.moveTo(boardX(i)+STONE_SIZE,boardY(i));
+ ctx.arc(boardX(i),boardY(i),STONE_SIZE,0,2*Math.PI,true);
+ ctx.fill();
+ }
+}
+
+function interfaceGameState(state){
+ gameState=state;
+ cvs.classList[gameState==GS_TURN?"add":"remove"]("mouse-pointer");
+
+ if(gameState==GS_TURN){
+ setGameStatus("Your turn.");
+ } else if(gameState==GS_WAIT){
+ setGameStatus("Waiting for move from opponent.");
+ } else if(gameState==GS_FINISH){
+ var linktext="<a href=\"javascript:doCloseGame()\">Click here</a> to close the game.";
+ if(winningPlayer!=null){
+ var s="Player <b>"+winningPlayer.name+"</b> has won the game! ";
+ s+=["Congratulations!","Too bad, maybe better next time."][+(winningPlayer.id==myId)];
+ s+="<br>"+linktext;
+ setGameStatus(s);
+ } else {
+ var s="The other player closed the game.<br>"+linktext;
+ setGameStatus(s);
+ }
+ }
+}
+
+function doCreateGame(){
+ var otherid=document.getElementById("other_player_select").value;
+ if(!otherid){
+ alert("No other player selected!");
+ return;
+ }
+ var size=+document.getElementById("board_size").value;
+ if(isNaN(size)||size<5||size>99||size%1!=0){
+ alert("Invalid board size!");
+ return;
+ }
+
+ socket.emit("create_game",+otherid,size);
+}
+
+function doCloseGame(){
+ socket.emit("leave_game",currentGame.id);
+ interfaceSwitch("connect");
+}
+
+function mouseEventToIndex(ev){
+ var bbox=cvs.getBoundingClientRect();
+ var x=~~((ev.clientX-bbox.left)/CELL_WID),y=~~((ev.clientY-bbox.top)/CELL_WID);
+ if(x<0||x>=currentGame.size||y<0||y>=currentGame.size)return null;
+ return y*currentGame.size+x;
+}
+
+function initCanvasListeners(){
+ cvs.addEventListener("click",function(ev){
+ if(!currentGame||gameState!=GS_TURN)return;
+ var i=mouseEventToIndex(ev);
+ if(i==null)return;
+
+ if(currentGame.board[i]!=0)return;
+
+ socket.emit("game_move",currentGame.id,i);
+ });
+ cvs.addEventListener("mousemove",function(ev){
+ if(!currentGame||gameState!=GS_TURN)return;
+ var i=mouseEventToIndex(ev);
+ if(i==null)return;
+
+ if(currentGame.board[i]!=0)return;
+
+ redrawBoard();
+ ctx.fillStyle=["rgba(0,0,0,0.5)","rgba(255,255,255,0.5)"][currentGame.onturn];
+ ctx.beginPath();
+ ctx.moveTo(boardX(i)+STONE_SIZE,boardY(i));
+ ctx.arc(boardX(i),boardY(i),STONE_SIZE,0,2*Math.PI,true);
+ ctx.fill();
+ });
+ cvs.addEventListener("mouseleave",function(ev){
+ redrawBoard();
+ });
+}
+
+window.addEventListener("load",function(){
+ cvs=document.getElementById("cvs");
+ ctx=cvs.getContext("2d");
+ initConnect();
+ initCanvasListeners();
+});
+</script>
+<style>
+body {
+ font-family: sans-serif;
+}
+canvas {
+ border: 1px black solid;
+}
+#info {
+ padding: 5px;
+ border-radius: 8px;
+ border: 1px black solid;
+ display: inline-block;
+ margin-bottom: 5px;
+}
+#status {
+ font-style: italic;
+}
+#colour_note {
+ font-style: italic;
+}
+.invisible {
+ display: none;
+}
+.mouse-pointer {
+ cursor: pointer;
+}
+</style>
+</head>
+<body>
+<h2>CaptureGo</h2>
+
+<div id="info"></div><br>
+<div id="status"></div>
+
+<div id="cont_connect" class="invisible">
+ <h3>Create a game with a friend</h3>
+ Select the other player to invite: <select id="other_player_select"></select><br>
+ Board size: <input type="number" id="board_size" value="9" style="width:60px"><br>
+ <input type="button" value="Create Game" onclick="doCreateGame()">
+</div>
+
+<div id="cont_game" class="invisible">
+ <h3 id="game_header"></h3>
+ <div id="game_status"></div>
+ <canvas id="cvs"></canvas><br>
+ <div id="colour_note"></div>
+</div>
+</body>
+</html>