В этом уроке я покажу вам, как создать игру с балансом в Corona SDK. Вы узнаете больше о сенсорном управлении и обнаружении столкновений без физики. Цель игры — не дать мячу касаться пола. Читай дальше.
1. Обзор приложения
Используя готовую графику, мы создадим развлекательную игру с использованием Lua и API Corona SDK. Игрок сможет перемещать ракетку для пинг-понга по экрану, чтобы ударить по мячу. Вы можете изменить параметры в коде, чтобы настроить игру.
2. Целевое устройство
Первое, что нам нужно сделать, это выбрать платформу, на которой мы хотим запустить наше приложение, чтобы мы могли выбрать размер изображений, которые мы будем использовать.
Платформа iOS предъявляет следующие требования:
- iPad 1/2 / Mini: 1024px x 768px, 132 ppi
- Сетчатка iPad: 2048px x 1536px, 264 ppi
- iPhone / iPod Touch: 320px x 480px, 163 ppi
- Сетчатка iPhone / iPod: 960 x 640 пикселей, 326 ppi
- iPhone 5 / iPod Touch: 1136 пикселей x 640 пикселей, 326 пикселей на дюйм
Поскольку Android является открытой платформой, существует множество различных устройств и разрешений. Вот некоторые из наиболее распространенных характеристик экрана:
- Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
- Motorola Droid X: 854 x 480 пикселей, 228 ppi
- Samsung Galaxy SIII: 720px x 1280px, 306 ppi
В этом уроке мы сосредоточимся на платформе iOS с точки зрения графики. В частности, мы будем разрабатывать для iPhone и iPod touch. Тем не менее, код этого руководства также может быть использован, если вы ориентируетесь на платформу Android.
3. Интерфейс
Мы будем использовать простой пользовательский интерфейс, включающий несколько фигур, кнопок, растровых изображений и многое другое. Графики, которые мы будем использовать для этого урока, можно найти в проекте, включенном в этот урок.
4. Экспорт графики
В зависимости от выбранного устройства вам может потребоваться преобразовать графику в рекомендованное разрешение (ppi), что вы можете сделать в своем любимом графическом редакторе. Я использовал параметр « Настроить размер …» в меню « Инструменты» приложения «Просмотр» в 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
|
Necesary Classes
Variables and Constants
Declare Functions
contructor (Main function)
class methods (other functions)
call Main function
|
8. Скрыть строку состояния
1
|
display.setStatusBar(display.HiddenStatusBar)
|
Этот фрагмент кода скрывает строку состояния. Строка состояния — это строка в верхней части экрана устройства, на которой отображаются время, сигнал и другие индикаторы.
9. Справочная информация
Простой фон для пользовательского интерфейса приложения. Фрагмент кода ниже рисует фон на экране.
1
2
3
4
5
|
— Graphics
— [Background]
local bg = display.newImage(‘bg.png’)
|
10. Заголовок
Это заголовок. Это первый интерактивный экран, который появится в нашей игре. Эти переменные хранят его компоненты.
1
2
3
4
5
6
|
— [Title View]
local title
local playBtn
local creditsBtn
local titleView
|
11. Кредиты Просмотр
Представление «Кредиты» отображает кредиты и авторские права на приложение. Эта переменная используется для ее хранения.
1
2
3
|
— [CreditsView]
local creditsView
|
12. Инструкция Сообщение
В начале игры появится сообщение с инструкциями, которое исчезнет после первого нажатия.
1
2
3
|
— Instructions
local ins
|
13. Весло
Это рисунок для пинг-понга. Он будет размещен в центре просмотра.
1
2
3
4
5
|
— Paddle
local paddle
local paddleTop
local paddleBottom
|
14. Мяч
И это рисунок для мяча для пинг-понга, используемого в игре.
1
2
3
|
— Ball
local ball
|
15. Оповещение
Предупреждение отображается, когда игрок пропускает мяч и игра окончена. Он отображает сообщение и заканчивает игру.
1
2
3
|
— Alert
local alertView
|
16. звуки
Мы будем использовать звуковые эффекты, чтобы оживить игру. Звуки, используемые в этой игре, можно найти в freesound , базе данных лицензированных звуков Creative Commons.
1
2
3
|
— Sounds
local pong = audio.loadSound(‘pong.mp3’)
|
17. Переменные
Следующий фрагмент кода показывает переменные, которые мы будем использовать. Прочитайте комментарии, чтобы понять, для чего используется каждая переменная.
1
2
3
4
5
6
7
8
|
— Variables
local scoreTF — score textfield
local scale = 1.1 — initial ball scale
local variation = 0.05 — controls the scale variation
local ballX = 0
local ballY = 0
local ballVar = 0.5 — ball variation
|
18. Объявить функции
Объявите все функции как local
в начале.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
— Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local gameListeners = {}
local startGame = {}
local hitTestObjects = {}
local update = {}
local movePaddle = {}
local alert = {}
|
19. Конструктор
Далее мы создаем функцию, которая будет инициализировать игровую логику.
1
2
3
|
function Main()
— code…
end
|
20. Добавить заголовок просмотра
Мы начнем с размещения представления заголовка на сцене и вызовем функцию, которая добавит прослушиватели касаний к кнопкам.
1
2
3
4
5
6
7
8
|
function Main()
titleBg = display.newImage(‘titleBg.png’, 26, 72)
playBtn = display.newImage(‘playBtn.png’, 125, 225)
creditsBtn = display.newImage(‘creditsBtn.png’, 115, 290)
titleView = display.newGroup(titleBg, playBtn, creditsBtn)
startButtonListeners(‘add’)
end
|
21. Пуск кнопки прослушивания
Следующая функция добавляет необходимых слушателей к 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
|
22. Показать кредиты
Экран кредитов отображается, когда пользователь нажимает кнопку о. Прослушиватель касаний добавляется в представление кредитов, чтобы отклонить его, когда пользователь нажимает на него.
1
2
3
4
5
6
7
8
9
|
function showCredits:tap(e)
playBtn.isVisible = false
creditsBtn.isVisible = false
creditsView = display.newImage(‘credits.png’, 0, display.contentHeight)
lastY = titleBg.y
transition.to(titleBg, {time = 300, y = (display.contentHeight * 0.5) — (titleBg.height + 50)})
transition.to(creditsView, {time = 300, y = (display.contentHeight * 0.5) + 35, onComplete = function() creditsView:addEventListener(‘tap’, hideCredits) end})
end
|
23. Скрыть кредиты
Когда пользователь нажимает на просмотр кредитов, он анимируется со сцены и удаляется.
1
2
3
4
|
function hideCredits:tap(e)
transition.to(creditsView, {time = 300, y = display.contentHeight + 25, onComplete = function() creditsBtn.isVisible = true playBtn.isVisible = true creditsView:removeEventListener(‘tap’, hideCredits) display.remove(creditsView) creditsView = nil end})
transition.to(titleBg, {time = 300, y = lastY});
end
|
24. Показать игровой вид
При нажатии кнопки воспроизведения вид заголовка анимируется за пределами экрана и открывается вид игры. Есть несколько движущихся частей, поэтому мы подробнее рассмотрим каждую из них.
1
2
|
function showGameView:tap(e)
transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners(‘rmv’) display.remove(titleView) titleView = nil bg:addEventListener(‘tap’, startGame) end})
|
25. Инструкция Сообщение
Следующий фрагмент кода добавляет сообщение с инструкцией.
1
|
ins = display.newImage(‘ins.png’, 112, 370)
|
26. Детали весла
Далее мы добавляем части весла. Это разделено на две части для лучшего обнаружения столкновения.
1
2
3
4
5
|
— Paddle
paddleBottom = display.newImage(‘paddleBottom.png’, 138.6, 262)
paddleTop = display.newImage(‘paddleTop.png’, 110, 166)
paddle = display.newGroup(paddleBottom, paddleTop)
|
27. Мяч
Добавляем шар и устанавливаем его масштаб.
1
2
3
4
|
— Ball
ball = display.newImage(‘ball.png’, 146, 201)
ball:scale(scale, scale)
|
28. Оценка
Мы создаем текстовое поле счета в правом верхнем углу сцены.
1
2
3
4
5
6
7
8
|
— Score
score = display.newImage(‘score.png’, 260, 0)
scoreTF = display.newText(‘0’, 278, 21, ‘Marker Felt’, 30)
scoreTF:setTextColor(238, 238, 238)
gameListeners(‘add’)
end
|
29. Игровые слушатели
Следующая функция добавляет слушателей, необходимых для запуска игровой логики.
1
2
3
4
5
6
7
8
|
function gameListeners(action)
if(action == ‘add’) then
bg:addEventListener(‘touch’, movePaddle)
else
bg:removeEventListener(‘touch’, movePaddle)
Runtime:removeEventListener(‘enterFrame’, update)
end
end
|
30. Функция запуска
Функция startGame
удаляет сообщение с инструкциями и добавляет слушателя в основную функцию игры. В функции случайная позиция y
выбирается из ранее созданной таблицы и впоследствии добавляет физику к вновь созданному объекту. Мы добавляем слушателя столкновений каждому врагу, а также добавляем его в таблицу врагов.
1
2
3
4
5
|
function startGame()
display.remove(ins)
bg:removeEventListener(‘tap’, startGame)
Runtime:addEventListener(‘enterFrame’, update)
end
|
31. Хит объектов теста
Для обнаружения столкновений без использования физики мы используем замечательную функцию, которую вы можете найти на веб-сайте Corona Labs 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
|
32. Весовой шар
Функция update
, показанная ниже, запускает каждый кадр. В этой функции мы сначала масштабируем шар, основываясь на значениях, установленных переменными.
1
2
3
4
5
|
function update()
— Scale Balls
scale = scale — variation
ball.xScale = scale
ball.yScale = scale
|
33. Поднятие мяча
Эта часть увеличивает размер шара, чтобы имитировать увеличение его высоты.
1
2
3
4
|
— Raising
if(math.floor(ball.xScale * 10) >= 15) then
variation = 0.05
end
|
34. Мяч пропущен
Тот же самый метод используется, чтобы проверить, касался ли мяч пола, существенный аспект игры.
1
2
3
4
|
— Missed
if(math.floor(ball.xScale * 10) < 3) then
alert()
end
|
35. Переместить мяч
В следующем фрагменте кода мы перемещаем мяч. В зависимости от значения переменных он перемещается вверх или вниз.
1
2
3
4
|
— Move Ball
ball.x = ball.x — ballX
ball.y = ball.y — ballY
|
36. Бал Хит
Шкала устанавливается на одинаковую высоту весла, что означает, что мяч коснулся весла. Затем мы увеличиваем счет и воспроизводим звук, чтобы предоставить обратную связь пользователю.
1
2
3
4
5
6
7
|
— Falling and Hit with paddle
if(math.floor(ball.xScale * 10) == 3 and hitTestObjects(paddleTop, ball)) then
variation = -0.05
— Increase Score
scoreTF.text = tostring(tonumber(scoreTF.text) + 1)
— Play Sound
audio.play(pong)
|
37. Изменить направление мяча
Весло разделено на четыре секции: верхний левый, верхний правый, нижний левый и нижний правый. Каждая секция перемещает мяч в другом направлении.
01
02
03
04
05
06
07
08
09
10
11
|
— Move Ball based on where it hits
if(ball.x < paddle.x + 50) then ballX = (math.random() * 0.5) + ballVar end if(ball.x > paddle.x) then
ballX = (math.random() * -0.5) — ballVar
end
if(ball.y < paddle.y + 75) then ballY = (math.random() * 0.5) + ballVar end if(ball.y > paddle.y — 70) then
ballY = (math.random() * -0.5) — ballVar
end
— Increase moving distance
ballVar = ballVar + 0.025 — Every four hits increases 0.1
end
end
|
38. Переместить весло
Функция movePaddle
управляет движением весла с помощью сенсорного управления.
1
2
3
4
5
6
|
function movePaddle(e)
if(e.phase == ‘moved’) then
paddle.x = ex
paddle.y = ey
end
end
|
39. Оповещение
Функция alert
создает представление оповещения. Функция анимирует вид оповещения на экран и завершает игру.
1
2
3
4
5
|
function alert()
gameListeners(‘rmv’)
alert = display.newImage(‘alert.png’, (display.contentWidth * 0.5) — 105, (display.contentHeight * 0.5) — 55)
transition.from(alert, {time = 300, xScale = 0.5, yScale = 0.5})
end
|
40. Вызов основной функции
Чтобы начать игру, необходимо вызвать функцию Main . С остальной частью кода мы делаем это здесь.
1
|
Main()
|
41. Экран загрузки
На платформе iOS файл с именем Default.png
отображается во время запуска приложения. Добавьте это изображение в исходную папку вашего проекта, оно будет автоматически добавлено компилятором Corona.
42. Иконка
Используя графику, которую вы создали ранее, теперь вы можете создать красивый значок. Размеры значков для iPhone без сетчатки составляют 57px x 57px, в то время как версия Retina должна быть 114px x 114px. Иллюстрации для iTunes должны быть размером 1024px x 1024px. Я предлагаю сначала создать обложку iTunes, а затем создать изображения меньшего размера, уменьшив обложку iTunes до нужных размеров. Нет необходимости делать значок приложения глянцевым или добавлять закругленные углы, поскольку об этом позаботится операционная система.
43. Тестирование в симуляторе
Пришло время протестировать наше приложение в симуляторе. Откройте Corona Simulator, перейдите в папку вашего проекта и нажмите « Открыть» . Если все работает, как ожидалось, вы готовы к последнему шагу.
44. Строительный проект
В Corona Simulator перейдите в File> Build и выберите целевое устройство. Заполните обязательные поля и нажмите « Построить» . Подождите несколько секунд, и ваше приложение готово к тестированию на устройстве и / или будет отправлено для распространения.
Вывод
В этом уроке мы узнали о сенсорных слушателях и обнаружении столкновений. Поэкспериментируйте с конечным результатом и попробуйте изменить игру, чтобы создать собственную версию игры. Я надеюсь, что вам понравился этот урок, и вы нашли его полезным. Спасибо за чтение.