道具 (Item)
須知
當道具被玩家取得時會依序執行以下的三個方法,其中 receiver 為道具獲得的對象,即是玩家,開發者可以透過重載這三個方法變更道具的效果
visualEffect(receiver)
這個方法負責處理道具獲得時的視覺效果,預設為彈射出 5 個星星
playGotSound(receiver)
這個方法負責處理道具獲得時的音效,預設音效為 sfx.scoreUp
mentalEffect(receiver)
這個方法負責處理實際影響玩家的效果,預設並未實作此方法
靜態屬性
透過直接指定道具的某些屬性,在道具被獲得的時候會直接影響玩家,屬性值的影響會跟著玩家,直到玩家死亡或遊戲結束,這些屬性這裡稱為道具的靜態屬性,分別為:
lifes
影響玩家的生命值,玩家的 lifes
並無設定預設上限,最低為 0
。
power
影響玩家武器的威力,玩家的 power
最低為 0
,最高為 5
shootSpeed
影響玩家的射擊速度,玩家的 shootSpeed
最低為 0
,最高為 5
score
影響得分,玩家的 score
並無預設上限,最低為 0
自訂道具
建立道具檔案
首先先建立一個道具檔案,引用 Item.lua
,並繼承它,以下是最精簡的道具範例:
local Item = require("Item")
local MyItem = {}
MyItem.new = function(options)
local item = Item.new()
return item
end
return MyItem
新增道具圖像
上述的例子中我們並沒有指定任何的圖像,所以獲得的只是一個看不見得道具,這在遊戲中是沒有用處的,所以我們用 Sprite
來建立道具的圖像與玩家互動:
local sprite = Sprite["expansion-1"].new("Items/28")
item:insert(sprite)
指定靜態屬性
靜態屬性可以快速的影響角色數值,注意數值為 差值,下述例子中指定 score
為 50
,life
為 1,代表玩家取得道具的時候,分數會加 50,生命值會增加 1,你也可以指定負值代表負面效果的道具。
item.score = 50
item.lifes = 1
開啟物理引擎
別忘記開啟物理引擎,讓道具與玩家之間可以互相碰撞:
item:enablePhysics()
角色死亡時是否掉落
你可以透過重寫 item:needKeep()
來決定道具是否要在角色死亡後掉落,回傳 false
代表不掉落,反之道具會在角色死亡後掉落:
function item:needKeep(receiver)
return false
end
如果不指定,只會在角色數值發生變化時才掉落該道具,目的是為了讓玩家撿回來,如下程式碼所示:
function item:needKeep(receiver)
local result = receiver:testUpdateAttr(self)
if result.change then
return true
end
return false
end
receiver:testUpdateAttr()
會檢查獲得道具後屬性是否發生變化。這個檢查在許多時候是必要的,例如玩家不斷的取得增加power
的道具,但由於玩家的power
有上限,多餘的道具是不需要保留的。
變化視覺效果
你可以透過覆寫 item:visualEffect
來改變獲得道具時的視覺效果,注意:由於 effect
也是顯示物件,你必須將它加入遊戲場景中,即是玩家所處的群體之中,所以下面的例子中才會使用 receiver.parent
獲得玩家所在的群體,並將特效加入其中:
function item:visualEffect(receiver)
local effect = Effect.new({time = 700})
effect.x = receiver.x
effect.y = receiver.y
if receiver.parent then
receiver.parent:insert(effect)
end
effect:start()
end
如果你想保留舊的特效,可以透過以下的技巧將舊特效暫存起來:
item.oldVisualEffect = item.visualEffect
function item:visualEffect(receiver)
item:oldVisualEffect(receiver)
local effect = Effect.new({time = 700})
effect.x = receiver.x
effect.y = receiver.y
if receiver.parent then
receiver.parent:insert(effect)
end
effect:start()
end
播放自訂音效
你可以透過覆寫 item:playGotSound
播放自訂的音效:
function item:playGotSound(receiver)
sfx:play("scoreUp")
end
直接影響玩家
透過覆寫 item:mentalEffect
可以直接改變玩家的行為,這裡是示範如何張開玩家的護盾,openShield
中的第一個參數為護盾的張開時間(毫秒)
function item:mentalEffect(receiver)
receiver:openShield(3000)
end
完整的程式碼
--levels.myLevel.MyItem.lua
local gameConfig = require("gameConfig")
local Item = require("Item")
local Effect = require("effects.PixelEffect1")
local Sprite = require("Sprite")
local sfx = require("sfx")
local MyItem = {}
MyItem.new = function(options)
local item = Item.new()
local sprite = Sprite["expansion-1"].new("Items/28")
item:insert(sprite)
item.score = 50
item.lifes = 1
item:enablePhysics()
function item:needKeep(receiver)
return false
end
function item:visualEffect(receiver)
local effect = Effect.new({time = 700})
effect.x = receiver.x
effect.y = receiver.y
if receiver.parent then
receiver.parent:insert(effect)
end
effect:start()
end
function item:playGotSound(receiver)
sfx:play("scoreUp")
end
function item:mentalEffect(receiver)
receiver:openShield(3000)
end
return item
end
return MyItem
使用道具檔案
使用自訂道具檔案的方式就與使用一般道具檔案相同,以下為關卡檔案,在其中新增一個敵人與一個道具,並在註解中介紹其他道具的使用方式:
--levels.myLevel.level_custom_item.lua
local gameConfig = require("gameConfig")
local Sublevel = require("Sublevel")
local MyItem = require("levels.myLevel.MyItem")
local LifeUp = require("items.LifeUp")
local PowerUp = require("items.PowerUp")
local ShieldUp = require("items.ShieldUp")
local SpeedUp = require("items.SpeedUp")
local MyEnemy = require("enemies.EnemyPlane")
local myLevel = Sublevel.new("9999999-057", "level name", "author name", {duration = 4000})
function myLevel:show(options)
local myEnemy = MyEnemy.new()
self:insert(myEnemy)
myEnemy.x = gameConfig.contentWidth * 0.75
myEnemy.y = -100
--move the enemy from the top to bottom with speed 100 pixels/second
myEnemy:setScaleLinearVelocity( 0, 50 )
--destroy the enemy properly
myEnemy:autoDestroyWhenInTheScreen()
--local myItem = LifeUp.new()
--local myItem = SpeedUp.new({ level = 1 })
--local myItem = PowerUp.new({ level = 1 })
--local myItem = ShieldUp.new({ level = 1 })
local myItem = MyItem.new()
self:insert(myItem)
--place the item out of the screen
myItem.x = gameConfig.contentWidth/4
myItem.y = -100
--move the item from the top to bottom with speed 100 pixels/second
myItem:setScaleLinearVelocity( 0, 50 )
--destroy the item properly
myItem:autoDestroyWhenInTheScreen()
end
return myLevel