// Some code was implemented from //https://editor.p5js.org/cs4all/sketches/Bk3TOJzlE// https://github.com/processing/p5.js/wiki/Positioning-your-canvas// refereces// https://www.geeksforgeeks.org/p5-js-position-function/#:~:text=js%20%7C%20position()%20Function,-Improve%20Article&text=The%20position()%20function%20is,y%20position%20of%20the%20element.// https://learn.microsoft.com/et-ee/dotnet/desktop/wpf/controls/how-to-use-the-attached-properties-of-canvas-to-position-child-elements?view=netframeworkdesktop-4.8// P5 code
AB.world.newRun =function(){
AB.socketStart();// AB starts the socket
AB.runReady =false;// set run ready to false so it the start button can work};functionInfoScreen(){
let text ="Welcome to X and O. To win the game you have to get 3 rows with either X or O. This is a 2 player Game. You can play On 2 different browsers or you can play on the same browser";return(text);// display welcome message on splash screen }//
AB.newSplash(InfoScreen());// displays the info screen function
$("#splash").click (function(){// when start button is clicked splash screen goes away
AB.removeSplash();
AB.backgroundMusic ( music );// Start the background music when the user interacts with the page
AB.runReady =true;// run ready is true now because the game can run});
AB.world.nextStep =function(){}//some constants used
let table;
let p1;
let p2;
let turn;
let divbox;
let TText="";var ready;var info ={//dictionary to store information to be sent via websocket};const soundaffect ='/uploads/destinyjames/mixkit-game-click-1114.wav';//constant to store soundconst music ='/uploads/destinyjames/the-incident-soundroll-main-version-16775-01-32.mp3';
let height;var canvas;function setup(){// function called by p5 when game stats up
height = windowHeight -300;
p1 =newPlayer("X");//defined player 1
p2 =newPlayer("O");//defined player 2var canvas = createCanvas(height, height);//squares that reps board var x =(windowWidth - width)/2;// canvas positioningvar y =(windowHeight - height)/2;// canvas positioning
canvas.position(x, y);//canvas position
divbox = createDiv('').size(100,100);//for which players turn
table =newBoard(p1, p2);//element on bord class
ready = p1;}function draw(){// this function will be called automatically by p5 after set up
background(color("brown"));// background colour
AB.hideRunHeader();// hides ancient brain controls
table.display();// dispays board// style for player box
divbox.style('font-size','50px');
divbox.style('font-family','sans-serif');
divbox.style('padding-top','25px');
divbox.style('width','100%');
divbox.style('height','100%');
divbox.style('text-align','center');
divbox.style('margin','auto');
divbox.style('color','black');// background image
divbox.style('background-repeat','no-repeat');
divbox.style('background-image','url(/uploads/destinyjames/1669759381.png)');
divbox.style('background-position','center');
divbox.style('background-attachment','fixed');
divbox.style('background-size','cover');}functionSound(instance){// function to play soundif(instance =="click"){//when ckick is passed to Sound functionvar sound =newAudio(soundaffect);// gets sound from aound file stored variable
sound.play();// sound plays}}function mousePressed(){//automatically called by p5 when mouse is pressed// console.log ( mouseX + " " + mouseY ); // MH edit if(mouseX >0&& mouseX <500&& mouseY >0&& mouseY <500&& AB.runReady ===true){// console.log ( "processing click" ); // MH edit if(!table.winState){// if the game has not been won if(table.turn ==="X"){// if it is player x's turn Sound("click");// play the sound
p1.select(table);// places player piece - calls select function on player one passes in bpard and updates the board}elseif(table.turn ==="O"){// if it is player o's turnSound("click");// same as above
p2.select(table);// same as above}
table.toggleTurn();// switches players turn}else{// someone has won start a new game
table.newGame();
AB.socketOut("Start")// telling the socket to start again since the game has finished}}}// This class defines board attributes and methodsclassBoard{
constructor(p1, p2){// defines attributes of the board// empty array to hokd the board - gets filled in newGame functionthis.cells =[];// little blocks on the boardthis.cellSize =(width -1)/3;// size of little blocksthis.p1 = p1;// player onethis.p2 = p2;//player twothis.turn =this.p1.s;//turn has startedthis.winState =false;// game hasn't been wonthis.resultText ="";// text that will be updated and displayed depending on game resultthis.newGame();// new game function}
display(){//displays the board
let cellSize =this.cellSize;// sets little blocks sizeif(this.winState){// someone has won, display the result
textSize(20);
textAlign(CENTER);
text(this.resultText, width /2, height /2);// display result text
text("Click anywhere for a new game", width /2, height /2+30);// new gamevar bc = color("black");
fill(bc);// text colour teal}else{// nobody has won yet, display the boardthis.cells.forEach(function(element){// draw the cell
strokeWeight(20);//adds a border around the squares
stroke('rgba(0, 5, 0, 0.8)');// colour of strokevar c = color('brown');// box colour
fill(c);
rect(element.r * cellSize, element.c * cellSize, cellSize, cellSize);//creates each cell
c = color('black');// piece colour
fill(c);
strokeWeight(10);// border is added to piece
stroke('black)');// colour of border
textSize(100);// size of piece
textAlign(CENTER);// center piece in little block// draw the X or O// centre the text in the cell
text(element.s, element.r * cellSize + cellSize /2, element.c * cellSize + cellSize /2+35);// creates elements
strokeWeight(0);// resets stroke to zero});}}// update the board after a turn takes place
update(r, c, s){
let turn =this.turn;this.cells.forEach(function(element){// element.c is the column and element.r is the row// element is the object in the game// if the cell's row and column match the row and column of the moveif(element.r === r && element.c === c && element.val ===0){// update the cell's text and value
element.s = s;if(turn ==="X"){// if it's X's turn, the value is 1
element.val =1;// info.totalOnes++;
info["element"]= element;}else{// if it's O's turn, the value is -1
element.val =-1;// info.totalMinusOnes++;
info["element"]= element;}}});// check if the game has been won and who has won// updating the result
let result =this.checkResult();if(result ==="X"){this.winState =true;this.resultText ="X wins!";}elseif(result ==="O"){this.winState =true;this.resultText ="O wins!";}elseif(result ==="tie"){this.winState =true;this.resultText ="Its a draw!";}}
toggleTurn(){// if it's X's turn, make it O's turnif(this.turn == p1.s){
info["Whosturn"]= p2.s;this.turn = p2.s;
ready = p2;TText="Turn: "+ p2.s;}else{// if it's O's turn, make it X's turn
info["Whosturn"]= p1.s;this.turn = p1.s;
ready = p1;TText="Turn: "+ p1.s;}
info["ready"]= ready
// console.log(turnText);
divbox.html(TText);
info["TText"]=TText;
AB.socketOut(info);}// check if someone has won
checkResult(){
let winner;
let p1 =this.p1;
let p2 =this.p2;
let rowSums =newArray(3);
let colSums =newArray(3);
let diagSums =newArray(3);// numOpen is the number of open cells
let numOpen =9;// initialize the rowSums, colSums, and diagSums arraysfor(let i =0; i <3; i++){
rowSums[i]=0
colSums[i]=0
diagSums[i]=0}// loop through the cellsthis.cells.forEach(function(element){// if the cell is open, decrement numOpen
rowSums[element.r]+= element.val;
colSums[element.col]+= element.val;
numOpen -= abs(element.val);if(abs(element.r - element.c)===0){// add the cell's value to the main diagonal sum
diagSums[0]+= element.val;}if(abs(element.r - element.c)===2||(element.r ==1&& element.c ==1)){// add the cell's value to the secondary diagonal sum
diagSums[1]+= element.val;}});// check if any of the sums are 3 or -3
rowSums.forEach(function(element){if(element ===3){
winner = p1.s;// if the sum is 3, X won
p1.win();}if(element ===-3){
winner = p2.s;// if the sum is -3, O won
p2.win();}});
colSums.forEach(function(element){if(element ===3){
winner = p1.s;
p1.win();}if(element ===-1*3){
winner = p2.s;
p2.win();}});
diagSums.forEach(function(element){if(element ===3){
winner = p1.s;
p1.win();}if(element ===-1*3){
winner = p2.s;
p2.win();}});// when all the squares are filled with no winner then its a tieif(numOpen ===0){
winner ="tie";}return winner;}// configure the board's state at the beginning of a game
newGame(){
console.log("p1 score"+ p1.score);
console.log("p2 score"+ p2.score);this.winState =false;// the game is not overthis.turn =this.p1.s;// X goes first
divbox.html("Turn: "+this.p1.s);// reset the cellsthis.cells =[];// create the cellsfor(let i =0; i <3; i++){for(let j =0; j <3; j++){this.cells.push({// the row"r": i,// the column"c": j,// the player's s is X or O."s":"",// the value"val":0});}}}}classPlayer{
constructor(s){// the player's s, X or Othis.s = s;this.score =0;}
select(table){// if it's X's turn, the value is 1if(table.turn ==this.s){
console.log(table.turn,this.s)// cx and cy are the coordinates of the mouse
let cx =int(Math.floor(mouseX / table.cellSize));
let cy =int(Math.floor(mouseY / table.cellSize));// squaree on board gets updated
table.update(cx, cy,this.s);// sending live board state to other player
info["r"]= cx;
info["c"]= cy;
info["s"]=this.s;}}
win(){
console.log("yes");this.score++}}// Our socket funtion
AB.socketIn =function(info){
console.log(info.TText);// the game gets updated on both browsers
divbox.html(info.TText);
table.update(info.r, info.c, info.s);
console.log(info.Whosturn);
table.turn = info.Whosturn;
ready = info.ready;if(info =="start"){
table.newGame();}};