feat: Introduce tekton_walking 3D model, implement a CameraContextManager for dynamic camera positioning, and add a ScreenShakeManager script.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
extends Node
|
||||
|
||||
# CameraContextManager
|
||||
# Handles camera position based on player's row on the board.
|
||||
|
||||
# var screen_shake_manager: Node # Removed
|
||||
var camera: Camera3D
|
||||
var player: Node3D
|
||||
|
||||
# Configuration Map: Row Threshold -> Target Position
|
||||
# We use a list of dictionaries to define ranges.
|
||||
# Setup A: Rows 0-5
|
||||
# Setup B: Rows 6-9
|
||||
# Setup C: Rows 10+
|
||||
var camera_setups = [
|
||||
{ "max_row": 5, "position": Vector3(7.0, 19.636, 15.0) },
|
||||
{ "max_row": 9, "position": Vector3(7.0, 19.636, 19.0) },
|
||||
{ "max_row": 999, "position": Vector3(7.0, 19.22636, 22.5) } # Default/Bottom
|
||||
]
|
||||
|
||||
var unique_id: int
|
||||
|
||||
func initialize(p_camera: Camera3D, _p_shake_manager: Node):
|
||||
camera = p_camera
|
||||
# screen_shake_manager = p_shake_manager
|
||||
print("[CameraContextManager] Initialized with camera")
|
||||
|
||||
func set_player(p_player: Node3D):
|
||||
player = p_player
|
||||
unique_id = p_player.name.to_int()
|
||||
# Try to get movement manager (might be initializing)
|
||||
var movement_mgr = player.get("movement_manager")
|
||||
|
||||
if not movement_mgr and player.get("movement_manager") == null:
|
||||
# Try direct access if script variable
|
||||
movement_mgr = player.movement_manager
|
||||
|
||||
if movement_mgr:
|
||||
if not movement_mgr.movement_finished.is_connected(_on_player_moved):
|
||||
movement_mgr.movement_finished.connect(_on_player_moved)
|
||||
else:
|
||||
print("[CameraContextManager] Warning: movement_manager not found on player. Retrying in 0.5s...")
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
if player == p_player: # Ensure player hasn't changed
|
||||
set_player(p_player) # Retry
|
||||
_update_camera_target()
|
||||
|
||||
func _on_player_moved():
|
||||
# print("[CameraContextManager] Player moved signal received")
|
||||
_update_camera_target()
|
||||
|
||||
func _update_camera_target():
|
||||
if not player or not camera:
|
||||
return
|
||||
|
||||
# Get player row (Z coordinate in 3D world / Y in GridMap)
|
||||
# In this game: Grid Y maps to World Z.
|
||||
# Player current_position is Vector2i(grid_x, grid_y)
|
||||
|
||||
var current_row = player.current_position.y
|
||||
var target_pos = Vector3.ZERO
|
||||
|
||||
for i in range(camera_setups.size()):
|
||||
var setup = camera_setups[i]
|
||||
if current_row <= setup.max_row:
|
||||
target_pos = setup.position
|
||||
break
|
||||
|
||||
# print("[CameraContextManager] Player Row: %d -> Selected Setup: %d (Target: %s)" % [current_row, setup_index, target_pos])
|
||||
|
||||
# Update ScreenShakeManager's target
|
||||
# Update Camera Position directly with Tween
|
||||
if camera.position != target_pos:
|
||||
var tween = create_tween()
|
||||
tween.tween_property(camera, "position", target_pos, 1.0).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
@@ -0,0 +1 @@
|
||||
uid://btvpagdk2gwhg
|
||||
@@ -6,7 +6,7 @@ var camera: Camera3D
|
||||
var shake_intensity: float = 0.0
|
||||
var shake_duration: float = 0.0
|
||||
var shake_timer: float = 0.0
|
||||
var original_position: Vector3
|
||||
var target_position: Vector3 # Replaces original_position
|
||||
|
||||
# Shake presets
|
||||
const SHAKE_TARGETED: Dictionary = {"intensity": 0.15, "duration": 0.4}
|
||||
@@ -17,56 +17,17 @@ func initialize(p_camera: Camera3D):
|
||||
"""Initialize with specific camera instance."""
|
||||
camera = p_camera
|
||||
if camera:
|
||||
original_position = camera.position
|
||||
target_position = camera.position
|
||||
print("[ScreenShakeManager] Initialized with camera: ", camera.name)
|
||||
else:
|
||||
push_warning("[ScreenShakeManager] Initialized with null camera")
|
||||
|
||||
func _process(delta):
|
||||
if shake_timer > 0:
|
||||
shake_timer -= delta
|
||||
if camera:
|
||||
var shake_offset = Vector3(
|
||||
randf_range(-shake_intensity, shake_intensity),
|
||||
randf_range(-shake_intensity, shake_intensity),
|
||||
randf_range(-shake_intensity * 0.5, shake_intensity * 0.5)
|
||||
)
|
||||
camera.position = original_position + shake_offset
|
||||
|
||||
if shake_timer <= 0:
|
||||
_reset_camera()
|
||||
|
||||
func _reset_camera():
|
||||
if camera:
|
||||
camera.position = original_position
|
||||
shake_timer = 0.0
|
||||
shake_intensity = 0.0
|
||||
|
||||
func shake(intensity: float, duration: float):
|
||||
"""Trigger camera shake with given intensity and duration."""
|
||||
if not camera:
|
||||
push_warning("Screen shake requested but no camera assigned!")
|
||||
func set_target_position(new_pos: Vector3, duration: float = 1.0):
|
||||
"""Smoothly transition to a new base camera position."""
|
||||
if target_position == new_pos:
|
||||
return
|
||||
|
||||
if camera:
|
||||
# If already shaking, reset camera first to get true original position
|
||||
if shake_timer > 0:
|
||||
camera.position = original_position
|
||||
else:
|
||||
original_position = camera.position
|
||||
|
||||
shake_intensity = intensity
|
||||
shake_duration = duration
|
||||
shake_timer = duration
|
||||
# Tween the target position
|
||||
var tween = create_tween()
|
||||
tween.tween_property(self, "target_position", new_pos, duration).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
|
||||
func shake_targeted():
|
||||
"""Called when local player is targeted by opponent's powerup."""
|
||||
shake(SHAKE_TARGETED.intensity, SHAKE_TARGETED.duration)
|
||||
|
||||
func shake_goal_complete():
|
||||
"""Called when local player completes a goal."""
|
||||
shake(SHAKE_GOAL_COMPLETE.intensity, SHAKE_GOAL_COMPLETE.duration)
|
||||
|
||||
func shake_light():
|
||||
"""Light shake for minor events."""
|
||||
shake(SHAKE_LIGHT.intensity, SHAKE_LIGHT.duration)
|
||||
|
||||
Reference in New Issue
Block a user