extends Spatial class_name Board onready var CardTemplate := preload("res://Scenes/Components/Card.tscn") onready var camera := $Camera onready var hand := $Camera/Hand onready var ui := $BoardUI onready var cards := $Cards export var mouseHandThreshold = 0.85 var holdingCard: Card = null var focusedCard: Card = null var mouseOrigin: Vector2 var lastCameraTransform: Transform func _ready(): add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, true) add_card("ff36", 0, false) reorder_hand() func _input(event: InputEvent): # Camera zoom if event.is_action("zoom_in"): camera.zoom(true) elif event.is_action("zoom_out"): camera.zoom(false) # Save original camera and mouse position before panning if event.is_action_pressed("pan"): mouseOrigin = get_viewport().get_mouse_position() lastCameraTransform = camera.transform func _process(delta: float): # If mouse is under a certain area then we're managing our hand var absMousePos := get_viewport().get_mouse_position() # If panning, translate mouse delta to camera delta if Input.is_action_pressed("pan"): var mouseDelta := absMousePos - mouseOrigin var mousePos: Vector2 = mouseDelta * 0.0096 * (1-camera.get_zoom()/5) # Magic numbers everywhere camera.transform.origin = lastCameraTransform.origin - Vector3(mousePos.x, 0, mousePos.y) # If holding a card, move it between board/hand if holdingCard != null: var relPos: float = absMousePos.y / get_viewport().size.y var selectingHand: bool = relPos > mouseHandThreshold if selectingHand and not holdingCard.inHand: holdingCard.inHand = true call_deferred("reparent", holdingCard, cards, hand) elif not selectingHand and holdingCard.inHand: holdingCard.inHand = false call_deferred("reparent", holdingCard, hand, cards) func _card_picked(card: Card): holdingCard = card holdingCard.animation.play("lift") func _card_dropped(card: Card): if card.inHand: card.animation.play("drop") else: card.animation.play_backwards("lift") holdingCard = null func _card_selected(card: Card): if card.inHand and focusedCard == null: focusedCard = card card.animation.play("focus") func _card_unselected(card: Card): if focusedCard == card: focusedCard = null card.animation.play("blur") func reparent(object: Node, from: Node, to: Node): from.remove_child(object) to.add_child(object) object.set_owner(to) reorder_hand() func add_card(cardID: String, playerID: int, inHand: bool): var card := CardTemplate.instance() card.cardID = cardID card.playerID = playerID card.inHand = inHand card.connect("card_dropped", self, "_card_dropped", [card]) card.connect("card_picked", self, "_card_picked", [card]) card.connect("card_selected", ui, "_card_selected", [card]) card.connect("card_unselected", ui, "_card_unselected", [card]) card.connect("card_selected", self, "_card_selected", [card]) card.connect("card_unselected", self, "_card_unselected", [card]) card.connect("card_dropped_anim", self, "check_hand_drop", [card]) card.connect("card_menu", ui, "show_card_menu", [card]) if inHand: # TODO if player != me, put in opponent's hand hand.add_child(card) else: cards.add_child(card) func check_hand_drop(card: Card): # Re-order hand as soon as the animation is over if card.inHand: card.reset_transform() reorder_hand() const MAX_CARD_DISTANCE := 0.5 const HAND_SCREEN_PERC := 0.6 const CARD_ROTATION := 0.03 const UNITSPERPX := 0.003 func reorder_hand(): var cardsInHand: Array = hand.get_children() cardsInHand.sort_custom(TransformSorter, "sort") var size := cardsInHand.size() # Calculate total width of the player's hand and other things # This is done in two ways, for small hands, MAX_CARD_DISTANCE is usually used # as constant distance between cards, however, as the hand gets larger we don't # want them to go offscreen, therefore a "maximum screen %" is used to determine # how to fit all the cards within a % of the viewport's width var distancePerc := get_viewport().size.x * HAND_SCREEN_PERC * UNITSPERPX / size var distance := min(distancePerc, MAX_CARD_DISTANCE) var totalWidth := distance * (size-1) var minX := -totalWidth/2 # Iterate over all items, keep track of the index var i := 0 for child in cardsInHand: child.tween_move_to(Vector3(minX + distance * i, 0.02*i, -0.005*i)) child.tween_rotate(Vector3(0, CARD_ROTATION * (size/2.0 - i), 0)) i += 1 child.reset_transform() child.tween() class TransformSorter: static func sort(a, b): if a.transform.origin.x < b.transform.origin.x: return true return false