游戏碰撞测试,游戏中的碰撞检测常用方法
游戏效果图
通过鼠标拖拽在画布上添加墙壁,通过方向键控制多边形上下左右移动,遇到墙壁则无法前进。需要解决的问题
鼠标按下,鼠标拖动,鼠标释放事件的检测
多边形的绘制
墙壁的绘制
多边形和墙壁的碰撞检测(实质上是圆和线段的相交判断)MYCode: 复制代码代码如下:
超文本标记语言
头
标题迷宫/标题
脚本
var canvas _宽度=900
var canvas _ height=350
var ctx
定义变量画布;
var everything=[];
var曲线壁
可变墙宽;
var wall_style=rgb(200,0,200);
var walls=[];
变量运动=假
定义变量单位=10;
函数令牌(sx,sy,rad,style_string,n)
{
this.sx=sx
这. sy=sy
this.rad=rad
这个. draw=draw _ token
这个。n=n
this.angle=(2 *数学. PI)/n;
this.move=移动令牌
this.fill _ style=style _ string
}
函数draw_token()//绘制正n边形
{
CTX。fill _ style=this。填充_样式;
CTX。begin path();
var I;
var rad=this.rad
CTX。移到(这个。sx rad * math。cos(-0.5 *这个。角度),这个。赛拉德*数学。sin(-0.5 *这个。角度));
for(I=1;我这个我)
CTX。行到(这个。sx rad * math。cos((I-0.5)*这个。角度),这个。赛拉德*数学。sin((I-0.5)*这个。角度));
CTX。fill();
}
函数move_token(dx,dy)
{
this.sx=dx
this.sy=dy
var I;
定义变量墙;
for(I=0;我。墙壁。长度;我)
{
wall=walls[I];
if (intersect(wall.sx,wall.sy,wall.fx,wall.fy,this.sx,this.sy,this.rad))
{
这个。sx-=dx;
这个。sy-=dy;
打破;
}
}
}
函数墙(sx,sy,fx,fy,width,styleString)
{
this.sx=sx
这. sy=sy
this.fx=外汇
this.fy=fy
this.width=宽度;
this.draw=draw _ line
这个。stroke style=样式字符串;
}
函数draw_line()
{
CTX。线宽=这个。宽度;
CTX。笔画风格=这个。笔画风格;
CTX。begin path();
ctx.moveTo(this.sx,this。sy);
ctx.lineTo(this.fx,this。fy);
CTX。笔画();
}
//注意
var mypent=new Token(100,100,20, rgb(0,0,250),5);
一切。push(mypent);
函数初始化()
{
画布=文档。getelementbyid(“canvas”);
CTX=画布。获取上下文(“2d”);
//注意
画布。addevent侦听器( mousedown ,start_wall,false);
画布。addevent侦听器( mousemove ,stretch_wall,false);
画布。addevent侦听器( mouseup ,finish_wall,false);
窗户。addevent侦听器( keydown ,getkey_and_move,false);
draw _ all();
}
函数开始_墙壁(电动)
{
var mx
var my
如果(电动层rX 电动层rx==0)
{
mx=ev.layerX
my=ev.layerY
}
else if(ev。offsetx ev。offsetx==0)
{
mx=ev.offsetX
我的=ev。关闭sety
}
cur_wall=new Wall(mx,my,mx 1,my 1,wall_width,Wall _ style);
运动中=真
一切。push(cur _ wall);
draw _ all();
}
函数伸展_墙壁(电动)
{
如果(运动中)
{
var mx
var my
如果(电动层rX 电动层rX==0)
{
mx=ev.layerX
my=ev.layerY
}
else if(ev。offsetx ev。offsetx==0)
{
mx=ev.offsetX
我的=ev。关闭sety
}
cur _ wall.fx=mx
cur _ wall.fy=my
draw _ all();
}
}
函数饰面_墙壁(电动)
{
动态=假
墙壁。push(cur _ wall);
}
函数draw_all()
{
ctx.clearRect(0,0,canvas_width,canvas _ height);
var I;
for(I=0;我一切。长度;我)
{
一切[我]。draw();
}
}
函数getkey_and_move(事件)
{
定义变量键码;
if (event==null)
{
键码=窗口。事件。关键代码;
窗户。事件。防止默认();
}
其他
{
键码=事件。关键代码;
事件。防止默认();
}
开关(键码)
{
案例37://左箭头
mypent.move(-unit,0);
打破;
案例38://向上箭头
mypent.move(0,-单位);
打破;
案例39://右箭头
mypent.move(单位,0);
打破;
案例40:
mypent.move(0,单位);
打破;
默认值:
//窗口。removeeventlistener( keydown ,getkey_and_move,false);
}
draw _ all();
}
函数交集(sx,sy,fx,fy,cx,cy,rad)
{
var dx
var dy
var t;
var rt
dx=FX-sx;
dy=fy-sy;
t=0.0-(((sx-CX)* dx(sy-cy)* dy)/(dx * dx dy * dy));
如果(t 0.0)
{
t=0.0
}
else if (t 1.0)
t=1.0
var dx1=(sx t * dx)-CX;
var dy1=(sy t * dy)-cy;
var rt=dx1 * dx1 dy1 * dy1
中频(rt rad * rad)
返回true
其他
返回false
}
/脚本
body onLoad= init();
canvas id=canvas 宽度=900 高度=350/canvas
/body
/html
困难
和多边形线碰撞检测方法。
intersect()函数负责检测多边形和线段是否相交。
在线段上写下一个点p(x,y)。
线段的两个端点是(sx,sy)和(fx,fy)。
纪念
dx=fx-sx
dy=fy-sy
x和y可以表示如下
x=sx t*dx
y=sy t*dy
判断线段是否与多边形相交,转化为判断线段的外接圆是否与多边形相交。
要做到这一点,需要找到线段上最靠近中心o的点P。
如果op圆的半径,则可以判断线段与圆相交。
否则,它们不会相交。
如何找到线段上离圆心最近的点?
从点P到点O的距离可以表示为
距离=sqrt((x-CX)*(x-CX)(y-cy)*(y-cy));
代替
X=sx t*dx,y=sy t*dy
可以得出结论,距离是t的函数。
这个函数的导数
函数值为0时,通过寻找对应的T值,可以得到离圆心最近的点。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。