Godot概覽之角色之間的交互

上一講完成了基本項目的創(chuàng)建翎苫,這一講會帶著大家快速的實現(xiàn)角色之間的交互兔院,Godot中角色之間的交互使用信號來完成姿鸿。

一谆吴、角色之間的簡單交互

按照上一篇文章創(chuàng)建一個新的項目,添加assets和scene兩個文件夾苛预,在assets中加入一些圖片資源句狼。
首先創(chuàng)建一個新的2D場景,在2D場景中添加Sprite和一個Button热某。


添加一個信號

在Sprite中添加相應(yīng)的代碼腻菇,讓角色開始運動

extends Sprite

var flag = false

func _process(delta):
    if flag    :
        rotation += PI/2 * delta

設(shè)置了一個flag來控制角色的運動,之后需要為按鈕添加相應(yīng)的信號


添加信號

添加成功之后有如下一些顯示


信號添加成功

以上代碼代表著只要按下按鈕昔馋,之后就發(fā)_on_Button_pressed()筹吐,這個信號是傳遞給這個節(jié)點的Sprite,在這個信號里面修改了flag的值秘遏。此時只要點擊按鈕丘薛,就可以角色就開始運動了。也可以直接使用set_process方法來進行處理垄提,此時就可以不需要flag標(biāo)簽了榔袋。

extends Sprite
#var flag = false
func _process(delta):
#    if flag    :
    rotation += PI/2 * delta
func _on_Button_pressed():
#    print("ok")
#    flag = !flag
    set_process(!is_processing())

二周拐、實現(xiàn)角色之間的復(fù)雜交互

下面將會實現(xiàn)一個Tank和齒輪之間的交互铡俐,通過這個例子讓我一起來體會一下信號的特點。

  • Saw角色的創(chuàng)建
    為了進行碰撞妥粟,角色就不能僅僅只是Sprite了审丘,但是依然需要Sprite,通過Sprite可以插入Texture(圖片素材)勾给。按照流程添加角色的Scene(名稱是Saw)滩报,此時要添加碰撞檢測锅知,需要選擇Area2D。這個是帶碰撞檢測節(jié)點需要添加Sprite和CollistionShape2D并且為后者添加碰撞區(qū)域脓钾。


    添加Saw節(jié)點

為Saw添加saw.gd的腳本代碼

extends Area2D

#export導(dǎo)出的變量可以在配置項中設(shè)置
export var max_dis = 100 #最大的距離售睹,默認(rèn)是100
export var move_dir = "h" #轉(zhuǎn)動的方向是水平 v是垂直
var dis = 0 #記錄移動的距離
var dir = 1 #移動的方向

func _process(delta):
    dis += dir * 1
    if dis >= max_dis*delta or dis <= -1 * max_dis*delta:
        dir *= -1
    if move_dir == "h":
        position.x += 200 * dir * delta
    if move_dir == "v":
        position.y += 200 * dir * delta

    rotation += -PI * delta #移動的過程中不斷進行旋轉(zhuǎn)。

以上代碼中創(chuàng)建了兩個變量max_dis和move_dir可训,一個用來存儲最大的移動距離昌妹,另一個用來確定移動方向,是水平還是垂直(在后續(xù)講解完成向量之后握截,會有更好的控制方法)飞崖。這兩個變量都設(shè)置為export,這表示可以在Saw的屬性欄進行值的修改谨胞。代碼的基本思路是固歪,讓Saw不斷反復(fù)移動,如果移動距離大于max_dis或者小于-max_dis胯努,就變向牢裳,相當(dāng)于修改dir的值,在移動端過程中不斷的旋轉(zhuǎn)康聂。

  • 創(chuàng)建一個可以上下移動的角色

按照同樣一種方式創(chuàng)建一個Area2D贰健,之后添加兩個節(jié)點(Sprite和CollisionShape2D),Sprite為了加入材質(zhì)恬汁,CollisionShape2D加入碰撞檢測區(qū)域

var speed = 200

func _process(delta):
    if Input.is_action_pressed("ui_up"):
        position.y -= speed*delta
    if Input.is_action_pressed("ui_down"):
        position.y += speed*delta
    if Input.is_action_pressed("ui_left"):
        position.x -= speed*delta
    if Input.is_action_pressed("ui_right"):
        position.x += speed*delta
  • 將角色添加到舞臺

