init game files
This commit is contained in:
184
scripts/visual/ZoneVisual.gd
Normal file
184
scripts/visual/ZoneVisual.gd
Normal file
@@ -0,0 +1,184 @@
|
||||
class_name ZoneVisual
|
||||
extends Node3D
|
||||
|
||||
## ZoneVisual - Visual representation of a card zone
|
||||
|
||||
signal card_clicked(card_visual: CardVisual)
|
||||
|
||||
# Zone configuration
|
||||
@export var zone_type: Enums.ZoneType = Enums.ZoneType.HAND
|
||||
@export var player_index: int = 0
|
||||
|
||||
# Layout settings
|
||||
@export var card_spacing: float = 0.7
|
||||
@export var stack_offset: float = 0.02 # Vertical offset for stacked cards
|
||||
@export var max_visible_cards: int = 10
|
||||
@export var fan_angle: float = 5.0 # Degrees for hand fan
|
||||
|
||||
# Position settings
|
||||
@export var zone_position: Vector3 = Vector3.ZERO
|
||||
@export var zone_rotation: float = 0.0 # Y rotation in degrees
|
||||
|
||||
# Card visuals in this zone
|
||||
var card_visuals: Array[CardVisual] = []
|
||||
|
||||
# Zone indicator (optional visual for empty zones)
|
||||
var zone_indicator: MeshInstance3D = null
|
||||
|
||||
func _ready() -> void:
|
||||
position = zone_position
|
||||
rotation.y = deg_to_rad(zone_rotation)
|
||||
_create_zone_indicator()
|
||||
|
||||
func _create_zone_indicator() -> void:
|
||||
zone_indicator = MeshInstance3D.new()
|
||||
add_child(zone_indicator)
|
||||
|
||||
var plane = PlaneMesh.new()
|
||||
plane.size = Vector2(CardVisual.CARD_WIDTH * 1.1, CardVisual.CARD_HEIGHT * 1.1)
|
||||
zone_indicator.mesh = plane
|
||||
|
||||
var mat = StandardMaterial3D.new()
|
||||
mat.albedo_color = Color(0.2, 0.2, 0.3, 0.3)
|
||||
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
zone_indicator.material_override = mat
|
||||
|
||||
zone_indicator.rotation.x = deg_to_rad(-90) # Lay flat
|
||||
zone_indicator.visible = true
|
||||
|
||||
## Add a card to this zone
|
||||
func add_card(card_instance: CardInstance) -> CardVisual:
|
||||
var card_visual = CardVisual.new()
|
||||
add_child(card_visual)
|
||||
card_visual.setup(card_instance)
|
||||
|
||||
# Connect signals
|
||||
card_visual.clicked.connect(_on_card_clicked)
|
||||
|
||||
card_visuals.append(card_visual)
|
||||
_arrange_cards()
|
||||
|
||||
return card_visual
|
||||
|
||||
## Remove a card from this zone
|
||||
func remove_card(card_visual: CardVisual) -> void:
|
||||
var index = card_visuals.find(card_visual)
|
||||
if index >= 0:
|
||||
card_visuals.remove_at(index)
|
||||
card_visual.queue_free()
|
||||
_arrange_cards()
|
||||
|
||||
## Remove card by instance
|
||||
func remove_card_instance(card_instance: CardInstance) -> CardVisual:
|
||||
for card_visual in card_visuals:
|
||||
if card_visual.card_instance == card_instance:
|
||||
remove_card(card_visual)
|
||||
return card_visual
|
||||
return null
|
||||
|
||||
## Find card visual by instance
|
||||
func find_card_visual(card_instance: CardInstance) -> CardVisual:
|
||||
for card_visual in card_visuals:
|
||||
if card_visual.card_instance == card_instance:
|
||||
return card_visual
|
||||
return null
|
||||
|
||||
## Arrange cards based on zone type
|
||||
func _arrange_cards() -> void:
|
||||
match zone_type:
|
||||
Enums.ZoneType.HAND:
|
||||
_arrange_hand()
|
||||
Enums.ZoneType.DECK, Enums.ZoneType.DAMAGE, Enums.ZoneType.BREAK:
|
||||
_arrange_stack()
|
||||
Enums.ZoneType.FIELD_FORWARDS, Enums.ZoneType.FIELD_BACKUPS:
|
||||
_arrange_field()
|
||||
_:
|
||||
_arrange_row()
|
||||
|
||||
# Update zone indicator visibility
|
||||
zone_indicator.visible = card_visuals.size() == 0
|
||||
|
||||
## Arrange as a fan (for hand)
|
||||
func _arrange_hand() -> void:
|
||||
var count = card_visuals.size()
|
||||
if count == 0:
|
||||
return
|
||||
|
||||
var total_width = (count - 1) * card_spacing
|
||||
var start_x = -total_width / 2
|
||||
|
||||
for i in range(count):
|
||||
var card = card_visuals[i]
|
||||
var x = start_x + i * card_spacing
|
||||
var angle = (i - (count - 1) / 2.0) * fan_angle
|
||||
|
||||
card.move_to(
|
||||
Vector3(x, i * 0.01, 0), # Slight y offset for overlap
|
||||
Vector3(0, 0, deg_to_rad(-angle))
|
||||
)
|
||||
|
||||
## Arrange as a stack (for deck, damage, break zone)
|
||||
func _arrange_stack() -> void:
|
||||
for i in range(card_visuals.size()):
|
||||
var card = card_visuals[i]
|
||||
card.move_to(Vector3(0, i * stack_offset, 0))
|
||||
|
||||
## Arrange in a row (for field zones)
|
||||
func _arrange_field() -> void:
|
||||
var count = card_visuals.size()
|
||||
if count == 0:
|
||||
return
|
||||
|
||||
var total_width = (count - 1) * card_spacing
|
||||
var start_x = -total_width / 2
|
||||
|
||||
for i in range(count):
|
||||
var card = card_visuals[i]
|
||||
var x = start_x + i * card_spacing
|
||||
|
||||
# Apply dull rotation if card is dull
|
||||
var rot_y = 0.0
|
||||
if card.card_instance and card.card_instance.is_dull():
|
||||
rot_y = deg_to_rad(90)
|
||||
|
||||
card.move_to(Vector3(x, 0, 0), Vector3(0, rot_y, 0))
|
||||
|
||||
## Arrange in a simple row
|
||||
func _arrange_row() -> void:
|
||||
var count = card_visuals.size()
|
||||
if count == 0:
|
||||
return
|
||||
|
||||
var total_width = (count - 1) * card_spacing
|
||||
var start_x = -total_width / 2
|
||||
|
||||
for i in range(count):
|
||||
var card = card_visuals[i]
|
||||
card.move_to(Vector3(start_x + i * card_spacing, 0, 0))
|
||||
|
||||
## Clear all cards
|
||||
func clear() -> void:
|
||||
for card_visual in card_visuals:
|
||||
card_visual.queue_free()
|
||||
card_visuals.clear()
|
||||
zone_indicator.visible = true
|
||||
|
||||
## Get card count
|
||||
func get_card_count() -> int:
|
||||
return card_visuals.size()
|
||||
|
||||
## Highlight all cards that can be interacted with
|
||||
func highlight_interactive(predicate: Callable) -> void:
|
||||
for card_visual in card_visuals:
|
||||
var can_interact = predicate.call(card_visual.card_instance)
|
||||
card_visual.set_highlighted(can_interact)
|
||||
|
||||
## Clear all highlights
|
||||
func clear_highlights() -> void:
|
||||
for card_visual in card_visuals:
|
||||
card_visual.set_highlighted(false)
|
||||
card_visual.set_selected(false)
|
||||
|
||||
## Card click handler
|
||||
func _on_card_clicked(card_visual: CardVisual) -> void:
|
||||
card_clicked.emit(card_visual)
|
||||
Reference in New Issue
Block a user