Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I deflect the ball properly in a Javascript pong game?

I have written a simple pong game in Javascript. But I am having two problems with it.

  1. I don't know why the ball doesn't deflect off of the computer's paddle which is the "playerB" according to the code.

  2. How can I create some randomness when the ball deflects from the paddles? Currently the game seems very repetitive.

How can I fix these two problems?

Link to Jsfiddle

HTML

<!DOCTYPE html>
<html>
<head>
  <title>Pong game</title>
  <script type="text/javascript" src="jquery-2.1.4.min.js"></script>
  <script type="text/javascript" src="js/pong.js"></script>
  <link rel="stylesheet" href="css/pong.css">
</head>
<body>
  <header>
    <p>
    Computer:<span id="scoreB"></span> Human:<span id="scoreA"></span>
    </p>
  </header>
  <div id="playground">
    <div id="ball"></div>
    <div id="playerA" class="paddle right"></div>
    <div id="playerB" class="paddle left"></div>
  </div>
</body>
</html>

CSS

html,body{
  margin: 0 atuo;
  height:100%;
}
#playground{
  position: relative;
  width:700px;
  height:400px;
  border: 1px solid grey;
  overflow:hidden;
}
#ball{
  position: absolute;
  background: #fbb;
  width:20px;
  height:20px;
  left:200px;
  top:100px;
  border-radius:10px;
}
.paddle{
  position: absolute;
  border:1px solid grey;
  width:10px;
  height:80px;
}
.left.paddle{
  left:0px;
  background-color: green;
}
.right.paddle{
  right:0px;
  background-color: blue;
}

Javascript

$(document).ready(function(){
  var values = {
    ball:{
      speed:5,
      x:50,
      y:50,
      directionX: 1,
      directionY: 1,
      radius: 10
    },
    playground:{
      width: parseInt($("#playground").width()),
      height: parseInt($("#playground").height())
    },
    playerA:{
      y:0,
      top: $("#playerA").offset().top,
      height: $("#playerA").height(),
      width: $("#playerA").width(),
      score:0
    },
    playerB:{
      y:0,
      top: $("#playerB").offset().top,
      height: $("#playerB").height(),
      width: $("#playerB").width(),
      score:0
    }
  };
  //collision detection
  function hitsTopBottom(){
    var y = values.ball.y;
    return y>values.playground.height-20 || y < 0;
  }
  function hitsRight(){
    return values.ball.x > values.playground.width-20;
  }
  function hitsLeft(){
    return values.ball.x < 0;
  }
  //ball hits playerA's paddle. Works properly but open to improvement
  function hitsPlayerA(){
    var ballX = values.ball.x;
    var ballY = values.ball.y;
    var playerAY = values.playerA.y;
    return ballY<=playerAY+values.playerA.height && ballY>playerAY && ballX>=700-values.playerA.width-values.ball.radius;
  }
  //ball hits playerB's paddle. Doesn't work at all
  function hitsPlayerB(){
    var ballX = values.ball.x;
    var ballY = values.ball.y;
    var playerBY = values.playerB.y;
    return ballY<=playerBY+values.playerB.height && ballY>=playerBY && ballX<=values.playerB.width-values.ball.radius;
  }
  //rendering the position of the ball
  function renderball(){
    $("#ball").css("left",values.ball.x);
    $("#ball").css("top",values.ball.y);
    $("#scoreB").text(values.playerB.score);
    $("#scoreA").text(values.playerA.score);
  }
  //moving ball
  function moveball(){
    if(hitsTopBottom()){
      values.ball.directionY *= -1;
    }
    if(hitsPlayerA()){
      values.ball.directionX *= -1;
    }
    if(hitsPlayerB()){
      values.ball.directionX = 1;
    }
    if(hitsRight()){
      values.ball.x = 200;
      values.ball.y = 200;
      values.playerB.score += 1;
    }
    if(hitsLeft()){
      values.ball.x = 200;
      values.ball.y = 200;
      values.playerA.score += 1;
    }
    values.ball.x += values.ball.speed*values.ball.directionX;
    values.ball.y += values.ball.speed*values.ball.directionY;
    renderball();
    var playerB_pos = values.ball.y - values.playerB.height/2;
    $("#playerB").css("top",playerB_pos);
  }
  //player movements
  $("#playground").mousemove(function(e){
    values.playerA.y = e.pageY-values.playerA.top-parseInt($("#playerA").height()/2);
    $("#playerA").css("top",values.playerA.y);
  });
  setInterval(moveball,1000/30);
});
like image 418
Behroz Avatar asked Oct 19 '22 01:10

Behroz


2 Answers

The ball was not deflecting off the computer paddle because its position was not being stored. By setting values.playerB.y = playerB_pos in the loop it will correctly bounce off now. However since it is the same as the y position of the ball the computer will never lose. To correct for this and add some randomness I used jQuery's animate function to tween the computer paddle between points and fake momentum:

 if(!isAnimating) {
    isAnimating = true;
    $("#playerB").animate({"top": playerB_pos}, {
      duration: (values.ball.speed*16),
      easing: "linear",
      step: function( now, fx ) {
        values.playerB.y = parseInt($("#playerB").offset().top - parseInt($("#playerA").height()));
      }, 
      complete: function() {
        isAnimating = false;
      }
    }); 
  }

You can see it in action here: http://jsfiddle.net/yb290ow9/5/

like image 53
Paul Graffam Avatar answered Oct 31 '22 15:10

Paul Graffam


You forgot to edit the actual playerB.y value (you just changed the css):

var playerB_pos = values.ball.y - values.playerB.height/2;
values.playerB.y = playerB_pos; // Forgot this!
$("#playerB").css("top",playerB_pos);

Working JSFiddle: http://jsfiddle.net/yb290ow9/6/

About the randomness: you could make the paddle "bouncy": change the speed of the ball, not just the direction

like image 28
Ángela Avatar answered Oct 31 '22 16:10

Ángela