Reputation: 6753
Intended behavior
Sample values: Velocity: 10; Angle: 45; Color: red; Radius: 50.
On clicking "Shoot!" button, ball should move until it finally disappears behind one of the walls. Note that I want to simulate real world ball with gravity.
Each time we click Shoot, one more ball should be added to the balls
array which will also be drawn.
What happens
A black ellipse is shown on clicking shoot once/multiple time. No console errors seen.
Code:
(function () {
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
WIDTH = canvas.width,
HEIGHT = canvas.height;
// our ball object
function Ball(radius, color) {
this.radius = radius;
this.color = color;
this.x = 50; // start coordinates
this.y = 50;
this.velX = 0;
this.velY = 0;
this.accX = 0;
this.accY = 0;
this.gravity = 0;
this.start = function (angle, velocity) {
this.gravity = 9.8;
this.angle = angle / 180 * Math.PI; // convert to radians
this.velX = velocity * Math.cos(this.angle);
this.velY = velocity * Math.sin(this.angle);
this.accX = 0; // zero intially
this.accY = 0; // TODO: set option for user to set himself
};
this.update = function () {
this.velY -= this.gravity;
};
this.draw = function () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.fillSyle = this.color;
ctx.fill();
ctx.closePath();
}
}
// balls array
var balls = [];
document.querySelector("input[type='button']").onclick = function () {
var color = gId("color").value, // getElementById; defined in jsfiddle
velocity = gId("velocity").value,
angle = gId("angle").value,
radius = gId("radius").value;
var ball = new Ball(radius, color);
ball.start(angle, velocity);
balls.push(ball);
};
setInterval(function () {
for (var i = 0, len = balls.length; i < len; i++) {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
balls[i].draw();
balls[i].update();
}
}, 1000 / 60); // 1000/x depicts x fps
I have no idea why it doesn't work. System: Windows 7 on Chrome/Firefox latest.
Any help is appreciated. Please comment for more information.
Upvotes: 1
Views: 396
Reputation: 1481
1) Set width and height attributes on your canvas element instead of applying a css style i.e:
<canvas width="400px" height="400px">You don't support canvas.</canvas>
2) divide the value of gravity by 60 because your update function is invoked every 1/60th of a second i.e:
this.start = function (angle, velocity) {
this.gravity = 9.8 / 60;
this.angle = angle / 180 * Math.PI; // convert to radians
this.velX = velocity * Math.cos(this.angle);
this.velY = velocity * Math.sin(this.angle);
this.accX = 0; // zero intially
this.accY = 0; // TODO: set option for user to set himself
};
3) change the update function to:
this.update = function () {
this.velY += this.gravity;
this.x += this.velX;
this.y += this.velY;
};
4) move the ctx.clearRect method outside the for loop otherwise you will only see one ball animating always i.e
setInterval(function () {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i = 0, len = balls.length; i < len; i++) {
balls[i].draw();
balls[i].update();
}
}, 1000 / 60); // 1000/x depicts x fps
Here the updated js-fiddle: http://jsfiddle.net/km6ozj6L/1/
Upvotes: 1