【问题标题】:Adding collision detection to images drawn on canvas向画布上绘制的图像添加碰撞检测
【发布时间】:2012-12-04 17:08:54
【问题描述】:

我正在使用 HTML5 画布和 JavaScript 创建一个简单的基于网络的游戏。我目前在画布上显示了一些图像,每个图像都代表在快餐店中发现的物品。我还有四个“描述框”,每个都标有资产、负债、收入或支出。

每张图片都属于这些描述框之一,用户需要将每张图片拖放到正确的描述框。

我计划通过使用保存盒子图像的 JS 变量的名称和每个项目图像的 HTML alt 标签来检查用户是否将图像拖到正确的盒子,即 img "chair" 有 alt标记“asset”,并且资产的描述框具有变量名称“assetsDescriptionBox”,因此我将使用“if”语句来检测用户拖动的图像是否被拖动到画布的与资产相同的区域描述框正在显示,如果该图像具有 alt 标签“asset”,那么它将从画布上消失(并添加到数组中以供稍后在游戏中使用)。

但是,如果用户拖动的图像没有 alt 标签“asset”,但有一些其他标签,即“liability”,那么它将在画布上重新绘制,回到最初绘制的位置。

我不确定如何实现这一点。我看过碰撞检测,似乎一种方法是使用 JS 方法 getBoundingClientRect 来获取图像的“外部限制”,然后检查两个图像的外部限制是否完全重叠,如果他们这样做了,那就做点什么。但是,我不确定如何使用此方法,并且在进行快速 Google 搜索时找不到任何特别有用的东西。

有谁知道这是否是最好的方法?如果是这样,您能否发布一个如何使用 getBoundingClientRect 方法的示例?如果没有,你会怎么做?

编辑 17/12/2012 @ 16:45

顺便说一句,我正在使用 KineticJS 库(我在本地保存的一个副本以进行一两次更改)来添加拖放功能,所以我假设库中会有我需要的东西更改/添加以添加碰撞检测。

有人有什么想法吗?

编辑 01/01/2013 @ 12:35

您好,感谢您的回答——这似乎就是我想要做的。我已经将所有图像都显示在画布上,其中有四个不能在画布周围拖动的“静态”图像——这些是我想用作“拖放区”的图像,并且可以拖动和放下其余的。我不太确定如何将您的代码提供的功能添加到我已有的功能中?如果您访问 URL:users.aber.ac.uk/eef8/project/development/featureset2dev,您将能够看到我已经在工作的内容。

要将“dropzone”功能添加到我的描述框中,我应该将它们添加到画布中吗

var i = new Image(200, 200, 50, 50, 'cat.jpg', 300, 300, 60, 60); 

正如您在示例中所做的那样?

【问题讨论】:

  • getBoundingClientRect 作用于 dom 元素。在您的画布上,您的图像只是像素,没有与之关联的 DOM 元素,因此此功能不起作用。您需要跟踪图像的边界框,以便您可以检测单击了哪个图像,并且通过跟踪目标的边界框,您还可以找出它被放置在哪个位置(不是 kineticjs lib有什么东西吗?)。基本上,跟踪交互式对象的所有边界框,碰撞检测只是找出哪些边界框重叠

标签: javascript html5-canvas collision-detection kineticjs


【解决方案1】:

我认为最好的方法是跟踪每个对象的 X/Y 位置以及宽度和高度;使用像这样的简单矩形碰撞函数需要两个对象并检查它们的边界框是否重叠。

function collides(a, b)
{
    if (a.x < b.x + b.width &&
        a.x + a.width > b.x &&
        a.y < b.y + b.height &&
        a.y + a.height > b.y) return true;
}

如果我打算这样做,我可能会使用一个附加了拖放区对象的对象来设置它,这样图像就只能触发一个拖放区,而不是使用纯 JS 来检查 alt 标签。

function Image(x, y, w, h, i, dx, dy, dw, dh)
{
    this.x = x;
    this.y = y;
    this.width = w;
    this.height = h;
    this.image = i;
    this.dropzone = new DropZone(dx, dy, dw, dh);
}

function DropZone(x, y, w, h)
{
    this.x = x;
    this.y = y;
    this.width = w;
    this.height = h;
}

var i = new Image(200, 200, 50, 50, 'cat.jpg', 300, 300, 60, 60);

然后你会有一个循环,当你移动它时更新拖动图像的坐标。请注意,您不能在画布内的绘制精灵上使用单击处理程序,只能在画布本身上使用;您检查鼠标坐标是否在绘制的精灵内。

当然,另一种方法是使用 HTML5 拖放 API,虽然我没有使用经验,但它可能更适合您的需求。

http://www.html5rocks.com/en/tutorials/dnd/basics/

【讨论】:

  • 函数碰撞应该返回 false(在 'else' 的情况下)。
  • 当然可以,虽然我发现不需要返回 false 值;如果发生碰撞,则采取一些行动,以防敌人被摧毁/分数增加,否则一切正常。
  • 您好,感谢您的回答——这似乎就是我想要做的。我已经将所有图像都显示在画布上,其中有四个不能在画布周围拖动的“静态”图像——这些是我想用作“拖放区”的图像,并且可以拖动和放下其余的。我不太确定如何将您的代码提供的功能添加到我已有的功能中?如果您访问 URL:users.aber.ac.uk/eef8/project/development/featureset2dev,您将能够看到我已经完成的工作。
  • 要将“dropzone”功能添加到我的描述框中,我是否应该像您在示例中所做的那样使用 var i = new Image(200, 200, 50, 50, 'cat.jpg', 300, 300, 60, 60); 行将它们添加到画布中?
  • 是的,我就是这样设置的;使用图像的 x/y/w/h,然后是 dropzone 的 x/y/w/h。您当然可以修改这些值,因为它们在创建时传递给新图像。然后,在您的更新函数中(查看 requestAnimationFrame),使用collides 函数检查图像是否与其放置区发生冲突; if (collides(i, i.dropzone)) { // success! }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多