Files
jass-learner/docs/API.md
Aspergerli ade3d0fb01 init
2026-03-09 19:18:47 +01:00

26 KiB

Card Framework API Reference

Complete API reference for the Godot 4.x Card Framework addon. This framework provides a modular system for creating 2D card games with drag-and-drop functionality, flexible container management, and extensible card factories.

Table of Contents


Configuration

CardFrameworkSettings

Extends: RefCounted

Centralized configuration constants for all Card Framework components. This class provides consistent default values without requiring Autoload, allowing components to reference framework-wide constants directly.

Animation Constants

Constant Type Value Description
ANIMATION_MOVE_SPEED float 2000.0 Speed of card movement animations in pixels per second
ANIMATION_HOVER_DURATION float 0.10 Duration of hover animations in seconds
ANIMATION_HOVER_SCALE float 1.1 Scale multiplier applied during hover effects
ANIMATION_HOVER_ROTATION float 0.0 Rotation in degrees applied during hover effects

Physics Constants

Constant Type Value Description
PHYSICS_HOVER_DISTANCE float 10.0 Distance threshold for hover detection in pixels
PHYSICS_CARD_HOVER_DISTANCE float 30.0 Distance cards move up during hover in pixels

Visual Layout Constants

Constant Type Value Description
VISUAL_DRAG_Z_OFFSET int 1000 Z-index offset applied to cards during drag operations
VISUAL_PILE_Z_INDEX int 3000 Z-index for pile cards to ensure proper layering
VISUAL_SENSOR_Z_INDEX int -1000 Z-index for drop zone sensors (below everything)
VISUAL_OUTLINE_Z_INDEX int 1200 Z-index for debug outlines (above UI)

Container Layout Constants

Constant Type Value Description
LAYOUT_DEFAULT_CARD_SIZE Vector2 Vector2(150, 210) Default card size used throughout the framework
LAYOUT_STACK_GAP int 8 Distance between stacked cards in piles
LAYOUT_MAX_STACK_DISPLAY int 6 Maximum cards to display in stack before hiding
LAYOUT_MAX_HAND_SIZE int 10 Maximum number of cards in hand containers
LAYOUT_MAX_HAND_SPREAD int 700 Maximum pixel spread for hand arrangements

Debug Constants

Constant Type Value Description
DEBUG_OUTLINE_COLOR Color Color(1, 0, 0, 1) Color used for sensor outlines and debug indicators

Usage

# Reference constants directly in component @export variables
@export var moving_speed: int = CardFrameworkSettings.ANIMATION_MOVE_SPEED
@export var hover_distance: int = CardFrameworkSettings.PHYSICS_HOVER_DISTANCE

# Or use in code
z_index = stored_z_index + CardFrameworkSettings.VISUAL_DRAG_Z_OFFSET

Core Classes

CardManager

Extends: Control

The central orchestrator for all card game operations. Manages card containers, handles drag-and-drop operations, and maintains game history for undo functionality.

Properties

Property Type Default Description
card_size Vector2 Vector2(150, 210) Default size for all cards in the game
card_factory_scene PackedScene - Scene containing the CardFactory implementation
debug_mode bool false Enables visual debugging for drop zones

Methods

undo() -> void

Undoes the last card movement operation by restoring cards to their previous container.

card_manager.undo()
reset_history() -> void

Clears all stored history elements, preventing further undo operations.

card_manager.reset_history()

Internal Methods

These methods are called automatically by the framework:

  • _add_card_container(id: int, card_container: CardContainer) - Registers a container
  • _delete_card_container(id: int) - Unregisters a container
  • _on_drag_dropped(cards: Array) - Handles completed drag operations
  • _add_history(to: CardContainer, cards: Array) - Records movement for undo

Card

Extends: DraggableObject

Represents an individual playing card with front/back faces and interaction capabilities.

Properties

Property Type Default Description
card_name String "" Unique identifier for the card
card_size Vector2 Vector2(150, 210) Dimensions of the card
front_image Texture2D - Texture for card front face
back_image Texture2D - Texture for card back face
show_front bool true Whether front face is visible

Variables

Variable Type Description
card_info Dictionary Additional card data from JSON
card_container CardContainer Container currently holding this card

