В этом уроке я покажу вам, как создать шутер с ограниченными возможностями с помощью Corona SDK. Цель игры — стрелять в большое количество целей всего пятью пулями. В этом уроке вы будете работать с таймерами, сенсорным управлением и физикой. Чтобы узнать больше, читайте дальше!
1. Обзор приложения
Используя прилагаемую графику, мы создадим код для стрелялки, используя Lua и API Corona SDK . В игре игрок использует пять пуль, чтобы стрелять по своим врагам. Затем каждый враг создаст еще четыре пули, которые помогут уничтожить большее количество целей. Во время кодирования вы можете изменить параметры в коде, чтобы настроить свою игру.
2. Целевое устройство
Наш первый шаг — выбрать платформу, на которой мы хотим запустить наше приложение. Это важно, чтобы мы могли выбрать размер для наших изображений.
Платформа iOS имеет следующие характеристики:
- iPad 1/2 / Mini: 1024×768 пикселей, 132 т / д
- iPad Retina: 2048×1536, 264 ppi
- iPhone / iPod Touch: 320×480 пикселей, 163 т / д
- iPhone / iPod Retina: 960×640 пикселей, 326 точек на дюйм
- iPhone 5 / iPod Touch: 1136×640, 326 т / д
Поскольку Android является открытой платформой, существует несколько различных устройств и разрешений. Вот некоторые из наиболее распространенных характеристик экрана:
- Asus Nexus 7 Tablet: 800×1280 пикселей, 216 пикселей на дюйм
- Motorola Droid X: 854×480 пикселей, 228 пикселей на дюйм
- Samsung Galaxy SIII: 720×1280 пикселей, 306 пикселей на дюйм
В этом уроке мы сконцентрируемся на платформе iOS с графическим дизайном, специально для разработки для распространения на iPhone / iPod touch, но представленный здесь код применим и к разработке Android с Corona SDK.
3. Интерфейс
Мы будем использовать простой интерфейс с несколькими формами, кнопками и растровыми изображениями. Графические ресурсы интерфейса, необходимые для этого урока, можно найти в прилагаемой загрузке.
4. Экспорт графики
В зависимости от выбранного устройства вам может потребоваться экспортировать графику в рекомендованном ppi. Вы можете сделать это в вашем любимом графическом редакторе. Я использовал функцию « Настроить размер …» в приложении «Просмотр» в Mac OS X.
Не забудьте дать изображениям описательное имя и сохранить их в папке вашего проекта.
5. Конфигурация приложения
Внешний файл делает приложение полноэкранным на всех устройствах (файл config.lua ). Этот файл показывает исходный размер экрана и метод, используемый для масштабирования этого содержимого в случае, если приложение запускается с другим разрешением экрана.
1
2
3
4
5
6
7
8
9
|
application =
{
content =
{
width = 320,
height = 480,
scale = «letterbox»
},
}
|
6. Main.lua
Теперь давайте напишем заявку! Откройте предпочитаемый редактор Lua (любой текстовый редактор будет работать, но у вас не будет подсветки синтаксиса) и подготовьтесь к написанию нового приложения. Не забудьте сохранить файл как main.lua в папке вашего проекта.
7. Структура кода
Мы будем структурировать наш код, как если бы это был класс. Если вы знаете ActionScript или Java, вы найдете структуру знакомой.
01
02
03
04
05
06
07
08
09
10
11
|
Necessary Classes
Variables and Constants
Declare Functions
contructor (Main function)
class methods (other functions)
call Main function
|
8. Скрыть строку состояния
1
|
display.setStatusBar(display.HiddenStatusBar)
|
Этот код скрывает строку состояния. Строка состояния — это строка в верхней части экрана устройства, которая показывает время, сигнал и другие индикаторы.
9. Импортировать физику
Мы будем использовать библиотеку физики для обработки столкновений. Используйте этот код для его импорта:
1
|
— Physics local physics = require(‘physics’) physics.start()
|
10. Фон
Следующая строка кода создает простой фон для интерфейса приложения.
1
2
3
4
5
|
— Graphics
— [Background]
local gameBg = display.newImage(‘gameBg.png’)
|
11. Заголовок
Это заголовок; это будет первый интерактивный экран, который появится в нашей игре. Эти переменные хранят его компоненты:
1
2
3
4
5
6
|
— [Title View]
local title
local playBtn
local creditsBtn
local titleView
|
12. Кредиты Просмотр
Это представление показывает кредиты и авторские права на игру. Эта переменная хранит это:
1
2
3
|
— [CreditsView]
local creditsView
|
13. Инструкция Сообщение
Сообщение с инструкциями появится в начале игры и отключится через две секунды. Вы можете изменить время позже в коде.
1
2
3
|
— Instructions
local ins
|
14. Башенка
Это изображение башни, оно будет размещено в центре нашей игры.
1
2
3
|
— Turret
local turret
|
15. Враг
Враги появляются с края экрана, следующая Group
хранит их.
1
2
3
|
— Enemy
local enemies
|
16. Оповещение
Это предупреждение, которое отображается, когда у игрока кончились патроны. Он показывает счет и заканчивает игру.
1
2
3
|
— Alert
local alertView
|
17. Звуки
Мы будем использовать звуковые эффекты, чтобы улучшить ощущение игры. Звуки, используемые в этой игре, были созданы в as3sfx, а фоновая музыка от PlayOnLoop .
1
2
3
4
5
|
— Sounds
local bgMusic = audio.loadStream(‘POL-hard-corps-short.mp3’)
local shootSnd = audio.loadSound(‘shoot.wav’)
local exploSnd = audio.loadSound(‘explo.wav’)
|
18. Переменные
Эти переменные мы будем использовать. Вы можете прочитать комментарии в коде, чтобы узнать больше о них.
1
2
3
4
5
6
7
|
— Variables
local timerSrc
local yPos = {58, 138, 218} —posible Y positions for enemies
local speed = 3
local targetX —stores position of enemy when shot
local targetY
|
19. Объявить функции
Объявите все функции как локальные в начале.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
— Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local gameListeners = {}
local createEnemy = {}
local shoot = {}
local update = {}
local onCollision = {}
local addExBullets = {}
local alert = {}
|
20. Конструктор
Далее мы создадим функцию, которая инициализирует игровую логику:
1
2
3
|
function Main()
— code…
end
|
21. Добавить заголовок просмотра
Теперь мы поместим TitleView на сцену и вызовем функцию, которая добавляет прослушиватели касаний к кнопкам.
1
2
3
4
5
6
7
8
|
function Main()
titleBg = display.newImage(‘title.png’)
playBtn = display.newImage(‘playBtn.png’, 212, 163)
creditsBtn = display.newImage(‘creditsBtn.png’, 191, 223)
titleView = display.newGroup(titleBg, playBtn, creditsBtn)
startButtonListeners(‘add’)
end
|
22. Пуск кнопки прослушивания
Эта функция добавляет необходимых слушателей к кнопкам 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
|
23. Показать кредиты
Экран кредитов отображается, когда пользователь нажимает кнопку «О программе». Прослушиватель касаний добавляется в представление кредитов, чтобы удалить его.
1
2
3
4
5
6
|
function showCredits:tap(e)
playBtn.isVisible = false
creditsBtn.isVisible = false
creditsView = display.newImage(‘credits.png’, -110, display.contentHeight-80)
transition.to(creditsView, {time = 300, x = 55, onComplete = function() creditsView:addEventListener(‘tap’, hideCredits) end})
end
|
24. Скрыть кредиты
При нажатии на экран кредитов, он будет отключен со сцены и удален.
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
|
25. Показать игровой вид
При нажатии кнопки « Воспроизведение» вид заголовка изменяется и удаляется, открывая вид игры. В этом представлении много частей, поэтому мы разделим их на следующие несколько шагов.
1
2
|
function showGameView:tap(e)
transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners(‘rmv’) display.remove(titleView) titleView = nil end})
|
26. Инструкция Сообщение
Следующие строки добавляют сообщение с инструкциями.
1
2
|
ins = display.newImage(‘ins.png’, 135, 255)
transition.from(ins, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(2000, function() transition.to(ins, {time = 200, alpha = 0.1, onComplete = function() display.remove(ins) ins = nil end}) end) end})
|
27. Пули Левый Индикатор
Этот раздел добавляет маркеры в верхнем левом углу экрана. Он представляет доступные кадры, оставленные игроком.
1
2
3
4
5
6
7
8
|
— Bullets Left
bullets = display.newGroup()
bulletsLeft = display.newGroup()
for i = 1, 5 do
local b = display.newImage(‘bullet.png’, i*12, 12)
bulletsLeft:insert(b)
end
|
28. Оценка TextField
Это текстовое поле Score, созданное в правом верхнем углу сцены:
1
2
3
4
|
— TextFields
scoreTF = display.newText(‘0’, 70, 23.5, ‘Courier Bold’, 16)
scoreTF:setTextColor(239, 175, 29)
|
29. Башенка
Теперь мы разместим башню на сцене.
1
2
3
|
— Turret
turret = display.newImage(‘turret.png’, 220, 301)
|
30. Враги Стол & Фоновая музыка
Далее мы создадим таблицу врагов, вызовем функцию, которая добавляет слушателей игры, и запустим фоновую музыку.
1
2
3
4
|
enemies = display.newGroup()
gameListeners(‘add’)
audio.play(bgMusic, {loops = -1, channel = 1})
end
|
31. Слушатели игр
Эта функция добавляет необходимых слушателей для запуска логики игры:
01
02
03
04
05
06
07
08
09
10
11
|
function gameListeners(action)
if(action == ‘add’) then
timerSrc = timer.performWithDelay(1200, createEnemy, 0)
Runtime:addEventListener(‘enterFrame’, update)
else
timer.cancel(timerSrc)
timerSrc = nil
Runtime:removeEventListener(‘enterFrame’, update)
gameBg:removeEventListener(‘tap’, shoot)
end
end
|
32. Создать врага
Следующая функция создает врагов. Он начинается с выбора случайной позиции Y из ранее созданной таблицы, затем добавляет физику к вновь созданному объекту. Мы добавим слушателя столкновений каждому врагу, а также добавим их в таблицу врагов.
01
02
03
04
05
06
07
08
09
10
11
|
function createEnemy()
local enemy
local rnd = math.floor(math.random() * 4) + 1
enemy = display.newImage(‘enemy.png’, display.contentWidth, yPos[math.floor(math.random() * 3)+1])
enemy.name = ‘bad’
— Enemy physics
physics.addBody(enemy)
enemy.isSensor = true
enemy:addEventListener(‘collision’, onCollision)
enemies:insert(enemy)
end
|
33. Стреляй
Когда игрок касается экрана, создается пуля и воспроизводится звук. Он имеет физические свойства, которые обнаруживают столкновения.
1
2
3
4
5
6
|
function shoot()
audio.play(shootSnd)
local b = display.newImage(‘bullet.png’, turret.x, turret.y)
physics.addBody(b)
b.isSensor = true
bullets:insert(b)
|
34. Обновление пули слева
Удалите пулю из области «Пули слева» в верхнем левом углу сцены.
1
2
3
4
5
6
7
|
— Remove Bullets Left
bulletsLeft:remove(bulletsLeft.numChildren)
— End game 4 seconds after last bullet
if(bulletsLeft.numChildren == 0) then
timer.performWithDelay(4000, alert, 1)
end
end
|
35. Двигай врагов
Следующая функция запускает каждый кадр. Здесь мы используем его для перемещения каждого врага в таблице врагов.
1
2
3
4
5
6
7
|
function update()
— Move enemies
if(enemies ~= nil)then
for i = 1, enemies.numChildren do
enemies[i].x = enemies[i].x — speed
end
end
|
36. Переместить стрелять пули
Аналогичный метод используется для пуль.
1
2
3
4
5
6
|
— Move Shoot bullets
if(bullets[1] ~= nil) then
for i = 1, bullets.numChildren do
bullets[i].y = bullets[i].y — speed*2
end
end
|
37. Переместить Взрыв Пули
Когда пуля попадает во врага, образуются четыре дополнительные пули, которые перемещаются четырьмя различными способами. Этот код перемещает каждую пулю в правильном направлении.
01
02
03
04
05
06
07
08
09
10
|
— Move Explosion Bullets
if(exploBullets[1] ~= nil) then
for j = 1, #exploBullets do
if(exploBullets[j][1].y ~= nil) then exploBullets[j][1].y = exploBullets[j][1].y + speed*2 end
if(exploBullets[j][2].y ~= nil) then exploBullets[j][2].y = exploBullets[j][2].y — speed*2 end
if(exploBullets[j][3].x ~= nil) then exploBullets[j][3].x = exploBullets[j][3].x + speed*2 end
if(exploBullets[j][4].x ~= nil) then exploBullets[j][4].x = exploBullets[j][4].x — speed*2 end
end
end
end
|
38. Столкновения
Эта функция запускается, когда пуля сталкивается с противником. Он воспроизводит звук, вызывает функцию, которая добавляет четыре дополнительных маркера, увеличивает счет и удаляет объекты, вовлеченные в столкновение.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
function onCollision(e)
audio.play(exploSnd)
targetX = e.target.x
targetY = e.target.y
timer.performWithDelay(100, addExBullets, 1)
— Remove Collision Objects
display.remove(e.target)
e.target = nil
display.remove(e.other)
e.other = nil
— Increase Score
scoreTF.text = tostring(tonumber(scoreTF.text) + 50)
scoreTF.x = 90
end
|
39. Добавить Взрыв Пули
Этот код создает и размещает четыре дополнительных маркера в правильном положении для перемещения с помощью функции обновления.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
function addExBullets()
— Explosion bullets
local eb = {}
local b1 = display.newImage(‘bullet.png’, targetX, targetY)
local b2 = display.newImage(‘bullet.png’, targetX, targetY)
local b3 = display.newImage(‘bullet.png’, targetX, targetY)
local b4 = display.newImage(‘bullet.png’, targetX, targetY)
physics.addBody(b1)
b1.isSensor = true
physics.addBody(b2)
b2.isSensor = true
physics.addBody(b3)
b3.isSensor = true
physics.addBody(b4)
b4.isSensor = true
table.insert(eb, b1)
table.insert(eb, b2)
table.insert(eb, b3)
table.insert(eb, b4)
table.insert(exploBullets, eb)
end
|
40. Оповещение
Функция оповещения создает представление оповещения, оживляет его и завершает игру.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
function alert()
audio.stop(1)
audio.dispose()
bgMusic = nil
gameListeners(‘rmv’)
alertView = display.newImage(‘alert.png’, 160, 115)
transition.from(alertView, {time = 300, xScale = 0.5, yScale = 0.5})
local score = display.newText(scoreTF.text, (display.contentWidth * 0.5) — 18, (display.contentHeight * 0.5) + 5, ‘Courier Bold’, 18)
score:setTextColor(44, 42, 49)
— Wait 100 ms to stop physics
timer.performWithDelay(1000, function() physics.stop() end, 1)
end
|
41. Вызов основной функции
Чтобы начать игру, необходимо вызвать функцию Main . С помощью приведенного выше кода мы сделаем это здесь:
1
|
Main()
|
42. Экран загрузки
Файл Default.png — это изображение, которое отображается сразу после запуска приложения, пока iOS загружает основные данные для отображения главного экрана. Добавьте это изображение в исходную папку вашего проекта, оно будет автоматически добавлено компилятором Corona.
43. Иконка
Используя графику, которую вы создали ранее, теперь вы можете создать красивый значок. Размер значка для iPhone без использования сетчатки составляет 57x57px, но для версии с сетчаткой — 114x114px, а для магазина iTunes требуется версия 512x512px. Я предлагаю сначала создать версию 512×512, а затем уменьшить ее для других размеров.
Он не должен иметь закругленные углы или прозрачные блики, iTunes и iPhone сделают это за вас.
44. Тестирование в симуляторе
Время финального теста! Откройте Corona Simulator, перейдите в папку вашего проекта и нажмите «Открыть». Если все работает как положено, вы готовы к последнему шагу!
45. Построить
В симуляторе Corona зайдите в File> Build и выберите ваше целевое устройство. Заполните необходимые данные и нажмите Build . Подождите несколько секунд, и ваше приложение готово для тестирования устройства и / или отправки для распространения!
Вывод
В этом уроке мы узнали о физике, таймерах, сенсорных слушателях и других навыках, которые полезны в самых разных играх. Поэкспериментируйте с конечным результатом и попробуйте сделать свою собственную версию игры!
Надеюсь, вам понравился этот сериал, и вы нашли его полезным. Спасибо за чтение!