Javascript p5.js中的角碰撞角度 总结:

Javascript p5.js中的角碰撞角度 总结:,javascript,processing,collision-detection,physics,p5.js,Javascript,Processing,Collision Detection,Physics,P5.js,为了尝试在一个移动的矩形和一个下降的圆之间建立一个简单的碰撞检测系统,我想让它更真实 主要问题: -我想解决的主要问题是,检测圆对象何时撞击矩形的角,反过来,使圆基于该角度反弹 守则: var-balls=[]; var障碍; 函数设置(){ createCanvas(400400); 障碍=新障碍(); } 函数绘图(){ 背景(75); 障碍物显示(); 障碍。更新(); 对于(变量i=0;i=高度-this.r){ this.y=高度-this.r; this.velocity=this

为了尝试在一个移动的矩形和一个下降的圆之间建立一个简单的碰撞检测系统,我想让它更真实

主要问题: -我想解决的主要问题是,检测圆对象何时撞击矩形的角,反过来,使圆基于该角度反弹

守则:

var-balls=[];
var障碍;
函数设置(){
createCanvas(400400);
障碍=新障碍();
}
函数绘图(){
背景(75);
障碍物显示();
障碍。更新();
对于(变量i=0;i=高度-this.r){
this.y=高度-this.r;
this.velocity=this.velocity*-1;
this.gravity=this.gravity*1.1;
}
}
}
功能障碍(){
x=宽度-宽度;
这.y=高度/2;
这是w=200;
这个h=25;
this.display=函数(){
填充(0);
中风(255);
rect(this.x,this.y,this.w,this.h);
}
this.update=函数(){
这个.x++;
如果(此.x>宽度+此.w/2){
this.x=-this.w;
}
}
}
功能矩形环形滚球(球、障碍物){
//定义障碍边界
var oRight=障碍物.x+障碍物.w;
var oLeft=障碍物x;
var-oTop=障碍物y;
var oBottom=障碍物.y+障碍物.h;
//比较球的位置(计算半径)和障碍物的边界
如果(球x+球r>oLeft){
if(球x-球r<或右){
if(Ball.y+Ball.r>oTop){
if(Ball.y-Ball.r

先决条件

球的速度必须是一个矢量(XY分量),而不仅仅是一个数字


1.确定圆是否可能碰到边或角 获取从矩形中心到圆的向量分量,并对照矩形的尺寸进行检查:

// Useful temporary variables for later use
var hx = 0.5 * obstacle.w;
var hy = 0.5 * obstacle.h;
var rx = obstacle.x + hx;
var ry = obstacle.y + hy;

// displacement vector
var dx = ball.x - rx;
var dy = ball.y - ry;

// signs
var sx = dx < -hx ? -1 : (dx > hx ? 1 : 0);
var sy = dy < -hy ? -1 : (dy > hy ? 1 : 0);

3.确定碰撞法向量
(tx,ty)
是法向量的分量,但仅当球的中心位于矩形之外时:

// epsilon to account for numerical imprecision
const EPSILON = 1e-6;

var nx = 0, ny = 0, nl = 0;
if (sx == 0 && sy == 0) {  // center is inside
  nx = dx > 0 ? 1 : -1;
  ny = dy > 0 ? 1 : -1;
  nl = Math.hypot(nx, ny);
} else {                   // outside
  nx = tx;
  ny = ty;
  nl = dc;
}
nx /= nl;
ny /= nl;

4.解决任何“渗透” (请不要讲不成熟的笑话)

这样可以确保球永远不会穿透矩形的表面,从而提高碰撞的视觉质量:

ball.x += (ball.r - dc) * nx; 
ball.y += (ball.r - dc) * ny;

5.解决冲突 如果圆沿法线方向移动,不要解决碰撞问题,因为球可能会粘在曲面上:

// dot-product of velocity with normal
var dv = ball.vx * nx + ball.vy * ny;

if (dv >= 0.0) {
    /* exit and don't do anything else */
}

// reflect the ball's velocity in direction of the normal
ball.vx -= 2.0 * dv * nx;
ball.vy -= 2.0 * dv * ny;

工作JS代码段
const重力=250.0;
功能球(x,y,r){
这个.x=x;
这个。y=y;
这个。r=r;
该值为0.vx=0;
这是0.vy=0;
this.display=函数(){
填充(255,0,100);
中风(255);
椭圆(这个.x,这个.y,这个.r*2);
}
this.collidePage=函数(b){
如果(this.vy>0&&this.y+this.r>=b){
this.y=b-this.r;
this.vy=-this.vy;
}
}
this.updatePosition=函数(dt){
这个.x+=这个.vx*dt;
这个.y+=这个.vy*dt;
}
this.updateVelocity=函数(dt){
这.vy+=重力*dt;
}
}
功能障碍(x、y、w、h){
这个.x=x;
这个。y=y;
这个.w=w;
这个,h=h;
this.display=函数(){
填充(0);
中风(255);
rect(this.x,this.y,this.w,this.h);
}
this.update=函数(){
这个.x++;
如果(此.x>宽度+此.w/2){
this.x=-this.w;
}
}
}
var=[];
var障碍;
函数设置(){
createCanvas(400400);
障碍物=新障碍物(0,高度/220025);
}
常数DT=0.05;
函数绘图(){
背景(75);
障碍。更新();
障碍物显示();
对于(变量i=0;ihx?1:0);
var sy=dy<-hy-1:(dy>hy-1:0);
var tx=sx*(数学绝对值(dx)-hx);
var ty=sy*(数学abs(dy)-hy);
var dc=数学形压(tx,ty);
如果(dc>ball.r)
返回false;
变量nx=0,ny=0,nl=0;
如果(sx==0&&sy==0){
nx=dx>0?1:-1;ny=dy>0?1:-1;
nl=数学形下压(nx,ny);
}否则{
nx=tx;ny=ty;
nl=dc;
}
nx/=nl;ny/=nl;
ball.x+=(ball.r-dc)*nx;ball.y+=(ball.r-dc)*ny;
var dv=ball.vx*nx+ball.vy*ny;
如果(dv>=0.0)
返回false;
ball.vx-=2.0*dv*nx;ball.vy-=2.0*dv*ny;
返回true;
}

我将尝试提出一种解决方案,它尽可能与原始代码保持一致。解决方案是对问题中提出的代码进行改进

将侧向移动(
selv.sideV
)添加到
// dot-product of velocity with normal
var dv = ball.vx * nx + ball.vy * ny;

if (dv >= 0.0) {
    /* exit and don't do anything else */
}

// reflect the ball's velocity in direction of the normal
ball.vx -= 2.0 * dv * nx;
ball.vy -= 2.0 * dv * ny;