Статьи

Создайте бесконечную игру для бегунов с нуля: меню игры

Добро пожаловать в последний выпуск серии Endless Runner. В сегодняшнем уроке вы узнаете, как создать игровое меню с использованием класса Director. Давайте начнем!

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

Мы собираемся сделать это с помощью класса Director, который представляет собой невероятно хорошо сделанную маленькую библиотеку Рикардо Раубера, которая сделает всю работу за вас. Как только вы увидите, насколько это легко, вы сможете быстро реализовать это в любом проекте.

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

Теперь, когда у нас есть файл Director.lua, поместите его в ту же папку, что и ваш main.lua. Говоря о вашем файле main.lua, продолжайте и переименуйте его. Неважно, на что вы его измените, потому что мы все равно удалим его. После того, как вы это сделаете, вы создадите три новых файла в этой папке. Назовите их main.lua, menu.lua и game.lua. Основа того, как это будет работать, заключается в том, что main.lua будет вызван для запуска игры. Это будет основа нашей программы, в то время как menu.lua и game.lua будут действовать как компоненты (displayGroups), которые отображаются внутри displayGroup внутри самого main.lua, почти так же, как все Все группы дисплеев в нашей игре удерживаются и отображаются из экрана displayGroup в нашей текущей игре.

Итак, обо всем по порядку, давайте настроим наш новый файл main.lua. Откройте его и добавьте туда этот код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
display.setStatusBar(display.HiddenStatusBar)
—by telling Corona to require «director» we are
—telling it to include everything in that file,
—giving us easy access to its functions.
—also how you would include any functions or
—«classes» that you created in outside files.
local director = require(«director»)
local mainGroup = display.newGroup()
local main = function()
     —this creates a view that we will use to load
     —the other scenes into, so as our game progresses
     —technically we are staying in the main.lua file
     —and just loading new views or scenes into it
     mainGroup:insert(director.directorView)
     —we tell the director to load the first scene which
     —is going to be the menu
     director:changeScene(«menu»)
end
—be sure to actually call the main function
main()

Вот и все! Уберите комментарии, и вы увидите, что для того, чтобы подготовить класс директора, требуется всего около 5 строк. Как отмечается в комментариях, в действительности сначала работает main.lua, но затем вместо того, чтобы диктовать ход игры внутри файла main.lua, мы позволяем классу директор вступить во владение. Мы создаем display.newGroup и резервируем его как наш основной вид. Поэтому, когда игра действительно загружается, все, что вы видите, на самом деле просматривается из файла main.lua внутри этой группы отображения. Довольно аккуратно, да! Итак, как только вы вставите в него это представление, нам просто нужно указать директору, какую сцену загрузить, и он автоматически доставит нас туда. Достаточно просто, правда?

