with one click
godot-camera-system
Godot 2D相机系统专家,专门处理多角色相机管理、视野控制、平滑跟随和动态视角系统
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Godot 2D相机系统专家,专门处理多角色相机管理、视野控制、平滑跟随和动态视角系统
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Godot技能统一入口,根据用户需求智能选择并调用最适合的Godot子技能,提供15个专业技能的一站式开发体验
为中文开发者提供完整的项目本地化、环境配置和开发工作流指导,确保中英文双语环境下的最佳开发体验
自动使用Context7进行文档研究,当用户需要代码生成、配置步骤或库/API文档时无需明确请求即可自动获取最新信息
GDScript 语法权威指南,提供最新 Godot 4.5 语法规范、最佳实践、缩进规则和代码风格
Godot 资源与动画创建专家,支持自然语言描述自动完成精灵导入、动画配置、特效制作、音效集成等资源工作
提供批量操作Godot节点的能力,支持批量更新属性、重命名、删除和创建节点,大幅提升开发效率
| name | godot-camera-system |
| description | Godot 2D相机系统专家,专门处理多角色相机管理、视野控制、平滑跟随和动态视角系统 |
重要提示: 本技能专门解决Godot 2D游戏中的相机配置和角色显示问题,基于 Godot 4.5 最佳实践。 特别适用于格斗游戏、平台游戏、多人游戏等需要复杂相机管理的场景。
godot-camera-system 是专门用于Godot 2D游戏相机系统配置和优化的智能化技能,能够根据用户需求自动实现多角色相机管理、视野控制、平滑跟随、动态视角切换等完整的相机系统解决方案。
用户: "我需要为格斗游戏配置双人相机系统"
系统: 自动实现:
- 双角色中点跟随算法
- 动态视野调整
- 攻击时的镜头特效
- 角色分离时的智能处理
用户: "为平台跳跃游戏创建跟随相机"
系统: 智能生成:
- 垂直跟随系统
- 平台边界限制
- 跳跃时的预测跟随
- 掉落检测和救援机制
用户: "为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)
# 诊断和修复
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
# 优化相机跟随
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)
# 修复多人相机缩放
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 工具集 + 相机系统知识