天天看點

[GODOT]技能系統初探

設計思路

提供一個單例腳本

SkillDatabase

,提供關于此技能的固定資料,如技能id, 技能名稱技能最大等級,技能描述,技能更新消耗等。

提供一個抽象節點,此節點用于描述一個技能,我将此節點注冊為一個GoDot新的類型,開發者通過擴充腳本功能完成技能的開發。

SkillDatabase

SkillDatabase

提供

get_skill_arg

函數來提取技能固定資料,實作如下:

#技能資料庫 用于提取技能資訊
extends Node

var skills:Dictionary = {}

func _ready():
    init_skill_dic()
    pass

func init_skill_dic() :
    #在此處初始化技能資訊, 可以從其他資料庫,excel等載體中讀取,此處為了示例直接寫在代碼裡
    #請這些技能資訊:并非完整的數值資訊和傷害邏輯
    skills = {        #id
                    "skill_0000001":{        
                    #最大等級
                    "max_leve": 20,
                    #名稱
                    "name":"普通射擊",
                    #描述 展現你的傷害邏輯
                    "desp":"對目标位置進行射擊, 造成 {base_damage} 實體傷害,如果目标處于眩暈、虛弱、減速等移動受限狀态,則傷害提高 {ext_increment}%",
                    #等級提升所需消耗 此處隻消耗一項經驗值 可以自行擴充為字典,用以消耗多個資源
                    "leve_up_cost": [10,10,10,20,20,20,30,30,50,50,100,100,100,150,150,150,200,300,400]
                },

                "skill_0000002":{
                    #最大等級
                    "max_leve": 30,
                    #名稱
                    "name":"精準射擊",
                    #描述
                    "desp":"花費時間對這一擊精心準備,短暫延遲後,對目标進行精确打擊,造成 {base_damage} + {ext_incremnt}%額外實體傷害{damage_out} 此攻擊無視目标閃避率",
                    #等級提升所需消耗 此處隻消耗一項經驗值 可以自行擴充為字典,用以消耗多個資源
                    "leve_up_cost": [10,10,10,20,20,20,30,30,50,50,100,100,100,150,150,150,200,300,400]        
                }
            }
    pass


func get_skill_arg(arg_name:String, id:String) :
    return skills[id][arg_name]
           

SkillBase

###############技能模型########################
#繼承此腳本用以建立新的技能
#需要你初始化的變量 skill_id , skill_level
#需要你重新實作的函數:
#    _replace_skill_var 
##############################################
extends Node
class_name SkillBase
###########以下成員繼承後需要子類進行初始化#################
onready var skill_id:String = "x"
onready var skill_level:int  = 0

#技能面闆上展示的技能名稱
func _get_skill_title() -> String:
    return SkillDatabase.get_skill_arg("name",skill_id) + "(LV" + String(skill_level) + ")"
    pass

#如果你的技能描述中存在變量,例如 : 造成 {base_damage} 實體傷害
#則你必須重寫此函數 将_skill_raw_desp 中的 變量 {base_damage} 替換為此技能的實際數值
#預設的實作僅僅傳回參數而不做任何事
#func _replace_skill_var(_skill_raw_desp : String) ->String:
#     return _skill_desp.format({"base_damage":20})
func _replace_skill_var(_skill_raw_desp : String) ->String:
    return _skill_raw_desp
    pass


func get_desp_string() -> String:
    var raw_desp:String =  SkillDatabase.get_skill_arg("desp", skill_id)
    return _replace_skill_var(raw_desp)
    pass


#計算技能影響乘區 請根據技能傷害邏輯在子類中實作傷害計算
func _get_skill_damage() -> float :
    return 0.0

#如果是需要選中目标的技能 則傳回最大目标數
func _get_skill_target_count() -> int :
    return 0

           

實作一個技能

建立一個節點,選擇新增的

SkillBase

節點

[GODOT]技能系統初探

更改節點名稱為

Skill_0001

(實際項目不要這樣取名字...),并選擇擴充腳本

[GODOT]技能系統初探

按照父節點要求,我們進行如下實作:

在這個腳本中,我們會實作一個簡單的技能,技能會擁有完整說明

extends SkillBase

var base_damage :=  0.0
var target_state := "眩暈"

func _ready():
    skill_id = "skill_0000001"
    skill_level = 1
    pass


#計算技能影響乘區 請根據技能傷害邏輯在子類中實作傷害計算
#"對目标位置進行射擊, 造成 {base_damage} 實體傷害,如果目标處于眩暈、虛弱、減速等移動受限狀态,則傷害提高 {ext_increment}%",
func _get_skill_damage() -> float :
    base_damage = calc_base_damage() #此處可計算其他邏輯 比如傷害加成 什麼的。。。。

    #注意 由于隻示範技能系統 是以代碼與其他系統互動存在不完善, 如此處 ["眩暈","減速","虛弱"] 僅僅是示例, 
    #應該提供一個函數傳回所有 移動受限狀态
    #且 target_state 應由戰鬥系統給出 此處僅做示例!!
    if ["眩暈","減速","虛弱"].has(target_state) :
        base_damage += base_damage * calc_ext_increment() / 100.0 
    return 0.0

#如果你的技能描述中存在變量,例如 : 造成 {base_damage} 實體傷害
#則你必須重寫此函數 将 skill_var_list 中的 變量 {base_damage} 替換為此技能的實際數值
#預設的實作僅僅傳回參數而不做任何事
#func _replace_skill_var(_skill_raw_desp : String) ->String:
#     return _skill_desp.format({"base_damage":20})
func _replace_skill_var(_skill_raw_desp : String) ->String:
    _skill_raw_desp.format({"base_damage":calc_base_damage()})
    _skill_raw_desp.format({"ext_increment":calc_ext_increment()})
    return _skill_raw_desp
    pass


#如果是需要選中目标的技能 則傳回最大目标數
func _get_skill_target_count() -> int :
    #隻示範最簡單的情況
    match skill_level :
        1,5 :
            return 1
        6,20 :
            return 2

    return 0


func calc_base_damage() -> float:
    return skill_level * 15.0
func calc_ext_increment() -> float:
    return 20.0

           

測試

在場景中添加一個Sprite并添加以下腳本進行測試

extends Sprite
onready var skill = preload("res://Scene/Skill_0001.tscn").instance()

func _ready():    
    print("sprite ready")    
    add_child(skill)
    skill.skill_level = 1

    pass

func _process(delta):
    if Input.is_action_just_pressed("ui_accept") :
        print(skill.skill_id)
        print(skill.skill_level)
        print("技能名稱: ",skill._get_skill_title())
        print("技能輸出: ",skill._get_skill_damage())
        print("技能描述: ",skill.get_desp_string())
        print("技能目标數: ", skill._get_skill_target_count())


    if Input.is_action_just_pressed("ui_page_up") :
        skill.skill_level += 1
        print("技能更新!")