Reputation: 19
So I'm new to javascript and trying to make a ball I designed bounce off the canvas so far I've gotten the code to make the ball bounce up and down now I'm just wondering how I would be able to do so horizontally.
I have tried making an xPosistion as I assumed a ypostion is vertital and that by using x must mean it's horizontal but trying this it's like my code just gets frozen, I've commented it out so that when you try the code you can see what I'm trying to achieve as the ball is bouncing up and down perfectly
// Gets a handle to the element with id canvasOne.
var canvas = document.getElementById("canvas-for-ball");
// Get a 2D context for the canvas.
var ctx = canvas.getContext("2d");
// The vertical location of the ball.
var yPos = 10;
var yVel = 2;
// A function to repeat every time the animation loops.
function repeatme() {
ctx.clearRect(0, 0, 300, 300)
// Draw the ball (stroked, not filled).
ctx.beginPath();
ctx.arc(70, yPos, 7, 0, 2 * Math.PI);
ctx.stroke();
// Update the y location.
yPos += yVel;
//console.log(yPos);
/*xPos += xVel;
console.log(xPos);*/
// Thos of statement shows if ball hits off this position bounce back
if (yPos > 290)
yVel *= -1;
if (yPos < 10)
yVel *= -1;
/* if (xPos > 200)
xVel *= -1;
if (xPos < 100)
xVel *= -1;*/
window.requestAnimationFrame(repeatme);
}
// Get the animation going.
repeatme();
background-color: white;
<h1>Akeem Jokosenumi</h1>
<canvas id="canvas-for-ball" width="300" height="300" style="border:1px solid"></canvas>
Upvotes: 2
Views: 738
Reputation: 17584
You should start using the canvas dimension (width, height) in your code so those numbers don't look like magic, here is the code that does what you need:
var canvas = document.getElementById("canvas-for-ball");
var ctx = canvas.getContext("2d");
var ball = { x: 45, y: 10, r: 7, xVel: 1, yVel: 1 }
function repeatme() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, 2 * Math.PI);
ctx.fill();
// Update the location.
ball.x += ball.xVel;
ball.y += ball.yVel;
// ball hits wall then bounce back
if ((ball.x > canvas.width - ball.r) || (ball.x < ball.r)) {
ball.xVel *= -1;
}
if ((ball.y > canvas.height - ball.r) || (ball.y < ball.r)) {
ball.yVel *= -1;
}
window.requestAnimationFrame(repeatme);
}
repeatme();
background-color: white;
<canvas id="canvas-for-ball" width="90" height="90" style="border:1px solid"></canvas>
You can see I'm putting all the ball related variables in one object:
var ball = { x: 45, y: 10, r: 7, xVel: 1, yVel: 1 }
there we have initial position (x, y) and radius (r) and the velocity
Later in the condition I'm not using any magic numbers...
instead of:
if (yPos > 290) ...
you can see:
if ((ball.y > canvas.width - ball.r) ...
The ball bounces on the right wall when the position is greater than the canvas width minus the ball radius, similar logic can be applied to all other walls.
This way we can change the canvas size and ball radius without having to change our logic.
Here is another implementation... This time I'm using a class to abstract the ball logic, that way we can have multiple instances with different parameters
var canvas = document.getElementById("canvas-for-ball");
var ctx = canvas.getContext("2d");
class Ball {
constructor(x, y, r, xVel, yVel) {
this.x = x
this.y = y
this.r = r
this.xVel = xVel
this.yVel = yVel
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
ctx.stroke();
// Update the location.
this.x += this.xVel;
this.y += this.yVel;
// ball hits wall then bounce back
if ((this.x > canvas.width - this.r) || (this.x < this.r)) {
this.xVel *= -1;
}
if ((this.y > canvas.height - this.r) || (this.y < this.r)) {
this.yVel *= -1;
}
}
}
balls = []
balls.push(new Ball(45, 10, 7, 1, 1))
balls.push(new Ball(9, 4, 3, -2, -2))
balls.push(new Ball(50, 20, 14, 0.5, 0.5))
function repeatme() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
balls.forEach(ball => ball.draw());
window.requestAnimationFrame(repeatme);
}
repeatme();
background-color: white;
<canvas id="canvas-for-ball" width="200" height="140" style="border:1px solid"></canvas>
The real fun begins with the collisions between the balls...
Upvotes: 3
Reputation: 37227
Simply adding the same variables and logic for xPos
works perfectly.
// Gets a handle to the element with id canvasOne.
var canvas = document.getElementById("canvas-for-ball");
// Get a 2D context for the canvas.
var ctx = canvas.getContext("2d");
// The horizontal location of the ball.
var xPos = 10;
var xVel = 2;
// The vertical location of the ball.
var yPos = 10;
var yVel = 2;
// A function to repeat every time the animation loops.
function repeatme() {
ctx.clearRect(0, 0, 300, 300)
// Draw the ball (stroked, not filled).
ctx.beginPath();
ctx.arc(xPos, yPos, 7, 0, 2 * Math.PI);
ctx.stroke();
// Update the y location.
yPos += yVel;
//console.log(yPos);
xPos += xVel;
//console.log(xPos);
// Thos of statement shows if ball hits off this position bounce back
if (yPos > 290)
yVel *= -1;
if (yPos < 10)
yVel *= -1;
if (xPos > 290)
xVel *= -1;
if (xPos < 10)
xVel *= -1;
window.requestAnimationFrame(repeatme);
}
// Get the animation going.
repeatme();
background-color: white;
<h1>Akeem Jokosenumi</h1>
<canvas id="canvas-for-ball" width="300" height="300" style="border:1px solid"></canvas>
The problem with your original code is, assuming your initial xPos
is 70 (inferred from your argument to ctx.arc
), you set the range to 100-200. Because your ball moves by only 2 pixels on each frame, it'll never reach "range 100" and will constantly switch between x = 70 and 72. Just pay attention to the initial values w.r.t your if
conditions.
Upvotes: 0