• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    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值就可以得到距离圆心最近的点
    上一篇:html5弹跳球示例代码
    下一篇:html5 乒乓球(碰撞检测)实例二
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    html5 迷宫游戏(碰撞检测)实例一 html5,迷宫,游戏,碰撞,检测,