Methods

set_faces(front_face: Texture2D, back_face: Texture2D) -> void

Sets both front and back textures for the card.

card.set_faces(front_texture, back_texture)
return_card() -> void

Returns card to its original position with no rotation.

card.return_card()
start_hovering() -> void

Initiates hover effect, raising card visually and adjusting global hover count.

card.start_hovering()
end_hovering(restore_object_position: bool) -> void

Ends hover effect and optionally restores position.

card.end_hovering(true)  # Restore position
card.end_hovering(false) # Keep current position
set_holding() -> void

[Deprecated] Legacy method for setting holding state. Use state machine transitions instead.

card.set_holding()  # Put card into holding state
get_string() -> String

Returns string representation of the card for debugging.

var card_info = card.get_string()  # Returns card_name

Static Variables

Variable Type Description
hovering_card_count int Global count of currently hovering cards

CardContainer

Extends: Control

Abstract base class for all card containers. Provides core functionality for holding, managing, and organizing cards with drag-and-drop support.

Drop Zone Properties

Property Type Default Description
enable_drop_zone bool true Enables drop zone functionality
sensor_size Vector2 Vector2(0, 0) Size of drop sensor (follows card_size if unset)
sensor_position Vector2 Vector2(0, 0) Position offset for drop sensor
sensor_texture Texture - Visual texture for sensor (debugging)
sensor_visibility bool false Whether sensor is visible

Variables

Variable Type Description
unique_id int Auto-generated unique identifier
cards_node Control Node containing all card children
card_manager CardManager Reference to parent CardManager
debug_mode bool Debug mode state from CardManager

Core Methods

add_card(card: Card, index: int = -1) -> void

Adds a card to the container at specified index (-1 for end).

container.add_card(my_card)        # Add to end
container.add_card(my_card, 0)     # Add to beginning
remove_card(card: Card) -> bool

Removes a card from the container. Returns true if successful.

var success = container.remove_card(my_card)
has_card(card: Card) -> bool

Checks if container holds the specified card.

if container.has_card(my_card):
	print("Card is in this container")
get_card_count() -> int

Returns the number of cards currently in the container.

var count = container.get_card_count()
print("Container has %d cards" % count)
clear_cards() -> void

Removes all cards from the container.

container.clear_cards()
move_cards(cards: Array, index: int = -1, with_history: bool = true) -> bool

Moves multiple cards to this container with optional history tracking.

var cards_to_move = [card1, card2, card3]
container.move_cards(cards_to_move, 0, true)  # Move to beginning with history
shuffle() -> void

Randomly shuffles all cards in the container using Fisher-Yates algorithm.

deck_container.shuffle()
undo(cards: Array, from_indices: Array = []) -> void

Restores cards to their original positions with index precision. Supports both simple restoration and precise index-based positioning for complex undo scenarios.

Parameters:

  • cards: Array of cards to restore to this container
  • from_indices: Optional array of original indices for precise positioning (since v1.1.4)

Features:

  • Adaptive Algorithm: Automatically detects consecutive vs non-consecutive card groups
  • Order Preservation: Maintains correct card order for bulk consecutive moves
  • Fallback Safety: Gracefully handles missing or invalid index data
# Simple undo (backward compatible)
source_container.undo([card1, card2])

# Precise index-based undo (new in v1.1.4)
source_container.undo([card1, card2, card3], [0, 1, 2])

# Handles complex scenarios automatically
hand_container.undo(moved_cards, original_indices)

Drop Zone Methods

check_card_can_be_dropped(cards: Array) -> bool

Determines if the provided cards can be dropped into this container.

if container.check_card_can_be_dropped([my_card]):
	# Cards can be dropped here
get_partition_index() -> int

Gets the drop partition index based on mouse position. Returns -1 if no partitioning.

var drop_index = container.get_partition_index()

Event Handlers

on_card_move_done(_card: Card) -> void

Called when a card finishes moving. Override in subclasses for custom behavior.

func on_card_move_done(card: Card):
	print("Card movement completed: ", card.card_name)
on_card_pressed(_card: Card) -> void

Called when a card in this container is pressed. Override for custom behavior.

