1、创建游戏

创建项目

2、创建 Player

先创建 Area2D 节点作为场景的根节点 然后再创建两个子节点

image.png

AnimatedSprite2D 节点用作显示动画效果的角色节点,我们添加对应状态的动画帧

image.png

使用资源的动画帧拖入分组为 up 和 walk,这代表两个状态,每个状态两帧

image.png

然后,CollisionShape2D 节点为动画节点套上碰撞体,选择胶囊体

image.png

通过拖拽,把动画节点包裹住

screen008.gif

3、编写 Player 脚本

选择 Player 节点,为其添加脚本

image.png

使用默认

image.png

编写脚本

extends Area2D

@export var speed = 400
var screen_size

使用 @export 标注的变量可以在检查器中进行编辑,编辑器中如果赋值会覆盖脚本的值

func _ready():
	screen_size = get_viewport_rect().size

节点进入场景树的时候,_ready() 函数会被调用,此时我们查看游戏窗口大小

接下来使用 _process() 函数定义玩家的行为,_process() 函数每一帧都会被调用,可以用来更新我们希望经常变化的游戏元素,通常执行如下操作:

  • 检查输入
  • 沿给定方向移动
  • 播放合适的动画

输入动作在项目设置中的“输入映射”下定义,先输入一个动作 move_right,并进行添加

image.png

然后为这个动作分配按键

image.png

在事件那边按键盘上的方向键,会监听,选中后确定

image.png

此时,完成按键和动作的绑定

image.png

继续补充剩余几个方向的内容

image.png

继续,回到脚本,使用 Input.is_action_pressed() 检测是否按下了某个按键,按下会返回 true,否则返回 false

func _process(delta: float) -> void:
	var velocity = Vector2.ZERO
	if Input.is_action_pressed("move_right"):
		velocity.x += 1
	if Input.is_action_pressed("move_left"):
		velocity.x -= 1
	if Input.is_action_pressed("move_down"):
		velocity.y += 1
	if Input.is_action_pressed("move_up"):
		velocity.y -= 1
	
	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()

Vector2.ZERO 对应的是(0,0)向量,因为默认情况下玩家不移动 然后根据 if 分支去每帧检验用户的输入,这里根据方向分为 xy 两个维度,如果同时按右和下,则对应(1,1)向量,表示右下

此时斜向移动速度会快于水平,因此需要进行归一化处理,即将速度长度设置为 1,再乘上想要的速度(对应方向的单位向量)

$get_node() 的简写,$AnimatedSprite2D.play() 等同于 get_node("AnimatedSprite2D").play()

根据 velocity.length() 判断角色是否需要移动,如果需要就 play(),不需要就 stop()

现在有了运动方向,接下来需要更新玩家的位置 clamp() 一个值意味着将其限制在给定范围内,此时,角色是可以移动的

position += velocity * delta   # 每一帧时间以固定速度移动
position = position.clamp(Vector2.ZERO, screen_size)   # (0,0) 到屏幕右下角

screen009.gif

_process()delta 参数是帧长度,即完成上一帧所花费的时间,使用这个保证移动不会被帧率变化影响

3.1、选择动画

现在在角色可以动的基础上为其提供正确的动画

3.2、准备碰撞

4、创建敌人

5、游戏主场景

6、游戏信息显示