### Component Script Attachment Example Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Illustrates the process of attaching a script to a component's root node in Godot, specifying inheritance and template options. ```gdscript # In Godot Editor: # 1. Right-click the root node of your component scene. # 2. Select "Attach Script". # 3. In the "Inherits" field, type 'Component'. # 4. Choose a base component from the "Template" dropdown. ``` -------------------------------- ### Add Combat Components to Entities Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Guidance on integrating combat capabilities into entities. This involves adding Faction, Health, and Damage components, and ensuring correct physics collision setup for interaction. ```gdscript 1. Add a `FactionComponent` and set the Faction to either `players` or `enemies` 2. Add a `HealthComponent` + `DamageReceivingComponent` * For monsters, add a `DamageComponent` to hurt the player on contact. ❕ _Remember to set the correct Physics Collision Layers and Masks for all bodies/areas, otherwise they won't be able to detect collisions with each other._ 💡 _You may also add `HealthVisualComponent` + `InvulnerabilityOnHitComponent` etc._ ``` -------------------------------- ### GDScript Enum Naming Example Source: https://github.com/invadingoctopus/comedot/blob/develop/Conventions.md Provides an example of how text names or IDs, such as for input actions, should follow camelCase conventions, similar to enum values. ```gdscript GlobalInput.Actions.yeet = &"yeet" ``` -------------------------------- ### Comedot Runtime Component Swapping: Platformer to Flying Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot facilitates dynamic gameplay changes at runtime by allowing components to be added or removed. An example is swapping between platformer physics and flying/overhead movement by dynamically changing the active movement component. ```gdscript ## Runtime Component Swapping Comedot's architecture enables dynamic modification of an entity's behavior at runtime by adding or removing components. This is particularly useful for implementing state changes or different movement modes. **Example:** Switching between platformer physics and flying/overhead movement. **Scenario:** A player character can transition from standard platformer controls to a free-flying mode. **Implementation:** 1. **Define Movement Components:** Create separate components for each movement type (e.g., `PlatformerMovementComponent`, `FlyingMovementComponent`). 2. **Manage Components:** The entity or a dedicated manager component will handle adding and removing these components. ```gdscript # Assuming an Entity node with a 'MovementManager' component or similar # The Entity itself might have methods to add/remove components. # In PlayerMovementManager.gd (attached to the player entity): # extends Node # @export var platformer_component_path: PackedScene # @export var flying_component_path: PackedScene # var current_movement_component = null # func _ready(): # # Start with platformer movement # set_movement_mode("platformer") # func set_movement_mode(mode: String): # # Remove existing component if any # if current_movement_component: # remove_child(current_movement_component) # current_movement_component.queue_free() # current_movement_component = null # # Add new component based on mode # if mode == "platformer": # current_movement_component = platformer_component_path.instantiate() # add_child(current_movement_component) # # Initialize platformer component if needed # elif mode == "flying": # current_movement_component = flying_component_path.instantiate() # add_child(current_movement_component) # # Initialize flying component if needed # Example of triggering the switch: # func _input(event): # if event.is_action_pressed("toggle_flight"): # if current_movement_component is PlatformerMovementComponent: # set_movement_mode("flying") # else: # set_movement_mode("platformer") # The PlatformerMovementComponent would handle gravity, jumping, etc. # The FlyingMovementComponent would handle free movement in 2D space. ``` This dynamic component management allows for fluid transitions between different gameplay states and abilities without requiring the entity to reload or change its fundamental structure. ``` -------------------------------- ### Debugging with Comedot Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Provides information on using Comedot's debugging features, including the `debugMode` property and the `Debug.gd` AutoLoad script for enhanced logging and visualization. ```apidoc Debug Properties & Methods: debugMode (property on Components/Scripts) - Enables extra debug information and visual cues. Debug.gd (AutoLoad Script): printTrace() - Prints detailed trace information to the logs. printHighlight(message) - Prints a highlighted message to the logs. DebugComponent/ChartWindow/Chart (for real-time monitoring): - Monitor variables and properties in real-time graphs. - Example path: `../CharacterBodyComponent:body:velocity:x` ``` -------------------------------- ### Instantiate Component Scenes in Godot Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Explains the correct method for adding components to entities in Godot, emphasizing the use of 'Instantiate Child Scene' over 'Add Child Node' to ensure all component properties and child nodes are included. ```gdscript * Use **"Instantiate Child Scene"** (SHIFT+Control/Command+A) ❌ Do **NOT** use "Add Child Node" (Control/Command+A): This will not include the component's child nodes or other properties. * Drag the `.tscn` Scene file of a Component from the FileSystem Dock to add it as a child node of an Entity. ❌ Do **NOT** drag a Component's `.gd` Script file to an Entity node; entities should only have a Script which `extends Entity` or `TurnBasedEntity` 📖 _Read the documentation comments in the script of each component to see how to use it._ ``` -------------------------------- ### Turn-Based Game Flow Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Details the lifecycle methods for turn-based components within the TurnBasedCoordinator system. Components should implement these methods to define their behavior during each turn phase. ```apidoc TurnBasedCoordinator: startTurnProcess() - Initiates the turn processing cycle. TurnBasedComponent Lifecycle: processTurnBegin() - Called at the start of a turn for each component. processTurnUpdate() - Called during the main update phase of a turn. processTurnEnd() - Called at the end of a turn for each component. ``` -------------------------------- ### Add Player Control Components Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Instructions for adding control and physics components to a player entity in Godot. It details specific component combinations for different movement types like platformer or overhead movement. ```gdscript 1. Select the Player Entity Node in the Godot Scene Editor. 2. Add components from `/Components/Control/` and `/Components/Physics/` as children of the Entity node. For platformer "run and jump" movement: `PlatformerControlComponent` + `JumpControlComponent` + `PlatformerPhysicsComponent` For "overhead" RPG or flying movement: `OverheadControlComponent` + `OverheadPhysicsComponent` 3. Add `/Components/Physics/CharacterBodyComponent.tscn` as the _last_ component in the Entity's tree. This component takes the velocity updates from other components and applies them to the Entity's `CharacterBody2D`. ``` -------------------------------- ### Extending Component Functionality Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Demonstrates how to subclass an existing component script in GDScript, allowing for custom features while retaining original functionality via `super` calls. ```gdscript extends DamageComponent func take_damage(amount): # Custom logic before calling the original function print("Taking extra damage!") super.take_damage(amount) # Call the original function # Custom logic after calling the original function print("Damage taken.") ``` -------------------------------- ### Create Player Entity in Godot Source: https://github.com/invadingoctopus/comedot/blob/develop/HowTo.md Steps to create a player entity in the Godot Engine. This involves creating a CharacterBody2D node, attaching a specific script, adding visual and collision components, and configuring physics layers. ```gdscript 1. Create a `CharacterBody2D` Node. 2. Attach the `/Entities/Characters/PlayerEntity.gd` Script. 3. Add other necessary nodes like `Sprite2D` or `AnimatedSprite2D`, `Camera2D` and set them up. 4. Set the Body's Physics Collision Layer to `players` and the Mask to `terrain`. Add other categories as needed. ``` -------------------------------- ### Comedot Settings System: Save/Load Preferences Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot includes a utility for saving and loading player preferences via a simple configuration file. This system allows for easy persistence of game settings using a straightforward key-value assignment syntax. ```gdscript ## Settings System Comedot provides a simple way to manage game settings and preferences, allowing them to be saved to and loaded from a configuration file. **Saving Settings:** Settings can be assigned directly, and the system handles persistence. ```gdscript # Accessing the settings manager (assuming it's globally available or via a singleton) Settings.player_volume = 0.8 Settings.graphics_quality = "high" Settings.auto_save = true # The system automatically saves these changes to a config file. # Example: Settings.anyName = 69 ``` **Loading Settings:** Settings are automatically loaded when the game starts or when the settings manager is initialized. You can then access them like any other variable. ```gdscript var current_volume = Settings.player_volume print("Player volume is set to: ", current_volume) if Settings.auto_save: print("Auto-save is enabled.") ``` This system simplifies the process of managing user preferences, such as audio levels, graphics settings, or control schemes, ensuring a consistent player experience across sessions. ``` -------------------------------- ### Comedot API: Component and Entity Management Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot provides an API for managing components attached to entities. This includes methods for adding, removing, and retrieving components, facilitating the dynamic composition of game objects. ```APIDOC ## Comedot Entity-Component API This API outlines the core functionalities for managing components attached to entities within the Comedot framework. **Entity Object (Conceptual):** Represents a game object that can have multiple components attached to it. **Component Object (Conceptual):** Represents a piece of functionality or data that can be attached to an Entity. --- ### Entity Methods **1. `add_component(component: Node)`** - **Description**: Attaches a given component to the entity. - **Parameters**: - `component`: The component instance (a Godot Node) to add. - **Returns**: `void` - **Notes**: The component is typically added as a child node to the entity. **2. `remove_component(component: Node)`** - **Description**: Removes a specific component from the entity. - **Parameters**: - `component`: The component instance to remove. - **Returns**: `void` - **Notes**: The component is removed from the entity's children and should be freed. **3. `get_component(component_type: String or Node)`** - **Description**: Retrieves a component attached to the entity. - **Parameters**: - `component_type`: The type (class name as String) or the Node instance of the component to find. - **Returns**: The component Node instance if found, otherwise `null`. - **Example**: `var movement_comp = entity.get_component("MovementComponent")` **4. `has_component(component_type: String or Node)`** - **Description**: Checks if the entity has a component of the specified type. - **Parameters**: - `component_type`: The type (class name as String) or the Node instance of the component to check for. - **Returns**: `true` if the component exists, `false` otherwise. --- ### Component Lifecycle Integration Components are expected to integrate with Godot's node lifecycle. - **`_ready()`**: Called when the component is added and ready. - **`_process(delta)` / `_physics_process(delta)`**: For frame-by-frame or physics updates. - **`_exit_tree()`**: Called when the component is removed from the scene tree. --- ### Example Usage Scenario: ```gdscript # Assuming 'player' is an Entity node # Add a movement component var movement_comp = preload("res://components/PlayerMovement.gd").new() player.add_component(movement_comp) # Add a health component var health_comp = preload("res://components/HealthComponent.gd").new() player.add_component(health_comp) # Accessing components if player.has_component("PlayerMovement"): player.get_component("PlayerMovement").set_speed(150) # Triggering an action via component player.get_component("HealthComponent").take_damage(10) # Removing a component # player.remove_component(movement_comp) ``` This API provides a robust foundation for building complex game entities through the composition of modular components. ``` -------------------------------- ### Comedot Tools.gd: Reusable Logic and Debugging Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md The `Tools.gd` script within Comedot contains a collection of helper functions and debugging tools. Developers are encouraged to copy and utilize these utilities in their own projects, as they address common programming patterns and potential edge cases. ```gdscript ## Tools.gd - Helper Functions The `Tools.gd` file in Comedot is a repository of useful utility functions designed to streamline development and assist with debugging. **Purpose:** - Provides common helper functions that can be reused across different projects. - Offers debugging aids and utilities to inspect game state. **Usage:** Developers can copy the `Tools.gd` script or specific functions from it into their own projects. ```gdscript # Example: Copying a function from Tools.gd # Assume 'Tools.gd' has a function like 'is_vector_zero(vec)' # In your script: # extend Node # You might copy the function directly or use a singleton pattern # For direct copy: # func is_vector_zero(vec): # return vec.x == 0 and vec.y == 0 # Or if Tools.gd is a singleton: # func _ready(): # var my_vector = Vector2(0, 0) # if Tools.is_vector_zero(my_vector): # print("Vector is zero!") # The script contains functions for various purposes, such as: # - Math utilities # - String manipulation # - Debug printing with context # - Input handling helpers # - Scene management utilities # It's recommended to review the contents of Tools.gd for specific utilities that can benefit your project. ``` This practice allows developers to leverage well-tested code for common tasks, saving time and reducing the likelihood of introducing bugs. ``` -------------------------------- ### Comedot Debugging: Real-time Variable Monitoring Charts Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot includes utilities for real-time monitoring of game variables through visual charts. This feature aids in debugging and understanding game state by providing immediate feedback on variable changes during gameplay. ```gdscript ## Debugging with Real-time Charts Comedot offers integrated tools for debugging and performance analysis, including the ability to display real-time charts of game variables. **Purpose:** - Visualize the behavior of key game variables (e.g., player health, enemy count, score) over time. - Identify performance bottlenecks or unexpected variable fluctuations. **Usage:** Developers can typically enable these charts through a debug menu or by calling specific functions. ```gdscript # Assuming a DebugUI singleton or manager that handles chart display: # func _ready(): # # Enable the debug UI overlay # DebugUI.show_overlay() # func _process(delta): # # Add variables to be monitored # DebugUI.add_variable_to_chart("Player Health", player.health) # DebugUI.add_variable_to_chart("Enemies Alive", get_tree().get_nodes_in_group("enemies").size()) # DebugUI.add_variable_to_chart("Delta Time", delta) # The DebugUI system would then render these variables as line graphs on screen. # This might involve creating custom UI elements or using Godot's built-in GraphNode. # Example of how a variable might be added: # class DebugUI: # static var charts = {} # static var chart_data_limit = 100 # Number of points to keep # static func add_variable_to_chart(name: String, value): # if not charts.has(name): # charts[name] = [] # charts[name].append(value) # if charts[name].size() > chart_data_limit: # charts[name].pop_front() # static func get_chart_data(name): # return charts.get(name, []) # # ... rendering logic for the charts ... ``` These visual debugging tools are invaluable for understanding complex game systems and ensuring that mechanics are functioning as intended. ``` -------------------------------- ### Comedot Composition Architecture: Gun and Mouse Rotation Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot's composition architecture allows for flexible game object behavior by attaching multiple components, such as a `GunComponent` and `MouseRotationComponent`, to any entity. This enables dynamic combinations of abilities and interactions, exemplified by an object that can shoot and rotate towards the mouse. ```gdscript ## Composition Architecture Example Comedot's composition-over-inheritance model allows for flexible and dynamic behavior by attaching multiple components to a single entity. **Scenario:** An entity that can shoot a projectile and rotate its orientation to face the mouse cursor. **Components Involved:** - `GunComponent`: Handles shooting mechanics (e.g., firing rate, projectile spawning). - `MouseRotationComponent`: Handles rotating the entity to face the mouse cursor. **Implementation:** Attach both components to a single entity (e.g., a player character, an enemy, or a turret). ```gdscript # Assuming an Entity node with the following components attached: # - Sprite2D (visual representation) # - GunComponent (script for shooting) # - MouseRotationComponent (script for rotating to mouse) # In the main scene or entity script: # extend Node2D # @onready var gun_component = $GunComponent # @onready var rotation_component = $MouseRotationComponent # func _process(delta): # # MouseRotationComponent handles its own rotation logic based on mouse position # # GunComponent might be triggered by player input # if Input.is_action_just_pressed("fire"): # gun_component.fire() # The MouseRotationComponent would typically look something like this: # class MouseRotationComponent extends Node: # func _process(delta): # var mouse_pos = get_global_mouse_position() # var direction = (mouse_pos - owner.global_position).normalized() # owner.rotation = direction.angle() # The GunComponent would handle projectile spawning: # class GunComponent extends Node: # export var projectile_scene: PackedScene # export var fire_rate = 0.5 # var can_fire = true # # func fire(): # if can_fire: # var projectile = projectile_scene.instantiate() # # Position and orient projectile # projectile.global_position = owner.global_position # projectile.rotation = owner.rotation # get_tree().current_scene.add_child(projectile) # can_fire = false # # Use a Timer or Timer node to reset can_fire # # $FireTimer.start() ``` This composition allows for great flexibility: the same `GunComponent` can be used on different entities, and the `MouseRotationComponent` can be applied to any object that needs to face the mouse, without complex inheritance or code duplication. ``` -------------------------------- ### GDScript Signal Naming Conventions Source: https://github.com/invadingoctopus/comedot/blob/develop/Conventions.md Illustrates recommended naming patterns for signals in GDScript, focusing on tense (did/will) and object/action order for clarity and consistency. ```gdscript signal healthDidZero signal didFire(bullet: Entity) signal didSpawn(newSpawn: Node2D, parent: Node2D) signal willRemoveFromEntity ``` -------------------------------- ### Comedot Core Concepts: Entities and Components Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot uses 'Entities' and 'Components' as core building blocks for gameplay, analogous to Godot Nodes. This architecture allows for flexible composition of game logic by attaching various components to entities, enabling dynamic behavior and easy modification. ```gdscript ## Entities and Components Comedot's architecture revolves around Entities and Components. - **Entities**: Similar to Godot Nodes, they are the base objects in your game world. - **Components**: These are scripts or data containers that add specific functionalities or properties to Entities. By attaching components to entities, you can build complex game objects and behaviors without deep inheritance hierarchies. **Example Usage (Conceptual):** ```gdscript # Assuming an Entity node exists var player_entity = get_node("Player") # Add a movement component var movement_component = preload("res://components/MovementComponent.gd").new() player_entity.add_component(movement_component) # Add a combat component var combat_component = preload("res://components/CombatComponent.gd").new() player_entity.add_component(combat_component) # Components can be accessed and used player_entity.get_component("MovementComponent").move_left() player_entity.get_component("CombatComponent").attack() ``` This approach promotes modularity and reusability, allowing for rapid iteration and easier management of game logic. ``` -------------------------------- ### Comedot Gameplay Edge Cases: Collectibles and Climbing Source: https://github.com/invadingoctopus/comedot/blob/develop/README.md Comedot's components are designed to handle tricky gameplay edge cases, such as ensuring collectibles are only picked up when needed and implementing robust climbing mechanics. These features aim to improve the 'feel' of the game by addressing common player interaction issues. ```gdscript ## Gameplay Edge Case Handling Comedot components are engineered to manage complex gameplay scenarios and player interactions, ensuring a polished experience. **1. Smart Collectibles:** Collectibles (like health or ammo) are designed to be picked up only if the player's corresponding stat is not already at maximum. If the player's stat drops while they are still standing on the item, it can then be picked up. ```gdscript # Conceptual example of a collectible pickup logic: # In Player script: # func _on_Collectible_body_entered(body): # if body.is_in_group("Player"): # var collectible_item = get_parent() # Assuming collectible is parent # var stat_to_increase = collectible_item.stat_type # e.g., "health" # var current_stat = body.get_stat(stat_to_increase) # var max_stat = body.get_max_stat(stat_to_increase) # # if current_stat < max_stat: # body.increase_stat(stat_to_increase, collectible_item.value) # collectible_item.queue_free() # Remove collectible # else: # # Player's stat is already max, item remains until stat drops # pass ``` **2. Advanced Climbing Mechanics:** Handles nuanced climbing interactions, such as: - Grabbing a ladder/rope while holding the climb input mid-jump. - Aligning the player with the ladder if not perfectly centered. - Allowing horizontal movement on fences or ledges. ```gdscript # Conceptual example of climbing input handling: # In PlayerMovementComponent: # func _process(delta): # if Input.is_action_pressed("climb"): # if is_on_ladder(): # # Handle vertical movement on ladder # var direction = Input.get_axis("move_up", "move_down") # velocity.y = direction * climb_speed # # Snap to ladder center if not aligned # if not is_aligned_to_ladder(): # snap_to_ladder_center() # elif is_jumping_towards_ladder(): # # Allow grabbing ladder mid-jump if close enough # snap_to_ladder_center() # velocity.y = 0 # Stop vertical momentum # # Transition to climbing state # elif Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"): # if is_on_fence(): # # Handle horizontal movement on fences # var direction = Input.get_axis("move_left", "move_right") # velocity.x = direction * fence_move_speed ``` These features contribute to a more responsive and forgiving player experience by anticipating and managing common player inputs and environmental interactions. ``` -------------------------------- ### GDScript Signal Handler Naming Conventions Source: https://github.com/invadingoctopus/comedot/blob/develop/Conventions.md Demonstrates the convention for naming functions that handle signals, typically prefixed with 'on' followed by the emitter and signal name, or just the signal name if within the emitter's script. ```gdscript func onCollectibleComponent_didCollideCollector(…) func onGunComponent_ammoDepleted() func onHealthChanged(…) func onTimeout() # in the script of a Timer node ``` -------------------------------- ### Coding Conventions: Avoiding Sentinel Values Source: https://github.com/invadingoctopus/comedot/blob/develop/Conventions.md This snippet illustrates a recommended coding practice to avoid using special numerical values like -1 to indicate invalid states. Instead, it suggests using separate boolean flags for clarity and to simplify downstream calculations. ```General // Instead of: // maxLevel = -1 // Use: allowInfiniteLevels = true ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.