Следующее, что нам нужно сделать для того, чтобы это действительно заработало, это создать сцену меню. Код действительно прост, и большую его часть мы уже видели, поэтому я сначала опубликую весь файл, а затем объясню несколько новых вещей. Давайте откроем menu.lua и посмотрим, насколько просто создать простую систему меню. Скопируйте следующее в ваше menu.lua:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
—this line is required so that director knows that
—this is a scene that can be loaded into its view
module(…, package.seeall)
—we need to be able to access the director class of
—course so be sure to include this here
local director = require(«director»)
local sprite = require(«sprite»)
—everything that you want this scene to do should be
—included in the new function.
—loads a new scene it will look here to figure out what
—to load up.
new = function( params )
     —this function will be returned to the director
     local menuDisplay = display.newGroup()
     —everything from here down to the return line is what makes
     —up the scene so… go crazy
     local background = display.newImage(«background.png»)
     background.x = 240
     background.y = 160
     local spriteSheet = sprite.newSpriteSheet(«monsterSpriteSheet.png», 100, 100)
     local monsterSet = sprite.newSpriteSet(spriteSheet, 1, 7)
     sprite.add(monsterSet, «running», 1, 6, 600, 0)
     local monster = sprite.newSprite(monsterSet)
     monster:prepare(«running»)
     monster:play()
     monster.x = 60
     monster.y = 200
     local monster2 = sprite.newSprite(monsterSet)
     monster2:prepare(«running»)
     monster2:play()
     monster2.x = 420
     monster2.y = 200
     monster2.xScale = monster2.xScale * -1
     local title = display.newImage(«title.png»)
     title.x = 240
     title.y = 80
     local playButton = display.newImage(«playButton.png»)
     playButton.x = 240
     playButton.y = 220
     menuDisplay:insert(background)
     menuDisplay:insert(monster)
     menuDisplay:insert(monster2)
     menuDisplay:insert(title)
     menuDisplay:insert(playButton)
     —this is what gets called when playButton gets touched
     —the only thing that is does is call the transition
     —from this scene to the game scene, «downFlip» is the
     —name of the transition that the director uses
     local function buttonListener( event )
          director:changeScene( «game», «downFlip» )
          return true
     end
     —this is a little bit different way to detect touch, but it works
     —well for buttons.
     —that is the button send the event «touch», which will call the function
     —buttonListener everytime the displayObject is touched.
     playButton:addEventListener(«touch», buttonListener )
     —return the display group at the end
     return menuDisplay
end

Одна вещь, которая здесь нова, это строка Director: changeScene (). Это довольно просто, поскольку делает именно то, о чем вы думаете. Однако я хотел указать на второй параметр, «downFlip». Есть много встроенных переходов, которые могут сделать вашу игру совершенно необычной при переключении между сценами, это зависит только от того, как вы хотите, чтобы ваша игра выглядела. Вот изображение нашего перехода в процессе.

переход

Обязательно попробуйте некоторые из различных переходов, чтобы найти тот, который лучше всего подойдет для вашей игры. Вы можете найти их полный список в файле Director.lua. Достаточно взглянуть на все различные эффекты и привести их в движение. Еще несколько примеров, которые вы можете попробовать быстро, если не хотите копать, — это «crossfade», «overfromtop» и «flipFromBottom», и это лишь некоторые из них! Итак, кроме этого, там очень мало того, чего вы раньше не видели. Все это просто делает маленький дешевый экран главного меню. Там есть пара вещей, которые вы должны принять к сведению, которые потребуются в каждой сцене, в которой нуждается режиссер. Первое существо:

1
module(…, package.seeall)

Легко и просто. Вам нужна эта точная строка вверху каждого * .lua-файла, который режиссер собирается использовать в качестве сцены. После этого у вас есть функция new (), которая вызывается при входе в сцену, и все, что вы хотите, чтобы сцена делала, должно быть включено сюда. Первое, что вам нужно сделать, это создать displayObject, который будет возвращен для отображения директору, а затем просто убедитесь, что он возвращен в конце новой функции. Это все. Звучит легко? Это потому что это так! Класс директора действительно делает это так легко. Если ваши изображения находятся в нужном месте для сцены меню, вы сможете запускать файл main.lua и запускать его без проблем.

Пока у нас есть основной файл и файл главного меню. Последнее, что нам нужно сделать, это внести некоторые изменения в файл нашей игры. Это также будет легко. Откройте файл game.lua и добавьте следующий код:

1
2
3
4
5
6
7
module(…, package.seeall)
local director = require(«director»)
new = function( params )
    local gameDisplay = display.newGroup()
    —paste code here
    return gameDisplay
end

