学习笔记并不需要开头语!

1·创建角色(player)

新建好以2D节点为根节点的场景后,点击选中根节点(名字默认为Node2D,但是我将它改成了world)然后点击左上方的加号创建一个新节点,此节点名为:KinematicBody2D,如下图:


创建完成后,它会在world根节点的节点树下,如果它没有在节点树下,记得把它拽进来!之后我们将它改名为player,以此表示它是我们玩家可以控制的角色。

(这里的截图示例是取自我之前写好的项目,所以与下面会有些不一样xD)


将分支保存为场景!

此外,因为Godot的每一个场景(我们称为Level)都会让你重新创建节点,为了方便后续的开发,我们可以将这个player保存为一个场景,在我们之后创建新的场景的时候,可以直接将这个名为player的场景拖入新场景,这样一来就很迅猛,很快捷力!

如下图,我们右键这个player,点击 将分支保存为场景

之后会创建以这个 Player 为根节点的新场景,同时,在刚刚的world场景里, Player 节点的后面多出来了一个像拍电影时的打板机一样的图标,以表示此分支节点现在其实是一个场景了!


现在我们点击这个打板机一样的图标,进入这个player场景

现在,我们在这个player场景内,为它新建一个名为sprite的节点


现在选中这个sprite节点,可以看见右侧出现了它的属性面板,并且可以看见Texture现在是空的!这表示,它没有任何贴图,这样一来,我们的player没有任何可以见人的模样,它就是一个完全隐身的个体xD,接下来我们要给他添加贴图的话,就需要从左下角的资源库内拖动用作贴图的文件岛Texture旁的空槽里。

贴图导入后就会像这个样子,一般我们的像素游戏的贴图,是会逐帧排列绘画的,所以我们需要把贴图设置一下让它只显示一帧的图片。

sprite的属性栏里,有一栏名为Animation的属性,点开后现点击Hframes行右侧的箭头上,增加这个数字,此时我们的贴图文件会越来越小,最后只显示一帧的图像,这个数字并不固定,视贴图文件的帧数而定。

现在要注意一点是,我们在添加完贴图后,拖动角色时,其实只是在拖动我们的sprite节点,而player节点其实并没有移动,可以视为贴图动了,真正的角色却没动qwq!(皮套跑了)

现在我们要做一个调整,让playersprite一起动。选中player节点,然后点击编辑器上部的 确保对象的子项不可选择 ,将此功能开启。

这时候我们就可以将角色拖着到处跑啦!


2.让角色动起来!

现在我们的Player已经有脸见人力!但是它还是一个残疾人,不能走来走去。

此时我们点击选中Player,再点选场景框右上角的添加脚本按钮,或右键player,然后选择添加脚本

这时候会弹出一个框,事我们这个新脚本的设定,Godot自带的GDScript非常强大,所以我们语言选择GDScript,并为它选择一个保存路径,因为这事player节点的脚本,所以我们把它放进资源库/Player/文件夹里。


extends KinematicBody2D


# Declare member variables here. Examples:
# var a = 2
# var b = "text"


# Called when the node enters the scene tree for the first time.
func _ready():
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#	pass

有很多种代码可以让我们的角色开始移动,但是我学会了一种最方便的!

创建完脚本后,我们可以看见很多用 # 号写下来的注释,我们可以把它们都删掉,或者留着自己慢慢看xD

第一行的extends KinematicBody2D表示此脚本是拓展自 KinematicBody2D 节点的。

此时我们写下这样的代码,为我们的角色赋予上下左右行走的权力!

extends KinematicBody2D

var velocity = Vector2.ZERO

func _physics_process(delta):
	var input_vector =Vector2.ZERO
	input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
	input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")

注意,从var input*****开始后,它们是有缩进的!表示这些代码都是在func _physics_process(delta): 下运行的!

解释:

Vector2.ZERO

在上面代码中,我定义了一个名为 velocity 的变量,赋值为Vector2.ZERO

var velocity = Vector2.ZERO

在这里,Vector2是一个“二维数学的向量”

ZERO则是它的一个常量,它将Vector2定义为 ( 0, 0 ) ,它表示零向量,它将所有分量都设置为0的向量。也就是说,接下来我们做的任何向量都是从坐标轴的 ( 0, 0 ) 开始的。


