Мы уже прошли долгий путь в создании нашей бесконечной игры для раннеров. На этом этапе серии у вас уже должен быть игровой и приятный опыт, но этот урок научит вас, как добавить еще один поворот: битвы с боссами!
К настоящему времени наша игра начинает выглядеть как настоящая игра! У нас есть управляемый персонаж с различными типами препятствий, которые генерируются случайным образом, у нас есть прокрутка параллакса, реализованная в трех разных слоях, и у нас есть базовая система подсчета очков, которая дает нашим игрокам чувство выполненного долга. Все идет нормально. Теперь, возможно, этого достаточно для той игры, которую вы разрабатываете, и это все, что вам нужно. Однако, допустим, вы хотите оживить свою игру чем-то новым. Что-то вроде … битвы с боссом !!! Хотя в большинстве бесконечных игр с прокруткой нет битвы с боссами, будет хорошей идеей посмотреть, как мы будем разрабатывать подобные мероприятия. Итак, начнем!
Вы заметите, что мы снова следуем тому же формату со старой папкой в прилагаемой загрузке, содержащей весь созданный нами проект, и новой папкой, содержащей проект, после того, как мы закончили это руководство. Первое, что нужно сделать, это убедиться, что у нас есть изображения в правильной папке. Вы можете взять boss.png и bossSpit.png из новой папки в прилагаемом файле загрузки. Обратите внимание, что босс не анимированный, а просто одно изображение. Если вы хотите анимированного босса и забыли, как анимировать спрайт в Corona, обратитесь к руководству по анимации спрайтов, выпущенному ранее в этой серии.
Теперь, когда они находятся в той же папке, что и наш файл main.lua, откройте файл main.lua в вашем любимом текстовом редакторе. Я не собираюсь объяснять многое из того, что здесь происходит (Обязательно прочитайте комментарии для подсказок и небольших объяснений!), Так как в этот момент мы уже говорили обо всем несколько раз, и я уверен, что вы просто пропустить это все равно. Это также поможет нам быстро пройти обучение, как и все, что мы делали здесь, мы делали раньше, так что это просто много небольших изменений. Итак, начнем.
Первое, что мы сделаем, это загрузим наши изображения в игру. Опять же, все это должно выглядеть знакомо. Добавьте этот код вверху, где мы загружаем все остальные изображения. Просто убедитесь, что bossSpits объявлен, прежде чем пытаться что-то добавить в него!
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
local boss = display.newImage(«boss.png», 150, 150)
boss.x = 300
boss.y = 550
boss.isAlive = false
boss.health = 10
boss.goingDown = true
boss.canShoot = false
—spitCycle is the only thing that is not self explantory
—every time we move a ground piece back to the right of the
—screen we update the score by one.
—spite cycle.
—the boss will shoot his projectile.
—of that for us!
boss.spitCycle = 0
for a=1, 3, 1 do
bossSpit = display.newImage(«bossSpit.png»)
bossSpit.x = 400
bossSpit.y = 550
bossSpit.isAlive = false
bossSpit.speed = 3
bossSpits:insert(bossSpit)
end
|
Затем обязательно добавьте их на экран рядом с другими дополнениями, хорошее место для их размещения будет прямо перед тем, как вы вставите collisionRect.
1
2
|
screen:insert(boss)
screen:insert(bossSpits)
|
Сохраните это и запустите. Попробуйте это в версии для iPhone 4, и вы должны увидеть что-то вроде этого:
Теперь давайте заставим их что-то сделать. То, как мы собираемся справиться с боссом, заключается в том, что, как и другие события, мы случайным образом вступаем в игру, и мы хотим, чтобы это произошло в определенное время. В этом примере мы собираемся установить его на меньшее число, чтобы он быстро попадал на событие, но вы, вероятно, захотите сделать его более разумным в своей игре. Таким образом, каждый раз, когда вашему монстру приходится преодолевать дистанцию, кратную 10, будет происходить босс. По мере появления босса земля становится плоской на земле. Мы также предотвращаем появление невидимых призраков и шипов, чтобы не отвлекаться от боя! Когда он появляется, он выходит на сцену сверху и начинает подпрыгивать, пока плюется жаром в поисках желтых шаров … смерти!
Поэтому, когда босс стреляет в игрока, игрок должен убить босса, стреляя в него десять раз. Игрок также может защитить себя от косы, стреляя в них. Таким образом, основной стратегией победы будет прыгать и спамить свои навыки стрельбы! Еще пара вещей, на которые стоит обратить внимание: в этой игре я решил не обновлять счет, пока босс жив, так что игрок вынужден победить босса, чтобы продолжать получать более высокие оценки. Последнее, перед тем как мы продолжим, это то, что у меня есть босс, готовый стрелять каждые три обновления блока. Это снова имеет то преимущество, что сложность автоматически масштабируется с игрой. Это также обеспечивает простой способ получить последовательные снимки. Ничего слишком сумасшедшего, но в целом это добавляет приятный поворот в игре.
Чтобы освободить место для босса на экране, я переместил игрока немного дальше назад на экран. Теперь я начинаю героя так:
1
|
monster.x = 60
|
Это немного откроет уровень. Следующее, что мы должны сделать, это запустить наши функции, которые обновят босса и плевок босса:
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
|
function updateBoss()
—check to make sure that the boss hasn’t been killed
if(boss.health > 0) then
—check to see if the boss needs to change direction
if(boss.y > 210) then
boss.goingDown = false
end
if(boss.y < 100) then
boss.goingDown = true
end
if(boss.goingDown) then
boss.y = boss.y + 2
else
boss.y = boss.y — 2
end
else
—if the boss has been killed make him slowly disappear
boss.alpha = boss.alpha — .01
end
—once the monster has been killed and disappear officially
—kill him off and reset him back to where he was
if(boss.alpha <= 0) then
boss.isAlive = false
boss.x = 300
boss.y = 550
boss.alpha = 1
boss.health = 10
inEvent = 0
boss.spitCycle = 0
end
end
function updateBossSpit()
for a = 1, bossSpits.numChildren, 1 do
if(bossSpits[a].isAlive) then
(bossSpits[a]):translate(speed * -1, 0)
if(bossSpits[a].y > monster.y) then
bossSpits[a].y = bossSpits[a].y — 1
end
if(bossSpits[a].y < monster.y) then
bossSpits[a].y = bossSpits[a].y + 1
end
if(bossSpits[a].x < -80) then
bossSpits[a].x = 400
bossSpits[a].y = 550
bossSpits[a].speed = 0
bossSpits[a].isAlive = false;
end
end
end
end
|
После этого нам просто нужно внести некоторые изменения в некоторые другие наши функции и добавить их в нашу функцию update ():
1
2
3
4
5
6
7
|
updateBossSpit()
if(boss.isAlive == true) then
updateBoss()
end
|
Добавьте их в функцию обновления, затем перейдите к функции checkEvent (), где вы увидите код, который выглядит следующим образом:
1
2
3
|
if(inEvent > 0 and eventRun > 0) then
—Do nothing
else
|
Прямо под этим оператором else очищается все, что было там, и заменяется следующим:
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
61
62
63
|
—this is where we spawn the boss after every 10 blocks
—also control the boss’s health from here
if(boss.isAlive == false and score%10 == 0) then
boss.isAlive = true
boss.x = 400
boss.y = -200
boss.health = 10
end
—if the boss is alive then keep the event set to 15
—this will prevent the other events from spawning
if(boss.isAlive == true) then
inEvent = 15
else
—everything down here should be the same as it was before
check = math.random(100)
if(check > 80 and check < 99) then
inEvent = math.random(10)
eventRun = 1
end
if(check > 98) then
inEvent = 11
eventRun = 2
end
if(check > 72 and check < 81) then
inEvent = 12
eventRun = 1
end
if(check > 60 and check < 73) then
inEvent = 13
eventRun = 1
end
end
|
Там не должно быть ничего слишком сумасшедшего. Если вы новичок в программировании, вы, возможно, не знакомы с символом модуля:%. Для этого нужно взять все имеющиеся у вас числа, разделить первое число на второе и вернуть остаток. Таким образом, если счет равен 15, счет% 10 вернет 5, что не равно 0, поэтому он не вызовет событие босса. То же самое касается любого числа, не кратного 10. Таким образом, мы легко можем контролировать частоту появления чего-либо. Следующий шаг вернется в updateBlocks (). Прямо под утверждением if, которое гласит:
1
|
if((blocks[a]).x < -40) then
|
Вы собираетесь взять раздел ScoreText и поместить его в оператор if, который проверяет, жив ли босс или нет (опять же, мы не собираемся обновлять счет, пока он жив! Как часть оператора if вы собираюсь добавить еще, что дает боссу часть его поведения). Сделайте этот раздел похожим на это:
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
|
—only update the score if the boss is not alive
if (boss.isAlive == false) then
score = score + 1
scoreText.text = «score: » .. score
scoreText:setReferencePoint(display.CenterLeftReferencePoint)
scoreText.x = 0
scoreText.y = 30
else
—have the boss spit every three block passes
boss.spitCycle = boss.spitCycle + 1
if(boss.y > 100 and boss.y < 300 and boss.spitCycle%3 == 0) then
for a=1, bossSpits.numChildren, 1 do
if(bossSpits[a].isAlive == false) then
bossSpits[a].isAlive = true
bossSpits[a].x = boss.x — 35
bossSpits[a].y = boss.y + 55
bossSpits[a].speed = math.random(5,10)
break
end
end
end
end
if(inEvent == 15) then
groundLevel = groundMin
end
|
Все еще ничего ужасно сложного, как я сказал, здесь не должно быть много нового материала. Следующая часть просто больше того же самого, и тогда мы закончили. Следующее, что мы собираемся добавить, это проверки обнаружения столкновений, чтобы увидеть убийства. Давайте начнем со взрыва монстра, нам нужно проверить как плевок босса, так и самого монстра.
Добавьте эти строки в функцию updateBlasts ():
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
—check for collisions with the boss
if(boss.isAlive == true) then
if(blasts[a].y — 25 > boss.y — 120 and blasts[a].y + 25 < boss.y + 120 and boss.x — 40 < blasts[a].x + 25 and boss.x + 40 > blasts[a].x — 25) then
blasts[a].x = 800
blasts[a].y = 500
blasts[a].isAlive = false
—everything is the same only 1 hit will not kill the boss so just take a little health away
boss.health = boss.health — 1
end
end
—check for collisions between the blasts and the bossSpit
for b = 1, bossSpits.numChildren, 1 do
if(bossSpits[b].isAlive == true) then
if(blasts[a].y — 20 > bossSpits[b].y — 120 and blasts[a].y + 20 < bossSpits[b].y + 120 and bossSpits[b].x — 25 < blasts[a].x + 20 and bossSpits[b].x + 25 > blasts[a].x — 20) then
blasts[a].x = 800
blasts[a].y = 500
blasts[a].isAlive = false
bossSpits[b].x = 400
bossSpits[b].y = 550
bossSpits[b].isAlive = false
bossSpits[b].speed = 0
end
end
end
|
Еще одно обнаружение столкновений, которое нужно проверить, это проверка слюны босса на нашего игрока. Добавьте это в функцию checkCollisions ():
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
—make sure the player didn’t get hit by the boss’s spit!
for a = 1, bossSpits.numChildren, 1 do
if(bossSpits[a].isAlive == true) then
if((( ((monster.y-bossSpits[a].y))<45)) and (( ((monster.y-bossSpits[a].y))>-45)) and (( ((monster.x-bossSpits[a].x))>-45)) ) then
—stop the monster
speed = 0
monster.isAlive = false
—this simply pauses the current animation
monster:pause()
gameOver.x = display.contentWidth*.65
gameOver.y = display.contentHeight/2
end
end
end
|
Опять же, все это должно выглядеть довольно знакомым. Последнее, что нам нужно сделать, — это зайти в нашу функцию restartGame () и обновить ее информацией босса вместе с его слюной.
Также обратите внимание, что, поскольку мы изменили позицию monster.x в этом уроке, важно, чтобы вместо сброса monster.x на 110 мы теперь обновили monster.x, чтобы отразить его новую позицию, которая равна 60.
01
02
03
04
05
06
07
08
09
10
|
—reset the boss
boss.isAlive = false
boss.x = 300
boss.y = 550
—reset the boss’s spit
for a = 1, bossSpits.numChildren, 1 do
bossSpits[a].x = 400
bossSpits[a].y = 550
bossSpits[a].isAlive = false
end
|
Сохраните это, запустите и наслаждайтесь новым дополнением к игре! Вы должны качать что-то вроде этого сейчас:
и
Как я уже говорил несколько раз, нового контента действительно не было много, но я подумал, что будет хорошим упражнением показать вам, как легко обновить вашу игру новым контентом. Также он показывает новые подходы к добавлению событий, чтобы они были более случайными по требованию. В большинстве игр такого типа, вероятно, будет реализовано сочетание того и другого. Хорошим примером игры, которая делает это хорошо, является bit.trip runner . Проверьте это, чтобы лучше понять, что можно сделать с этим стилем игры. Если мы обсудили что-то слишком быстро, и у вас есть вопросы, дайте мне знать, если не будете готовы в следующий раз немного лучше организовать нашу игру с хорошей новой системой меню, которая сделает эту игру полной. Спасибо за то, что подписались, и мы увидимся в следующий раз!