Godot Engine遊戲引擎 ① 製作玩家跳躍精靈和場景——KinematicBody2D、Sprite

tyrocoder發表於2019-02-23

寫在前面:

寫文章時本人是在校大三學生,上週才接觸到Godot,也才初學三四天,如果文章有問題的話還請大佬們不吝賜教 這是第一篇教程,面向和我一樣的初學者,可能寫的有點囉嗦,請勿噴,哈哈;其中,有個單詞寫錯了,我是想寫World的結果寫成Word了,請原諒四級還沒過的我,淚目!!!前半部分圖片上的錯字就不改了,大家知道就行,哈哈哈(不失禮貌的尬笑)

最終專案成果如下:

GIF.gif

知識內容:

  • 認識godot引擎編輯器
  • 基本的場景節點新增
  • 瞭解基本的碰撞體與碰撞形狀
  • 認識KinematicBody2D 基本操作
  • 幀動畫製作與切換

製作過程:

1. 新建專案

圖片.png

  • 1.填好專案名稱、選擇好一個專案目錄
  • 2.點選“[建立|編輯]”開啟專案,專案的所有檔案都會儲存在那個專案目錄下

如果你的選單介面是英文,可以在新建專案的上方找到語言en改成zh_CN即可改成中文

2.初識編輯器佈局

圖片.png

3.新增專案資源

  • 1.在專案目錄下新建image目錄,把所有的圖片資源放到image目錄下 點我下載圖片
  • 2.可以看到資源管理皮膚新增了image目錄和目錄下的圖片,godot會預設為每一個資源新增一個同名的字尾為".import"的文字檔案
    圖片.png

4.製作World場景——背景、太陽、雲

【編輯區的滑鼠操作】:滾輪控制編輯區的放大縮小,滑鼠中鍵按下並移動滑鼠可以移動編輯區內容,滑鼠左鍵選中編輯區節點

  • 1.新增一個根節點Node2D重新命名為“World"
    • (1)在場景視窗,點選"+"號新增
      圖片.png
    • (2)在彈出的節點選中視窗中選中Node2D,點選建立
      圖片.png
      *(3)滑鼠單擊,重新命名為”world"
    1. 為world新增子節點Sprite,並重新命名為bg

Sprite表示精靈節點,可以為該節點新增一個圖片Texture資源

場景視窗中滑鼠指向world,右鍵新增子節點,在節點選擇框搜尋Sprite,選擇Sprite點選建立,就在world下面新建了一個子節點,重新命名為bg

圖片.png
圖片.png

  • 3 為bg新增圖片 場景中選中bg節點,可以看到bg的屬性值
    圖片.png
    將資源視窗中的image資料夾下bg.png檔案拖到bg的Texture屬性位置
    GIF.gif
    滑鼠選中編輯區bg移動,選中周圍的點拉大,撐滿遊戲視窗
    GIF.gif

編輯區那個紅綠線交叉點為原點,第四象限的矩形框就是遊戲視窗,在godot中,遊戲視窗的原點(0,0)在左上角,往右為x軸正方向,往下為y軸正方向

    1. 新增太陽sun節點 這裡我們採用直接把圖片拖進編輯區的方法,我們直接將sun.png圖片拖曳進編輯區,在場景視窗也對應生成一個與圖片檔案同名的Sprite節點,如圖:
      GIF.gif
    1. 參照上一個步驟,把兩片雲彩新增進來
      圖片.png

5.製作World場景——地面

因為主角需要和地面進行互動的,所以地面不能直接使用Sprite來做,我們需要用到StaticBody2D節點,然後再給StaticBody2D新增Sprite子節點來顯示圖片

  • 1.給World新增子節點StaticBody2D並重新命名為floor,並選中編輯區組合按鈕,如圖解釋
    圖片.png
    我們發現floor右邊有個黃色三角形的警告按鈕,你可以點選看看是因為什麼問題

因為我們設定的floor節點屬於StaticBody2D,表示的是一個物理靜態體,記住所有的物理靜態體在godot裡都要新增碰撞形狀子節點

    1. 先給floor新增圖片吧 之前說過Sprite節點可以新增圖片,所以這裡我們就給floor新增一個Sprite子節點,並將land.png圖片拖到texture屬性裡,將floor放到遊戲視窗底部,最後如圖顯示
      圖片.png
    1. 新增碰撞區域

在前面我們知道floor右邊的警告三角形的資訊需要新增一個形狀體,形狀體有兩種CollisionShape2D和CollisionPolygon2D,即規則形狀和多邊形形狀,

給floor新增CollisionShape2D子節點,然後選擇CollisionShape2D的Shape屬性,選擇“新建RectangleShape2D”,放大編輯區我們可以看到有一個淺藍色的矩形塊,這個矩形塊就是碰撞區域

