Defold公式にあるwar-battles でDefoldの基本的な使い方を学習してみます。
タイルパレットから配置したい地面を選択し、タイルマップに塗りマップを作成します。
タイルマップ上で、Shift + マウスドラッグすることでタイルマップの範囲コピーが可能なので、よく似たマップは便利な機能を使ってサクサク作りましょう。
からっぽのAtlasが作成されたので、中身を埋めていきます。
これで、シーンにプレイヤーが配置されました。
プレイヤーキャラがマップより後ろの表示されてしまう場合
function init(self)
msg.post(".", "acquire_input_focus")
self.moving = false
self.input = vmath.vector3()
self.dir = vmath.vector3(0, 1, 0)
self.speed = 50
end
function final(self)
msg.post(".", "release_input_focus")
end
function update(self, dt)
if self.moving then
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
end
self.input.x = 0
self.input.y = 0
self.moving = false
end
function on_message(self, message_id, message, sender)
end
function on_input(self, action_id, action)
if action_id == hash("up") then
self.input.y = 1
elseif action_id == hash("down") then
self.input.y = -1
elseif action_id == hash("left") then
self.input.x = -1
elseif action_id == hash("right") then
self.input.x = 1
end
if vmath.length(self.input) > 0 then
self.moving = true
self.dir = vmath.normalize(self.input)
end
end
function on_reload(self)
end
function init(self)
msg.post(".", "acquire_input_focus")
self.moving = false
self.firing = false -- add
self.input = vmath.vector3()
self.dir = vmath.vector3(0, 1, 0)
self.speed = 50
end
function update(self, dt)
if self.moving then
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
end
-- add
if self.firing then
local angle = math.atan2(self.dir.y, self.dir.x)
local rot = vmath.quat_rotation_z(angle)
local props = { dir = self.dir }
factory.create("#rocketfactory", nil, rot, props)
end
self.input.x = 0
self.input.y = 0
self.moving = false
self.firing = false -- add
end
function on_input(self, action_id, action)
if action_id == hash("up") then
self.input.y = 1
elseif action_id == hash("down") then
self.input.y = -1
elseif action_id == hash("left") then
self.input.x = -1
elseif action_id == hash("right") then
self.input.x = 1
-- add
elseif action_id == hash("fire") and action.pressed then
self.firing = true
end
if vmath.length(self.input) > 0 then
self.moving = true
self.dir = vmath.normalize(self.input)
end
end
add と書かれた部分のコードを追加します。
fire キーが押された時に、rocketfactory を生成するスクリプトになっています。
go.property("dir", vmath.vector3())
function init(self)
self.speed = 200
end
function final(self)
end
function update(self, dt)
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
end
function on_message(self, message_id, message, sender)
end
function on_input(self, action_id, action)
end
function on_reload(self)
end
dir プロパティを追加。initでロケットの速度を初期化し、updateで移動処理を実装しています。
function init(self)
self.speed = 200
self.life = 1 -- 追加。
end
function update(self, dt)
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
self.life = self.life - dt
-- 追加
if self.life < 0 then
self.life = 1000
go.set_rotation(vmath.quat())
self.speed = 0
msg.post("#sprite", "play_animation", { id = hash("explosion") })
end
end
実行するとロケットが飛んで1秒後に爆発エフェクトが再生されます。 しかしこのままでは爆発エフェクトのゴミが残ってしまいます。エフェクトのゲームオブジェクトが削除される様に修正します。
function on_message(self, message_id, message, sender)
if message_id == hash("animation_done") then
go.delete()
end
end
onmessage にスクリプトを追加します。hash値でチェックしている“animationdone” は“playanimation”が呼ばれたたあと送られてくるゲームエンジンのに内包されているメッセージです。この場合、“playanimation”でのSpriteアニメーションの再生が完了時に“animation_done”が呼ばれる形になっています。その時go.delete()関数でゲームオブジェクトを削除します。こうすることで、爆発アニメーションが終了したあと、rocketゲームオブジェクトが削除されます。
– 関数化。爆発アニメーションの再生。
local function explode(self)
self.life = 1000
go.set_rotation(vmath.quat())
self.speed = 0
msg.post("#sprite", "play_animation", { id = hash("explosion") })
end
function update(self, dt)
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
self.life = self.life - dt
if self.life < 0 then
explode(self)
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("animation_done") then
go.delete()
-- Add
elseif message_id == hash("collision_response") then
explode(self)
go.delete(message.other_id)
end
end
爆発アニメーションをexplode 関数にまとめました。onmessage 関数で“collisionresponse”が送られてきた時に、explode で爆発アニメーションを再生し、対象のGameObjectを削除しています。実行するとロケットが戦車に当たると爆発アニメーションと共に消える様になっています。
スコアの表示や、クリア用のUIを作ります。
画面にスコアが表示されました。次はスコアを加算していくためのスクリプトを書いていきます。
function init(self)
-- score の変数を定義し0で初期化します。
self.score = 0
end
function on_message(self, message_id, message, sender)
-- "add_score"メッセージが返された時に
if message_id == hash("add_score") then
-- scoreを加算する。
self.score = self.score + message.score
-- score ノードを取得して、テキストを更新します。
local scorenode = gui.get_node("score")
gui.set_text(scorenode, "SCORE: " .. self.score)
end
end
elseif messageid == hash(“collisionresponse”) then
explode(self)
go.delete(message.otherid)
– スコアを100点追加。
msg.post(”/gui#ui“, “addscore”, {score = 100})
end
end
</code>
これでロケットで戦車を倒すとスコアが100点加算される様になります。