10、相机系统

第10章 相机系统

10.1 Camera2D 基础

gdscript 复制代码
extends Camera2D

@onready var target: Node2D = get_parent()  # 跟随目标

func _ready() -> void:
    # 设置为当前相机
    make_current()

# 方式1:使用内置平滑(推荐,简单)
# 在检查器中设置:
#   Position Smoothing → Enabled ✅
#   Position Smoothing → Speed = 8.0
# 然后在 _physics_process 中直接设置 global_position 即可
# Camera2D 会自动平滑插值

func _physics_process(delta: float) -> void:
    # 跟随目标(配合 Position Smoothing 使用)
    global_position = target.global_position

# 方式2:手动平滑(更灵活,可以添加前瞻/偏移)
# func _physics_process(delta: float) -> void:
#     var target_pos := target.global_position
#     global_position = global_position.lerp(target_pos, 10.0 * delta)

10.2 相机边界限制

gdscript 复制代码
# 限制相机不超出关卡边界
func set_camera_limits(level_rect: Rect2) -> void:
    limit_left = int(level_rect.position.x)
    limit_top = int(level_rect.position.y)
    limit_right = int(level_rect.end.x)
    limit_bottom = int(level_rect.end.y)
    
    # 也可以从 TileMap 获取边界
    # var used_rect := tilemap.get_used_rect()
    # var cell_size := tilemap.tile_set.tile_size
    # limit_left = int(used_rect.position.x * cell_size.x)
    # ...

10.3 屏幕震动

gdscript 复制代码
extends Camera2D

@export var shake_decay: float = 5.0

var shake_intensity: float = 0.0
var shake_offset: Vector2 = Vector2.ZERO

func shake(intensity: float, duration: float = 0.2) -> void:
    shake_intensity = intensity
    var tween := create_tween()
    tween.tween_property(self, "shake_intensity", 0.0, duration)

func _process(delta: float) -> void:
    if shake_intensity > 0:
        shake_offset = Vector2(
            randf_range(-1, 1) * shake_intensity,
            randf_range(-1, 1) * shake_intensity
        )
    else:
        shake_offset = Vector2.ZERO
    
    offset = shake_offset

# 使用
# 受伤时震动
$Camera2D.shake(10.0, 0.3)
# 爆炸时强烈震动
$Camera2D.shake(20.0, 0.5)

10.4 相机 Zoom 脉冲

gdscript 复制代码
# 打击感增强:攻击时短暂放大再恢复
func zoom_pulse(intensity: float = 1.1, duration: float = 0.1) -> void:
    var tween := create_tween()
    tween.tween_property(self, "zoom", Vector2.ONE * intensity, duration * 0.3)
    tween.tween_property(self, "zoom", Vector2.ONE, duration * 0.7)

# 使用
func on_attack_hit() -> void:
    $Camera2D.zoom_pulse(1.15, 0.15)
    $Camera2D.shake(8.0, 0.1)

10.5 相机区域切换

gdscript 复制代码
# 进入房间时切换相机边界
extends Area2D

@export var camera_limits: Rect2

func _ready() -> void:
    body_entered.connect(_on_body_entered)

func _on_body_entered(body: Node2D) -> void:
    if body.is_in_group("player"):
        var camera: Camera2D = body.get_node("Camera2D")
        var tween := create_tween()
        tween.tween_property(camera, "limit_left", int(camera_limits.position.x), 0.5)
        tween.parallel().tween_property(camera, "limit_top", int(camera_limits.position.y), 0.5)
        tween.parallel().tween_property(camera, "limit_right", int(camera_limits.end.x), 0.5)
        tween.parallel().tween_property(camera, "limit_bottom", int(camera_limits.end.y), 0.5)

10.6 小地图(SubViewport 方案)

gdscript 复制代码
# 场景结构:
# SubViewportContainer
#   SubViewport
#     MiniMapCamera (Camera2D) - zoom 很大,俯瞰全局
#     MiniMapPlayerDot (ColorRect) - 玩家位置标记
#     MiniMapEnemyDot (ColorRect) - 敌人位置标记

extends SubViewportContainer

@onready var camera: Camera2D = $SubViewport/MiniMapCamera
@onready var player_dot: Control = $SubViewport/MiniMapPlayerDot

func _process(delta: float) -> void:
    # 相机跟随玩家
    camera.global_position = player.global_position
    
    # 更新玩家点位置
    player_dot.position = Vector2(50, 50)  # 小地图中心

实操练习

练习:智能相机

gdscript 复制代码
extends Camera2D

@export var target: Node2D
@export var look_ahead: float = 50.0  # 前瞻距离
@export var vertical_offset: float = -30.0  # 垂直偏移

func _process(delta: float) -> void:
    var target_pos := target.global_position
    
    # 前瞻:根据移动方向偏移
    if target is CharacterBody2D:
        var vel: Vector2 = target.velocity
        target_pos.x += vel.x * look_ahead / 300.0
    
    # 垂直偏移
    target_pos.y += vertical_offset
    
    # 平滑跟随
    global_position = global_position.lerp(target_pos, 10.0 * delta)
相关推荐
不吃凉粉1 天前
Unity与AS通信
unity·游戏引擎
两水先木示2 天前
【Unity】探索小地图迷雾散开Shader效果(基础版)
unity·游戏引擎
WarrenMondeville2 天前
AI复刻街头霸王到 Unity
unity·游戏引擎
烛阴2 天前
Godot 4 入门(03):用第一份 GDScript 驱动节点
godot
xcLeigh3 天前
Unity基础:MonoBehaviour的生命周期——Awake、OnEnable、Start、Update执行顺序
unity·游戏引擎
辻弋2013 天前
自动检测硬件生成驱动清单、实时监控FPS、120秒性能记录——30+项优化模块化开关,所有改动可精确复原
服务器·windows·游戏引擎·电脑·开源软件
点心的游戏开发世界3 天前
GDScript 入门笔记:目录
开发语言·笔记·游戏引擎·godot
想做后端的前端3 天前
Unity · 性能优化:内存管理完全指南:从托管堆到跨桥开销
unity·性能优化·游戏引擎
点心的游戏开发世界4 天前
GDScript 入门笔记(十六):文件读写与数据持久化
开发语言·笔记·游戏引擎·godot