Agent Skills: Godot 2D相机系统专家技能

Godot 2D相机系统专家,专门处理多角色相机管理、视野控制、平滑跟随和动态视角系统

UncategorizedID: hhhh124hhhh/godot-mcp/godot-camera-system

Install this agent skill to your local

pnpm dlx add-skill https://github.com/hhhh124hhhh/godot-mcp/tree/HEAD/.claude/skills/godot-skills/sub-skills/godot-camera-system

Skill Files

Browse the full folder contents for godot-camera-system.

Download Skill

Loading file tree…

.claude/skills/godot-skills/sub-skills/godot-camera-system/SKILL.md

Skill Metadata

Name
godot-camera-system
Description
Godot 2D相机系统专家,专门处理多角色相机管理、视野控制、平滑跟随和动态视角系统

Godot 2D相机系统专家技能

重要提示: 本技能专门解决Godot 2D游戏中的相机配置和角色显示问题,基于 Godot 4.5 最佳实践。 特别适用于格斗游戏、平台游戏、多人游戏等需要复杂相机管理的场景。

技能概述

godot-camera-system 是专门用于Godot 2D游戏相机系统配置和优化的智能化技能,能够根据用户需求自动实现多角色相机管理、视野控制、平滑跟随、动态视角切换等完整的相机系统解决方案。

核心功能

📷 多角色相机管理

  • 智能跟随: 自动计算多个角色的最佳视野
  • 焦点切换: 动态切换相机焦点目标
  • 边界适应: 智能调整相机边界以适应所有角色
  • 群组管理: 支持角色群组的统一相机控制

🎬 平滑跟随系统

  • 插值算法: 使用lerp实现平滑的相机移动
  • 速度控制: 可配置的跟随速度和响应性
  • 预测跟随: 基于角色速度的前瞻性相机调整
  • 弹性效果: 自然的弹性跟随效果

🖼️ 视野控制

  • 缩放管理: 动态调整相机缩放以适应场景
  • 边界限制: 设置相机移动范围防止越界
  • 视口适配: 自动适配不同屏幕分辨率
  • 安全区域: 确保重要内容始终在视野内

🎯 动态视角系统

  • 状态驱动: 基于游戏状态的相机行为切换
  • 动画集成: 与角色动画系统深度集成
  • 特效支持: 震动、缩放、旋转等相机特效
  • 场景切换: 流畅的场景间相机过渡

使用方法

格斗游戏相机系统

用户: "我需要为格斗游戏配置双人相机系统"
系统: 自动实现:
- 双角色中点跟随算法
- 动态视野调整
- 攻击时的镜头特效
- 角色分离时的智能处理

平台游戏相机

用户: "为平台跳跃游戏创建跟随相机"
系统: 智能生成:
- 垂直跟随系统
- 平台边界限制
- 跳跃时的预测跟随
- 掉落检测和救援机制

多人游戏相机

用户: "为4人合作游戏配置相机系统"
系统: 全面开发:
- 4人位置的最优视野计算
- 动态缩放以包含所有玩家
- 玩家分散时的处理策略
- 领导者跟随模式

相机系统实现

🎮 格斗游戏相机管理器

# 格斗游戏专用相机系统
class_name FightingGameCameraSystem extends Node
@export var camera: Camera2D
@export var player1: Node2D
@export var player2: Node2D

# 相机参数
@export var follow_speed: float = 5.0
@export var base_zoom: float = 1.0
@export var max_distance: float = 400.0
@export var min_zoom: float = 0.8
@export var max_zoom: float = 1.5

# 动画特效参数
@export var shake_intensity: float = 5.0
@export var shake_duration: float = 0.3

func _ready():
    _setup_camera()
    _connect_player_signals()

func _setup_camera():
    if not camera:
        camera = Camera2D.new()
        add_child(camera)

    # 配置基础属性
    camera.position_smoothing_enabled = true
    camera.position_smoothing_speed = follow_speed

    # 设置边界限制
    camera.limit_left = -1024
    camera.limit_right = 1024
    camera.limit_top = -600
    camera.limit_bottom = 600

