HTML5 Canvas Physics
Hi I have the following Canvas application: http://dev.driz.c开发者_运维知识库o.uk/canvas/
As you will see it renders a load of balls. The problem I am having is that the balls are being cut-off by the canvas edge when the app first starts. They should not do this they should bounce off the canvas edge if they touch it!
I'm having difficulty sorting the physics out, they bounce off if you move the mouse but not if on the start up.
THANKS
You can just examine, and if any ball is being cut off (it extends past the wall), then just reposition it at the wall, or, move the ball that far from the wall in the direction it should be going.
So, if the ball is 3 pixels past the wall, then you can just position it 3 pixels away from the wall, in the new direction.
This will help in that if your time period is too small, and the balls are moving too fast you can fix it.
UPDATE:
After looking at your code, for some reason I can't see it moving in Chrome nor does it draw on Firefox 4b7, but by looking at your code this line may be an issue:
Balls[i].x += Balls[i].vx;
If x + vx < 0
then it will still be to the left of the wall.
The reason it can be off is you have this code: Balls[i].vx *= 0.99;
, which will keep decreasing vx
before you do your check. You may want to put this at the end, after you made adjustments.
Also, you have both the code for the left and right wall in the same if statement block, which I expect should be handled separately.
To troubleshoot this your best bet is to use Firebug, on Firefox, with one ball, and put a break statement when it goes past a wall, and then see what the values are in each step.
You are also assuming that the balls travel in a straight line, when you adjust, as you are only correcting in one direction, depending on which if
statement fails, though it can be possible, in case of corners, to have both fail. That is a failure in your physics model, if I am going at a 45 degree angle and I hit the wall, I should rebound at a 45 degree angle, if the wall is ideal, for example.
Learn to use the debuggers, Chrome, IE and Firefox have good ones, but I tend to prefer to use Firebug, perhaps due to experience with it.
Here's the Fix
if (ball[i].x - ball[i].r <= 0 || ball[i].x + ball[i].r >= cwidth) {
ball[i].vx = -ball[i].vx;
ball[i].x += ball[i].vx;
}
if (ball[i].y - ball[i].r <= 0 || ball[i].y + ball[i].r >= cheight) {
ball[i].vy = -ball[i].vy;
ball[i].y += ball[i].vy;
}
You will love the Mozilla Developer Network article: Basic Animations.
As far as I can tell, you need to update the canvas whenever it changes with the canvas.restore()
function.
You can use Box2D for the physics.
You had a problem with your syntax
vX not vx. vY not vy.
Plus you needed a function to call to render. Post your final results at jsdo.it ( when you finish the physics ). Looks really cool.
window.onload=App function App() { var pool = document.getElementById('pool'); var canvas = pool.getContext('2d'); var cwidth = pool.width = window.innerWidth; var cheight = pool.height = window.innerHeight; var ctop = pool.offsetTop; var cleft = pool.offsetLeft; var size = [5, 10, 15, 20, 25, 30]; var numBalls = 100; // CREATES THE BALL function Ball(x, y, vx, vy, r, s) { this.color = rgb(); this.x = x; this.y = y; this.vX = vx; this.vY = vy; this.r = r; this.size = s; } // GIVES EACH BALL A RANDOM COLOR function rgb() { var color = 'rgb('; for (var i = 0; i < 3; i++) { color += Math.floor(Math.random() * 255) + ','; } return color.replace(/\,$/, ')'); } var Balls = [], x, y, vx, vy, r, s;for (var i = 0; i < numBalls; i++) { x = Math.random() * cwidth >> 0; y = Math.random() * cheight >> 0; vx = Math.random() * 20 - 6; vy = Math.random() * 20 - 6; r = Math.random() * 15 + 30; s = size[~~(Math.random() * size.length >> 0)]; // CREATES THE BALLS Balls.push(new Ball(x, y, vx, vy, r, s)); } function render(){ // DRAWS THE CANVAS AND BALLS
// PHYSICS Balls.map(function(item){ // BALLS SHOULD BOUNCE OFF CANVAS EDGE
item.vX *= 0.99; item.vY *= 0.99;item.x += item.vX; item.y += item.vY; if (item.x < item.r ){ item.vX *= -.99; item.x += item.vX; } if(item.x > pool.width - item.r) { item.vX *= -.99; item.x += item.vX; } if (item.y < item.r ){ item.vY *= -.99; item.y += item.vY; } if( item.y > pool.height - item.r) { item.vY *= -1; item.y += item.vY; }
}) // END PHYSICS canvas.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
for (var i in Balls) { var b = Balls[i]; var grad = canvas.createRadialGradient(b.x + b.r / 4 , b.y - b.r / 4 , b.r / 5 , b.x, b.y, b.r); grad.addColorStop(0, '#fff'); grad.addColorStop(.85, b.color); grad.addColorStop(1, '#222'); canvas.beginPath(); canvas.fillStyle = grad; canvas.arc(b.x, b.y, b.r, 0, Math.PI * 2, 0); canvas.fill(); }
}
// END FOR // MOUSE MOVEMENT - BALLS SHOULD MOVE AWAY FROM MOUSE CURSOR pool.onmousemove = function(e) { x = e.pageX - this.offsetLeft; y = e.pageY - this.offsetTop; for (i = 0; i < numBalls; i++) { if (Math.abs(x - Balls[i].x) < 20 && Math.abs(y - Balls[i].y) < 20 ) { Balls[i].vX = (x - Balls[i].x) ; Balls[i].vY = (y - Balls[i].y) ; } } };
setInterval(render,50);
// END APP
};
精彩评论