processing - 碰撞后反弹不起作用,并且物体通过地形剪辑
问题描述
编辑我将我的代码更改为下面的代码,但有时它仍然会穿过地形。它还喜欢在应该滑落的角落弹跳。我尝试为我正在制作的一个小游戏实现我自己的碰撞。这是我的球类的代码。
class Ball {
//config
float gforce = 1;
float friction = 0.8;
float elasticity = 0.5;
//vars
PVector position;
PVector velocity = new PVector(0, 0);
Ball(PVector p) {position = p;}
void render(){fill(255, 255, 0); noStroke(); circle(position.x, height-position.y, 16);}
PVector bounce(PVector v, PVector n){ //calculate velocity after bounce
PVector u = PVector.mult(n,v.dot(n)/n.dot(n));
PVector w = PVector.sub(v, u);
return PVector.sub(PVector.mult(w, friction), PVector.mult(u, elasticity));
}
Boolean intersect(PVector c, PVector p1, PVector p2, float r){
if (c.dist(p1)<=r || c.dist(p2)<=r){return true;}
float len = p1.dist(p2);
float dot = ( ((c.x-p1.x)*(p2.x-p1.x)) + ((c.y-p1.y)*(p2.y-p1.y)) )/(len*len);
PVector closest = PVector.add(p1, PVector.mult(PVector.sub(p2, p1), dot));
float d1 = closest.dist(p1);
float d2 = closest.dist(p2);
if (d1+d2>=len-0.1 && d1+d2<=len+0.1){if(closest.dist(c)<=r){return true;}}
return false;
}
Boolean intersect(PVector p1, PVector p2, PVector p3, PVector p4){ //if the line p1p2 intersects line p3p4
float uA = ((p4.x-p3.x)*(p1.y-p3.y) - (p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x) - (p4.x-p3.x)*(p2.y-p1.y));
float uB = ((p2.x-p1.x)*(p1.y-p3.y) - (p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x) - (p4.x-p3.x)*(p2.y-p1.y));
if (uA>=0 && uA<=1 && uB>=0 && uB<=1){return true;}else{return false;}
}
void moveBall(){
//if the ball is stationary
if(velocity.mag()==0 || velocity.mag()==1 || velocity.mag()==2){
PVector v = new PVector(min(280, max(-280, mX-mouseX)), min(280, max(-280, mouseY-mY))).div(28);
int n = int(max(abs(v.x), abs(v.y)));
v.normalize().mult(25);
//render arrow
if(mX!=0 && mousePressed){
strokeWeight(5); stroke(#75D5FD); line(mX, mY, mouseX, mouseY);
for (int i=0; i<n+1; i++){
noStroke(); fill(510*(float)i/12, 510*(1-(float)i/12), 0, 55+200*(1-(float)i/12)); circle(mX+(v.x*i), mY-(v.y*i), 15);
}
}
if(mX==0 && mouseP){mX=mouseX; mY=mouseY; mouseP=false;}
if(mX!=0 && mouseR){b.velocity = new PVector(min(280, max(-280, mX-mouseX)), min(280, max(-280, mouseY-mY))).div(8); mX=0; mouseR=false;} //apply velocity
}else {
//if the ball is still, do not allow additional movement
if(mX!=0 && mousePressed){stroke(200); line(mX, mY, mouseX, mouseY);}
if(mX==0 && mouseP){mX=mouseX; mY=mouseY; mouseP=false;}
if(mX!=0 && mouseR){mX=0; mouseR=false;}
}
}
void collision(){
//test collision with terrain
for (int i=1; i<l.points.length; i++){
PVector centerout = PVector.div(velocity, velocity.mag()).mult(8);
strokeWeight(5); stroke(255,0,0); line(position.x, height-position.y, position.x+centerout.x+velocity.x, height-position.y-centerout.y-velocity.y);
if(intersect(position, l.points[i-1], l.points[i], 7) || intersect(position, PVector.add(position,velocity,centerout), l.points[i-1], l.points[i])){
velocity = bounce(velocity, l.normals[i-1]);
}
}
}
void move() {
moveBall();
collision();
position.add(velocity);
if(velocity.y>-10){velocity.y-=gforce;}
if(velocity.mag()<0.5){velocity.x=0; velocity.y=0;}
}
}
还有另一个对象 l(地形),它存储数组 points[],其中包含地形的所有坐标。有一条线连接每个点,球会检测它的速度矢量是否与该线相交,或者球本身是否与该线相交。
当我拖动并释放鼠标时,它会将速度更改为鼠标拖入的任何矢量。然后它会检测碰撞并根据当前速度和地形的法线改变速度。然而,当它这样做时,它会朝相反的方向飞行,并在地板上一甩。
如何修复我的代码以使碰撞和弹跳按预期工作?此外,如果弹跳一段时间后速度最终变为 0,那就太好了。
哦,通常 y 位置越往下走就越高,但我改变了它,使 y 位置越往下走,你越往下走。所以在最底部,y 位置是 0 而不是画布的高度。
解决方案
关于您当前的问题,我实际上有两个不同的建议, 我在考虑后决定只提供第一个,因为第二个可能会让您陷入递归疯狂,但如果需要,我愿意扩展它。但是,如果没有工作示例,我无法真正测试它们或为您提供真实代码,因此我将停留在伪代码级别。
解决方案 1:简单而强大
这个非常简单:保存预反弹向量。当球实际弹起时,如果反弹有削波,请忘记它并反转初始向量。由于球来自这个确切的方向,你可以非常确定它可以从那个方向返回。
算法会是这样的:
if ValidateMove(CurrentVector):
Move(CurrentVector)
else:
NewVector = CalculateNewVector
if ValidateMove(NewVector):
Move(NewVector)
else:
Move(CurrentVector.Invert)
但是,可能存在有问题的边缘情况。如果另一个物体在运动,它可能会挡住球的倒转路径。老实说,除非你的游戏特别容易出现这种情况,否则我不会关心这种情况发生的可能性。
希望这会有所帮助!
推荐阅读
- r - 在 Shiny 中不同的导入 xlsx-Sheets 上运行 R-Code
- delphi - Delphi C++ Indy UDP Server BytesToString 没有收到正确的字符串?
- git - GIT:无法暂存更改以提交,在我提交更改之前无法拉取
- ncurses - 屏幕真彩 Ubuntu 18.04 坏了
- java - 如何维护 2 个不同的 Web 应用程序之间的用户会话?
- google-chrome - Chrome 扩展原生消息在 MacOS 上不起作用
- c# - 需要一种策略来缓存有关对象的信息而不使其保持活动状态
- android - Android:layout_weight 不适用于 Button 和 LinearLayout
- jenkins - 詹金斯构建触发器不等待孩子的孩子完成
- node.js - 在 Restify API 中实现的 Socket.io 的蝗虫负载测试导致显着减速