HOME / 第 7 部分 · 完整游戏项目实战 / 第 90 课
MODULE 7 · 完整游戏项目实战
第 90 课 · 2D RPG 实战(一):角色与地图
🎯 本课学习目标
- 设计 RPG 游戏框架
- 实现大地图与相机
- 实现角色移动与动画
RPG 三课之第一课:大地图、可移动主角、相机跟随。
📖 详细教学步骤
RPG 设计设计
- 玩家:在村庄/地图自由移动
- NPC:对话触发剧情/任务
- 物品:宝箱、商店
- 战斗:简单回合制或接触战斗
- 本课:地图与移动
大地图搭建
- 用 TileMap 铺一块大区域(草地、道路、水、建筑)
- 地图尺寸如 40×30 瓦片(每瓦片 16px = 640×480 逻辑)
- 用第 23 课 Camera2D 跟随 + Limit 边界
- 注意:TileMap 的地形瓦片要有物理碰撞(第 29 课)
角色(四方向)搭建
RPG 角色四方向行走,用 AnimatedSprite2D:
- 动画:walk_down / walk_up / walk_left / walk_right + idle 对应方向
- AnimatedSprite2D 动画命名带方向
- 移动时切对应方向动画
四方向移动代码代码
核心:
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)
测试测试
- F5 运行:四方向移动、动画切换、碰撞阻挡
- 相机跟随、地图边界正确
- 调移动速度与动画手感
🎉 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 遮挡排序。