func _process(delta):
    if player1 and player2:
        _update_camera_follow(delta)

func _update_camera_follow(delta: float) -> void:
    # 计算两个角色的中点
    var center_point = (player1.global_position + player2.global_position) * 0.5
    var distance = player1.global_position.distance_to(player2.global_position)

    # 动态调整缩放
    var target_zoom = _calculate_dynamic_zoom(distance)
    camera.zoom = camera.zoom.lerp(Vector2(target_zoom, target_zoom), follow_speed * delta * 0.5)

    # 平滑跟随中点
    var target_position = center_point + Vector2(0, -100)  # 向上偏移
    camera.global_position = camera.global_position.lerp(target_position, follow_speed * delta)

func _calculate_dynamic_zoom(distance: float) -> float:
    # 根据角色距离动态调整缩放
    var normalized_distance = clamp(distance / max_distance, 0.0, 1.0)
    return lerp(min_zoom, max_zoom, normalized_distance)

# 特效系统
func play_hit_effect(hit_position: Vector2):
    # 攻击命中时的相机震动
    _start_camera_shake(shake_intensity, shake_duration)

func _start_camera_shake(intensity: float, duration: float):
    var tween = create_tween()
    var original_position = camera.offset

    # 震动效果
    for i in range(5):
        var random_offset = Vector2(
            randf_range(-intensity, intensity),
            randf_range(-intensity, intensity)
        )
        tween.tween_property(camera, "offset", random_offset, duration * 0.1)
        tween.tween_property(camera, "offset", original_position, duration * 0.1)

🏃 平台游戏相机跟随

# 平台游戏相机系统
class_name PlatformerCameraSystem extends Node
@export var camera: Camera2D
@export var target: CharacterBody2D
@export var follow_ahead_distance: float = 100.0

# 跟随参数
@export var vertical_follow_speed: float = 8.0
@export var horizontal_follow_speed: float = 5.0
@export var look_ahead_strength: float = 0.1

# 边界参数
@export var level_bounds: Rect2 = Rect2(-1000, -1000, 2000, 2000)

var _look_ahead_position: Vector2
var _target_bounds: Rect2

func _ready():
    _setup_camera()
    _target_bounds = level_bounds

func _setup_camera():
    if not camera:
        camera = Camera2D.new()
        add_child(camera)

    camera.position_smoothing_enabled = true

func _process(delta):
    if target:
        _update_platformer_camera(delta)

func _update_platformer_camera(delta: float) -> void:
    var target_position = target.global_position

    # 水平方向的前瞻跟随
    var look_ahead = Vector2.ZERO
    if target.velocity.x > 0:  # 向右移动
        look_ahead.x = follow_ahead_distance
    elif target.velocity.x < 0:  # 向左移动
        look_ahead.x = -follow_ahead_distance

    _look_ahead_position = _look_ahead_position.lerp(look_ahead, look_ahead_strength)
    target_position += _look_ahead_position

    # 限制在关卡边界内
    target_position = _clamp_to_bounds(target_position)

    # 平滑跟随
    camera.global_position = camera.global_position.lerp(target_position, horizontal_follow_speed * delta)

func _clamp_to_bounds(position: Vector2) -> Vector2:
    var viewport_size = get_viewport().get_visible_rect().size / camera.zoom
    var half_viewport = viewport_size / 2

    # 限制相机位置,确保视口不超出关卡边界
    position.x = clamp(position.x, _target_bounds.position.x + half_viewport.x,
                      _target_bounds.position.x + _target_bounds.size.x - half_viewport.x)
    position.y = clamp(position.y, _target_bounds.position.y + half_viewport.y,
                      _target_bounds.position.y + _target_bounds.size.y - half_viewport.y)

    return position

# 处理角色掉落
func handle_fall_off_level():
    # 角色掉出关卡边界时的救援处理
    if target.global_position.y > _target_bounds.position.y + _target_bounds.size.y + 200:
        # 重置角色到安全位置
        target.global_position = _find_safe_spawn_point()
        _play_fall_recovery_effect()

