Добавление обнаружения столкновений к изображениям, нарисованным на холсте

Я создаю простую веб-игру, используя холст HTML5 и JavaScript. В настоящее время у меня есть несколько изображений, отображаемых на холсте, каждое из которых представляет предметы, найденные в ресторане быстрого питания. У меня также есть четыре «поля описания», каждое из которых помечено как актив, обязательство, доход или расход.

Каждое изображение принадлежит одному из этих полей описания, и пользователь должен перетащить каждое изображение в правильное поле описания.

Я планирую проверить, перетащил ли пользователь изображение в нужное поле, используя имя переменной JS, содержащей изображение поля, и HTML-тег alt каждого из изображений элемента, т.е. img «стул» имеет тег alt «актив ", а поле описания для активов имеет имя переменной "assetsDescriptionBox", поэтому я бы использовал оператор "if", чтобы определить, было ли изображение, которое перетаскивает пользователь, перетащено в ту же область холста, где находится поле описания активов. отображается, и если у этого изображения есть тег alt «актив», оно исчезнет с холста (и будет добавлено в массив для использования позже в игре).

Однако, если изображение, которое перетаскивал пользователь, не имело alt-тега «актив», но имело какой-то другой тег, то есть «обязательство», то оно было бы перерисовано на холсте там, где оно было изначально нарисовано.

В чем я не уверен, так это в том, как это реализовать. Я взглянул на обнаружение столкновений, и кажется, что один из способов сделать это - использовать JS-метод getBoundingClientRect для получения «внешних границ» изображения, а затем проверить, перекрываются ли внешние границы двух изображений вообще , а если и делают, то что-то делают. Но я не уверен, как использовать этот метод, и не нашел ничего особенно полезного при быстром поиске в Google.

Кто-нибудь знает, будет ли это лучшим способом сделать это? Если да, не могли бы вы опубликовать пример использования метода getBoundingClientRect? Или, если нет, как еще вы могли бы это сделать?

Изменить 17/12/2012 в 16:45

Кстати, я использую библиотеку KineticJS (копия, которую я сохранил локально, чтобы внести одно или два изменения), чтобы добавить функцию перетаскивания, поэтому я предполагаю, что в библиотеке будет что-то, что мне нужно изменить/ добавить, чтобы добавить обнаружение столкновений.

У кого-нибудь есть идеи?

Редактировать 01.01.2013 в 12:35

Привет, спасибо за ваш ответ - похоже, это то, что я хочу сделать. У меня уже есть все изображения, отображаемые на холсте, с четырьмя «статическими», которые нельзя перетаскивать по холсту — это те, которые я хочу использовать в качестве «зон перетаскивания», и их можно перетаскивать. скинь остальные. Я не совсем уверен, как мне добавить функциональность, предоставляемую вашим кодом, к тому, что у меня уже есть? Если вы перейдете по URL-адресу: users.aber.ac.uk/eef8/project/development/featureset2dev, вы сможете увидеть, над чем я уже работал.

Чтобы добавить функцию «зоны сброса» в поля описания, я должен добавить их на холст с помощью строки

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

как вы сделали в своем примере?


person Noble-Surfer    schedule 17.12.2012    source источник
comment
getBoundingClientRect работает с элементом dom. На вашем холсте ваше изображение представляет собой просто пиксели и не имеет связанного с ним элемента DOM, поэтому эта функция не будет работать. Вам нужно отслеживать ограничивающую рамку изображения, чтобы вы могли определить, какое изображение было нажато, и, отслеживая ограничивающие рамки цели, вы также можете выяснить, в какое место она была переброшена есть что-то для этого?). По сути, отслеживайте все ограничивающие рамки для интерактивных объектов, а обнаружение столкновений просто выясняет, какие ограничивающие рамки перекрываются.   -  person Damp    schedule 17.12.2012


Ответы (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;
}

Если бы я собирался об этом, я мог бы настроить его с помощью объекта, к которому прикреплен объект зоны перетаскивания, чтобы это изображение могло запускать только одну зону перетаскивания вместо проверки тега alt, используя чистый JS.

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);

Тогда у вас будет цикл, который обновляет координаты перетаскиваемого изображения при его перемещении. Обратите внимание, что у вас не может быть обработчиков кликов на нарисованных спрайтах внутри холста, только на самом холсте; вы проверяете, находятся ли координаты мыши внутри нарисованных спрайтов.

Другой способ сделать это, конечно, использовать API перетаскивания HTML5, хотя у меня нет опыта использования, который может быть более подходящим для ваших нужд.

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

person Ben    schedule 27.12.2012
comment
коллизия функций должна возвращать false (в случае else). - person GameAlchemist; 28.12.2012
comment
Конечно, хотя я не нашел необходимости возвращать ложное значение; если есть столкновение, то предпринимаются какие-то действия, в случае уничтожения врага/увеличения очков, в противном случае все продолжается как обычно. - person Ben; 28.12.2012
comment
Чтобы добавить функцию «зоны перетаскивания» в поля описания, мне нужно добавить их на холст со строкой var i = new Image(200, 200, 50, 50, 'cat.jpg', 300, 300, 60, 60);, как вы сделали в своем примере? - person Noble-Surfer; 01.01.2013
comment
Да, я так настроил; с x/y/w/h изображения, а затем x/y/w/h dropzone. Конечно, вы можете изменить эти значения, поскольку они передаются новому образу при создании. Затем в вашей функции обновления (загляните в requestAnimationFrame) используйте функцию collides, чтобы проверить, не сталкивается ли изображение с его dropzone; if (collides(i, i.dropzone)) { // success! } - person Ben; 03.01.2013