func on_card_pressed(card: Card):
	print("Card pressed: ", card.card_name)

Utility Methods

hold_card(card: Card) -> void

Puts a card into holding state, preparing it for drag operations.

container.hold_card(my_card)  # Put card into holding state
get_string() -> String

Returns string representation for debugging.

print(container.get_string())  # "card_container: 1"

Abstract Methods

These methods should be overridden in subclasses:

update_card_ui() -> void

Updates visual positioning and appearance of all cards.

_card_can_be_added(_cards: Array) -> bool

Returns true if the specified cards can be added to this container. Base implementation always returns true.

_update_target_positions() -> void

Calculates and applies target positions for all cards.

_update_target_z_index() -> void

Updates Z-index layering for all cards.


CardFactory

Extends: Node

Abstract base class for creating cards. Implement this class to define custom card creation logic.

Variables

Variable Type Description
preloaded_cards Dictionary Cache for card data to improve performance
card_size Vector2 Size to apply to created cards

Abstract Methods

create_card(card_name: String, target: CardContainer) -> Card

Creates and returns a new card instance. Must be implemented by subclasses.

# In your custom factory:
func create_card(card_name: String, target: CardContainer) -> Card:
	var new_card = card_scene.instantiate()
	# Configure card...
	return new_card
preload_card_data() -> void

Preloads card data for improved performance. Called automatically by CardManager.

func preload_card_data() -> void:
	# Load and cache card data
	pass

JsonCardFactory

Extends: CardFactory

Concrete implementation of CardFactory that creates cards from JSON metadata and image assets.

Properties

Property Type Description
default_card_scene PackedScene Base card scene to instantiate
card_asset_dir String Directory containing card image files
card_info_dir String Directory containing JSON card definitions
back_image Texture2D Common back face texture for all cards

Methods

create_card(card_name: String, target: CardContainer) -> Card

Creates a card from JSON data and image assets.

var my_card = factory.create_card("ace_of_spades", target_container)

The factory looks for:

  • JSON file: {card_info_dir}/{card_name}.json
  • Image file: {card_asset_dir}/{front_image} (from JSON)

JSON Card Format

Cards are defined using JSON files with the following structure:

{
	"name": "ace_of_spades",
	"front_image": "cardSpadesA.png",
	"suit": "spades",
	"value": "A",
	"custom_property": "additional_data"
}

Required fields:

  • front_image: Filename of the card's front face image

Optional fields:

  • name: Display name for the card
  • Any additional properties for game-specific logic

Specialized Containers

Pile

Extends: CardContainer

A container that stacks cards in a pile formation with configurable direction and display options.

Enums

enum PileDirection {
    UP,     # Cards stack upward
    DOWN,   # Cards stack downward  
    LEFT,   # Cards stack leftward
    RIGHT   # Cards stack rightward
}

Properties

Property Type Default Description
stack_display_gap int 8 Pixel distance between cards in stack
max_stack_display int 6 Maximum cards to show stacked
card_face_up bool true Whether cards show front face
layout PileDirection UP Direction to stack cards
allow_card_movement bool true Whether cards can be moved
restrict_to_top_card bool true Only top card is interactive
align_drop_zone_with_top_card bool true Drop zone follows top card

Methods

get_top_cards(n: int) -> Array

Returns the top N cards from the pile.

var top_three = pile.get_top_cards(3)  # Get top 3 cards
var top_card = pile.get_top_cards(1)[0]  # Get just the top card

Usage Example

# Create a deck pile
@export var deck_pile: Pile

func _ready():
    deck_pile.layout = Pile.PileDirection.UP
    deck_pile.card_face_up = false  # Cards face down
    deck_pile.restrict_to_top_card = true
    
    # Add cards to deck
    for card_name in card_names:
        var card = card_factory.create_card(card_name, deck_pile)

Hand

Extends: CardContainer

A container that displays cards in a fan-like hand formation with curves and spacing.

Properties

Property Type Default Description
max_hand_size int 10 Maximum cards that can be held
max_hand_spread int 700 Maximum pixel spread of hand
card_face_up bool true Whether cards show front face
card_hover_distance int 30 Distance cards hover when interacted with

