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点加算される様になります。