圖片.png
選中藍色塊的邊緣兩個紅點其中一個,拖動設定藍色塊大小,
圖片.png
使其如圖所示,長度與圖片一致,寬度在垂直居中位置即可,這個藍色塊的上邊決定了待會角色站的位置
圖片.png

  • 4 同理複製貼上第二個地面,拼接好兩個地面,最終效果如圖:
    圖片.png

做了這麼久還沒有儲存過唉,記得及時儲存哦,萬一程式奔潰了呢,Ctrl+S儲存,在彈出的視窗點選儲存即可

圖片.png
然後我們可以點選右上角執行按鈕
圖片.png
, 如果彈出一個請選擇主場景點選選擇即可,然後在新視窗選中我們儲存的World.tscn檔案,點選開啟,就可以看到彈出一個遊戲視窗,就能看到我們佈置的場景啦,如圖
圖片.png

6.製作World場景 —— 椰樹、草叢

與第四步新增背景的流程是一樣的,大家自己新增(tree.png樹木, grass.png草叢),新增好之後的效果和場景節點順序如圖:

圖片

7.新增角色

我們的角色要會走,會跳,而且還會站到地面上,可以用KinematicBody2D節點來建立角色,然後新增子節點Sprite來給角色新增圖片,所以基本操作跟製作floor類似

給world新增子節點KinematicBody2D並改名“player”,選中組合按鈕防止子節點被選中,給player新增子節點Sprite(texture屬性使用stand.png圖片)和CollisionShape2D並設定碰撞區為圖片大小,移動到遊戲視窗中央,如下圖所示:

圖片.png

8.讓角色動起來——新增指令碼

godot使用內建的GDScript指令碼,是一種類似python的語言,如果你不懂GDScript但是有其他高階面嚮物件語言(Java,python,JavaScript,ruby等)基礎的話,可以參考官方文件GDScript入門 當然Godot還支援C#語言開發,你可以自己嘗試學習

    1. 給player新增指令碼,滑鼠右鍵單擊選擇新增指令碼,在彈出的視窗中選擇建立,這時編輯區會顯示指令碼編輯視窗
      圖片.png
      player.gd指令碼檔案內容如下,它繼承了KinematicBody2D這個類,所以在指令碼里面可以直接使用這個類或這個類的父類方法或屬性; 其中_ready()函式是初始化函式,_process(delta)函式是每一幀會執行一次,通俗的講就是這個函式裡的內容會隔一段時間就執行一次,delta引數是相鄰兩次執行的間隔時間
extends KinematicBody2D

# class member variables go here, for example:
# var a = 2
# var b = "textvar"

func _ready():
	# Called when the node is added to the scene for the first time.
	# Initialization here
	pass

#func _process(delta):
#	# Called every frame. Delta is time since last frame.
#	# Update game logic here.
#	pass
複製程式碼

9. 移動角色指令碼編寫

指令碼內容如下所示:

extends KinematicBody2D

var speed = 200   # 移動速度
var motion = Vector2()  # 移動向量

func _process(delta):  # 每幀執行一次
	if Input.is_action_pressed("ui_right"): # 當按下右方向鍵時
		motion.x = speed;  # 移動向量設定x正方向的向量變化值
	elif Input.is_action_pressed("ui_left"): # 當按下右方向鍵時
		motion.x = -speed; # 移動向量設定x負方向的向量變化值
	else: # 沒有按鍵按下
		motion.x = 0  # 設定x軸方向移動向量為0
	move_and_slide(motion) # 按移動向量方向移動

複製程式碼

Vector2是godot裡面的一個資料型別,表示的是二維的向量,有x和y兩個方向屬性 move_and_slide方法是KinematicBody2D物件的一個移動控制方法,第一個引數是移動向量,第二個引數是地面初始化向量,具體參考:

圖片.png

最後點選執行,按下鍵盤的左右方向鍵,有以下效果:

GIF.gif

10. 讓角色有重力效果

新增移動變數y方向加速度值,修改程式碼_process()函式內如下:

func _process(delta):  # 每幀執行一次
	motion.y += 9.8  # 新增向下的加速度
	if Input.is_action_pressed("ui_right"): # 當按下右方向鍵時
		motion.x = speed;  # 移動向量設定x正方向的向量變化值
	elif Input.is_action_pressed("ui_left"): # 當按下右方向鍵時
		motion.x = -speed; # 移動向量設定x負方向的向量變化值
	else: # 沒有按鍵按下
		motion.x = 0  # 設定x軸方向移動向量為0
	move_and_slide(motion) # 按移動向量方向移動
複製程式碼

執行後我們會看到角色先掉到地板上,然後我們可以控制角色左右移動

GIF.gif

11.讓角色跑起來