Curve Properties

Property Type Description
hand_rotation_curve Curve Controls rotation of cards across hand
hand_vertical_curve Curve Controls vertical positioning of cards

Drop Zone Properties

Property Type Default Description
align_drop_zone_size_with_current_hand_size bool true Drop zone adapts to hand size
swap_only_on_reorder bool false Reordering swaps positions instead of shifting

Methods

get_random_cards(n: int) -> Array

Returns N random cards from the hand without removing them.

var random_cards = hand.get_random_cards(3)
move_cards(cards: Array, index: int = -1, with_history: bool = true) -> bool

Enhanced version of CardContainer.move_cards() with hand-specific optimizations:

  • Single Card Reordering: Optimized reordering when moving cards within same hand
  • Swap Mode: Uses swap_card() when swap_only_on_reorder is enabled
  • Fallback: Uses parent implementation for external card moves
# Move card to specific position in hand
hand.move_cards([my_card], 2)  # Move to index 2

# External card move (uses parent implementation)
hand.move_cards([external_card], -1)  # Add external card to end
swap_card(card: Card, index: int) -> void

Swaps a card with the card at the specified index.

hand.swap_card(my_card, 0)  # Move card to first position

Usage Example

# Configure hand curves
@export var hand: Hand

func _ready():
    # Create rotation curve: -30° to +30°
    hand.hand_rotation_curve = Curve.new()
    hand.hand_rotation_curve.add_point(0.0, -30.0)
    hand.hand_rotation_curve.add_point(1.0, 30.0)
    
    # Create vertical curve: arc shape
    hand.hand_vertical_curve = Curve.new()
    hand.hand_vertical_curve.add_point(0.0, 0.0)
    hand.hand_vertical_curve.add_point(0.5, 50.0)  # Peak in middle
    hand.hand_vertical_curve.add_point(1.0, 0.0)

Supporting Classes

DraggableObject

Extends: Control

State machine-based drag-and-drop system with Tween animations. Provides robust interaction handling with safe state transitions and smooth visual feedback.

Enums

DraggableState

Defines possible interaction states with controlled transitions.

State Description
IDLE Default state - ready for interaction
HOVERING Mouse over with visual feedback
HOLDING Active drag state following mouse
MOVING Programmatic movement ignoring input

Properties

Property Type Default Description
moving_speed int 2000 Speed of programmatic movement (pixels/second)
can_be_interacted_with bool true Whether object responds to input
hover_distance int 10 Distance to hover when interacted with
hover_scale float 1.1 Scale multiplier when hovering
hover_rotation float 0.0 Rotation in degrees when hovering
hover_duration float 0.10 Duration for hover animations

State Management

Variable Type Description
current_state DraggableState Current interaction state
is_pressed bool Legacy compatibility - mouse pressed
is_holding bool Legacy compatibility - being dragged
stored_z_index int Original Z-index before interactions

Methods

move(target_destination: Vector2, degree: float) -> void

Moves object to target position with optional rotation using smooth Tween animation. Automatically transitions to MOVING state.

draggable.move(new_position, deg_to_rad(45))  # Move with 45° rotation
draggable.move(Vector2(100, 200), 0)         # Move without rotation
return_to_original() -> void

Returns the object to its original position with smooth animation. Sets internal tracking flag for proper position management.

draggable.return_to_original()  # Return to original position and rotation
change_state(new_state: DraggableState) -> bool

Safely transitions between interaction states using predefined rules. Returns true if transition was successful.

# Manual state transitions
if draggable.change_state(DraggableObject.DraggableState.HOVERING):
    print("Now hovering")

# State machine prevents invalid transitions
draggable.change_state(DraggableObject.DraggableState.MOVING)  # Force to MOVING

State Transition Rules:

  • IDLEHOVERING, HOLDING, MOVING
  • HOVERINGIDLE, HOLDING, MOVING
  • HOLDINGIDLE, MOVING
  • MOVINGIDLE

Virtual Methods

_on_move_done() -> void

Called when movement animation completes. Override in subclasses for custom behavior.

func _on_move_done():
    print("Movement finished")
    # Custom post-movement logic
