layout, card, and design camera fixes

This commit is contained in:
2026-01-26 19:18:27 -05:00
parent cbe55820e9
commit 7ce6560225
14 changed files with 523 additions and 54 deletions

View File

@@ -9,45 +9,66 @@ extends Camera3D
@export var camera_height_offset: float = -4.0 # Offset to look slightly above center
# Smooth movement
@export var smooth_speed: float = 5.0
@export var smooth_speed: float = 3.0
var target_position: Vector3 = Vector3.ZERO
var target_look_at: Vector3 = Vector3.ZERO
var is_animating: bool = false
# Current player side (0 = positive Z, 1 = negative Z)
var current_player: int = 0
func _ready() -> void:
_setup_isometric_view()
_setup_for_player(0, false)
func _setup_isometric_view() -> void:
func _setup_for_player(player_index: int, animate: bool = true) -> void:
# Set perspective projection
projection = PROJECTION_PERSPECTIVE
fov = 50.0
# Calculate position - camera is positioned behind Player 1's side
var angle_rad = deg_to_rad(camera_angle)
current_player = player_index
# Height based on angle
var angle_rad = deg_to_rad(camera_angle)
var height = camera_distance * sin(angle_rad)
# Distance along Z axis (positive Z is toward Player 1)
var z_offset = camera_distance * cos(angle_rad)
# Position camera behind Player 1 (positive Z), looking toward center/opponent
position = Vector3(0, height, z_offset)
# Flip Z direction based on player
var side = 1 if player_index == 0 else -1
var new_position = Vector3(0, height, z_offset * side)
# Look at center of table
look_at(Vector3(0, camera_height_offset, 0), Vector3.UP)
target_look_at = Vector3(0, camera_height_offset, 0)
target_position = position
if animate:
target_position = new_position
is_animating = true
else:
position = new_position
target_position = new_position
look_at(target_look_at, Vector3.UP)
is_animating = false
func _process(delta: float) -> void:
# Smooth camera movement if needed
if position.distance_to(target_position) > 0.01:
if is_animating:
position = position.lerp(target_position, smooth_speed * delta)
look_at(Vector3(0, camera_height_offset, 0), Vector3.UP)
look_at(target_look_at, Vector3.UP)
if position.distance_to(target_position) < 0.05:
position = target_position
look_at(target_look_at, Vector3.UP)
is_animating = false
## Switch camera to view from a player's perspective
func switch_to_player(player_index: int) -> void:
if player_index != current_player:
_setup_for_player(player_index, true)
## Set camera to look at a specific point
func focus_on(point: Vector3) -> void:
var angle_rad = deg_to_rad(camera_angle)
var side = 1 if current_player == 0 else -1
target_position = point + Vector3(0, camera_distance * sin(angle_rad),
camera_distance * cos(angle_rad))
camera_distance * cos(angle_rad) * side)
is_animating = true
## Reset to default position
func reset_position() -> void:
_setup_isometric_view()
_setup_for_player(current_player, false)

View File

