我试图用Java进行Brick Breaker游戏,我希望我的球有一个弯曲的轨迹,基于划桨的加速度(不涉及重力)。如何计算给定时刻的球位置?我想我需要先计算速度,但我无法弄清楚如何做到这一点。
答案 0 :(得分:1)
弯曲的轨迹?你的意思是当你击球时你加入旋转球然后旋转会让球在空中弯曲吗?
如果是,请使用以下方法。
球需要以下属性
ball = {
x, // position x, y
y,
dx, // delta x and y
dy,
dr, // delta rotation
radius, // balls radius
}
还有一只蝙蝠
bat = {
top, // y pos of top of bat
dx, // delta x (sideways speed
// plus what ever else you have
}
当球击中球棒时,做正常反射。
ball.dy = -ball.dy;
ball.y = bat.top - ball.radius
要将蝙蝠侧向移动转换为球旋转,只需要球的半径(对于最简单的方法)假设蝙蝠位于屏幕的底部。
旋转量与球相对于球的侧向运动有关,然后除以半径以给出每帧的旋转变化。将其添加到球的当前轮换
ball.dr += (ball.dx - bat.dx) / ball.radius
我们不打算进行完整的流体动力学模拟,而是进行近似。
当球在空中移动时,正在旋转,球的一侧在气流(外侧)中向前移动,另一侧在相反方向(内侧)移动。表面上气流的不平衡以及内部旋转与空气一起拉动空气的方式会在垂直于球运动的方向上产生内部的低压区域。
这个低压区域施加的力分散在球的直径
上Force = (airDensity * ballVelocity * Math.pow(2 * PI * ball.radius,2) * ball.dr ) / (2 * ball.radius)
我们并不需要这一切。空气密度与球半径一样固定。因此,力是球速度和球旋转速率之间的线性关系。其余的可以设置为我们可以调用spinCof的系数值
力增加加速度,这取决于质量。同样,这不会改变,所以我们可以将它添加到spinCof值。
所以最终的公式是
Acceleration = spinCof * ballVelocity * ball.dr;
spinCof的值未知,您需要尝试找到可播放的值。
在代码中执行此操作
spinCof = ? some value
var ballVelocity = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
var nx = ball.dx / ballVelocity; // get normalised vector of motion
var ny = ball.dy / ballVelocity;
var accel = spinCof * ballVelocity * ball.dr; // get the acceleration due to spin
ball.dx -= ny * accel; // apply acceleration perpendicular to motion
ball.dy += nx * accel; //
就是这样。
在实践中快速举例说明
var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}
// create canvas and add to DOM
var canvas = createImage(512,200);
var ctx = canvas.ctx;
document.body.appendChild(canvas);
var w = canvas.width;
var h = canvas.height;
const spinCof = 0.01;
const airFriction = 0.001;
const spinFriction = 0.001;
var ball = {
x : ctx.canvas.width * 2, // start off screen
y : 0,
dx : 1,
dy : 0,
ang : 0,
dr : 0,
radius : 30,
holdFrames : 0, // time to wait befor firing ball
draw(){
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.setTransform(1,0,0,1,this.x,this.y);
ctx.rotate(this.ang);
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(0,0,this.radius,0,Math.PI * 2);
ctx.stroke();
ctx.setTransform(1,0,0,1,0,0);
},
update(){
if(this.holdFrames > 0){
this.holdFrames -= 1;
this.ang += this.dr;
}else{
this.dx *= (1-airFriction); // add friction due to air
this.dy *= (1-airFriction);
this.dr *= (1-spinFriction); // add friction to the balls spin
var ballVelocity = Math.sqrt(this.dx * this.dx + this.dy * this.dy);
var nx = this.dx / ballVelocity; // get normalised vector of motion
var ny = this.dy / ballVelocity;
var accel = spinCof * ballVelocity * this.dr; // get the acceleration due to spin
this.dx -= ny * accel; // apply acceleration perpendicular to motion
this.dy += nx * accel; //
this.x += this.dx;
this.y += this.dy;
this.ang += this.dr;
if(this.x > ctx.canvas.width + this.radius){ // ball off canvas so reset
this.dx = Math.random() * 5 + 4; // set random x speed
this.dy = 0;
this.dr = (Math.random() * 0.5) * (Math.random() < 0.5 ? -1 : 1); // set random spin
this.x = 0;
this.y = canvas.height / 2;
this.holdFrames = 60;
}
}
}
}
// Main animation loop
function mainLoop1(time){
ctx.globalCompositeOperation = "destination-out";
ctx.globalAlpha = 0.1;
ctx.fillRect(0,0,w,h); // clear da screen
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = 1;
ball.update();
ball.draw();
requestAnimationFrame(mainLoop1);
}
// start the animation
requestAnimationFrame(mainLoop1);
&#13;