HOME / 第 7 部分 · 完整游戏项目实战 / 第 90 课
MODULE 7 · 完整游戏项目实战

第 90 课 · 2D RPG 实战(一):角色与地图

⏱ 预计时长 50 分钟📊 难度 进阶📚 模块 第 7 部分 · 完整游戏项目实战

🎯 本课学习目标

RPG 三课之第一课:大地图、可移动主角、相机跟随。

📖 详细教学步骤

RPG 设计设计

  • 玩家:在村庄/地图自由移动
  • NPC:对话触发剧情/任务
  • 物品:宝箱、商店
  • 战斗:简单回合制或接触战斗
  • 本课:地图与移动

大地图搭建

  1. 用 TileMap 铺一块大区域(草地、道路、水、建筑)
  2. 地图尺寸如 40×30 瓦片(每瓦片 16px = 640×480 逻辑)
  3. 用第 23 课 Camera2D 跟随 + Limit 边界
  4. 注意:TileMap 的地形瓦片要有物理碰撞(第 29 课)

角色(四方向)搭建

RPG 角色四方向行走,用 AnimatedSprite2D:

  1. 动画:walk_down / walk_up / walk_left / walk_right + idle 对应方向
  2. AnimatedSprite2D 动画命名带方向
  3. 移动时切对应方向动画

四方向移动代码代码

核心:

GDSCRIPTextends CharacterBody2D

@export var speed: float = 120.0
@onready var anim: AnimatedSprite2D = $AnimatedSprite2D

var last_dir: String = "down"

func _physics_process(delta):
    var dir = Input.get_vector("move_left", "move_right", "move_up", "move_down")
    velocity = dir * speed
    move_and_slide()
    if dir != Vector2.ZERO:
        play_walk(dir)
    else:
        anim.play("idle_" + last_dir)

func play_walk(dir: Vector2):
    if abs(dir.x) > abs(dir.y):
        last_dir = "left" if dir.x < 0 else "right"
    else:
        last_dir = "up" if dir.y < 0 else "down"
    anim.play("walk_" + last_dir)

碰撞与地形实操

  • 地形碰撞:TileMap 瓦片加物理(第 29 课)
  • 水面阻挡:给水瓦片加碰撞
  • 用 Z 排序让角色「走到树后面」(Y 越大越靠前):
GDSCRIPTfunc _process(delta):
    # 伪 3D 遮挡:Y 越大画得越靠前(z_index 越大越靠上)
    z_index = int(global_position.y)

测试测试

  1. F5 运行:四方向移动、动画切换、碰撞阻挡
  2. 相机跟随、地图边界正确
  3. 调移动速度与动画手感

🎉 RPG 移动骨架完成!

⚠️
动画方向错?

判断主方向用 abs(dir.x) > abs(dir.y),别用简单的 if dir.x>0 优先。

⚠️
走到树后面没遮挡效果?

用 z_index = int(global_position.y) 实现遮挡排序(越高越靠前)。

🧪 动手试一试

🏋️ 课后练习

给地图加:一片水(阻挡)+ 一棵树(遮挡排序正确)+ 一条道路,让角色在地图里穿行。

TileMap 瓦片碰撞 + z_index 排序。

💡

RPG 动画集按方向命名(walk_up/walk_down/walk_left/walk_right)是惯例。

💡

Y 排序遮挡是 2D RPG 的必备技巧。

🎓 本课小结

RPG 基础:TileMap 大地图 + 相机跟随 + 四方向角色移动动画 + 碰撞阻挡 + z_index 伪 3D 遮挡排序。