JS Canvas Collision-Detection с использованием getImageData

Как очень неопытный программист, я пытаюсь написать игру, которая определяет, когда игрок сталкивается с определенными цветами на холсте. У меня есть черный квадрат с координатами «player.x» и «player.y» и размерами 50x50, который перемещается при нажатии клавиш со стрелками. У меня также есть неподвижный красный квадрат (255,0,0) в другом месте на холсте.

Функция ниже должна захватывать немного больший квадрат вокруг квадрата «игрока» и выяснять, есть ли в нем красный цвет. Если есть, он отправит предупреждение. Проблема в том, что это, похоже, не работает.

function collideTest(){
    var canvas = document.getElementById("canvas");
    var c = canvas.getContext("2d");

    var whatColor = c.getImageData(player.x - 5, player.y - 5,60,60);

    for (var i = 0; i < 3600; i++) {
        if (whatColor.data[i] == 255) {
            alert("red");
        }
    }
}

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

Проблема может заключаться в способе вызова функции. Она вызывается в конце другой функции, которая обнаруживает пользовательский ввод и изменяет координаты квадрата «игрока». ЭТА функция вызывается прямо перед тем, как все будет нарисовано на холсте.

Заранее благодарю за любую помощь!


person trevnewt    schedule 09.02.2013    source источник


Ответы (2)


Для каждого отдельного пикселя на холсте массив whatColor.data содержит 4 последовательных фрагмента информации о цвете: красный, зеленый, синий, альфа-канал (непрозрачность). Итак, whatColor.data для каждого пикселя выглядит следующим образом:

whatColor.data[i] — красный компонент цвета.

whatColor.data[i+1] — зеленый компонент цвета.

whatColor.data[i+2] — это синяя составляющая цвета.

whatColor.data[i+3] — это альфа-компонент (непрозрачность) цвета.

Итак, ваша итерация будет выглядеть так (4 индекса на пиксель):

 for(var i = 0, n = whatColor.data.length; i < n; i += 4) {
      var red = whatColor.data[i];
      var green = whatColor.data[i + 1];
      var blue = whatColor.data[i + 2];
      var alpha = whatColor.data[i + 3];
      if(red==255){ ... it's a hit, do your thing! ... }
 }

См. здесь мини-учебник по массиву imageData.data: http://www.html5canvastutorials.com/advanced/html5-canvas-get-image-data-tutorial/

Кстати, вы можете взглянуть на одну из библиотек холста, которые упрощают создание игр с помощью холста. Вот лишь некоторые из них: EaselJ, KineticJ, FabricJ и другие!

person markE    schedule 09.02.2013
comment
Спасибо за ответ! Однако, как я и подозревал, содержимое самой функции, похоже, не является проблемой. Даже когда я делаю то, что вы там написали, я не получаю ответа при нажатии на красный. Может дело в том, как функция вызывается? - person trevnewt; 10.02.2013
comment
Если вызов функции collideTest() происходит после того, как холст был полностью отрендерен, то функция collideTest() является подходящим местом для проверки попадания. Хотя я не знаю о логике вашей программы, если вы знаете координаты + размеры как черного ящика, так и красного ящика, вы можете выполнить тестирование попадания, проанализировав их два ограничивающих прямоугольника. - person markE; 10.02.2013

var whatColor = c.getImageData(player.x - 5, player.y - 5,60,60);

player.x и player.y не должны быть десятичными, убедитесь, что они округлены, иначе getImageData будет злиться и не будет вести себя хорошо.

person Xen_the    schedule 05.03.2016