Это то, что вам нужно для сцены. Кстати, это все, что вам нужно, чтобы вставить старый файл main.lua в файл game.lua. Когда у вас есть это, единственное, что вам нужно сделать, это скопировать весь старый файл main.lua и вставить его туда, где написано вставить код. Сделай это, и все готово. , .почти. Мы также собираемся внести некоторые изменения в то, как мы отображаем нашу игру поверх сообщения. Вместо того, чтобы иметь одну большую кнопку, мы собираемся разбить ее на несколько меньших кнопок, которые позволят нам перезапустить игру или вернуться в меню. Давайте начнем вносить некоторые из этих изменений (обратите внимание, что gameOver.png был изменен, чтобы соответствовать новому макету кнопок. Размеры изображения все те же, поэтому вам не нужно вносить какие-либо другие изменения в него). Первыми изменениями будут добавление новых кнопок в игру.

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

1
2
3
4
5
6
local yesButton = display.newImage(«yesButton.png»)
yesButton.x = 100
yesButton.y = 600
local noButton = display.newImage(«noButton.png»)
noButton.x = 100
noButton.y = 600

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

1
2
screen:insert(yesButton)
screen:insert(noButton)

Следующее, что вы захотите сделать, это перейти к функции touched () и удалить первый оператор if / else, чтобы он выглядел так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
function touched( event )
if(monster.isAlive == true) then
    if(event.phase == «began») then
        if(event.x < 241) then
            if(onGround) then
                monster.accel = monster.accel + 20
            end
            else
                for a=1, blasts.numChildren, 1 do
                    if(blasts[a].isAlive == false) then
                        blasts[a].isAlive = true
                        blasts[a].x = monster.x + 50
                        blasts[a].y = monster.y
                        break
                    end
                end
            end
        end
     end
 end

Делая это, он делает функцию касания, которая чисто обрабатывает взаимодействия в игре. Мы собираемся переместить логику, которая перезапускает игру, к ее собственной функции. Добавьте эти функции ниже функции touched ():

1
2
3
4
5
6
7
8
function noListener(event)
    director:changeScene( «menu», «downFlip» )
    return true
end
function yesListener(event)
    restartGame()
    return true
end

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

1
2
yesButton:addEventListener(«touch», yesListener )
noButton:addEventListener(«touch», noListener )

Итак, последние несколько вещей, которые мы должны сделать, это учесть изменения в положении двух кнопок, когда умирает наш монстр и когда мы перезагружаем игру. Вот дополнения, которые мы должны включить, чтобы убедиться, что они работают правильно. В функцию restartGame () добавьте это:

1
2
3
4
noButton.x = 100
noButton.y = 600
yesButton.x = 100
yesButton.y = 600

Затем перейдите к функции checkCollisions (), где вы должны увидеть эти строки несколько раз:

1
2
gameOver.x = display.contentWidth*.65
gameOver.y = display.contentHeight/2

Добавьте этот блок прямо под каждым экземпляром (всего должно быть 4, по одному на каждый способ умереть):

1
2
3
4
yesButton.x = display.contentWidth*.65 — 80
yesButton.y = display.contentHeight/2 + 40
noButton.x = display.contentWidth*.65 + 80
noButton.y = display.contentHeight/2 + 40

Как только вы внесете все эти изменения, вы сможете запустить игру с main.lua и перейти из своего главного меню в игру, умереть, а затем выбрать, хотите ли вы играть снова или вернуться к меню. Итак, при условии, что все хорошо, это конец, теперь мы переместили нашу игру в систему меню, используя класс Director! Мы продвинулись очень быстро по большей части этого, причина в том, что действительно не было очень много нового контента. Если у вас возникнут проблемы с каким-либо из шагов, дайте мне знать в комментариях, и я буду более чем рад помочь вам пройти через них. Новая папка в загружаемом файле также содержит готовый продукт, так что вы всегда можете использовать его в качестве справочного материала. Надеемся, что эта серия руководств была полезна для вас, чтобы вы начали разработку игр с помощью Corona SDK, поскольку вы видите, что процесс в целом действительно очень прост. Corona SDK является мощным и очень удобным для пользователя, когда вы освоите основы. Надеюсь, теперь вы можете двигаться вперед и сделать несколько классных игр.

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