Defold. Игровые объекты.

Defold. Игровые объекты.

Как добавить игровые объекты в Defold Game Engine.

В прошлом уроке мы добавили персонажа и научили его двигаться по земле и прыгать. В этом уроке мы добавим несколько игровых объектов (препятствий) и добавим анимацию смерти.

Создание объектов.

Откроем наш проект и немного приберемся, добавим папку Level и перенесем туда наши файлы ground.collection, ground.script, level.collection, controller.script. Добавим в эту папку еще одну папку images, для хранения изображений игровых объектов.

level

В папку images добавим изображение  rock_planks.PNG, все из того же архива из первого урока.

Добавим в папку level новый объект level.atlas и в окне Outline добавим это изображение Add image

levelatlas

В папку Level добавим Game Object file platform.go

platform

В сцене platform.go в окне Outline добавим sprite Add component

В окне Properties, в строке Images выберем level.atlas и в строке Defauit Animation выберем rock_planks

spriteplatform

Далее добавим компонент коллизии Collision Object и Add Shape — Box и изменим Type в окне Properties на kinematic. В строках Group и Mask пишем geometry и hero соответственно, для того, чтобы наш персонаж мог взаимодействовать с этим объектом.

platforcollision

Можете продублировать компонент sprite и настроить размеры Box Shape в окне Properties, подстроив под изображение платформ.

platformbox

Добавим в папку Level новый скрипт platform.script и напишем в нем такой код:

function init(self)
self.speed = 9      -- Default speed
end
 
function update(self, dt)
local pos = go.get_position()
if pos.x < -500 then
go.delete()
end
pos.x = pos.x - self.speed
go.set_position(pos)
end
 
function on_message(self, message_id, message, sender)
if message_id == hash("set_speed") then
self.speed = message.speed
end
end

В этом скрипте указывается скорость движения платформы и удаление платформы при достижении определенной позиции.

В platform.go к Game object в окне Outline добавим этот скрипт Add Component From File

В папке Level продублируйте platform.go и назовите platform_long.go и измените его (например, добавив или удалив платформы, изменяя при этом размеры box share)  и не забывая все сохранять.

platform_long

Появление платформ на сцене.

Для рандомного появления платформ на сцене откройте level.collection и в окне Outline к компоненту Controller добавьте Factory Add component

factory

В строке Protorype в окне Properties добавьте нашу платформу

factoryadd

Продублируйте компонент factory и измените Prototype на другую платформу.

В обоих Factory измените Id на platform_factory и platform_long_factory.

Откроем скрипт controller и изменим его, для того чтобы наши платформы появлялись