@@ -25,16 +25,17 @@ const MAT_MARGIN: float = 0.3 # Gap between mats and from table center
# Player 1 sits at +Z looking toward -Z
# Player's left = +X, Player's right = -X
const ZONE_POSITIONS = {
"damage": Vector3(7.0, 0.1, 1.5), # Front-left (player's left)
"deck": Vector3(-7.0, 0.1, 4.0), # Back-right (player's right, behind backups)
"break": Vector3(-7.0, 0.1, 1.5), # Front-right (player's right, front row)
"forwards": Vector3(0.0, 0.1, 2.0), # Center, front row
"backups": Vector3(0.0, 0.1, 5.0), # Center, back row
"damage": Vector3(-7.3, 0.1, 2.1), # Left column, top (forwards row)
"deck": Vector3(7.3, 0.1, 2.0), # Right column, top (forwards row)
"break": Vector3(7.3, 0.1, 5.4), # Right column, centered in break zone box
"forwards": Vector3(0.0, 0.1, 1.9), # Center, front row (near table center)
"backups": Vector3(0.0, 0.1, 4.5), # Center, back row (pulled forward to stay visible above hand)
"hand": Vector3(0.0, 0.5, 7.5) # Not used on table (2D overlay)
}
# Background texture path
const BACKGROUND_TEXTURE_PATH: String = "res://assets/table/background_1.png"
const CARD_BACK_TEXTURE_PATH: String = "res://assets/cards/card_back.png"
# Components
var table_mesh: MeshInstance3D
@@ -195,27 +196,47 @@ func _create_zones() -> void:
player_zones[player_idx]["break"] = break_zone
func _create_deck_indicators() -> void:
# Create simple card-back boxes for deck representation
var card_back_texture = load(CARD_BACK_TEXTURE_PATH)
for player_idx in range(2):
var flip = 1 if player_idx == 0 else -1
var pos = ZONE_POSITIONS["deck"] * Vector3(flip, 1, flip)
# Card back mesh (simple colored box)
# Deck stack (thin box for thickness)
var deck_mesh = MeshInstance3D.new()
add_child(deck_mesh)
var box = BoxMesh.new()
box.size = Vector3(1.26, 0.3, 1.76) # Card size with thickness for deck
box.size = Vector3(1.6, 0.3, 2.2)
deck_mesh.mesh = box
var mat = StandardMaterial3D.new()
mat.albedo_color = Color(0.15, 0.1, 0.3) # Dark blue for card back
deck_mesh.material_override = mat
var side_mat = StandardMaterial3D.new()
side_mat.albedo_color = Color(0.08, 0.06, 0.12) # Dark edges
deck_mesh.material_override = side_mat
deck_mesh.position = pos + Vector3(0, 0.15, 0) # Raise above table
deck_mesh.position = pos + Vector3(0, 0.15, 0)
deck_indicators[player_idx] = deck_mesh
# Card back face on top of the deck
var top_card = MeshInstance3D.new()
add_child(top_card)
var plane = PlaneMesh.new()
plane.size = Vector2(1.6, 2.2)
top_card.mesh = plane
var top_mat = StandardMaterial3D.new()
if card_back_texture:
top_mat.albedo_texture = card_back_texture
else:
top_mat.albedo_color = Color(0.15, 0.1, 0.3)
top_card.material_override = top_mat
top_card.position = pos + Vector3(0, 0.31, 0)
if player_idx == 1:
top_card.rotation.y = deg_to_rad(180)
# Card count label
var label = Label3D.new()
add_child(label)
@@ -224,13 +245,13 @@ func _create_deck_indicators() -> void:
label.position = pos + Vector3(0, 0.35, 0)
label.rotation.x = deg_to_rad(-90) # Face up
if player_idx == 1:
label.rotation.z = deg_to_rad(180) # Flip for opponent
label.rotation.z = deg_to_rad(180)
deck_count_labels[player_idx] = label
func _create_zone(zone_type: Enums.ZoneType, player_idx: int, pos: Vector3, rot: float) -> ZoneVisual:
var zone = ZoneVisual.new()
add_child(zone)
# Set properties BEFORE add_child so _ready() uses the correct values
zone.zone_type = zone_type
zone.player_index = player_idx
zone.zone_position = pos
@@ -243,6 +264,7 @@ func _create_zone(zone_type: Enums.ZoneType, player_idx: int, pos: Vector3, rot:
Enums.ZoneType.DAMAGE, Enums.ZoneType.BREAK:
zone.stack_offset = 0.02
add_child(zone)
zone.card_clicked.connect(_on_zone_card_clicked.bind(zone_type, player_idx))
return zone
@@ -333,3 +355,8 @@ func clear_all_highlights() -> void:
var zone = player_zones[player_idx][zone_name]
if zone:
zone.clear_highlights()
## Switch camera to a player's perspective
func switch_camera_to_player(player_index: int) -> void:
if camera:
camera.switch_to_player(player_index)