啟動游戲之后伶椿,Saw開始運行,角色也開始根據(jù)鍵盤控制進行移動氓侧,但是角色現(xiàn)在和電鋸接觸之后沒有任何反應(yīng)脊另,下一步就要添加碰撞檢測。

  • 添加碰撞檢測

只要是Area2D的角色都可以進行碰撞檢測约巷,碰撞檢測需要使用到信號(Signal)偎痛,具體的操作流程如下所示:


Saw的信號

area_entered就是我們需要使用的信號,接下來独郎,實現(xiàn)的效果是當(dāng)tank碰到saw之后踩麦,有個生命,生命會減少氓癌。所以首先為Tank增加一個life的變量谓谦。

var life = 100

此時如果把信號添加在其中的一個Saw上會有一些問題,如圖所示


為Saw添加信號

運行發(fā)現(xiàn)贪婉,只有第一個Saw節(jié)點能夠出發(fā)信號反粥。其他節(jié)點都沒有辦法觸發(fā)。這樣就需要為每個節(jié)點都添加。所以信號必須在tank上添加才顿,讓Saw節(jié)點來接收信號莫湘,此時就可以正常運行,但是代碼卻是在Saw中編寫郑气,這樣就需要在Saw中獲得Tank節(jié)點幅垮。


為Tank添加信號

具體的代碼如下所示

func _on_Tank_area_entered(area):
#    print("hit")
    var tankNode = get_node("../Tank")
#    print(tankNode.life)
    if tankNode.life >= 0:
        tankNode.life -= 10
    print(tankNode.life)

需要強調(diào)一下,此處獲取節(jié)點使用了get_node(../Tank)尾组,../表示的是上一級路徑军洼,這種方式是非常不合理的一種獲取節(jié)點方法,在實際的應(yīng)用中都不會使用演怎,但是由于本章節(jié)的內(nèi)容只是讓大家概覽一下流程匕争,所以先使用這種不合理的方案,在后續(xù)的內(nèi)容中會更新更合理的處理方案爷耀。
接下來甘桑,坦克受傷的代碼客觀來說應(yīng)該在tank中編寫更合理一些,所以可以在坦克中創(chuàng)建一個方法歹叮,injured方法跑杭。

#Tank.gd中添加代碼
func injured(lost_life):
    life -= lost_life
    if life <= 0:
        life = 0
    print(life)

改造Saw中的代碼

func _on_Tank_area_entered(area):
    var tankNode = get_node("../Tank")
#    print(tankNode.life)
#    if tankNode.life >= 0:
#        tankNode.life -= 10
#    print(tankNode.life)
    tankNode.injured(10)#讓tank損失10點生命

接著來實現(xiàn)Tank受傷之后,有一些反饋咆耿,改變一下顏色德谅。首先為tank節(jié)點添加一個動畫。


為Tank添加動畫節(jié)點

點擊 Add Track添加一個軌道萨螺,選擇Property Track窄做,選擇Sprite節(jié)點,之后添加modulate慰技,通過這個可以設(shè)置Sprite的基本屬性椭盏。之后將幀調(diào)整為0.4,意味著可以設(shè)置4幀的動畫吻商。


為modulate添加動畫的關(guān)鍵幀

modulate可以調(diào)整節(jié)點的顏色和透明度掏颊,之后添加五個關(guān)鍵幀,分別在0.1和0.3部分設(shè)置值即可艾帐。


設(shè)置關(guān)鍵幀

播放之后會發(fā)現(xiàn)tank已經(jīng)開始閃動了乌叶,之后在tank的受傷的代碼中添加這個播放效果即可。

func injured(lost_life):
    life -= lost_life
    if life <= 0:
        life = 0
#    print(life)
    get_node("AnimationPlayer").play("injured")

最后添加一個血條柒爸,血條需要使用TexureProcess節(jié)點准浴,所以先創(chuàng)建一個新的lifebar的scene,之后在assets中添加血條的圖片


添加血條節(jié)點

下一步就是當(dāng)收到傷害的時候通知血條減少值即可,此時需要創(chuàng)建一個自定義的信號來進行處理揍鸟。

signal life_change(final_life)