func _find_safe_spawn_point() -> Vector2:
    # 寻找安全的重生点
    return Vector2(_target_bounds.position.x + _target_bounds.size.x / 2,
                   _target_bounds.position.y)

👥 多人游戏相机系统

# 多人游戏相机管理器
class_name MultiplayerCameraSystem extends Node
@export var camera: Camera2D
@export var players: Array[Node2D] = []

# 相机参数
@export var padding: float = 50.0
@export var min_zoom: float = 0.5
@export var max_zoom: float = 2.0
@export var follow_speed: float = 3.0

enum CameraMode {
    ALL_PLAYERS,    # 显示所有玩家
    LEADER_FOLLOW,  # 跟随领导者
    SPLIT_SCREEN    # 分屏模式
}

var current_mode: CameraMode = CameraMode.ALL_PLAYERS
var leader_index: int = 0

func _ready():
    _setup_camera()

func _process(delta):
    match current_mode:
        CameraMode.ALL_PLAYERS:
            _update_all_players_camera(delta)
        CameraMode.LEADER_FOLLOW:
            _update_leader_follow_camera(delta)
        CameraMode.SPLIT_SCREEN:
            _update_split_screen_camera(delta)

func _update_all_players_camera(delta: float) -> void:
    if players.size() == 0:
        return

    # 计算所有玩家的边界
    var bounds = _calculate_players_bounds()

    # 计算需要的缩放
    var viewport_size = get_viewport().get_visible_rect().size
    var required_zoom = _calculate_zoom_for_bounds(bounds, viewport_size)
    required_zoom = clamp(required_zoom, min_zoom, max_zoom)

    # 更新相机
    camera.zoom = camera.zoom.lerp(Vector2(required_zoom, required_zoom), follow_speed * delta * 0.5)

    var center = bounds.get_center()
    camera.global_position = camera.global_position.lerp(center, follow_speed * delta)

func _calculate_players_bounds() -> Rect2:
    if players.size() == 0:
        return Rect2.ZERO

    var min_pos = players[0].global_position
    var max_pos = players[0].global_position

    for player in players:
        min_pos.x = min(min_pos.x, player.global_position.x)
        min_pos.y = min(min_pos.y, player.global_position.y)
        max_pos.x = max(max_pos.x, player.global_position.x)
        max_pos.y = max(max_pos.y, player.global_position.y)

    # 添加填充
    min_pos -= Vector2(padding, padding)
    max_pos += Vector2(padding, padding)

    return Rect2(min_pos, max_pos - min_pos)

func _calculate_zoom_for_bounds(bounds: Rect2, viewport_size: Vector2) -> float:
    var zoom_x = viewport_size.x / bounds.size.x
    var zoom_y = viewport_size.y / bounds.size.y
    return min(zoom_x, zoom_y)

# 切换相机模式
func set_camera_mode(mode: CameraMode):
    current_mode = mode
    print("相机模式切换到: ", CameraMode.keys()[mode])

相机特效系统

📳 震动效果

# 相机震动系统
class_name CameraShakeSystem extends Node
@export var camera: Camera2D
@export var default_shake_intensity: float = 5.0
@export var default_shake_duration: float = 0.3

var _shake_tween: Tween
var _original_offset: Vector2

func _ready():
    _original_offset = camera.offset

func play_shake(intensity: float = -1, duration: float = -1):
    if intensity < 0:
        intensity = default_shake_intensity
    if duration < 0:
        duration = default_shake_duration

    # 停止之前的震动
    if _shake_tween:
        _shake_tween.kill()

    _shake_tween = create_tween()
    _shake_tween.set_loops(5)  # 震动5次

    for i in range(5):
        var random_offset = Vector2(
            randf_range(-intensity, intensity),
            randf_range(-intensity, intensity)
        )
        _shake_tween.tween_property(camera, "offset", random_offset, duration * 0.1)
        _shake_tween.tween_property(camera, "offset", _original_offset, duration * 0.1)

    _shake_tween.finished.connect(_on_shake_finished)

