Godot3游戲引擎入門之五:上下左右移動(dòng)動(dòng)畫(下)

godot_cover.jpg

一、前言

本篇是上一節(jié)文章:Godot3游戲引擎入門之五:上下左右移動(dòng)動(dòng)畫(上)的繼續(xù)。上一篇使用動(dòng)畫和代碼實(shí)現(xiàn)了玩家的上下左右移動(dòng)功能,接下來我們解決一個(gè)問題:給游戲添加碰撞體,讓玩家在有限的地圖中移動(dòng)。

注意:我目前使用的是 Godot 3.1 預(yù)覽版,與 Godot 3.0 正式版有一些區(qū)別,不過界面上影響不大,如果要使用我所上傳的 Github Demo 代碼,記得去官網(wǎng)下載 3.1 預(yù)覽版然后就可以正常打開運(yùn)行 Demo 了。 Good luck!

主要內(nèi)容: Godot 2D 中玩家的上下左右移動(dòng)及碰撞實(shí)現(xiàn)
閱讀時(shí)間: 4-5 分鐘
永久鏈接:http://liuqingwen.me/blog/2018/10/11/introduction-of-godot-3-part-5-the-basic-top-down-movement-part-2/
系列主頁:http://liuqingwen.me/blog/tags/Godot/

二、正文

本篇目標(biāo)

  1. 使用 AnimationPlayer 節(jié)點(diǎn)工具創(chuàng)建狀態(tài)動(dòng)畫(上)
  2. 使用代碼控制玩家的上下左右移動(dòng)功能(上)
  3. 簡(jiǎn)單的攝像機(jī)使用和地圖碰撞檢測(cè)實(shí)現(xiàn)(上下)
  4. 通過代碼實(shí)現(xiàn) RigidBody2D 剛體節(jié)點(diǎn)的運(yùn)動(dòng)(下)

場(chǎng)景和代碼

基本場(chǎng)景的制作已經(jīng)在上篇中詳細(xì)解說過了,另外我們還在場(chǎng)景中增加了一個(gè) Camera2D 攝像機(jī)節(jié)點(diǎn),讓場(chǎng)景的視窗時(shí)刻聚焦在玩家周圍,但是玩家依然可以“鯉魚躍龍門”,對(duì)場(chǎng)景中的墻壁視而不見,豪邁奔放!游戲運(yùn)行結(jié)果如下:

godot_5_result2.gif

接下來利用物理引擎相關(guān)知識(shí)解決玩家移動(dòng)范圍限制的問題。

添加碰撞體

首先要做的是給墻壁添加上碰撞體,限制場(chǎng)景運(yùn)動(dòng)區(qū)域范圍。由于墻壁是靜止不動(dòng)的物體,所以我們給它添加一個(gè) StaticBody2D 靜態(tài)碰撞體節(jié)點(diǎn)。你可以直接在 Sprite 節(jié)點(diǎn)下添加一個(gè)靜態(tài)碰撞體,并設(shè)置好碰撞體大??;也可以把 Sprite 作為 StaticBody2D 的子節(jié)點(diǎn),這也是推薦的流程。但是在沒有特殊用途下(比如不需要添加代碼等),你可以隨便安排, Godot 中的節(jié)點(diǎn)是非常靈活的。

這里為了正確設(shè)置碰撞體的形狀,我把之前單一的墻壁背景拆分為了四面獨(dú)立的墻,然后分別設(shè)置碰撞體形狀。接著要在玩家節(jié)點(diǎn)上添加碰撞體,這里我們需要謹(jǐn)慎操作:第一是注意節(jié)點(diǎn)的類型,和墻壁不同,玩家是可以移動(dòng)的,且擁有物理屬性,所以不能使用靜態(tài)碰撞體;第二是節(jié)點(diǎn)的父子關(guān)系的順序問題,我們因?yàn)橐苿?dòng)碰撞體,而不是 Sprite 精靈圖片節(jié)點(diǎn),所以 Sprite 應(yīng)該作為碰撞體節(jié)點(diǎn)的子節(jié)點(diǎn),且不能弄反!詳細(xì)解說在我的入門文章第二篇中有詳述: Godot3 游戲引擎入門之二:第一個(gè)簡(jiǎn)單的游戲場(chǎng)景。

和大名鼎鼎的 Box2D 開源物理引擎類似, Godot 中也有三種常用的物理碰撞體: StaticBody2D | RigidBody2D | KinematicBody2D ,同屬于 PhysicsBody2D 類型下,它們之間的異同點(diǎn)大致如下;

節(jié)點(diǎn)名 StaticBody2D RigidBody2D KinematicBody2D
節(jié)點(diǎn)名稱 靜態(tài)碰撞節(jié)點(diǎn)( 2D ) 剛體節(jié)點(diǎn)( 2D ) 運(yùn)動(dòng)學(xué)節(jié)點(diǎn)( 2D )
基本特性 自動(dòng)碰撞檢測(cè),位置固定不變 自動(dòng)碰撞檢測(cè),產(chǎn)生碰撞響應(yīng):有線速度、角速度等 參與碰撞檢測(cè),無自動(dòng)響應(yīng),完全由代碼控制移動(dòng)
使用場(chǎng)景 一般用于固定的墻壁、地面等 一般用于受外界影響而產(chǎn)生運(yùn)動(dòng)的物體,比如球體、隕石等 主要用于由代碼控制的帶物理屬性的玩家