在Main場景中兄裂,選中Tank,之后會發(fā)現(xiàn)多了一個信號life_change阳藻,之后將Lifebar拖入到主場景中晰奖,這個信號連接到Lifebar。連接Lifebar之前需要為Lifebar增加相應(yīng)的gdscript代碼

extends TextureProgress

func _on_Tank_life_change(final_life):
    value = final_life

最后一步就是在Tank中發(fā)信號

func injured(lost_life):
    life -= lost_life
    if life <= 0:
        life = 0
#    print(life)
    get_node("AnimationPlayer").play("injured")
    emit_signal("life_change",life)#發(fā)信號life_change腥泥,傳入最終的值

實例中匾南,各個節(jié)點的代碼

#Tank
extends Area2D

var speed = 200
var life = 100

signal life_change(final_life)

func _ready():
    position.x = 500
    position.y = 200

func _process(delta):
    if Input.is_action_pressed("ui_left"):
        position.x -= speed * delta
    if Input.is_action_pressed("ui_right"):
        position.x += speed * delta
    if Input.is_action_pressed("ui_up"):
        position.y -= speed * delta
    if Input.is_action_pressed("ui_down"):
        position.y += speed * delta

func injured(lost_life):
    life -= lost_life
    if life <= 0:
        life = 0
#    print(life)
    get_node("AnimationPlayer").play("injured")
    emit_signal("life_change",life)#發(fā)信號life_change,傳入最終的值

Saw的代碼

extends Area2D

#export導(dǎo)出的變量可以在配置項中設(shè)置
export var max_dis = 100 #最大的距離蛔外,默認(rèn)是100
export var move_dir = "h" #轉(zhuǎn)動的方向是水平 v是垂直
var dis = 0 #記錄移動的距離
var dir = 1 #移動的方向

func _process(delta):
    dis += dir * 1
    if dis >= max_dis or dis <= -1 * max_dis:
        dir *= -1
    if move_dir == "h":
        position.x += 200 * dir * delta
    if move_dir == "v":
        position.y += 200 * dir * delta

    rotation += -PI * delta



func _on_Tank_area_entered(area):
#    print("hit")
    var tankNode = get_node("../Tank")
#    print(tankNode.life)
#    if tankNode.life >= 0:
#        tankNode.life -= 10
#    print(tankNode.life)
    tankNode.injured(10)#讓tank損失10點生命

Lifebar的代碼

extends TextureProgress

func _on_Tank_life_change(final_life):
    value = final_life

通過這個案例蛆楞,可以讓大家感受得到Godot編寫一個簡單游戲的流程,下一講夹厌,將會專門介紹向量數(shù)學(xué)方面的知識豹爹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市矛纹,隨后出現(xiàn)的幾起案子臂聋,更是在濱河造成了極大的恐慌,老刑警劉巖或南,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孩等,死亡現(xiàn)場離奇詭異,居然都是意外死亡采够,警方通過查閱死者的電腦和手機肄方,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹬癌,“玉大人权她,你說我怎么就攤上這事∈判剑” “怎么了伴奥?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長翼闽。 經(jīng)常有香客問我拾徙,道長,這世上最難降的妖魔是什么感局? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任尼啡,我火速辦了婚禮,結(jié)果婚禮上询微,老公的妹妹穿的比我還像新娘崖瞭。我一直安慰自己,他們只是感情好撑毛,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布书聚。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雌续。 梳的紋絲不亂的頭發(fā)上斩个,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音驯杜,去河邊找鬼受啥。 笑死,一個胖子當(dāng)著我的面吹牛鸽心,可吹牛的內(nèi)容都是我干的滚局。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼顽频,長吁一口氣:“原來是場噩夢啊……” “哼藤肢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起糯景,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤谤草,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后莺奸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丑孩,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年灭贷,在試婚紗的時候發(fā)現(xiàn)自己被綠了温学。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡甚疟,死狀恐怖仗岖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情览妖,我是刑警寧澤轧拄,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站讽膏,受9級特大地震影響檩电,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜府树,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一俐末、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奄侠,春花似錦卓箫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闷盔。三九已至,卻和暖如春旅急,著一層夾襖步出監(jiān)牢的瞬間逢勾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工坠非, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人果正。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓炎码,卻偏偏與公主長得像,于是被迫代替她去往敵國和親秋泳。 傳聞我的和親對象是個殘疾皇子潦闲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容