A complete procedural 2D dungeon map generation system using the Wave Function Collapse (WFC) algorithm, built with Godot Engine.
- Wave Function Collapse Algorithm: Generates dungeons using entropy-based tile selection with constraint propagation
- Deterministic Generation: Same seed produces identical dungeons every time
- Tileset System: Configurable tile adjacency rules for consistent dungeon layouts
- Interactive GUI: Real-time parameter adjustment and visualization
- Error Handling: Comprehensive validation and user-friendly error messages
- Customizable: Easy to modify tileset and generation parameters
- Godot Engine 4.2 or later
- No additional dependencies required
-
Open in Godot:
- Download and install Godot Engine 4.2+ from godotengine.org
- Open Godot and click "Import"
- Navigate to the project folder and select
project.godot - Click "Import & Edit"
-
Run the Project:
- Press F5 or click the "Play" button in Godot
- The main scene will launch with the dungeon generator interface
-
Prepare Your Tileset:
- Create a tileset image with tiles arranged in a grid
- Each tile should be the same size (default: 32x32 pixels)
- Tiles are arranged left-to-right, top-to-bottom
- Supported formats: PNG, JPEG
- See TILESET_GUIDE.md for detailed instructions
-
Load Tileset:
- Click the "Load Tileset Image" button
- Select your tileset image file
- The system will automatically detect and load all tiles
-
Using the Default Tileset:
- On startup, the system uses a built-in procedurally generated tileset
- You can always revert to this by restarting the application
-
Set Parameters:
- Seed: Enter a numeric seed value or click "Random Seed" for a random one
- Grid Width: Set the width of the dungeon (5-100 tiles)
- Grid Height: Set the height of the dungeon (5-100 tiles)
-
Generate:
- Click the "Generate Dungeon" button
- The system will create a dungeon layout based on your parameters
- The generated dungeon appears in the main viewport
-
Deterministic Generation:
- Note the seed value used for generation
- Use the same seed later to recreate the exact same dungeon
- Different seeds produce different layouts
The default tileset includes 8 tile types:
- Floor (Light Gray): Open walkable space
- Wall (Dark Gray): Solid walls
- Corridor H (Blue-Gray): Horizontal corridors
- Corridor V (Green-Gray): Vertical corridors
- Corner NW (Red-ish): Northwest room corner
- Corner NE (Green-ish): Northeast room corner
- Corner SW (Blue-ish): Southwest room corner
- Corner SE (Yellow-ish): Southeast room corner
TestEntrophyEngine/
├── project.godot # Godot project configuration
├── README.md # This file
├── icon.svg # Project icon
├── .gitignore # Git ignore rules
├── scenes/
│ └── Main.tscn # Main scene with GUI and tilemap
├── scripts/
│ ├── WFCGenerator.gd # Core WFC algorithm implementation
│ ├── TilesetManager.gd # Tileset and adjacency rules manager
│ ├── MainController.gd # GUI and generation controller
│ └── ErrorHandler.gd # Error handling and logging
└── assets/
├── tileset_config.json # Tileset configuration (optional)
├── sample_tilesets/ # Sample tileset images
│ └── sample_tileset.png # Example tileset (8 tiles, 128x64)
└── tiles/ # Future tile images (optional)
The WFC algorithm works by:
- Initialization: Start with a grid where each cell can be any tile
- Entropy Calculation: Find cells with the fewest possible tiles
- Collapse: Choose a random tile for the lowest entropy cell (weighted by tile probabilities)
- Constraint Propagation: Update neighboring cells to only allow tiles that are compatible
- Repeat: Continue until all cells are collapsed or a contradiction occurs
- Backtracking: If a contradiction occurs (no valid tiles for a cell), restart with the same seed
- Entropy-based selection: Always chooses the cell with minimum entropy (most constrained)
- Weighted tile selection: Tiles have weights that affect their selection probability
- Deterministic RNG: Seeded random number generator ensures reproducibility
- Constraint propagation: Efficiently propagates constraints to all affected neighbors
- Automatic restart: Handles contradictions by restarting generation
The easiest way to use custom graphics is to load a tileset image:
-
Create a Tileset Image:
- Arrange your tiles in a grid (e.g., 4x2 for 8 tiles)
- Each tile must be the same size (32x32 pixels recommended)
- Save as PNG or JPEG
-
Example Tileset Layout (128x64 pixels, 8 tiles):
Row 0: Floor | Wall | Corridor_H | Corridor_V Row 1: Corner_NW | Corner_NE | Corner_SW | Corner_SE -
Load in Application:
- Use the "Load Tileset Image" button in the UI
- The system automatically detects tiles and creates a tileset
- Initial adjacency rules allow all tiles to connect
-
Sample Tileset:
- A sample tileset is provided in
assets/sample_tilesets/sample_tileset.png - An advanced 16-tile set is also available:
assets/sample_tilesets/advanced_tileset.png - This matches the default procedural tileset layout
- A sample tileset is provided in
You can modify the tileset by editing scripts/TilesetManager.gd:
- Locate the
_create_default_tileset()function - Modify existing tile definitions or add new ones
- Each tile requires:
id: Unique integer identifiername: Descriptive nameweight: Probability weight (higher = more likely)allowed_neighbors: Dictionary with arrays for each direction (up, down, left, right)
Example tile definition:
tiles[0] = {
"id": 0,
"name": "Floor",
"weight": 3.0,
"allowed_neighbors": {
"up": [0, 1, 3],
"down": [0, 1, 3],
"left": [0, 1, 2],
"right": [0, 1, 2]
}
}You can also load tilesets from JSON files:
- Create a JSON file in
assets/(seeassets/tileset_config.jsonfor format) - Modify
MainController.gdto calltileset_manager.load_from_json(path) - The system will validate and load your custom tileset
- Seed: Controls the random number generation. Same seed = same result
- Grid Width: Number of tiles horizontally (affects generation time)
- Grid Height: Number of tiles vertically (affects generation time)
- Tile Weights: Higher weight = more likely to appear (defined in tileset)
The system validates:
- Grid dimensions (must be positive)
- Tileset data structure
- Adjacency rule consistency
- Generation constraints
Errors are:
- Logged to the console
- Displayed in a popup dialog
- Prevent invalid generation from starting
Generation takes too long:
- Reduce grid size
- Simplify adjacency rules
- Check for overly restrictive constraints
Generation fails (contradiction):
- Try a different seed
- Adjust adjacency rules to be less restrictive
- Ensure all tiles have valid neighbors
No dungeon appears:
- Check the console for error messages
- Verify tileset is loaded correctly
- Ensure grid dimensions are valid
- New Tile Types: Add to
TilesetManager.gdwith adjacency rules - Custom Graphics: Replace the procedural texture in
MainController.gd - New Parameters: Add UI controls and wire to generation logic
- Advanced WFC: Modify
WFCGenerator.gdfor different algorithms
The system includes built-in validation:
- Tileset validation on load
- Parameter validation before generation
- Constraint checking during propagation
This project is open source and available for educational and commercial use.
Created as a demonstration of the Wave Function Collapse algorithm for procedural generation.
(Screenshots will be added after first successful generation)
- Export generated dungeons as images
- Save/load dungeon layouts
- More complex tile types and rules
- 3D visualization option
- Procedural texture generation for tiles
- Multiple room types and biomes
- Load custom tileset images
- UI for editing adjacency rules for custom tilesets
- Auto-detect tile adjacency from sample maps
- Support for different tile sizes in UI
- Format: PNG or JPEG
- Layout: Grid arrangement (tiles go left-to-right, top-to-bottom)
- Tile Size: All tiles must be the same size (32x32 recommended)
- Size: Image width and height must be multiples of tile size
For an 8-tile set with 32x32 tiles:
- Image size: 128x64 (4 columns × 2 rows)
- Tile 0: Position (0,0) - Top-left
- Tile 1: Position (32,0) - Second from left, top row
- Tile 7: Position (96,32) - Bottom-right
- Keep it Simple: Start with 4-8 tiles for initial testing
- High Contrast: Use distinct colors/patterns for each tile type
- Clear Borders: Add borders to tiles for visual clarity
- Test Iteratively: Load, generate, adjust, and reload
When you load a custom tileset image:
- All tiles initially have "allow all" adjacency rules
- This may produce less structured results than the default tileset
- For best results, the tileset should have similar semantic meaning to the default (floor, walls, corridors, corners)
- Future versions will include a UI to configure adjacency rules