请原谅我对 JS 的新知识。 我已经创建了一个非常简单的 Canvas ,其中一个矩形由 keydownevents 控制,另一个只是在 rAF 中围绕 Canvas 移动。
我现在想知道,如果移动的球撞到用户的矩形会发生碰撞并反弹回来,但会以正确的 Angular 反弹,而不是像我尝试过但失败的那样反向反弹。
我知道我需要计算它在用户矩形上的位置,但我不知道从哪里开始或如何开始 有人能给我指出正确的方向或给我一小段该怎么做吗?
我将省略 Keycode 函数以节省空间,因为不需要它们。
function init() {
canvas = document.getElementById("canvasdemo");
ctx = canvas.getContext("2d");
canvasWidth = canvas.width;
canvasHeight = canvas.height;
drawSquare();
}
function drawSquare() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// user controlled square
ctx.fillStyle = "blue";
ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
requestAnimationFrame(drawSquare);
if (rect.x + rect.vx > canvasWidth - 20 || rect.x + rect.vx < 0)
rect.vx = -rect.vx;
if (rect.y + rect.vy > canvasHeight - 20 || rect.y + rect.vy < 0)
rect.vy = -rect.vy;
rect.x += rect.vx;
rect.y += rect.vy;
// Moving Square 1 (left-right):
requestAnimationFrame(squareTwo);
if (dir1 == "right") {
if (xpos < canvasWidth - 35) {
xpos += 2;
}else{
dir1 = "left";
}
}
if (dir1 == "left") {
if (xpos>0) {
xpos -= 2;
}else{
dir1 = "right";
}
}
}
// Second square
function squareTwo() {
ctx.fillStyle = "black";
ctx.fillRect(xpos, ypos, 35, 35);
ctx.fill();
}
最佳答案
要计算你可以做的反射 -
首先,将法线定义为基于焊盘 Angular 向量:
function getNormal(a) {
return {
x: Math.sin(a), // this will be 90° offset from the
y: -Math.cos(a) // incoming angle
}
}
然后用点积计算与传入向量的入射 Angular :
function reflect(n, v) {
var d = 2 * dot(v, n); // calc dot product x 2
v.x -= d * n.x; // update vectors reflected by
v.y -= d * n.y; // normal using product d
return v
}
// helper, calc dot product for two vectors
function dot(v1, v2) {
return v1.x * v2.x + v1.y * v2.y
}
然后你需要一个 HitTest 来触发反射。当被击中时,将传入的向量反射到与焊盘成 90° 切线的法线上。
一个简单的演示:
function getNormal(a) {
return {
x: Math.sin(a),
y: -Math.cos(a)
}
}
function reflect(n, v) {
var d = 2 * dot(v, n);
v.x -= d * n.x;
v.y -= d * n.y;
return v
}
function dot(v1, v2) {
return v1.x * v2.x + v1.y * v2.y
}
// --- for demo only ---
var ctx = document.querySelector("canvas").getContext("2d"),
balls = [], padAngle = 0, angleDlt = 0.005;
function Ball() { // a Ball object for demo (replace or use existing)
var me = this;
init();
this.update = function() {
if (this.posX < 0 || this.posX > 500 || this.posY < -4 || this.posY > 150) init();
this.posX += this.x;
this.posY += this.y;
ctx.rect(this.posX - 2, this.posY - 2, 4, 4);
};
function init() {
me.posX = Math.random() * 100 + 200;
me.posY = -4;
me.x = Math.random() - 0.5;
me.y = 1;
me.hit = false;
}
}
// init some balls
for(var i = 0; i < 4; i++) balls.push(new Ball());
// animate demo
(function loop() {
ctx.clearRect(0, 0, 500, 150);
// speeds up frames but preserves some accuracy
for(var subframes = 0; subframes < 3; subframes++) {
ctx.beginPath();
// render pad
padAngle += angleDlt;
if (padAngle < -Math.PI * 0.2 || padAngle > Math.PI * 0.2) angleDlt = -angleDlt;
drawPad(padAngle);
// get normal
var normal = getNormal(padAngle);
// hit test using the pad's path - this is where we do the reflection
for(var i = 0, ball; ball = balls[i++];) {
if (!ball.hit && ctx.isPointInPath(ball.posX, ball.posY)) {
ball.hit = true;
reflect(normal, ball);
}
}
// update balls
for(var i = 0, ball; ball = balls[i++];) ball.update();
}
ctx.fill();
requestAnimationFrame(loop)
})();
function drawPad(angle) {
ctx.translate(250, 100);
ctx.rotate(angle);
ctx.rect(-50, -3, 100, 6);
ctx.setTransform(1,0,0,1,0,0);
}
<canvas width=500></canvas>
关于javascript - 如何让球以正确的方向而不是直线从桨上反弹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29910502/