道具 (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)

指定靜態屬性

靜態屬性可以快速的影響角色數值,注意數值為 差值,下述例子中指定 score50life 為 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

results matching ""

    No results matching ""