aboutsummaryrefslogtreecommitdiff
path: root/draughts/public/javascripts/game.js
diff options
context:
space:
mode:
Diffstat (limited to 'draughts/public/javascripts/game.js')
-rw-r--r--draughts/public/javascripts/game.js124
1 files changed, 121 insertions, 3 deletions
diff --git a/draughts/public/javascripts/game.js b/draughts/public/javascripts/game.js
index ede6459..ffaf246 100644
--- a/draughts/public/javascripts/game.js
+++ b/draughts/public/javascripts/game.js
@@ -1,4 +1,122 @@
-//const ws = new WebSocket("ws://localhost:3000")
-//ws.addEventListener("open", () => console.log("We are connected!"))
+/* Initialize a new web socket to connect to the server */
+const ws = new WebSocket("ws://localhost:3000")
-document.getElementById("resign").addEventListener("click", () => ws.send("RESIGN"))
+/* Define some variables */
+let legalMoves, // Array of moves :: Moves that each piece can legally make
+ ourTurn, // Boolean :: Is it currently our turn?
+ selectedPiece, // Piece :: The current HTML piece we have selected
+ colorPrefix, // Character :: Either 'b' or 'r' depending on the clients side
+ opponentPrefix // Character :: The inverse of `colorPrefix'
+
+/* Remove all the position markers from the board */
+const removeMarkers = () => Array
+ .from(document.getElementsByClassName("position")) // Obtain the markers
+ .forEach(pos => pos.remove()) // Remove them all
+
+/* Add a position marker to the position specified by the given coordinates */
+const addMarker = ({ x, y, captures }) => {
+ /* Create and add the marker */
+ let img = document.createElement("img") // Create a new image element
+ img.className = "piece position" // Add it to the correct classes
+ img.style.transform = `translate(${x * 100}%, ${y * 100}%)` // Move it to the correct position
+ img.setAttribute("src", "images/position.svg") // Assign the actual image to it
+ document.querySelector("#board-container").append(img) // Add it to the board container
+
+ /* Add an event listener to move the selected piece when the marker is clicked */
+ img.addEventListener("click", () => {
+ /* Grab the old positions of the piece */
+ let [ox, oy] = selectedPiece
+ .style // Get the style attributes
+ .transform // Get the transformation style attribute
+ .match(/[0-9]+/g) // Get the percentage offsets in the translation
+ .map(n => n / 100) // Divide them by 100 to get board indicies
+
+ /* Get the ID of the selected piece so we can include it in the message to the server */
+ let id = selectedPiece.id.slice(1)
+
+ captures.forEach(p => document.getElementById(opponentPrefix + p.id).remove())
+
+ /* Move the selected piece, unselect it, remove the markers, and end our turn */
+ selectedPiece.style.transform = img.style.transform
+ selectedPiece = null
+ ourTurn = false
+ removeMarkers();
+
+ /* Inform the server that we have moved a piece, and tell it where the piece used to be and
+ * where it has moved to
+ */
+ ws.send(JSON.stringify({
+ head: Messages.MOVED,
+ body: {
+ id: id,
+ old: { x: ox, y: oy },
+ new: { x: x, y: y },
+ captures: captures
+ }
+ }))
+ })
+}
+
+const movePiece = ({ id, position, captures }) => {
+ document.getElementById(opponentPrefix + id).style.transform =
+ `translate(${position.x * 100}%, ${position.y * 100}%)`
+ captures.forEach(p => document.getElementById(colorPrefix + p.id).remove())
+}
+
+const setupPieceEventListeners = () => {
+ Array
+ .from(document.getElementsByClassName("piece")) // Get an array of pieces on the HTML board
+ .filter(p => p.id[0] == colorPrefix) // Get only the pieces of our own color
+ .forEach(p => p.addEventListener("click", () => { // Add an event listener to each piece
+ /* If it's not our turn, do nothing */
+ if (!ourTurn)
+ return
+
+ /* Remove any existing position markers from the board */
+ removeMarkers()
+
+ /* If we clicked on a piece that was not previously selected, we add the position markers to
+ * indicate where that piece can legally move to. If it was the piece that was already
+ * selected however, then do nothing, simply unselect the piece.
+ */
+ if (selectedPiece != p) {
+ legalMoves[p.id.slice(1)].forEach(addMarker)
+ selectedPiece = p
+ } else
+ selectedPiece = null
+ }))
+}
+
+/* Listen for a message from the client, and perform a different action based on the message.
+ * The `public/javascripts/game.js' file explains what each of the message headers mean.
+ */
+ws.addEventListener("message", ({ data }) => {
+ data = JSON.parse(data)
+ switch (data.head) {
+ case Messages.WELCOME:
+ colorPrefix = data.body
+ opponentPrefix = colorPrefix == "b" ? "r" : "b"
+ setupPieceEventListeners()
+ break
+ case Messages.RESIGN:
+ console.log("The opponent has resigned, you win!")
+ break
+ case Messages.DISCONNECT:
+ console.log("The opponent has disconnected, you win!")
+ break
+ case Messages.COMMENCE:
+ ourTurn = true
+ legalMoves = data.body
+ break
+ case Messages.MOVED:
+ movePiece(data.body)
+ break
+ }
+})
+
+/* Add an event listener to the resign button which will inform the server about when we have
+ * resigned the game
+ */
+document
+ .getElementById("resign")
+ .addEventListener("click", () => ws.send(JSON.stringify({ head: Messages.RESIGN })))