您好,欢迎访问一九零五行业门户网

html5 迷宫游戏(碰撞检测)实例一_html5教程技巧

游戏效果图
通过鼠标拖拽在画布上添加墙壁,通过方向键控制多边形上下左右移动,遇到墙壁则无法前进。
需要解决的问题
鼠标按下,鼠标拖动,鼠标释放事件的检测
多边形的绘制
墙壁的绘制
多边形和墙壁的碰撞检测(实质上是圆和线段的相交判断)
mycode:
代码如下:
<html> <head> <title>迷宫</title> <script> var canvas_width = 900; var canvas_height = 350; var ctx; var canvas; var everything = []; var cur_wall; var wall_width; var wall_style = "rgb(200,0,200)"; var walls = []; var in_motion = false; var unit = 10; function token(sx, sy, rad, style_string, n) { this.sx = sx; this.sy = sy; this.rad = rad; this.draw = draw_token; this.n = n; this.angle = (2 * math.pi) / n; this.move = move_token; this.fill_style = style_string; } function draw_token()//绘制正n边形 { ctx.fill_style = this.fill_style; ctx.beginpath(); var i; var rad = this.rad; ctx.moveto(this.sx + rad * math.cos(-0.5 * this.angle), this.sy + rad * math.sin(-0.5 * this.angle)); for (i = 1; i < this.n; i++) ctx.lineto(this.sx + rad * math.cos((i - 0.5) * this.angle), this.sy + rad * math.sin((i - 0.5) * this.angle)); ctx.fill(); } function move_token(dx, dy) { this.sx += dx; this.sy += dy; var i; var wall; for (i = 0; i < walls.length; i++) { wall = walls[i]; if (intersect(wall.sx, wall.sy, wall.fx, wall.fy, this.sx, this.sy, this.rad)) { this.sx -= dx; this.sy -= dy; break; } } } function wall(sx, sy, fx, fy, width, stylestring) { this.sx = sx; this.sy = sy; this.fx = fx; this.fy = fy; this.width = width; this.draw = draw_line; this.strokestyle = stylestring; } function draw_line() { ctx.linewidth = this.width; ctx.strokestye = this.strokestyle; ctx.beginpath(); ctx.moveto(this.sx, this.sy); ctx.lineto(this.fx, this.fy); ctx.stroke(); } //note var mypent = new token(100, 100, 20, "rgb(0,0,250)", 5); everything.push(mypent); function init() { canvas = document.getelementbyid("canvas"); ctx = canvas.getcontext('2d'); //note canvas.addeventlistener('mousedown', start_wall, false); canvas.addeventlistener('mousemove', stretch_wall, false); canvas.addeventlistener('mouseup', finish_wall, false); window.addeventlistener('keydown', getkey_and_move, false); draw_all(); } function start_wall(ev) { var mx; var my; if (ev.layerx || ev.layerx == 0) { mx = ev.layerx; my = ev.layery; } else if (ev.offsetx || ev.offsetx == 0) { mx = ev.offsetx; my = ev.offsety; } cur_wall = new wall(mx, my, mx + 1, my + 1, wall_width, wall_style); in_motion = true; everything.push(cur_wall); draw_all(); } function stretch_wall(ev) { if (in_motion) { var mx; var my; if (ev.layerx || ev.layerx == 0) { mx = ev.layerx; my = ev.layery; } else if (ev.offsetx || ev.offsetx == 0) { mx = ev.offsetx; my = ev.offsety; } cur_wall.fx = mx; cur_wall.fy = my; draw_all(); } } function finish_wall(ev) { in_motion = false; walls.push(cur_wall); } function draw_all() { ctx.clearrect(0, 0, canvas_width, canvas_height); var i; for (i = 0; i < everything.length; i++) { everything[i].draw(); } } function getkey_and_move(event) { var keycode; if (event == null) { keycode = window.event.keycode; window.event.preventdefault(); } else { keycode = event.keycode; event.preventdefault(); } switch (keycode) { case 37://left arrow mypent.move(-unit, 0); break; case 38://up arrow mypent.move(0, -unit); break; case 39://right arrow mypent.move(unit, 0); break; case 40: mypent.move(0, unit); break; default: //window.removeeventlistener('keydown', getkey_and_move, false); } draw_all(); } function intersect(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)); if (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; if (rt < rad * rad) return true; else return false; } </script> <body onload="init();"> <canvas id="canvas" width="900" height="350"></canvas> </body> </html>
难点
多边形和线段碰撞检测的方法
函数intersect()负责检测多边形和线段是否相交
记线段上一点p(x,y)
线段2个端点是(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点的距离可以表示为
distance=sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy));
代入
x=sx+t*dx和y=sy+t*dy
可以得到distance是一个关于t的函数
对此函数求导
求出函数值为0时对应的t值就可以得到距离圆心最近的点
其它类似信息

推荐信息