<!doctypehtml><htmllang="en"><head><metacharset="UTF-8"><metaname="Generator"content="EditPlus®"><metaname="Author"content=""><metaname="Keywords"content=""><metaname="Description"content=""><title>Document</title><style>*{box-sizing: border-box;}body{background-color: #F1F0F4;font-family: helvetica;}a{color: #7A7A7A;text-decoration: none;-webkit-transition: 0.3s opacity ease-out;transition: 0.3s opacity ease-out;}a:hover,
a:focus{opacity: .6;}.circle{width: 140px;height: 140px;border-radius: 100%;border: 5px solid rgba(48, 79, 134, 0.25);position: absolute;top: 50%;left: 50%;margin-top: -70px;margin-left: -70px;}.table{width: 800px;height: 550px;margin-top: -275px;margin-left: -400px;position: absolute;top: 50%;left: 50%;border: 15px solid #2e2e2e;border-radius: 70px;background-color: #FFF;box-shadow: inset 0 2px 5px 0 rgba(50, 50, 50, 0.25);}.table:before,
.table:after{content:'';position: absolute;background-color: #7A7A7A;width: 15px;height: 190px;top: 50%;left: -15px;margin-top: -95px;}.table:after{left: auto;right: -15px;}.table--canvas{width: 770px;height: 520px;margin-top: -260px;margin-left: -385px;background-color: transparent;border-radius: 55px;border: none;}.table--canvas:focus{outline: none;}.table-inner{overflow: hidden;display: block;position: relative;width: 100%;height: 100%;}.table__center-line{width: 5px;height: 100%;background-color:rgba(187, 4, 34, 0.25);position: absolute;left: 50%;margin-left: -2.5px;}.table__blue-line{position: absolute;left: 37%;width: 5px;margin-left: -2.5px;height: 100%;background-color:rgba(48, 79, 134, 0.25);}.table__blue-line--two{left: auto;right: 37%;margin-left: 0;margin-right: -2.5px;}.table__goal-crease{left: 0;margin-top: -95px;margin-left: -102.5px;width: 190px;height: 190px;background-color:rgba(48, 79, 134, 0.06);}.table__goal-crease--two{left: auto;margin-left: auto;right: 0;margin-top: -95px;margin-right: -102.5px;}.table__faceoff{width: 80px;height: 80px;border-color:rgba(187, 4, 34, 0.25);position: absolute;}.table__faceoff--top-left{margin-top: -40px;margin-left: -40px;left: 20%;top: 20%;}.table__faceoff--top-right{margin-top: -40px;margin-right: -40px;right: 20%;top: 20%;left: auto;}.table__faceoff--bottom-left{margin-bottom: -40px;margin-left: -40px;left: 20%;bottom: 20%;top: auto;}.table__faceoff--bottom-right{margin-bottom: -40px;margin-right: -40px;right: 20%;bottom: 20%;left: auto;top: auto;}.message{position: absolute;text-align: center;font-weight: bold;top: -60px;width: 100%;font-size: 18px;padding-top: 15px;}</style></head><body><divclass="table"><divclass="table-inner"><spanclass="table__goal-crease circle"></span><spanclass="table__faceoff table__faceoff--top-left circle"></span><spanclass="table__faceoff table__faceoff--bottom-left circle"></span><spanclass="table__blue-line"></span><spanclass="table__center-line"></span><spanclass="circle"></span><spanclass="table__blue-line table__blue-line--two"></span><spanclass="table__faceoff table__faceoff--top-right circle"></span><spanclass="table__faceoff table__faceoff--bottom-right circle"></span><spanclass="table__goal-crease table__goal-crease--two circle"></span></div></div><canvasid="canvas"class="table table--canvas"tabindex="0"></canvas><script>var board = document.getElementById("canvas"),
boardContext = board.getContext('2d'),
boardWidth =770,
boardHeight =520,
boardCenterX = boardWidth /2,
boardCenterY = boardHeight /2,
controllers =[],
goal = document.getElementsByClassName('table__goal-crease'),
goalHeight = goal[0].clientHeight,
goalPosTop =(boardHeight - goalHeight)/2,
score =[];// Set width & height for canvas
board.width = boardWidth;
board.height = boardHeight;// Set focus to canvas so keyboard events work
board.focus();// DiscfunctionDisc(){this.startingPosX = boardCenterX;this.startingPosY = boardCenterY;this.x =this.startingPosX;this.y =this.startingPosY;this.radius =34;this.mass =15;this.velocityX =0;this.velocityY =0;this.maxSpeed =10;this.frictionX =0.997;this.frictionY =0.997;this.acceleration =1;this.color ='#000000';this.keepControllerInBoard=function(){// Need to determine if goal scored on x axis as wellif(this.x >(boardWidth -this.radius)||this.x <this.radius){if(this.x <this.radius){this.velocityX =2;}else{this.velocityX =-2;}}// Determine if disc is to far up or downif(this.y >(boardHeight -this.radius)||this.y <this.radius){if(this.y <this.radius){this.velocityY =2;}else{this.velocityY =-2;}}// Keep player one controller on left hand side of screenif(controller.x >(boardCenterX - controller.radius)&& controller.x < boardCenterX){
controller.velocityX =-3;}// Keep player two controller on right hand side of screenif(controllerTwo.x > boardCenterX && controllerTwo.x <(boardCenterX +(controllerTwo.radius /2))){
controllerTwo.velocityX =+3;}},// Keep disc inside boardthis.keepPuckInBoard=function(){// Determine if disc is to far right or left// Need to determine if goal scored on x axis as wellif(this.x >(boardWidth -this.radius)||this.x <this.radius){// Stop puck from getting stuckif(this.x >(boardWidth -this.radius)){this.x = boardWidth -this.radius;}else{this.x =this.radius;}// Check to see if goal scoredif(this.y >(goalPosTop + puck.radius)&&this.y <(goalPosTop + goalHeight)- puck.radius){// Add new puck
puck =newDisc(boardCenterX, boardCenterY);}else{// Reverse X direction this.velocityX =-this.velocityX;}}// Determine if disc is to far up or downif(this.y >(boardHeight -this.radius)||this.y <this.radius){// Stop puck from getting stuckif(this.y >(boardHeight -this.radius)){this.y = boardHeight -this.radius;}else{this.y =this.radius;}// Reverse directionthis.velocityY =-this.velocityY;}}// Collide discs if in same spotthis.discCollision=function(){// Loop over two controllers to see if puck has come in contactfor(var i =0; i < controllers.length; i++){// Minus the x pos of one disc from the x pos of the other discvar distanceX =this.x - controllers[i].x,// Minus the y pos of one disc from the y pos of the other disc
distanceY =this.y - controllers[i].y,// Multiply each of the distances by this// Squareroot that number, which gives you the distance between the two disc's
distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY),// Add the two disc radius together
addedRadius =this.radius + controllers[i].radius;// Check to see if the distance between the two circles is smaller than the added radius// If it is then we know the circles are overlapping if(distance < addedRadius){// Had help from Reddit user Kraft_Punk on the below collision math//calculate angle, sine, and cosinevar angle = Math.atan2(distanceY, distanceX),
sin = Math.sin(angle),
cos = Math.cos(angle),//rotate controllers[i]'s position
pos0 ={x:0,y:0},//rotate this's position
pos1 =rotate(distanceX, distanceY, sin, cos,true),//rotate controllers[i]'s velocity
vel0 =rotate(controllers[i].velocityX, controllers[i].velocityY, sin, cos,true),//rotate this's velocity
vel1 =rotate(this.velocityX,this.velocityY, sin, cos,true),//collision reaction
velocityXTotal = vel0.x - vel1.x;
vel0.x =((controllers[i].mass -this.mass)* vel0.x +2*this.mass * vel1.x)/(controllers[i].mass +this.mass);
vel1.x = velocityXTotal + vel0.x;//update position - to avoid objects becoming stuck togethervar absV = Math.abs(vel0.x)+ Math.abs(vel1.x),
overlap =(controllers[i].radius +this.radius)- Math.abs(pos0.x - pos1.x);
pos0.x += vel0.x / absV * overlap;
pos1.x += vel1.x / absV * overlap;//rotate positions backvar pos0F =rotate(pos0.x, pos0.y, sin, cos,false),
pos1F =rotate(pos1.x, pos1.y, sin, cos,false);//adjust positions to actual screen positionsthis.x = controllers[i].x + pos1F.x;this.y = controllers[i].y + pos1F.y;
controllers[i].x = controllers[i].x + pos0F.x;
controllers[i].y = controllers[i].y + pos0F.y;//rotate velocities backvar vel0F =rotate(vel0.x, vel0.y, sin, cos,false),
vel1F =rotate(vel1.x, vel1.y, sin, cos,false);
controllers[i].velocityX = vel0F.x;
controllers[i].velocityY = vel0F.y;this.velocityX = vel1F.x;this.velocityY = vel1F.y;}}}// Draw discthis.draw=function(){
boardContext.shadowColor ='rgba(50, 50, 50, 0.25)';
boardContext.shadowOffsetX =0;
boardContext.shadowOffsetY =3;
boardContext.shadowBlur =6;
boardContext.beginPath();
boardContext.arc(this.x,this.y,this.radius,0,2* Math.PI,false);
boardContext.fillStyle =this.color;
boardContext.fill();}// Move disc with physic's appliedthis.move=function(){// Apply frictionthis.velocityX *=this.frictionX;this.velocityY *=this.frictionY;// Update positionthis.x +=this.velocityX;this.y +=this.velocityY;}// Play against a computerthis.computerPlayer=function(){// If pucks about to move into right hand side of screen// And controller isnt pushed up against the center lineif(puck.x >(boardCenterX -30)&& controllerTwo.x >(boardCenterX + controllerTwo.radius *2)){// Work out if puck is infront or behind controller// Try to hit the puck on right hand side and at the center.// If puck is infront on controllerif((puck.x + puck.radius)< controllerTwo.x){
controllerTwo.velocityX -= controllerTwo.acceleration;}else{
controllerTwo.velocityX += controllerTwo.acceleration;}// Do same on y axisif(puck.y < controllerTwo.y){
controllerTwo.velocityY -= controllerTwo.acceleration;}else{// Is behind
controllerTwo.velocityY += controllerTwo.acceleration;}}else{// Move back to its starting position so its not stuck at center line. // Give it a range to top inif(controllerTwo.x >(controllerTwo.startingPosX -50)&& controllerTwo.x <(controllerTwo.startingPosX +50)){
controllerTwo.velocityX =0;}elseif(controllerTwo.x <(controllerTwo.startingPosX -80)){
controllerTwo.velocityX += controllerTwo.acceleration;}else{
controllerTwo.velocityX -= controllerTwo.acceleration;}}}};// Run game functionsfunctionupdateGame(){// Clear board
boardContext.clearRect(0,0, boardWidth, boardHeight);// Draw & contain puck
puck.draw();
puck.move();
puck.discCollision();
puck.keepPuckInBoard();// Controllers
controller.draw();
controller.move();
controller.keepControllerInBoard();
controllerTwo.draw();
controllerTwo.computerPlayer();
controllerTwo.move();
controllerTwo.keepControllerInBoard();// LooprequestAnimationFrame(updateGame);}// Keyboard eventsfunctionmoveController(key){// Upif(key ===38&& controller.velocityY < controller.maxSpeed){
controller.velocityY -= controller.acceleration;}// Downif(key ===40&& controller.velocityY < controller.maxSpeed){
controller.velocityY += controller.acceleration;}// Rightif(key ===39&& controller.velocityX < controller.maxSpeed){
controller.velocityX += controller.acceleration;}// Left, decrease accelerationif(key ===37&& controller.acceleration < controller.maxSpeed){
controller.velocityX -= controller.acceleration;}}functionrotate(x, y, sin, cos, reverse){return{x:(reverse)?(x * cos + y * sin):(x * cos - y * sin),y:(reverse)?(y * cos - x * sin):(y * cos + x * sin)};}// Events
document.addEventListener("keydown",function(e){moveController(e.keyCode);});// Add puckvar puck =newDisc();// Add controller & adjust settingsvar controller =newDisc();
controller.color ='#2132CC';
controller.radius +=10;
controller.acceleration =5;
controller.startingPosX =125;
controller.mass =50;
controller.x = controller.startingPosX;// Add controller twovar controllerTwo =newDisc();
controllerTwo.color ='#2132CC';
controllerTwo.radius +=10;
controllerTwo.mass =50;
controllerTwo.startingPosX =(boardWidth -155);
controllerTwo.acceleration =0.2;
controllerTwo.x = controllerTwo.startingPosX;// Store controllers
controllers.push(controller, controllerTwo);// Start gameupdateGame();</script></body></html>