画布2D迷宫火炬效果

时间:2014-04-05 22:05:03

标签: javascript css html5 canvas

我正在开展一个包含以下条件的学校项目:

  • 仅使用JS,HTML5和CSS制作迷宫。
  • 围绕角色制作火炬效果。你无法透过墙壁。

我开始使用画布制作这个游戏。 我已成功围绕角色制作火炬效果,如下所示:

http://people.inf.elte.hu/tunyooo/web2/HTML5-Maze.html

然而,我不能让它不透过墙壁。

我很确定我应该这样做: 从角色的当前位置开始向所有方向循环,直到达到视距或者如果context.getImageData()返回[0,0,0,255]。通过这种方式,我可以获得角色与北部,东部,西部和南部墙壁的距离。 然后,我可以使用(viewdistance-DistanceFrom * Wall)矩形点亮角色周围的迷宫。

不幸的是,经过15个小时的思考后,我已经没有想法如何使这项工作。 任何提示都表示赞赏。

3 个答案:

答案 0 :(得分:1)

让您的迷宫走廊进入剪切路径。

您的火炬效果将包含在剪切路径中。

[根据提问者的评论添加回答]

从现有迷宫图像创建剪切路径:

在Paint程序中打开迷宫图像。当您在迷宫图像上移动时,通常会显示鼠标光标X / Y位置。

以阵列形式记录每个迷宫走廊的左上角和右下角。

var hallways=[];

hallways.push({left:100, y:50, right: 150, bottom: 65});  // for each hallway

侦听鼠标事件并确定鼠标位于哪个走廊。

// hallwayIndex is the index of the hallway the mouse is inside

var hallwayIndex=-1;

// x=mouse's x coordinate, y=mouse's y coordinate

for(var i=0;i<hallways;i++){

    var hall=hallways[i];

    if(x>=hall.left && 
       x<=hall.right && 
       y>=hall.top && 
       y<=hall.bottom)
       { hallwayIndex=i; }
}

在画布上重绘迷宫

为当前走廊创建剪切路径:

var width=hall.right-hall.left;
var height=hall.bottom-hall.top;

ctx.beginPath();
ctx.Rect(hall.left,hall.top,width,height);
ctx.clip();

将玩家+火炬拉入走廊(火炬不会通过墙壁发光)。

答案 1 :(得分:1)

更简单的方法是(ps:我在提供的链接上出现“禁止”错误,所以我看不到你做了什么):

  • 有迷宫版的迷宫,一个透明的白色图像,其中白色代表允许的绘图区域。此遮罩图像应与迷宫图像的大小和位置匹配。
  • 创建一个与火炬图像大小相符的离屏画布
  • 当您需要绘制火炬时,首先将遮罩图像绘制到离屏画布上。绘制偏移量,以便绘制遮罩的正确部分。例如:如果火炬将被绘制在迷宫上的位置100,100处,然后将遮罩绘制到-100,-100的离屏画布上 - 或者简单地创建与迷宫相同大小的画布并在遮罩中绘制在0,0和火炬在相对位置。使用的内存更多,但维护起来更简单。
  • 将复合模式更改为source-in,然后绘制火炬。将复合模式更改回copy以进行下一次抽奖。

现在你的火炬被夹住以适应墙壁。现在只需将离屏画布绘制到主画布而不是火炬。

注意:重要的是制作火炬,例如它不能到达墙壁的另一侧(直径尺寸),否则它将在“迷宫墙”下“闪亮” - 这可以通过其他方式解决,但使用遮罩根据玩家位置选择不同的区域(此处未显示)。

要进入下面的演示,只需将鼠标移到画布区域即可。

Live demo

Snapshot Matte

function mousemoved(e) {

    var rect = canvas.getBoundingClientRect(),   // adjust mouse pos.:
        x = e.clientX - rect.left - iTorch.width * 0.5, // center of torch
        y = e.clientY - rect.top - iTorch.height * 0.5;

    octx.drawImage(iMatte, 0, 0);                // draw matte to off-screen
    octx.globalCompositeOperation = 'source-in'; // change comp mode
    octx.drawImage(iTorch, x, y);                // clip torch
    octx.globalCompositeOperation = 'copy';      // change comp mode for next

    ctx.drawImage(iMaze, 0, 0);                  // redraw maze
    ctx.drawImage(ocanvas, 0, 0);                // draw clipped torch on top
}

在演示中,火炬的大小或多或少,实际上有点太大了 - 我做的很快又脏。但是试着在迷宫路径中移动以查看它被剪裁。屏幕外的画布将添加到主画布的大小上,以显示正在进行的操作。

额外的好处是你可以使用相同的遮罩进行命中测试。

答案 2 :(得分:0)

有关此主题的精彩文章:http://www.redblobgames.com/articles/visibility/

然而,准确地这样做是很多工作。如果您想使用快速而肮脏的解决方案,我建议如下。从大块建造世界(想想复古像素)。这使得碰撞检测也更简单。现在您可以考虑割炬半径内的所有点。从角色到点直线行走。如果你没有碰到墙壁到达那个点,那就让它变亮吧。

(对于1像素的块也可以这样做,但是你可能会遇到性能问题。)