Статьи

Создайте игру змея — добавление взаимодействия

В этом уроке вы узнаете, как создать игру, подобную Snake. Цель игры состоит в том, чтобы захватить яблоки на экране, чтобы поднять счет. Читай дальше!


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


Эта функция добавляет необходимых слушателей к кнопкам TitleView .

1
2
3
4
5
6
7
8
9
function startButtonListeners(action)
    if(action == ‘add’) then
        playBtn:addEventListener(‘tap’, showGameView)
        creditsBtn:addEventListener(‘tap’, showCredits)
    else
        playBtn:removeEventListener(‘tap’, showGameView)
        creditsBtn:removeEventListener(‘tap’, showCredits)
    end
end

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

1
2
3
4
5
6
function showCredits:tap(e)
    playBtn.isVisible = false
    creditsBtn.isVisible = false
    creditsView = display.newImage(‘credits.png’, display.contentCenterX — 110, display.contentHeight+40)
    transition.to(creditsView, {time = 300, y = display.contentHeight-20, onComplete = function() creditsView:addEventListener(‘tap’, hideCredits) end})
end

При нажатии на экран кредитов, он будет отключен со сцены и удален.

1
2
3
4
5
function hideCredits:tap(e)
    playBtn.isVisible = true
    creditsBtn.isVisible = true
    transition.to(creditsView, {time = 300, y = display.contentHeight+creditsView.height, onComplete = function() creditsView:removeEventListener(‘tap’, hideCredits) display.remove(creditsView) creditsView = nil end})
end

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

1
2
function showGameView:tap(e)
    transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners(‘rmv’) display.remove(titleView) titleView = nil end})

Этот код помещает фон игры в сцену.

1
2
3
4
5
— [Add GFX]
 
— Game Bg
 
gameBg = display.newImage(‘gameBg.png’)

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

01
02
03
04
05
06
07
08
09
10
11
— Pad
 
up = display.newImage(‘up.png’, 33.5, 219.5)
left = display.newImage(‘left.png’, 0, 252.5)
down = display.newImage(‘down.png’, 33.5, 286.5)
right = display.newImage(‘right.png’, 66.5, 252.5)
 
up.name = ‘up’
down.name = ‘down’
left.name = ‘left’
right.name = ‘right’

Эта строка добавляет текстовое поле оценки:

1
2
3
4
— Score Text
 
score = display.newText(‘0’, 74, 3, native.systemFontBold, 15)
score:setTextColor(252, 202, 1)

Затем мы добавляем голову змеи. Как упоминалось в предыдущем уроке, область попадания будет добавлена ​​поверх него, а затем оба будут сохранены в группе.

1
2
3
4
5
6
7
8
9
— Head
 
headGFX = display.newImage(‘head.png’, display.contentCenterX-0.3, display.contentCenterY-0.2)
headHitArea = display.newLine(display.contentCenterX+6, display.contentCenterY-0.2, display.contentCenterX + 8, display.contentCenterY-0.2)
headHitArea:setColor(0, 0, 0)
headHitArea.width = 2
head = display.newGroup(headGFX, headHitArea)
lastPart = head
parts = display.newGroup()

Первое яблоко добавляется этим кодом в случайной позиции.

01
02
03
04
05
06
07
08
09
10
    — Add first apple
     
    local randomX = 25 + math.floor(math.random() * 402)
    local randomY = 25 + math.floor(math.random() * 258)
         
    local apple = display.newImage(‘apple.png’, randomX, randomY)
    apples = display.newGroup(apple)
     
    gameListeners()
end

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

1
2
3
4
5
6
function gameListeners()
    up:addEventListener(‘tap’, movePlayer)
    left:addEventListener(‘tap’, movePlayer)
    down:addEventListener(‘tap’, movePlayer)
    right:addEventListener(‘tap’, movePlayer)
end

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

1
2
3
4
5
6
7
8
function movePlayer(e)
    dir = e.target.name
     
    if(started == nil) then
        timerSrc = timer.performWithDelay(speed, update, 0)
        started = true
    end
end

Мы будем использовать отличную и полезную функцию для обнаружения столкновений без физики. Вы можете найти оригинальный пример и исходный код на веб-сайте CoronaLabs Code Exchange .

1
2
3
4
5
6
7
function hitTestObjects(obj1, obj2)
        local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin
        local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax
        local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin
        local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax
        return (left or right) and (up or down)
end

Мы фиксируем последнюю позицию головы змеи, чтобы обновить положение частей, каждая из которых заменяет координаты x и y другой.

1
2
3
4
5
6
7
8
9
function update()
     
    — Capture head last position, this moves the first added piece
     
    local lastX = head.x
    local lastY = head.y
     
    local xPos = {}
    local yPos = {}

Это дополняет поведение, описанное в предыдущем шаге.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
for i = 1, parts.numChildren do
    — Capture parts position to move them
     
    xPos[i] = parts[i].x
    yPos[i] = parts[i].y
     
    — Move Parts
     
    if(parts[i-1] == nil) then
        parts[i].x = lastX
        parts[i].y = lastY
    else
        parts[i].x = xPos[i-1]
        parts[i].y = yPos[i-1]
    end