_can_start_hovering() -> bool

Virtual method to determine if hovering animation can start. Override for custom conditions.

func _can_start_hovering() -> bool:
    return not is_card_locked  # Example: prevent hover if locked

Animation System

The new Tween-based animation system provides:

  • Smooth Transitions: All state changes use smooth animations
  • Memory Management: Proper cleanup of animation resources
  • Interrupt Handling: Safe animation interruption and cleanup
  • Performance: Optimized for multiple simultaneous animations

DropZone

Extends: Control

Handles drop detection and partitioning for card containers.

Properties

Property Type Description
sensor_size Vector2 Size of the drop detection area
sensor_position Vector2 Position offset of the sensor
sensor_texture Texture Visual texture for debugging
sensor_visible bool Whether sensor is visible
sensor_outline_visible bool Whether debug outline is visible
accept_types Array Array of acceptable drop types

Variables

Variable Type Description
vertical_partition Array Global X coordinates for vertical partitions
horizontal_partition Array Global Y coordinates for horizontal partitions

Methods

init(_parent: Node, accept_types: Array = []) -> void

Initializes the drop zone with parent reference and accepted types.

drop_zone.init(self, ["card"])
check_mouse_is_in_drop_zone() -> bool

Returns true if mouse cursor is within the drop zone area.

if drop_zone.check_mouse_is_in_drop_zone():
    # Mouse is over drop zone
set_sensor(_size: Vector2, _position: Vector2, _texture: Texture, _visible: bool) -> void

Configures the drop sensor properties.

drop_zone.set_sensor(Vector2(200, 300), Vector2(10, 10), null, false)
set_vertical_partitions(positions: Array) -> void

Sets vertical partition lines for precise drop positioning.

drop_zone.set_vertical_partitions([100, 200, 300])  # Three partition lines
set_horizontal_partitions(positions: Array) -> void

Sets horizontal partition lines for precise drop positioning.

drop_zone.set_horizontal_partitions([50, 150, 250])  # Three partition lines
get_vertical_layers() -> int

Returns the vertical partition index under the mouse cursor.

var partition = drop_zone.get_vertical_layers()
if partition != -1:
    print("Dropping in partition: ", partition)
get_horizontal_layers() -> int

Returns the horizontal partition index under the mouse cursor.


HistoryElement

Extends: Object

Represents a single card movement operation for undo functionality.

Variables

Variable Type Description
from CardContainer Source container
to CardContainer Destination container
cards Array Array of cards that were moved

Methods

get_string() -> String

Returns string representation for debugging.

var history_info = history_element.get_string()
# Returns: "from: [container_1], to: [container_2], cards: [ace_of_spades, king_of_hearts]"

Usage Patterns

Basic Setup

# Scene structure:
# CardManager (CardManager)
# ├── DeckPile (Pile)  
# ├── PlayerHand (Hand)
# └── DiscardPile (Pile)

@onready var card_manager: CardManager = $CardManager
@onready var deck: Pile = $CardManager/DeckPile
@onready var hand: Hand = $CardManager/PlayerHand

func _ready():
    # Cards are automatically managed by CardManager
    deal_initial_cards()

func deal_initial_cards():
    var cards_to_deal = deck.get_top_cards(7)
    hand.move_cards(cards_to_deal)

Custom Container

class_name CustomPile
extends CardContainer

@export var max_cards: int = 5

func _card_can_be_added(cards: Array) -> bool:
    return _held_cards.size() + cards.size() <= max_cards

func _update_target_positions():
    for i in range(_held_cards.size()):
        var card = _held_cards[i]
        var offset = Vector2(i * 20, i * 5)  # Slight offset for each card
        card.move(global_position + offset, 0)

Custom Card Factory

class_name MyCardFactory
extends CardFactory

@export var custom_card_scene: PackedScene

func create_card(card_name: String, target: CardContainer) -> Card:
    var card = custom_card_scene.instantiate()
    card.card_name = card_name
    # Custom card setup logic
    return card

func preload_card_data():
    # Custom preloading logic
    pass

This API reference provides complete documentation for all public methods and properties in the Card Framework. For implementation examples, see the included example projects and the FreeCell game demonstration.