我們發現現在的角色移動起來太搞笑了,不生動對吧,那我們就讓角色加點動畫

    1. 第一步,把player的Sprite節點換成AnimatedSprite節點,在場景中選中player右鍵點選“更換型別”,在節點選擇視窗搜尋選擇AnimatedSprite
  • 2.切換成AnimatedSprite發現編輯區的角色不見了!選擇AnimatedSprite子節點,在屬性Frames選擇“新建SpriteFrames”
    圖片.png
    1. 點選Frames屬性的SpriteFrames內容,開啟動畫編輯視窗如下:
      圖片.png
    1. 重新命名幀動畫default為run,然後把幀動畫圖片新增進右邊的動畫幀,操作如下圖:
      GIF.gif
  • 5 再新增一個幀動畫stand,如圖:
    GIF.gif
  • 6 ok,動畫製作好了,我們再去修改指令碼:

因為我們是直接更新型別了,所以AnimatedSprite子節點的名字還是之前的Sprite,這裡記得修改下sprite為AnimatedSprite

圖片.png

指令碼更新如下

 func _process(delta):  # 每幀執行一次
	motion.y += 9.8
	if Input.is_action_pressed("ui_right"):
		motion.x = speed;  
		$AnimatedSprite.play("run")
	elif Input.is_action_pressed("ui_left"):
		motion.x = -speed; 
		$AnimatedSprite.play("run")
	else:
		motion.x = 0  
		$AnimatedSprite.play("stand")
	move_and_slide(motion)
複製程式碼

$childNodeName符號表示的是get_node(childNodeName),獲取子節點的節點物件,這樣就可以呼叫子節點的方法,如AnimatedSprite的play方法

GIF.gif

我們發現奇怪的一幕出現了,當角色往左行進的時候角色的朝向是右邊,因為run幀動畫的圖片都是向右的!該如何解決這個問題呢?我們可以設定AnimatedSprite的flip_h屬性為true使其發生水平映象改變

修改指令碼如下:

func _process(delta):  # 每幀執行一次
	motion.y += 9.8
	if Input.is_action_pressed("ui_right"):
		motion.x = speed;  
		$AnimatedSprite.play("run")
		$AnimatedSprite.flip_h = false
	elif Input.is_action_pressed("ui_left"):
		motion.x = -speed; 
		$AnimatedSprite.play("run")
		$AnimatedSprite.flip_h = true
	else:
		motion.x = 0  
		$AnimatedSprite.play("stand")
	move_and_slide(motion)
複製程式碼

12. 跳躍起來吧

主角現在可以正常的左右跑動了,現在我們要讓他跳起來;當然,主角必須在地面上才可以跳躍,所以不能只要按住上方向鍵就改變移動向量的y值。我們需要先判斷它是否在地板上,這個時候move_and_slide()的第二個引數就可以用啦 設定向上初識向量為 const UP = Vector2(0,-1) 修改的程式碼如下:

extends KinematicBody2D

var speed = 200   # 移動速度
var motion = Vector2()  # 移動向量
const UP = Vector2(0, -1)
const JUMP_HEIGHT = -380


func _process(delta):  # 每幀執行一次
	motion.y += 9.8
	if Input.is_action_pressed("ui_right"):
		motion.x = speed;  
		$AnimatedSprite.play("run")
		$AnimatedSprite.flip_h = false
	elif Input.is_action_pressed("ui_left"):
		motion.x = -speed; 
		$AnimatedSprite.play("run")
		$AnimatedSprite.flip_h = true
	else:
		motion.x = 0  
		$AnimatedSprite.play("stand")
	if is_on_floor():
		if Input.is_action_just_pressed("ui_up"):
			motion.y = JUMP_HEIGHT
	move_and_slide(motion, UP) # 修改了這裡
複製程式碼

當整個demo執行比較久時,發現角色跳躍後下降的速度變快了!原因就是我們的motion.y加速度一直在增加,所以為了避免這種情況,要把motion的值賦為當前motion值,修改最後一句程式碼就行

func _process(delta):
    ...
    motion = move_and_slide(motion, UP)
複製程式碼

13.最終程式碼

player.gd

extends KinematicBody2D

var speed = 200   # 移動速度
var motion = Vector2()  # 移動向量
const UP = Vector2(0, -1)
const JUMP_HEIGHT = -380


func _process(delta):  # 每幀執行一次
	motion.y += 9.8
	if Input.is_action_pressed("ui_right"):
		motion.x = speed;  
		$AnimatedSprite.play("run")
		$AnimatedSprite.flip_h = false
	elif Input.is_action_pressed("ui_left"):
		motion.x = -speed; 
		$AnimatedSprite.play("run")
		$AnimatedSprite.flip_h = true
	else:
		motion.x = 0  
		$AnimatedSprite.play("stand")
	if is_on_floor():
		if Input.is_action_just_pressed("ui_up"):
			motion.y = JUMP_HEIGHT
	motion = move_and_slide(motion,UP)

複製程式碼

14. 擴充

你也可以給雲朵新增動畫,防止角色跳出螢幕等功能,如圖

GIF.gif

寫在最後

第一次覺得寫文件好累,不過感覺還挺好,如果你喜歡就點個贊吧

相關文章