, а мне C++, но вот занимаюсь почему-то этим.
З.Ы. а скачек-то поболе стало.
Статья прошла проверку, поэтому выкладываю в открытый доступ (для незарегистрированных пользователей):
Часть 3.
Основные темы:
Работа со средствами ввода.
Работа с изображениями.
Создание основы для аркады.
Теория.
1. Немного о LUA.
1. Тип «булиан (boolean)»
Принимаемые значения: true или false.
Смысл типа: тип нужен для того, чтобы определять верно ли какое-то выражение или нет. Естественно, если верно, то тип возвратит значение true. Если нет – false.
Примеры:
1.
… -- некоторая часть программы
if not kartinka then -- если объект «kartinka» имеет значение nil(либо -- не существует)
error(“kartinka ne naydena”) -- выдаётся ошибка, оповещающая об отсутствии -- файла
end -- конец цикла
… -- некоторая часть программы
2.
b_otvet = false -- инициализируем контейнер булианского типа
… -- некоторая часть программы
if b_otvet == false then -- если b_otvet содержит значение false,
b_otvet = true -- то заменяем это значение на true
end -- конец цикла
… -- некоторая часть программы
Тип “булиан” может оказаться очень полезным в виде тумблера и т.п.
1. Параллельное присваивание.
Бывают случаи, когда вам нужно поменять значения, хранимые контейнерами “x” и “y”, т.е. присвоить “x” значение “y” и наоборот. Или же просто одновременно присвоить двум переменным новые значения (слово «двум» тут не ключевое. Можно одновременно присваивать значения и трём, и даже больше контейнерам). В этом нам поможет параллельное присваивание.
Шаблон:
, = ,
и примеры:
x, y, = y, x
x, y = true, false
x, y, z = z, x, y
Вам скорее всего не очень понятно для чего это нужно. Ведь можно вместо
x, y = y, x
написать
x = y
y = x
Вот тут-то мы и допустим ошибку. В первом случае значения присваиваются одновременно, т.е. x будет равно y, а y = x. Во втором же мы сначала присваиваем значение y x-у, а потом значение x , которое у нас = y, присваиваем y-у. У нас получается, что и y, и x имеют одинаковое значение – значение y.
Надеюсь, что вы всё поняли. Эта функция очень важна для программ, но в играх применений для неё маловато.
2. Средства ввода в PGE Lua.
Во всех играх есть управление персонажем, будь то танчики или шутер. Оно осуществляется через средства ввода, т.е. вы нажимаете кнопку – происходит действие. И конечно все мы знаем как это происходит с клавиатурой. Но у нас-то PSP! Как же она понимает, какую кнопку мы нажали? Принцип, конечно, остаётся прежним. Но как вы напишите в листинге программы кнопку «x» или треугольник?
Эти кнопки имеют свои зарезервированные имена. Вот их список:
крестовина:
вверх – UP
вниз – DOWN
влево – LEFT
вправо – RIGHT
панель служебных клавиш:
start – START
select – SELECT
панель с игровыми кнопками (X, O и т.д.):
крест – CROSS
круг – CIRCLE
треугольник – TRIANGLE
квадрат – SQUARE
курки (триггеры):
левый – LTRIGGER
правый – RTRIGGER
А теперь разберёмся как программа поймёт, что мы вообще нажали какую-то кнопку.
За это в PGE отвечают несколько функций в цикле if …. then. Вот их список:
pge.controls.pressed(PGE_CTRL_) -- если клавиша была нажата
pge.controls.held(PGE_CTRL_) -- если клавиша удерживается
pge.controls.released(PGE_CTRL_) -- если клавиша отпущена
Пример с функцией pge.controls.pressed (остальные - аналогичны):
… -- некоторая часть кода
if pge.controls.pressed(PGE_CTRL_CROSS) then -- если нажата кнопка -- «крест»
pr = true -- придаём переменной “pr”
-- значение true
end -- конец цикла
… --некоторая часть кода
3. Работа с изображениями.
Одиночные изображения.
Изображения – важная часть любой игры. С самими изображениями всё просто. Даже если вы не умеете рисовать, то, придерживаясь минимализма или пиксельной графики, можно сделать неплохую игру. Другое дело, как вывести изображения на экран? Не прописывать же в коде всё по пикселям, как это было раньше? Но как раз с этим в PGE LUA всё просто. Нам всего лишь надо иметь изображение в формате PNG (другие форматы не поддерживаются) и, желательно, не кривые руки (криворукость пятой степени).
Начнём. Для начала, нам нужно усвоить несколько вещей:
1. В PGE за графику отвечает модуль pge.texture. Если увидите его, то знайте – в этой части программы идут манипуляции с графикой (ну или танцы с бубном).
2. Любое изображение, для начала, надо занести в контейнер, потом активировать. Без этих двух шагов ничего не будет работать.
Переходим к коду. Всего функций, относящихся к одиночной графике(есть ещё и тайловая, но об этом – позже), довольно много, но основных – 3 штуки. Вот они:
pge.texture.load(“”) -- загрузка изображения (пока без
-- контейнера)
pge.texture.activate() -- активация изображения
pge.texture.draweasy(, x, y, , ) -- рисуем одиночное изображение, где x – координата x, y – координата y, - угол, под которым будет стоять изображение(обычно ставится 0), - степень прозрачности изображения, минимум – 0(не прозрачное), максимум – 255(полностью прозрачное - невидимое)
Теперь я расскажу о некоторых ошибках, возникающих у новичков:
1. Изображение нету! Экран чёрный! Хотя сделал вроде верно…
Довольно распространённая проблема. Вы либо забыли указать функцию pge.gfx.swapbuffers() для вывода изображения из буфера на экран, либо сделали функцию pge.gfx.clearscreen() после того, как нарисовали изображение в буфере. Ну или просто изображение не подходит (правда в этом случае выйдет соответствующая ошибка).
2. Какая-то муть с изображением. Одна картинка состоит из дублированной несколько раз другой!
Ха! Моя любимая. Вы сначала активировали 2 изображения, а потом – начали их выводить в буфер. Это в корне не верно. Последнее активированное изображение PGE использует для прорисовки всех следующих в буфер. Так что после активации одного изображения тут же совершайте все действия над ним, иначе – будут вот такие глюки.
Всё. Хватит с нас теории. Переходим к практике.
Практика.
1. Делаем заготовку для аркады.
Сейчас мы с вами сделаем каркас нашей игры – механику. В этом уроке мы всего лишь сделаем передвижение персонажа влево - вправо и прыжок. Для начала нарисуйте персонажа игры и сохраните его в формате .png в папку с нашим скриптом.
Давайте напишем первые строчки кода – инициализируем изображение персонажа и несколько контейнеров:
hero = pge.texture.load(“hero.png”) -- инициализируем изображение
hero_x = 10 -- координата x изображения
hero_y = 200 -- координата y изображения
hero_vel = 0 -- скорость изображения в прыжке
hero_g = 2 -- ускорение свободного падения (пусть даже немного не реалистичное, но так получается интереснее)
hero_jump = false -- изображение не в прыжке
Теперь сделаем луп программы, чтобы она не выключалачь после выполнения всех действий:
while pge.running() do
И стандартный набор:
pge.controls.update()
pge.gfx.startdrawing()
pge.gfx.clearscreen()
Отлично. Теперь переходим к выводу изображения в буфер:
hero:activate()
hero:draweasy(hero_x, hero_y, 0, 255) -- аналог функции pge.texture.draweasy()
И тут же заканчиваем прорисовку и выводим содержимое буфера на экран:
pge.gfx.enddrawing()
pge.gfx.swapbuffers()
Начинаем колдовать над управлением. Нам нужно чтобы координата x изменялась если мы нажмём кнопку влево/вправо:
if pge.controls.held(PGE_CTRL_LEFT) and hero_x > 0 then
hero_x = hero_x – 1
end
if pge.controls.held(PGE_CTRL_LEFT) and hero_x < 480 then
hero_x = hero_x + 1
end
Объясню значение слова «and» в цикле if. «and» просто добавляет ещё одно условие для цикла. Т.е. если первое условие верно, а второе – нет, то цикл не выполнится. В нашей программе мы просто ограничиваем движение игрока размерами экрана.
Теперь приступим к прыжку. Этот элемент довольно трудный для новичка. Он ещё не понимает, что нужно делать. Поэтому, для начала, расскажу теорию прыжка(да, да. Я знаю, что это отдел практики. Не нудите – это будет вас полезно. К тому же в отделе теории впихнуть это было некуда).
Рассмотрим прыжок с точки зрения физики. Мы придаём телу начальную вертикальную скорость, которая уменьшается из-за ускорения свободного падения. Когда наша вертикально направленная вверх скорость становится равной нулю – мы получаем скорость, вертикально направленную вниз, причём она увеличивается из-за ускорения свободного падения. Когда мы приземляемся, вертикальная скорость становится нулевой.
Представим это в виде словесного алгоритма:
герой не находится в прыжке
если мы нажали кнопку и герой стоит на земле, то
скорость = некоторая скорость
герой находится в прыжке
конец
если герой находится в прыжке, то
если скорость < допустимой, то
скорость = скорость – ускорение свободного падения
координата y = координата y + скорость
конец
конец
если герой стоит не земле, то
скорость = 0
герой находится не в прыжке
конец
Тут всё понятно. Теперь преобразуем алгоритм с человеческого языка на LUA. Ввиду одной особенности PGE - отсчёт координат y начинается сверху вниз, а не снизу вверх, мы немного изменим код. Вот так он будет выглядеть:
if pge.controls.pressed(PGE_CTRL_CROSS) and hero_y == 200 then
hero_vel = -18
hero_jump = true
end
if hero_jump then
if hero_vel < 18 then
hero_vel = hero_vel + hero_g
hero_y = hero_y + hero_vel
end
end
if hero_y >= 200 then
hero_vel = 0
hero_jump = false
end
Занесите эти строчки к себе в код. Можете немного пошаманить со значениями ускорения и скорости. Завершим программу:
end
Можете смело запускать программу. Герой будет бегать и прыгать.
Приложение.
Листинг программы 1:
hero_x = 10
hero_y = 200
hero_vel = 0
hero_g = 2
hero_jump = false
hero = pge.texture.load("hero.png")
while pge.running() do
pge.gfx.startdrawing()
pge.gfx.clearscreen()
hero:activate()
hero:draweasy(hero_x, hero_y, 0, 255)
pge.gfx.enddrawing()
pge.gfx.swapbuffers()
pge.controls.update()
if pge.controls.held(PGE_CTRL_LEFT) and hero_x >= 0 then
hero_x = hero_x - 2
end
if pge.controls.held(PGE_CTRL_RIGHT) and hero_x <= 480 then
hero_x = hero_x + 2
end
if pge.controls.pressed(PGE_CTRL_CROSS) and hero_y == 200 then
hero_vel = -18
hero_jump = true
end
if hero_jump then
if hero_vel < 18 then
hero_vel = hero_vel + hero_g
hero_y = hero_y + hero_vel
end
end
if hero_y >= 200 then
hero_vel = 0
hero_jump = false
end
end
Часть текста отображается неправильно, поэтому советую скачать файл.