效果预览

1 开发前的准备

1 默认渲染设置

因为是像素风,需要调整默认渲染设置:Nearest

image-20240130151931835

2 运行窗口大小设置

推荐的像素游戏窗口大小: 320 x 180

image-20240130152458241

3 开发窗口大小设置

此时开发时的窗口大小,跟随着上一步;如果不单独设置,就是上一步设置的、运行窗口大小,开发的时候根本看不清,所以打开高级设置,开启窗口高度覆盖

image-20240130152949471

4 拉伸模式设置

重新运行,发现只有运行窗口变大了,图片素材还是原大小,设置拉伸模式,使图片大小自适应拉伸

image-20240130153458812

2 创建玩家

1 前言:

Godot中有3种物理物体

1 StaticBody2D

适用于无法被外力移动的 2D 物理物体。手动移动时不会影响路径上的其他物体。

2 RigidBody2D

适用于由物理仿真进行移动的 2D 物理体。

image-20240524022657563

3 CharacterBody2D

(3.x版本叫KinematicBody2D)

用作玩家节点,选用CharacterBody2D,官方给出的介绍如下:

image-20240524023042753

2 创建玩家角色

在场景下创建一个CharacterBody2D节点,作为玩家对象,并添加一个Sprite2D子节点,给一个玩家图片

image-20240524024335599

接着,自动切割,选择一张,在Player节点上开启子节点不可选择,将Player节点和图片绑定在一起,这样移动玩家图片,Player节点(父节点)也会跟着移动。

PS:使子节点无法/可以选择快捷键:CTRL + SHIFT +G,CTRL + G

image-20240524031449257

3 玩家移动脚本 Player.gd

第1版 基础移动

通过x,y坐标实现基础移动

velocity在4.x版本已经定义好了,直接用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extends CharacterBody2D

func _physics_process(delta):
if Input.is_action_pressed("ui_right"):
velocity.x = 4
elif Input.is_action_pressed("ui_left"):
velocity.x = -4
elif Input.is_action_pressed("ui_down"):
velocity.y = 4
elif Input.is_action_pressed("ui_up"):
velocity.y = -4
else:
velocity.x=0
velocity.y=0
move_and_collide(velocity) #系统方法,传入向量

第2版 向量版,支持手柄

extends CharacterBody2D

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 = input_vector
	else :
		velocity = Vector2.ZERO
	
	move_and_collide(velocity)

存在问题:斜角移动更快,移速因帧率不同的问题

第3版 解决速度受帧影响的问题

delta和physics_process

physics_process这一个回调函数是每一次物理帧时调用:固定每1/60秒调用一次

此时速度在第2版的基础上, 乘了帧,帧的单位是秒

第2版移动速度是根据delta决定的,速度是x每帧,因此会受到帧率影响;

第3版移动速度在第2版基础上乘delta,速度从x每帧变为了x每秒 (v=s*t)

然后新增MAX_SPEED,控制移动速度,解决移动速度很慢的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extends CharacterBody2D

const MAX_SPEED = 100

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")
input_vector = input_vector.normalized()

if input_vector != Vector2.ZERO:
velocity = input_vector * MAX_SPEED
else :
velocity = Vector2.ZERO

move_and_collide(velocity * delta)

第4版 引入单位向量、加速度、摩擦力、最大速度

normalized(),单位向量,返回原本向量单位化的值

limit_length(),限制最大值的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extends CharacterBody2D

const ACCELERATION = 15 * 60
const MAX_SPEED = 100
const FRICTION = 15 * 60

func _physics_process(delta):
var input_vector = velocity
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")
input_vector = input_vector.normalized()

#非零向量
if input_vector != Vector2.ZERO:
velocity = velocity.move_toward(input_vector * MAX_SPEED,ACCELERATION * delta)
#velocity += input_vector * ACCELERATION * delta
#velocity = velocity.limit_length(MAX_SPEED) #限制最大速度,* delta放在后面,否则加上上一行代码的* delta就出现2次* delta,就不准确了
else :
velocity = velocity.move_toward(Vector2.ZERO,FRICTION * delta) #摩擦力

move_and_collide(velocity * delta)

第5版 最终版

之前的逻辑在持续按住移动键时不应用摩擦力,这是因为摩擦力的减速度只在没有输入时应用。现在进行修复。

并微调,减少重复计算,使用get_axis()获取轴输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
extends CharacterBody2D

const ACCELERATION = 15 * 60
const MAX_SPEED = 100
const FRICTION = 10 * 60

var input_vector = Vector2.ZERO

func _physics_process(delta: float) -> void:

# 更新输入向量(仅当输入发生变化时才重新计算归一化)
input_vector.x=Input.get_axis("ui_left", "ui_right")
input_vector.y=Input.get_axis("ui_up", "ui_down")
if input_vector.length() > 0.01: # 防止除以零
input_vector = input_vector.normalized()

#非零向量
if input_vector != Vector2.ZERO:
velocity = velocity.move_toward(input_vector * MAX_SPEED,ACCELERATION * delta - FRICTION * delta)
else :
velocity = velocity.move_toward(Vector2.ZERO,FRICTION * delta) #摩擦力

move_and_collide(velocity * delta)


完成