Чтобы объяснить это руководство, сначала вы должны посмотреть видео, чтобы лучше понимать понятие Сена:
Обучающее видео:scriptvideo4.wmv - Windows Media Video (640x480, 25fps, 18,4mb)
Что такое сено?
Сено - это карта, в которой цель состоит в том, чтобы полностью подняться на вершину объёмной башни, пройдя весь путь по... блокам сена. Это 4x4x50 башня не твердая, однако, заполнена для 31.25 %, позволяющее игрокам подняться между остановкой блоков сена. Блоки перемещаются в разнообразном порядке (когда возможно), чтобы препятствовать восхождению игрокам, передвигать их или помочь игрокам со следующим скачком. Для фактора напряжения, каждый блок перемещается в высоту быстрее, чем вы добираетесь. Таким образом, блок, находящийся на земле занимает 4 секунды, чтобы переместиться, в то время как наверху занимает только 2 секунды. Это довольно обидно, когда Вы прыгаете, и блок переезжает прежде, чем Вы приземляетесь на него. Для забавного фактора мы добавили камни, которые остаются на месте, пока их не тронешь. Тогда он разрушает каждый блок сена внизу и забирающий (по большей части) Вас и других вниз к смерти.
Локальные переменные
local options = {
x = 4,
y = 4,
z = 49, -- +1
b = 245,
r = 4}
Опции определяют ширину 'x', длина 'y', высота 'z', блоки, 'b', камни 'r', который используется для башни. 'z' имеет +1, потому что наверху мы делаем блок, который никогда не перемещается, плюс хороший пикап с другими не передвигаются.
Кроме этого, мы имеем:
-- Ничего не трогайте ниже!local matrix = {}-- Трехмерная матрица, содержащая информацию по позиции блоков local objects = {}--Список объектовlocal moving = {}--Список перемещающиеся объектов в данный (Мы не хотим перемещать уже перемещающиеся объекты)local leveltop = {}-- Список самого высокого уровня находящегося от каждого игрока local textDisplay -- Контейнер для textDisplaylocal textItem -- Контейнер для textItemlocal xy_speed -- Число мс блоков перемещающихся быстрее горизонтально с каждым уровнем local z_speed -- Число мс блоков перемещающихся быстрее вертикально с каждым уровнем local root = getRootElement()-- Главный элементlocal barrier_x -- Антибезудержный барьер положения xlocal barrier_y -- Антибезудержный барьер положения ylocal barrier_r -- Антибезудержный барьер радиуса
Инициализация
В инициализации мы делаем следующие вещи:
Вычислим статические переменные
Создание башни
Создание текста показывающегося игрокам
Начать перемещающийся процесс блоков
Появление игроков
Статистические переменные
Мы имеем 5 статических переменных, чтобы вычислить, Вы могли подумать: почему вычисление статических переменных? Хорошо мы обеспечиваем опции в местных переменных, чтобы изменить форму, плотность и число камней.
Как я и сказал, чем выше Вы добираетесь, тем быстрее перемещаются блоки. 'Нормальное' движущееся время 1 блока равняется 4 секундам по x/y-оси и 3 секундам по оси Z. Различие между x/y осью и осью Z, потому что измерения блоков сена - точно 4x4x3 единицам. Наверху перемещающееся время - половина 'нормального' времени. Чтобы вычислять время сокращения на уровень, мы делим половину 'нормального' времени (2000мс для x/y оси и 1500мс для оси Z) по числу уровней (options.z + 1).
Кроме этого, мы имеем некоторые переменные, чтобы вычислить для антибезудержного барьера:
-- Вычислите центр башни и радиус барьера
barrier_x = (options.x + 1) * -2
barrier_y = (options.y + 1) * -2
x = options.x * 2 + 4
y = options.y * 2 + 4
barrier_r = math.sqrt(x*x+y*y)
Здесь я должен сделать примечание, мы помещаем башню в x/y диапазон оси 0 до минус 3000. Все координаты x/y отрицательны. Это потому что мы помещаем башню рядом с фермой в середине карты, которая имеет координату 0,0.
Создание башни
Как вы могли увидеть в местных переменных, мы используем трехмерную матрицу для башни. Lua не знает точно матричный тип, таким образом мы фактически работаем с таблицей (Ось X) таблиц (Ось Y), которые содержат таблицу (Ось Z) переменных. Логично, правда?
--Очищение матрицыfor x = 1,options.x do--Для каждого X
matrix[x] = {}--Инициализация таблицы Yfor y = 1,options.y do--Для каждого Y
matrix[x][y] = {}-- Инициализация таблицы Zfor z = 1,options.z do--Для каждого Z
matrix[x][y][z] = 0-- Заполнить 0endendend
Размещение блоков сена легкоё: Для каждого, выберите случайное (1) не взятое положение (2) в матрице, отметьте, как это взято (3) и создайте объект на позиции относительно того положения. (4)
Чтобы заставить блоки сена выглядеть 'отличающимися' друг от друга, мы вращаем в разном порядке блоки сена в шагах 90 градусов по x/y-оси и 180 градусам по оси Z. (4)
-- Число положений блоков сена в матрицеlocal x,y,z
for count = 1,options.b dorepeat
x = randInt (1, options.x )--Отметить 1
y = randInt (1, options.y )
z = randInt (1, options.z )until(matrix[x][y][z] == 0)-- Отметить 2
matrix[x][y][z] = 1--Отметить 3
objects[count] = createObject (3374, x * -4, y * -4, z * 3, randInt (0, 3) * 90, randInt (0, 1) * 180 , randInt (0, 1) * 180)-- Отметить 4end
И то же самое для камней, но тогда "действительно" случайно вращаемый:
-- Число положений камней в матрице for count = 1,options.r dorepeat
x = randInt (1, options.x )-- Отметить 1
y = randInt (1, options.y )
z = randInt (1, options.z )until(matrix[x][y][z] == 0)-- Отметить 2
matrix[x][y][z] = 1-- Отметить 3
createObject (1305, x * -4, y * -4, z * 3, randInt (0, 359), randInt (0, 359), randInt (0, 359))-- Отметить 4end
После создания мы помещаем статический блок (1) на вершину плюс сюрприз (2):
-- Место главного блока сена + сюрприз
createObject (3374, barrier_x, barrier_y, options.z * 3 + 3)--Отметить 1
createPickup ( barrier_x, barrier_y, options.z * 3 + 6, 2, 38, 500)--Отметить 2
Создание показа текста
Как вы можете увидеть в видео в левой стороне был список имен всех игроков с текущим там уровнем, самый высокий достигнутый уровень и оставленное здоровье. Это сделано через показ текста. С показом текста Вы можете добавить текстовые сообщения в любой часте пользовательского экрана. Я не хочу сейчас углубляться в создании этого прямо сейчас, но в основном сводится к этому:
1. Создать контейнер пункта. 'textCreateDisplay ()'
2. Создайте пункты 'textCreateTextItem 'textCreateTextItem ( text, x, y, priority, red, green, blue, alpha, scale)'
3. Добавить пункты к контейнеру пункта ''textDisplayAddText ( display, item )'
4. Добавить игроков к контейнеру пункта, таким образом они будут видеть все пункты на их экране 'textDisplayAddObserver ( display, player )'
Это также, где мы инициализируем самый высокий достигнутый уровень игрока, который является 0 (5).
Как вы можете увидеть, это обновляется каждую секунду показывая, что это сделано устанавливая таймер на инициализации, чтобы вызывать функцию каждую секунду:
setTimer ("level", 1000, 0)
Начало перемещения блоков
Начало перемещения блока - снова таймер, который вызывает функцию каждые 100мс.
setTimer ("move", 100, 0)
Функция перемещения блоков
'Ядро' (core) сена. Сначала мы выбираем случайное число, которое назначаем блоку, между 1 и числом блоков (1). Если этот блок, не перемещается (2) мы получаем объект (3) и выбираем случайное передвижение (4). Затем мы делаем временную копию матрицы (5), заполняем во всех положениях игрока (6), и вычисляем положение объекта в матрице (7). Если выбранное движение возможно, (это не перемещается из матрицы и свободно (8), мы отмечаем блок как перемещаемый (9)). Затем это вычисляет скорость движения с использованием переменных "время сокращения на уровень" (reduction-time-per-level) (10). Если блок перемещается, мы хотим сделать некоторые настройки (11). После этого мы вычисляем новое положение блока (12). Чтобы предотвращать передвижение блоков друг в друга, мы отмечаем следующее местоположение блока в матрице как взятый (13). В конечном счете, мы перемещаем непосредственно блок (14).
function move ()local rand
repeat
rand = randInt (1, options.b )--Отметим 1until(moving[rand] ~= 1)--Отметим 2local object = objects[ rand ]--Отметим 3local move = randInt (0, 5)--Отметим 4local x,y,z
local x2,y2,z2 = getElementPosition ( object )local free = {}
copyTable(matrix,free)--Отметим 5
getFree(free)--Отметим 6
x = x2 / -4--Отметим 7
y = y2 / -4
z = z2 / 3if(move == 0)and(x ~= 1)and(free[x-1][y][z] == 0)then--Отметим 8
moving[rand] = 1--Отметим 9local s = 4000 - xy_speed * z --Отметим 10
setTimer ("done", s, 1, rand, x, y, z)--Отметим 11
x = x - 1--Отметим 12
matrix[x][y][z] = 1--Отметим 13
moveObject ( object, s, x2 + 4, y2, z2, 0, 0, 0)--Отметим 14elseif(move == 1)and(x ~= options.x)and(free[x+1][y][z] == 0)then
moving[rand] = 1local s = 4000 - xy_speed * z
setTimer ("done", s, 1, rand, x, y, z)
x = x + 1
matrix[x][y][z] = 1
moveObject ( object, s, x2 - 4, y2, z2, 0, 0, 0)elseif(move == 2)and(y ~= 1)and(free[x][y-1][z] == 0)then
moving[rand] = 1local s = 4000 - xy_speed * z
setTimer ("done", s, 1, rand, x, y, z)
y = y - 1
matrix[x][y][z] = 1
moveObject ( object, s, x2, y2 + 4, z2, 0, 0, 0)elseif(move == 3)and(y ~= options.y)and(free[x][y+1][z] == 0)then
moving[rand] = 1local s = 4000 - xy_speed * z
setTimer ("done", s, 1, rand, x, y, z)
y = y + 1
matrix[x][y][z] = 1
moveObject ( object, s, x2, y2 - 4, z2, 0, 0, 0)elseif(move == 4)and(z ~= 1)and(free[x][y][z-1] == 0)then
moving[rand] = 1local s = 3000 - z_speed * z
setTimer ("done", s, 1, rand, x, y, z)
z = z - 1
matrix[x][y][z] = 1
moveObject ( object, s, x2, y2, z2 - 3, 0, 0, 0)elseif(move == 5)and(z ~= options.z)and(free[x][y][z+1] == 0)then
moving[rand] = 1local s = 3000 - z_speed * z
setTimer ("done", s, 1, rand, x, y, z)
z = z + 1
matrix[x][y][z] = 1
moveObject ( object, s, x2, y2, z2 + 3, 0, 0, 0)endend
Обновление показа текста
Эта функция вызывается каждую секунду и обновляет показ текста с уровнем игрока в данный момент, оставшегося числа уровней и здоровье. Наверху показа текста мы сообщаем о числе уровней в башне (1), после которого мы повторяем через каждого игрока (2) и вычисляем текущий этаж (3). Поскольку эту систему вызывают каждую секунду, мы можем также сделать здесь проверку преграды. Если игрок заденет преграду, ему покажется сообщение и убьёт игрока (4). (Номер 700 в этом коде - часть координации, которую игрок получает, когда он умер и используется здесь, чтобы сохранить некоторые расчёты), Если он мертв, внесите в список его как являющийся на недействительном уровне '-'. (5). Если он живой показывать текущий уровень (6). Редактируйте пункт показа текста, и мы готовы. (7)
Наверху башни мы поместили сюрприз. Когда игрок поднимает это (1), мы делаем уведомление, что тот игрок достиг вершины (2) и разрушаем сюрприз. (3)
addEventHandler("onPickupHit", root, "onPickupHit")function onPickupHit ( player )--Отметим 1if(getPickupType ( source ) == 2)then
outputChatBox("* " .. getClientName ( player ) .. " made it to the top!", root, 255, 100, 100)--Отметим 2
destroyElement( source )--Отметим 3endend
Когда игрок присоединяется, мы должны добавить этого игрока к показу текста, чтобы позволить игроку видеть показ текста (1). Также мы должны инициализировать его самый высокий достигнутый уровень, который является 0. (2)
Когда блок перемещается, свободное предыдущее место (1) и пометить блок как не-перемещающийся. (2)
function done ( id, x, y, z )
moving[id] = 0--Отметим 1
matrix[x][y][z] = 0--Отметим 2end
Эта функция отмечает позиции в матрице как взято согласно местоположениям игрока. Это повторяется через каждого игрока (1), вычисляет его позицию (2), выполняет граничную проверку (3) и помечает в матрице как взято (4)
function getFree ( src )local x,y,z
local players = getElementsByType("player")for k,v in players do--Отметим 1
x,y,z = getElementPosition( v )
x = math.floor(x / -4 + 0.5)--Отметим 2
y = math.floor(y / -4 + 0.5)
z = math.floor(z / 3 + 0.5)if(x >= 1)and(x <options>= 1)and(y <options>= 1) and(z <= options.z)then--Отметим 3
src[x][y][z] = 2--Отметим 4endendend
Эта функция копирует таблицы.
function copyTable ( src, des )for k,v inpairs(src)doif(type(v) == "table")then
des[k] = {}
copyTable(src[k],des[k])else
des[k] = v
endendend
На этом всё, следите за дальнейшими обновлениями на нашем сайте.