go.property("speed", 6)
local grid = 460
local platform_heights = { 100, 200, 350 }
function init(self)
msg.post("ground/controller#script", "set_speed", { speed = self.speed })
self.gridw = 0
end function update(self, dt)
self.gridw = self.gridw + self.speed
if self.gridw >= grid then
self.gridw = 0
-- Maybe spawn a platform at random height
if math.random() > 0.2 then
local h = platform_heights[math.random(#platform_heights)]
local f = "#platform_factory"
if math.random() > 0.5 then
f = "#platform_long_factory"
end
local p = factory.create(f, vmath.vector3(1600, h, 0), nil, {}, 0.6)
msg.post(p, "set_speed", { speed = self.speed })
end
end
end

Сохраняем все и проверяем игру

platformbuild

Анимация смерти.

Теперь нам необходимо создать анимацию смерти при всех возможных факторах, например: столкновение с препятствием (с шипами на платформе).

Откроем скрипт hero и изменим его, перед функцией Update добавим

local function play_animation(self, anim)
-- only play animations which are not already playing
if self.anim ~= anim then
-- tell the spine model to play the animation
spine.play("#spinemodel", anim, go.PLAYBACK_LOOP_FORWARD, 0.15)
-- remember which animation is playing
self.anim = anim
end
end

local function update_animation(self)
-- make sure the right animation is playing
if self.ground_contact then
play_animation(self, hash("run_right"))
else
if self.velocity.y > 0 then
play_animation(self, hash("jump_right"))
else
play_animation(self, hash("fall_right"))       
 end   
 end
end

и в самой функции Update после

go.set_position(go.get_position() + self.velocity * dt)

добавим

update_animation(self)

В папку level/image добавим изображение spikes.png.

Откроем Level.atlas и добавим туда это изображение

spikesadd

Откроем platform.go и добавим еще один спрайт. В строке image окна Properties выберете level.atlas и в Defauit Animation выбрать наши шипы

Добавим еще один компонент collision для шипов и разместим его в нижней части платформы, Box shape самой платформы разместите в верхней части платформы и разместите шипы по бокам и по низу, дублируя sprite и изменяя их позицию в окне Properties.

В компоненте коллизинон (danger_spike) измените Type на kinematic, Group на danger и Mask hero

platform_longsnape

Откройте hero.go и добавьте в окне Outline к Colisionobject еще mask danger

dangeraddcollision

Откройте hero скрипт и измените функцию on_message()

function on_message(self, message_id, message, sender)
if message_id == hash("reset") then
self.velocity = vmath.vector3(0, 0, 0)
self.correction = vmath.vector3()
self.ground_contact = false
self.anim = nil
go.set(".", "euler.z", 0)
go.set_position(self.position)
msg.post("#collisionobject", "enable")
elseif message_id == hash("contact_point_response") then
-- check if we received a contact point message
if message.group == hash("danger") then
-- Die and restart
play_animation(self, hash("die_right"))
msg.post("#collisionobject", "disable")
go.animate(".", "euler.z", go.PLAYBACK_ONCE_FORWARD, 160, go.EASING_LINEAR, 0.7) 
go.animate(".", "position.y", go.PLAYBACK_ONCE_FORWARD, go.get_position().y - 200, go.EASING_INSINE, 0.5, 0.2,
function()
msg.post("#", "reset")
end)
elseif message.group == hash("geometry") then
handle_geometry_contact(self, message.normal, message.distance)
end
end
end

и функцию init()

function init(self)
-- this lets us handle input in this script
msg.post(".", "acquire_input_focus")
-- save position
self.position = go.get_position()
msg.post("#", "reset")
end

Можете запустить игру и проверить, наш персонаж при столкновении с шипами будет умирать, и появляться в том же месте.

Теперь давайте сделаем сброс уровня при смерти персонажа.

Откроем скрипт controller и изменим его

go.property("speed", 6)
local grid = 460
local platform_heights = { 100, 200, 350 }
function init(self)
msg.post("ground/controller#script", "set_speed", { speed = self.speed })
self.gridw = 0
self.spawns = {}
end
function update(self, dt)
self.gridw = self.gridw + self.speed
if self.gridw >= grid then
self.gridw = 0
-- Maybe spawn a platform at random height
if math.random() > 0.2 then
local h = platform_heights[math.random(#platform_heights)]
local f = "#platform_factory"
if math.random() > 0.5 then
f = "#platform_long_factory"
end
local p = factory.create(f, vmath.vector3(1600, h, 0), nil, {}, 0.6)
msg.post(p, "set_speed", { speed = self.speed })
table.insert(self.spawns, p)
end
end
end

function on_message(self, message_id, message, sender)
if message_id == hash("reset") then
-- Tell the hero to reset.
msg.post("hero#script", "reset")
-- Delete all platforms
for i,p in ipairs(self.spawns) do
go.delete(p)
end
self.spawns = {}
elseif message_id == hash("delete_spawn") then
for i,p in ipairs(self.spawns) do
if p == message.id then
table.remove(self.spawns, i)
go.delete(p)
end
end
end
end

Теперь, при смерти будут удалятся все платформы со сцены и игра будет начинаться заново.

Откроем срипт platform и изменим строку

go.delete()

на

msg.post("/level/controller#script", "delete_spawn", { id = go.get_id() })

И в скрипте hero изменим

go.animate(".", "position.y", go.PLAYBACK_ONCE_FORWARD, go.get_position().y - 200, go.EASING_INSINE, 0.5, 0.2,
function()
msg.post("#", "reset")
end)

на

go.animate(".", "position.y", go.PLAYBACK_ONCE_FORWARD, go.get_position().y - 200, go.EASING_INSINE, 0.5, 0.2,
function()
msg.post("controller#script", "reset")
end)

На этом данный урок завершен, можете запустить игру на данной стадии и протестировать. В следующем мы добавим монеты и научим нашего персонажа их собирать. Удачных проектов!

На главную


Оставить Комментарий