Игра заканчивается, когда голова змеи касается другой части змеи. Звук воспроизводится в качестве обратной связи.

01
02
03
04
05
06
07
08
09
10
11
12
— Game over if head touches other part of snake
         
        if(hitTestObjects(headHitArea, parts[i])) then
            print(parts[i].name)
            if(parts[i].name == ‘1’) then
                print(‘one’)
            else
                timer.cancel(timerSrc)
                timerSrc = nil
                audio.play(gameOver)
            end
        end

Эти линии перемещают голову в соответствии с направлением, заданным функцией movePlayer, созданной на шаге 11.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
— Move Head & Hit Area
 
if(dir == ‘up’) then
    head.y = head.y — mConst
     
    headHitArea.x = headGFX.x
    headHitArea.y = headGFX.y — 7
elseif(dir == ‘left’) then
    head.x = head.x — mConst
     
    headHitArea.x = headGFX.x — 8
    headHitArea.y = headGFX.y
elseif(dir == ‘down’) then
    head.y = head.y + mConst
     
    headHitArea.x = headGFX.x
    headHitArea.y = headGFX.y + 8
elseif(dir == ‘right’) then
    head.x = head.x + mConst
     
    headHitArea.x = headGFX.x + 7
    headHitArea.y = headGFX.y
end

Несколько действий происходят, когда змея ест яблоко, мы пройдем их в следующих шагах.

Сначала мы удалим яблоко.

1
2
3
4
5
6
7
— Detect apple-player collision
 
for i = 1, apples.numChildren do
    if(hitTestObjects(head, apples[i])) then
        — Remove Apple
         
        display.remove(apples[i])

Затем мы обновляем текстовое поле счета и воспроизводим звук, чтобы показать, что яблоко было съедено.

1
2
3
4
5
6
— Add Score
 
score.text = score.text + tostring(10)
score:setReferencePoint(display.TopLeftReferencePoint)
score.x = 74
audio.play(appleGrab)

Затем новая часть добавляется в змею. Его позиция рассчитывается по последней добавленной части (первый раз — голова), а затем они добавляются в группу.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
— Add snake body
 
local part = display.newImage(‘bodyPart.png’)
 
if(dir == ‘up’) then
    part.x = lastPart.x
    part.y = lastPart.y + mConst
elseif(dir == ‘left’) then
    part.x = lastPart.x + mConst
    part.y = lastPart.y
elseif(dir == ‘down’) then
    part.x = lastPart.x
    part.y = lastPart.y — mConst
elseif(dir == ‘right’) then
    part.x = lastPart.x — mConst
    part.y = lastPart.y
end
 
current = current + 1
part.name = tostring(current)
lastPart = part
parts:insert(part)

Наконец, мы создаем новое яблоко и помещаем его в случайную позицию на сцене.

1
2
3
4
5
6
7
8
9
      — Add new apple
       
      local randomX = 25 + math.floor(math.random() * 402)
      local randomY = 25 + math.floor(math.random() * 258)
   
      local apple = display.newImage(‘apple.png’, randomX, randomY)
      apples = display.newGroup(apple)
  end
end

Это заставляет змею появляться на другой стороне сцены.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
    — Screen Limits
     
    if(head.x < 0) then
        head.x = display.contentWidth — mConst
    elseif(head.x > display.contentWidth) then
        head.x = 0
    end
     
    — Vertical
     
    if(head.y < 0) then
        head.y = display.contentHeight — mConst
    elseif(head.y > display.contentHeight) then
        head.y = 0
    end
end

Чтобы начать игру, необходимо вызвать функцию Main . С помощью приведенного выше кода мы сделаем это здесь:

1
Main()

Файл Default.png — это изображение, которое будет отображаться сразу после запуска приложения, пока iOS загружает основные данные для отображения главного экрана. Добавьте это изображение в исходную папку вашего проекта, оно будет автоматически добавлено компилятором Corona.


Используя графику, созданную ранее, теперь вы можете создать красивый и красивый значок. Размер значка для iPhone без использования сетчатки составляет 57x57px, но для версии с сетчаткой — 114x114px, а для магазина iTunes требуется версия 512x512px. Я предлагаю сначала создать версию 512×512, а затем уменьшить ее для других размеров.

Для этого не нужно иметь закругленные углы или прозрачные блики, iTunes и iPhone сделают это за вас.


Пришло время сделать финальный тест. Откройте Corona Simulator, перейдите в папку вашего проекта и нажмите «Открыть». Если все работает, как ожидалось, вы готовы к последнему шагу!


В симуляторе Corona зайдите в File> Build и выберите ваше целевое устройство. Заполните необходимые данные и нажмите кнопку « Создать» . Подождите несколько секунд, и ваше приложение будет готово для тестирования устройства и / или отправки для распространения!


Поэкспериментируйте с конечным результатом и попробуйте сделать свою собственную версию игры!

Надеюсь, вам понравился этот урок, и вы нашли его полезным. Спасибо за чтение!