func _on_shake_finished():
    camera.offset = _original_offset

🔍 缩放特效

# 相机缩放特效
class_name CameraZoomEffect extends Node
@export var camera: Camera2D

func play_zoom_in(target_zoom: float, duration: float = 0.5):
    var tween = create_tween()
    tween.tween_property(camera, "zoom", Vector2(target_zoom, target_zoom), duration)

func play_zoom_out(target_zoom: float, duration: float = 0.5):
    var tween = create_tween()
    tween.tween_property(camera, "zoom", Vector2(target_zoom, target_zoom), duration)

func play_zoom_pulse(intensity: float = 1.2, duration: float = 0.3):
    var original_zoom = camera.zoom.x
    var tween = create_tween()
    tween.tween_property(camera, "zoom", Vector2(intensity, intensity), duration * 0.5)
    tween.tween_property(camera, "zoom", Vector2(original_zoom, original_zoom), duration * 0.5)

故障排除

常见相机问题

问题1: 角色不在相机视野内

# 诊断和修复
func fix_character_not_visible(camera: Camera2D, character: Node2D):
    print("诊断角色可见性问题...")

    # 计算角色在相机坐标系中的位置
    var camera_space_pos = camera.to_local(character.global_position)
    var viewport_size = get_viewport().get_visible_rect().size

    print("角色相机坐标: ", camera_space_pos)
    print("视口大小: ", viewport_size)

    # 如果角色不在视野内,调整相机位置
    if abs(camera_space_pos.x) > viewport_size.x / 2 or abs(camera_space_pos.y) > viewport_size.y / 2:
        print("角色不在视野内,调整相机位置...")
        camera.global_position = character.global_position

问题2: 相机跟随不流畅

# 优化相机跟随
func optimize_camera_following(camera: Camera2D, follow_speed: float):
    # 调整平滑参数
    camera.position_smoothing_enabled = true

    # 根据帧率动态调整速度
    var fps = Engine.get_frames_per_second()
    var adjusted_speed = follow_speed * (60.0 / max(fps, 30.0))

    camera.position_smoothing_speed = adjusted_speed
    print("相机跟随速度调整为: ", adjusted_speed)

问题3: 多人游戏相机缩放异常

# 修复多人相机缩放
func fix_multiplayer_zoom(camera: Camera2D, players: Array[Node2D]):
    if players.size() < 2:
        camera.zoom = Vector2.ONE
        return

    # 计算合理的缩放范围
    var max_distance = 0.0
    for i in range(players.size()):
        for j in range(i + 1, players.size()):
            var distance = players[i].global_position.distance_to(players[j].global_position)
            max_distance = max(max_distance, distance)

    # 限制最大距离,防止过度缩放
    max_distance = min(max_distance, 800.0)

    var target_zoom = 200.0 / max(max_distance, 200.0)
    target_zoom = clamp(target_zoom, 0.5, 1.5)

    camera.zoom = Vector2(target_zoom, target_zoom)
    print("多人相机缩放设置为: ", target_zoom)

智能特性

自动相机配置

  • 场景分析: 自动分析场景大小和角色位置
  • 参数优化: 根据游戏类型优化相机参数
  • 性能监控: 实时监控相机系统性能

自适应系统

  • 帧率适应: 根据性能动态调整跟随质量
  • 分辨率适配: 自动适配不同屏幕分辨率
  • 设备优化: 针对不同设备优化相机行为

调试工具

  • 可视化调试: 显示相机视野和跟随范围
  • 性能分析: 监控相机系统性能指标
  • 参数调节: 实时调节相机参数

技能状态: ✅ 可用 最后更新: 2025-11-09 兼容性: Godot 4.5+ 专长: 2D相机系统、多角色跟随、视野控制 依赖: Godot MCP 工具集 + 相机系统知识