func _physics_process(delta):

它在官方手册里的解释是:这允许有一个默认的物理进程(delta)实现,其中速度用于移动玩家(player)。作为可以修改玩家移动的方式是使用基类中定义的速度变量的方式。

我的简单理解则是,我们实现一个物理进程运行,这时候我们的Player接下来的速度运算都是相对于这个delta进程的,也就是说我们用这样的方式,来定义一个基本的移动速度。

需要注意的是,delta值会因为游戏卡顿(掉帧)而变化!比如此时你的游戏卡顿至30帧,那么我们的delta值会变成1/30,这样一来速度会比原本的1/60更快。


var input_vector =Vector2.ZERO

这串代码则是定义一个变量,赋值为 Vector2.ZERO


input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")

这串代码的意思则是,我们首先使用 Input.get_action_strength 代码,来返回一个介于0和1之间的值,该值表示给定操作的强度。例如,在使用手柄中,摇杆离原点越远,该值就越接近1。如果操作映射到键盘上的时候,则返回的值将为0或1。

后面的"ui_right" "ui_left"等都是规定我们这个返回值是从方向键右或左中获取的。

此时我们将两值相减:

 Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")

最后的出的值则是我们的角色的X轴移动速度了。

下方的input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up") 同理


二次定义速度!

现在我们需要为其再添加几个速度定义,分别是:

  • 加速度
  • 最高速度
  • 摩擦力

我们在extends KinematicBody2D代码下添加以下代码

const ACCELERATION = 500
const MAX_SPEED = 80
const FRICTION = 500

在这串代码里,我们将加速度定为500,最高速度定为80,摩擦力定为500

这样定义是最符合我的游戏移动速度的,当然我们也可以修改这些值,以达到我们想要的目的。

现在我们添加以下代码到我们已经写好的移动代码最下方,同样的它也有缩进。

	if input_vector != Vector2.ZERO:
		velocity = velocity.move_toward(input_vector * MAX_SPEED , ACCELERATION * delta)
	else:
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)

	move_and_slide(velocity)

解释:

if input_vector != Vector2.ZERO:

这事一个if语句,与下面的else一起使用,表示:如果我们之前定义的 input_vector 不等于 Vector2.ZERO 了,就执行下面的代码。


velocity = velocity.move_toward(input_vector * MAX_SPEED , ACCELERATION * delta)

接上,就把velocity这个变量赋值为这些东西:在这里面,move_toward() 是一个用于施加摩擦力的函数,然后这个函数的计算方式则是:输入值 * 最大速度 , 加速度 * delta,最后得出一个坐标值作为速度。

下方else则同理,在(Vector2.ZERO, FRICTION * delta)中,用Vector2.ZERO作为坐标值的0,再用 摩擦力*delta 得出另一个坐标值,最后得出一个速度,以实现玩家停止移动操作的时候有一定的惯性移动后停下来。


move_and_slide(velocity)

这个函数在手册里的解释是:沿向量移动实体。如果一个物体与另一个物体相撞,它将沿着另一个物体滑动而不是立即停止。如果另一个物体是运动体或刚体,它也会受到另一个物体的运动的影响。您可以使用它来移动或旋转平台,或使节点推动其他节点。

简单来说这个的用法就是让我们的角色移动更加自然。


3.结束!

以下则是整个脚本的代码展示~!

extends KinematicBody2D

const ACCELERATION = 500
const MAX_SPEED = 80
const FRICTION = 500

var velocity = Vector2.ZERO

func _physics_process(delta):
	var input_vector =Vector2.ZERO
	input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
	input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")

	if input_vector != Vector2.ZERO:
		velocity = velocity.move_toward(input_vector * MAX_SPEED , ACCELERATION * delta)
	else:
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
		
	move_and_slide(velocity)

至此,我们的移动脚本已经写完了,现在角色可以非常自然的上下左右移动,但是因为我们没有赋予它各个方向移动的动画,所以角色是呆呆的站在那滑动而已,在之后我会写赋予移动动画的笔记。

这是 学习笔记-Godot 系列文章中的第 1 篇,共 1 篇

  • 学习笔记-Godot中的角色与移动


收集一些有趣的小玩意,以及一些笔记