11 KiB
11 KiB
Code of Conduct - Skelly Project
Overview
Coding standards and development practices for the Skelly project. These guidelines help developers contribute effectively while maintaining code quality and project consistency.
Core Principles
1. Code Clarity Over Cleverness
- Write code that is easy to read
- Use descriptive variable and function names
- Prefer explicit code over "clever" solutions
- Comment complex logic and business rules
2. Consistency First
- Follow existing code patterns
- Use same naming conventions throughout
- Maintain consistent indentation and formatting
- Follow Godot's GDScript style guide
3. Incremental Development
- Make small, focused commits
- Test changes before committing
- Don't break existing functionality
- Use debug system to verify changes
GDScript Coding Standards
Naming Conventions
# Variables and functions: snake_case
var player_health: int = 100
func calculate_damage() -> int:
# Constants: SCREAMING_SNAKE_CASE
const MAX_HEALTH := 100
const TILE_SPACING := 54
# Classes: PascalCase
class_name PlayerController
# Signals: past_tense
signal health_changed
signal game_started
# Private functions: prefix with underscore
func _ready():
func _initialize_grid():
File Organization
# 1. extends statement
extends Node2D
# 2. class_name (if applicable)
class_name Match3Controller
# 3. Constants
const GRID_SIZE := Vector2i(8, 8)
# 4. Signals
signal match_found(tiles: Array)
# 5. Variables
var grid := []
@onready var debug_ui = $DebugUI
# 6. Functions (lifecycle first, then custom)
func _ready():
func _process(delta):
func custom_function():
Documentation Requirements
# Required for all public functions
func set_gem_pool(gem_indices: Array) -> void:
"""Set specific gem types as the active pool"""
_update_all_tiles_gem_pool(gem_indices)
print("Set gem pool to: ", gem_indices)
# Document complex algorithms
func _get_match_line(start: Vector2i, dir: Vector2i) -> Array:
"""Find all matching tiles in a line from start position in given direction"""
var line = [grid[start.y][start.x]]
var type = grid[start.y][start.x].tile_type
# Implementation...
Project-Specific Guidelines
Scene Management
- All scene transitions go through
GameManager - Never use
get_tree().change_scene_to_file()directly - Define scene paths as constants in GameManager
# ✅ Correct
GameManager.start_match3_game()
# ❌ Wrong
get_tree().change_scene_to_file("res://scenes/game.tscn")
Autoload Usage
- Use autoloads for global state only
- Don't access autoloads from deeply nested components
- Pass data through signals or direct references when possible
# ✅ Correct - using signals
signal settings_changed
SettingsManager.volume_changed.connect(_on_volume_changed)
# ✅ Also correct - direct access for global state
var current_language = SettingsManager.get_setting("language")
# ❌ Wrong - tight coupling
func some_deep_function():
SettingsManager.set_setting("volume", 0.5) # Too deep in call stack
Debug System Integration
- Always connect to DebugManager signals for debug UI
- Use structured logging instead of plain print statements
- Remove temporary debug logs before committing (unless permanently useful)
# ✅ Correct debug integration
func _connect_to_global_debug() -> void:
DebugManager.debug_ui_toggled.connect(_on_debug_ui_toggled)
debug_ui.visible = DebugManager.is_debug_ui_visible()
# ✅ Good structured logging
DebugManager.log_debug("Debug UI toggled to: " + str(visible), "Match3")
DebugManager.log_info("Initialized " + str(tiles.size()) + " tiles", "TileSystem")
# ❌ Bad logging practices
print("test") # Not descriptive, use structured logging
print(some_variable) # No context, use proper log level
Logging Standards
- Use
DebugManager.log_*()functions instead ofprint()orpush_error() - Choose log levels based on message importance and audience
- Include categories to organize log output by system/component
- Format messages with clear, descriptive text and relevant context
# ✅ Correct logging usage
DebugManager.log_info("Game scene loaded successfully", "SceneManager")
DebugManager.log_warn("Audio file not found, using default", "AudioManager")
DebugManager.log_error("Failed to save settings: " + error_message, "Settings")
# ❌ Wrong approaches
print("loaded") # Use DebugManager.log_info() with category
push_error("error") # Use DebugManager.log_error() with context
if debug_mode: print("debug info") # Use DebugManager.log_debug()
Asset Management
- Document every asset in
assets/sources.yaml - Include source information, license details, and attribution
- Document modifications made to original assets
- Verify license compatibility before adding assets
- Update sources.yaml in same commit as adding asset
# ✅ Correct asset addition workflow
# 1. Add asset file to appropriate assets/ subdirectory
# 2. Update assets/sources.yaml with complete metadata
# 3. Commit both files together with descriptive message
# Example sources.yaml entry:
# audio:
# sfx:
# "button_click.wav":
# source: "https://freesound.org/people/user/sounds/12345/"
# license: "CC BY 3.0"
# attribution: "Button Click by SoundArtist"
# modifications: "Normalized volume, trimmed silence"
# usage: "UI button interactions"
Error Handling
- Check if resources loaded successfully
- Use
DebugManager.log_error()for critical failures - Provide fallback behavior when possible
- Include meaningful context in error messages
# Good error handling with structured logging
func load_scene(path: String) -> void:
var packed_scene := load(path)
if not packed_scene or not packed_scene is PackedScene:
DebugManager.log_error("Failed to load scene at: %s" % path, "SceneLoader")
return
DebugManager.log_info("Successfully loaded scene: %s" % path, "SceneLoader")
get_tree().change_scene_to_packed(packed_scene)
Git Workflow
Commit Guidelines
- Use clear, descriptive commit messages
- Start with a verb in imperative mood
- Keep first line under 50 characters
- Add body if needed for complex changes
# Good commit messages
Add gem pool management to match-3 system
Fix debug UI visibility toggle issue
Update documentation for new debug system
# Bad commit messages
fix bug
update
wip
Branch Management
- Create feature branches for new functionality
- Use descriptive branch names:
feature/debug-ui,fix/tile-positioning - Keep branches focused on single features
- Delete branches after merging
Before Committing
- Test your changes in the Godot editor
- Check that existing functionality still works
- Use the debug system to verify your implementation
- Run the project and navigate through affected areas
- Remove temporary debug code
Code Review Guidelines
For Reviewers
- Focus on code clarity and maintainability
- Check for adherence to project patterns
- Verify that autoloads are used appropriately
- Ensure debug integration is properly implemented
- Test the changes yourself
For Contributors
- Explain complex logic in commit messages or comments
- Provide context for why changes were made
- Test edge cases and error conditions
- Ask questions if project patterns are unclear
Testing Approach
Manual Testing Requirements
- Test in Godot editor with F5 run
- Verify debug UI works with F12 toggle
- Check scene transitions work
- Test on different screen sizes (mobile target)
- Verify audio and settings integration
Debug System Testing
- Ensure debug panels appear/disappear correctly
- Test all debug buttons and controls
- Verify debug state persists across scene changes
- Check debug code doesn't affect release builds
Common Mistakes to Avoid
Architecture Violations
# Don't bypass GameManager
get_tree().change_scene_to_file("some_scene.tscn")
# Don't hardcode paths
var tile = load("res://scenes/game/gameplays/tile.tscn")
# Don't ignore null checks
var node = get_node("SomeNode")
node.do_something() # Could crash if node doesn't exist
# Don't create global state in random scripts
# Use autoloads instead
Asset Management Violations
# Don't add assets without documentation
# Adding audio/new_music.mp3 without updating sources.yaml
# Don't use assets without verifying licenses
# Using copyrighted music without permission
# Don't modify assets without documenting changes
# Editing sprites without noting modifications in sources.yaml
# Don't commit assets and documentation separately
git add assets/sprites/new_sprite.png
git commit -m "add sprite" # Missing sources.yaml update
# Correct approach
git add assets/sprites/new_sprite.png assets/sources.yaml
git commit -m "add new sprite with attribution"
Performance Issues
# Don't search nodes repeatedly
func _process(delta):
var ui = get_node("UI") # Expensive every frame
# Cache node references
@onready var ui = $UI
func _process(delta):
ui.update_display() # Much better
Debug System Misuse
# Don't create separate debug systems
var my_debug_enabled = false
print("debug: " + some_info) # Don't use plain print()
# Use the global debug and logging systems
if DebugManager.is_debug_enabled():
show_debug_info()
DebugManager.log_debug("Debug information: " + some_info, "MyComponent")
Learning Resources
Godot-Specific
- GDScript Style Guide
- Godot Best Practices
- Project documentation in
docs/map.md
General Programming
- Clean Code principles
- SOLID principles (adapted for game development)
- Git best practices
Getting Help
When Stuck
- Check existing code for similar patterns
- Review project documentation (
docs/) - Use the debug system to understand current state
- Ask specific questions about project architecture
- Test your understanding with small experiments
Code Review Process
- Submit pull requests early and often
- Ask for feedback on approach before implementing large features
- Be open to suggestions and alternative approaches
- Learn from review feedback for future contributions
Summary
This code of conduct emphasizes:
- Clarity: Write code that others can understand
- Consistency: Follow established patterns
- Integration: Use the project's systems properly
- Learning: Continuously improve your skills
Remember: It's better to ask questions and write clear, simple code than to guess and create complex, hard-to-maintain solutions. The goal is to contribute effectively to a codebase that will grow and evolve over time.