2. Обработка касаний

В этом уроке мы загрузим несколько изображений и попробуем их передвигать касанием пальцев

Ресурсы, которые мы будем загружать в наше приложение, вы можете скачать здесь:

resources.zip

Положите их в корневую папку с проектом.

Подготовка

Загружаем фон

Для начала загрузим фоновое изображение и растянем на весь экран.

local _W = display.contentWidth;
local _H = display.contentHeight;

local bg = display.newImageRect("resources/background.png", _W, _H)
bg.x = _W/2;
bg.y = _H/2;

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

Добавляем цифры

Давайте теперь загрузим объекты, которые мы будем двигать.

local numbers = display.newGroup();

local one = display.newImageRect(numbers, "resources/1.png", 32, 76);
one.x = 50;
one.y = 100;

local two = display.newImageRect(numbers, "resources/2.png", 52, 78);
two.x = 100;
two.y = 100;

local three = display.newImageRect(numbers, "resources/3.png", 51, 79);
three.x = 155;
three.y = 100;

Что за группы?

Вы могли заметить новую функцию, display.newGroup(). Довольно часто нам необходимо объеденить несколько объектов в какую-то группу, чтобы например двигать их вместе или управлять из видимостью на экране. Для этого группы и придумали.

Но как добавить их в группу?

Вы могли заметить, что я передаю группу numbers первым аргументом в функцию display.newImageRect. Это один из возможных способов. Также вы можете добавлять в группу другие объекты при создании, это работает и для других функций: display.newRect, display.newCircle, ... из первого урока

Что мы видим на экране?

Если вы все сделали правильно, у вас на экране должно отображаться, что-то вроде такого:

Loaded resources

Двигаем цифры

Настало время самого интересного. Добавим обработку касаний. Сделаем так, чтобы цифры можно было двигать своим пальцем.

Для того, среагировать на события касания экрана, нужно подписаться на них и добавить обработчик:

function touchListener(event)
end

one:addEventListener("touch", touchListener);

Итак, начнем с конца. Как видно из названия функции, мы подписались на событие touch и указали, что это событие должна обрабатывать функция touchListener, которую мы объявили ранее.

Теперь перейдем к самой функции обработки. Эта функция вызывается при каждом событии касания экрана. Важно отметить, что это может быть не просто касание, а мы можем нажать прижать палец к экрану и двигать его. И на каждый сдвиг вызовется функция touchListener.

Эта функция вызывается с одним аргументом event, который содержит все необходимые данные, которые нам понадобятся для двигания цифр.

Оно двигается!!!

Добавим следующий код в тело функции:

one.x = event.x
one.y = event.y

Теперь попробуйте нажать на цифру 1 и подвигать мышкой, цифра должна двигаться.

Немного улучшений

Скорее всего вы заметили, что мы приравниваем координаты центра нашей цифры к координате касания. Из-за этого есть небольшой лаг, и как только мы касаемся цифры, она немного сдвигается. Давайте же исправим это!

Чтоб это исправить нам достаточно посчитать расстояние от центра объекта до координаты касания в момент первого касания и прибавлять его к новой координате каждый раз, когда мы двигаем объект.

Фазы события

Здесь стоит упомянуть, что события имеют несколько состояний. Мы можем его узнать заглянув в поле phase объекта event: event.phase

В нашем случае у события будет 3 состояния:

  1. “began” - это когда мы только прикоснулись пальцем, но никуда еще его не сдвинули
  2. “moved” - тут как раз мы уже двигаем пальцем
  3. “ended” - это последнее состояние, когда палец с экрана убран.

Попробуйте добавить в touchListener следующую функцию:

	print("Event phase: ", event.phase)

И понаблюдайте, что печатается в Corona Simulator Console когда вы двигаете объект.

Двиагем объект правильно

Итак, как я и сказал, у нас есть три фазы события. И фаза begun очень подходящее место, чтобы запомнить расстояние между центром нашей цифры и координатой касания. А вот в фазе moved, мы как раз можем изменять координаты объекта с учетом этой дельты.

Измените существующий код следующим образом.

local deltaX = 0;
local deltaY = 0;

function touchListener(event)
   if event.phase == "began" then
      deltaX = one.x - event.x;
      deltaY = one.y - event.y;
   elseif event.phase == "moved" then
      one.x = event.x + deltaX;
      one.y = event.y + deltaY;
   elseif event.phase == "ended" then
      deltaX = 0;
      deltaY = 0;
   end
end

Мы объявили две переменные deltaX, deltaY для запоминания дельты координат объекта и касания. А в самом обработчике, как и говорил, в фазе begun запоминаем эти дельты (двигать нам объект тут не нужно, мы же пока никуда его и не двигали). В фазе moved мы двигаем объект с учетом дельты, которую записали моментом ранее. Ну и в фазе ended мы чистим наши переменные, потому что мы хорошие разработчики и убираемся за собой.

Посмотрите на результат: объект теперь двигается правильно и без всяких лагов.

А как двигать несколько объектов?

Нарисовалась еще одна проблема. Мы добавили обработчик только для одного объекта, но что если я хочу двигать также цифры 2 и 3?

Ничего сложного. Давайте для них тоже добавим подписку на событие:

two:addEventListener("touch", touchListener);
three:addEventListener("touch", touchListener);

Также нам нужно немного поменять сам обработчик. В нем мы двигаем конкретный объект: one, а нам нужно двигать любой объект, на события которого мы подписались.

Для этого нам всего лишь нужно поменять one на event.target везде, где мы меняем координаты. Должно получиться так:

function touchListener(event)
   if event.phase == "began" then
      deltaX = event.target.x - event.x;
      deltaY = event.target.y - event.y;
   elseif event.phase == "moved" then
      event.target.x = event.x + deltaX;
      event.target.y = event.y + deltaY;
   elseif event.phase == "ended" then
      deltaX = 0;
      deltaY = 0;
   end
end

Прекрасный event дает нам знать, что мы собираемся двигать.

Может подвигаем все цифры разом?

Помните я упомянул в начале про группы. И не зря. Сейчас мы одним легким взмахом сможем двигать все цифры разом.

Для начала уберите все подписки на отдельные объекты. И добавьте вместо них всего одну:

numbers:addEventListener("touch", touchListener)

Ого! Так просто, но теперь мы можем двигать все цифры разом. На этом урок окончен. Увидимся в следующем.

Предыдущий урок