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 containerfrom_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_reorderis 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:
IDLE→HOVERING,HOLDING,MOVINGHOVERING→IDLE,HOLDING,MOVINGHOLDING→IDLE,MOVINGMOVING→IDLE
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.