游戏效果图通过鼠标拖拽在画布上添加路径,通过方向键控制上下上下左右移动,遇到电场则无法前进。需要解决的问题鼠标单击,鼠标指针偏移,鼠标释放事件的检测替换的布局的朝向上方和上方的碰撞检测(代码为圆和线段的相交判定)
复制代码
代码如下:
<html><head><title>迷宫</title><script>varcanvas_width=900;varcanvas_height=350;varctx;varcanvas;vareverything=[];varcur_wall;varwall_width;varwall_style=“rgb(200,0,200)”;varwall=[];varin_motion=false;varunit=10;函数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;}函数draw_token()//呈现正n边形
{ctx.fill_style=this.fill_style;ctx.beginPath();vari;varrad=this.rad;ctx.moveTo(this.sx+rad*Math.cos(-0.5*this.angle),this.sy+rad*Math.sin(-0.5*this.angle));对于(i=1;i<this.n;i++)ctx.lineTo(this.sx+rad*Math.cos((i-0.5)*this.angle),this.sy+rad*Math.sin((我-0.5)*this.angle));ctx.fill();}函数move_token(dx,dy){this.sx+=dx;this.sy+=dy;vari;varwall;对于(i=0;i<walls.length;i++){wall=walls[i];如果(intersect(wall.sx,wall.sy,wall.fx,wall.fy,this.sx,this.sy,this.rad)){this.sx-=dx;
this.sy-=dy;打破;}}}函数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;}函数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();}//注意varmypent=newToken(100,100,20,“rgb(0,0,250)”,5);everything.push(mypent);
函数init(){canvas=document.getElementById(“canvas”);ctx=canvas.getContext('2d');//notecanvas.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();}函数start_wall(ev){varmx;varmy;如果(ev.layerX||ev.layerx==0){mx=ev.layerX;我=ev.layerY;}elseif(ev.offsetX||ev.offsetX==0){mx=ev.offsetX;my=ev.offsetY;
cur_wall=新的Wall(mx,my,mx+1,my+1,wall_width,wall_style);in_motion=true;everything.push(cur_wall);draw_all();}函数Stretch_wall(ev){if(in_motion){varmx;varmy;如果(ev.layerX||ev.layerX==0){mx=ev.layerX;我=ev.layerY;}elseif(ev.offsetX||ev.offsetX==0){mx=ev.offsetX;my=ev.offsetY;}cur_wall.fx=mx;cur_wall.fy=我的;draw_all();}}函数finish_wall(ev){in_motion=false;wall.push(cur_wall);
}函数draw_all(){ctx.clearRect(0,0,canvas_width,canvas_height);vari;for(i=0;i<everything.length;i++){everything[i].draw();}}函数getkey_and_move(event){varkeyCode;if(event==null){keyCode=window.event.keyCode;window.event.preventDefault();}else{keyCode=event.keyCode;event.preventDefault();}switch(keyCode){case37://左箭头mypent.move(-unit,0);打破;案例38://向上箭头mypent.move(0,-unit);
打破;案例39://右箭头mypent.move(unit,0);打破;情况40:mypent.move(0,unit);打破;默认值://window.removeEventListener('keydown',getkey_and_move,false);}draw_all();}函数intersect(sx,sy,fx,fy,cx,cy,rad){vardx;vardy;vart;varrt;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;}if(t>1.0)t=1.0;vardx1=(sx+t*dx)-cx;vardy1=(sy+t*dy)-cy;
varrt=dx1*dx1+dy1*dy1;如果(rt<rad*rad)返回true;否则返回假;}</script><bodyonLoad=“init();”><canvasid=“canvas”width=“900”height=“350”></canvas></body></html>
难点上方和线段碰撞检测的方法函数intersect()负责检测以上和线段是否相交记线段上一点p(x,y)线段2个端点是(sx,sy)和(fx,fy)记dx=fx-sxdy=fy-syx和y可以表示如下x=sx+t*dxy=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可以得到距离是一个关于t的函数原型函数求导求出函数变量0时对应的t值就可以得到距离圆心最近的点
如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h60713.shtml