了解了這三種節(jié)點(diǎn)后,得出的結(jié)論是不是應(yīng)該給我們的主角添加一個(gè) KinematicBody2D 運(yùn)行學(xué)節(jié)點(diǎn)呢?嗯……然而并不是,如果使用 KinematicBody2D 節(jié)點(diǎn),我們需要自己手動(dòng)控制物理反饋,雖然絕大多數(shù)的游戲應(yīng)該這樣,但是這不是本篇文章的做法,盡量不要?jiǎng)哟a是我的出發(fā)點(diǎn),以后再介紹 KinematicBody2D 節(jié)點(diǎn),現(xiàn)在我們暫時(shí)使用簡(jiǎn)單一點(diǎn)的 RigidBody2D 剛體節(jié)點(diǎn)進(jìn)行嘗試。(是不是聽上去有點(diǎn)不符合直覺?其實(shí)在有些游戲中,比如太空飛船射擊游戲,就可以使用 RigidBody2D 作為玩家節(jié)點(diǎn)進(jìn)行開發(fā)。)

理論到此為止,給我們的游戲場(chǎng)景添加一個(gè) RigidBody2D 剛體節(jié)點(diǎn),改名為 Player ,然后把之前的玩家 PlayerSprite )節(jié)點(diǎn)拖到 RigidBody2D 節(jié)點(diǎn)下作為其子節(jié)點(diǎn),同時(shí) AnimationPlayer 節(jié)點(diǎn)也要作為剛體節(jié)點(diǎn)的子節(jié)點(diǎn),保持和 Player 節(jié)點(diǎn)平級(jí)的關(guān)系,最后添加一個(gè) CollisionShape2D 節(jié)點(diǎn)用于設(shè)置碰撞體的形狀。

godot_5_rigidbody2d.jpg

最終場(chǎng)景中的節(jié)點(diǎn)如上圖,唯一要設(shè)置的是把 RigidBody2D 的重力影響屬性 Gravity Scale 設(shè)置為 0 ,即完全擺脫重力的影響,不這么設(shè)置的話,你會(huì)發(fā)現(xiàn)玩家會(huì)“情不自禁”地做自由落體運(yùn)動(dòng)。另外,值得注意的是,我在改名的過程中,原來的 Player 節(jié)點(diǎn)自動(dòng)更名為 Player1 ,然后動(dòng)畫全部失效,解決辦法很簡(jiǎn)單,在動(dòng)畫面板里把軌道的名字改過來即可,如下圖:

![
godot_5_change_node.jpg

最終代碼

場(chǎng)景一切就緒,接下來的任務(wù)就是修改代碼了!因?yàn)槲覀兊墓?jié)點(diǎn)關(guān)系產(chǎn)生了變化,還有節(jié)點(diǎn)的行為也變了( Sprite -> RigidBody2D ),所以對(duì)于新手朋友我要特別提醒的是:玩家已經(jīng)轉(zhuǎn)變成 RigidBody2D 剛體節(jié)點(diǎn)了,剛體節(jié)點(diǎn)是會(huì)自動(dòng)產(chǎn)生物理響應(yīng)的,所以我們不能像剛才那樣直接使用代碼操作玩家的位置,相反,我們應(yīng)該通過設(shè)置剛體的線速度、角速度來實(shí)現(xiàn)對(duì)剛體運(yùn)動(dòng)的控制!

具體修改我都在代碼中做了注釋,代碼量不大,相信大家都能看懂吧。這里全部的代碼我就不貼出來了,修改部分如下:

onready var animationPlayer = $Player/AnimationPlayer # 修改后
onready var camera = $Camera2D

player.linear_velocity = velocity # 添加部分,設(shè)置線速度,速度為0時(shí)有用
player.angular_velocity = 0 # 添加部分,設(shè)置角速度,防止player打轉(zhuǎn)
# 速度不為0,移動(dòng)玩家位置,同時(shí)更新攝像機(jī)
if velocity.length() > 0:
    # 注意這里normalize速度矢量
    # player.position += velocity.normalized() * speed * delta # 刪除
    player.linear_velocity = velocity.normalized() * speed # 添加,更新速度
    # 更新攝像機(jī),玩家始終在視窗內(nèi)活動(dòng)
    updateCameraPosition()
    # 省略代碼……

終于完工,按 F5 運(yùn)行游戲,看看我們的杰作吧:

godot_5_result3.gif

三、小結(jié)(下)

相對(duì)來說,這篇的知識(shí)點(diǎn)還是非常簡(jiǎn)單的,當(dāng)然對(duì)于編程初學(xué)者來說,代碼還是一個(gè)需要克服的地方。在接下來的文章里,我會(huì)針對(duì) 2D 游戲中的地圖創(chuàng)建做幾篇文章,也就是 TileMap 節(jié)點(diǎn)的功能介紹和使用,打造一個(gè)游戲該有的豐富世界!

最后,本篇上下節(jié)結(jié)束后,我要提醒新手朋友們幾個(gè)注意點(diǎn):

  1. 我們實(shí)際項(xiàng)目中使用 RigidBody2D 來作為玩家還是比較少的,相對(duì)多的還是 KinematicBody2D 節(jié)點(diǎn)
  2. 我們對(duì)物理碰撞的處理不應(yīng)該放在 _process(delta) 方法中,而應(yīng)該放在 _physics_process(delta) 方法中,后續(xù)再講
  3. 地圖太簡(jiǎn)單了,這也是這篇要埋下的伏筆,下篇介紹,“等著瞧”,哈哈

原創(chuàng)實(shí)屬不易,希望大家喜歡! :smile:

我的博客地址: http://liuqingwen.me ,歡迎關(guān)注我的微信公眾號(hào):

IT自學(xué)不成才

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容