├── icon.png ├── sprites.png ├── Screenshot (286).png ├── Screenshot (287).png ├── Screenshot (288).png ├── default_env.tres ├── maze_generator.tscn ├── tileset.tscn ├── README.md ├── icon.png.import ├── sprites.png.import ├── project.godot ├── tileset.tres ├── LICENSE └── maze_generator.gd /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/HEAD/icon.png -------------------------------------------------------------------------------- /sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/HEAD/sprites.png -------------------------------------------------------------------------------- /Screenshot (286).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/HEAD/Screenshot (286).png -------------------------------------------------------------------------------- /Screenshot (287).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/HEAD/Screenshot (287).png -------------------------------------------------------------------------------- /Screenshot (288).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/HEAD/Screenshot (288).png -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /maze_generator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://tileset.tres" type="TileSet" id=1] 4 | [ext_resource path="res://maze_generator.gd" type="Script" id=2] 5 | 6 | [node name="maze_generator" type="TileMap"] 7 | position = Vector2( -4, -4 ) 8 | tile_set = ExtResource( 1 ) 9 | cell_size = Vector2( 8, 8 ) 10 | format = 1 11 | tile_data = PoolIntArray( 3473436, 0, 0 ) 12 | script = ExtResource( 2 ) 13 | -------------------------------------------------------------------------------- /tileset.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://sprites.png" type="Texture" id=1] 4 | 5 | [node name="tileset" type="Node2D"] 6 | 7 | [node name="0" type="Sprite" parent="."] 8 | texture = ExtResource( 1 ) 9 | vframes = 2 10 | hframes = 3 11 | frame = 3 12 | 13 | [node name="1" type="Sprite" parent="."] 14 | position = Vector2( 8, 0 ) 15 | texture = ExtResource( 1 ) 16 | vframes = 2 17 | hframes = 3 18 | frame = 4 19 | 20 | [node name="2" type="Sprite" parent="."] 21 | position = Vector2( 20, 0 ) 22 | texture = ExtResource( 1 ) 23 | vframes = 2 24 | hframes = 3 25 | frame = 5 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # maze-generator-godot 2 | Maze generation with godot engine using Recursive Backtracking algorithm 3 | 4 | ## Notes 5 | 6 | MAZE SIZE must be an odd Vector2, such as Vector2 (11, 11), Vector2 (31,17), Vector2 (25,13), etc. 7 | 8 | ## Screenshots 9 | 10 | ![Screenshot 1](https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/master/Screenshot%20(286).png) 11 | ![Screenshot 2](https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/master/Screenshot%20(287).png) 12 | ![Screenshot 3](https://raw.githubusercontent.com/DeybisMelendez/maze-generator-godot/master/Screenshot%20(288).png) 13 | -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sprites.png-4ccbd8259ebc1e8488fec7711c8727a8.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites.png" 13 | dest_files=[ "res://.import/sprites.png-4ccbd8259ebc1e8488fec7711c8727a8.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ ] 12 | _global_script_class_icons={ 13 | 14 | } 15 | 16 | [application] 17 | 18 | config/name="Maze Generator" 19 | run/main_scene="res://maze_generator.tscn" 20 | config/icon="res://icon.png" 21 | 22 | [display] 23 | 24 | window/size/width=256 25 | window/size/height=144 26 | window/size/test_width=640 27 | window/size/test_height=360 28 | window/stretch/mode="2d" 29 | window/stretch/aspect="keep" 30 | 31 | [rendering] 32 | 33 | environment/default_environment="res://default_env.tres" 34 | -------------------------------------------------------------------------------- /tileset.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="TileSet" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://sprites.png" type="Texture" id=1] 4 | 5 | [resource] 6 | 0/name = "0" 7 | 0/texture = ExtResource( 1 ) 8 | 0/tex_offset = Vector2( 0, 0 ) 9 | 0/modulate = Color( 1, 1, 1, 1 ) 10 | 0/region = Rect2( 0, 8, 8, 8 ) 11 | 0/tile_mode = 0 12 | 0/occluder_offset = Vector2( 4, 4 ) 13 | 0/navigation_offset = Vector2( 4, 4 ) 14 | 0/shapes = [ ] 15 | 0/z_index = 0 16 | 1/name = "1" 17 | 1/texture = ExtResource( 1 ) 18 | 1/tex_offset = Vector2( 0, 0 ) 19 | 1/modulate = Color( 1, 1, 1, 1 ) 20 | 1/region = Rect2( 8, 8, 8, 8 ) 21 | 1/tile_mode = 0 22 | 1/occluder_offset = Vector2( 4, 4 ) 23 | 1/navigation_offset = Vector2( 4, 4 ) 24 | 1/shapes = [ ] 25 | 1/z_index = 0 26 | 2/name = "2" 27 | 2/texture = ExtResource( 1 ) 28 | 2/tex_offset = Vector2( 0, 0 ) 29 | 2/modulate = Color( 1, 1, 1, 1 ) 30 | 2/region = Rect2( 16, 8, 8, 8 ) 31 | 2/tile_mode = 0 32 | 2/occluder_offset = Vector2( 4, 4 ) 33 | 2/navigation_offset = Vector2( 4, 4 ) 34 | 2/shapes = [ ] 35 | 2/z_index = 0 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Deybis Melendez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /maze_generator.gd: -------------------------------------------------------------------------------- 1 | extends TileMap 2 | 3 | export var generate_on_ready = true 4 | export var MAZE_SIZE = Vector2(31,17) 5 | export var MAZE_POS = Vector2(1, 1) 6 | export var WALL_ID = 0 7 | export var PATH_ID = 1 8 | export var LIMIT_ID = 2 9 | const DIRECTIONS = [ 10 | Vector2.UP * 2, 11 | Vector2.DOWN * 2, 12 | Vector2.RIGHT * 2, 13 | Vector2.LEFT * 2, 14 | ] 15 | var current_cell = Vector2.ONE 16 | var visited_cells = [current_cell] 17 | var stack = [] 18 | var cells = [] 19 | 20 | func _ready(): 21 | current_cell += MAZE_POS - Vector2.ONE 22 | if generate_on_ready: 23 | generate_maze() 24 | 25 | func _input(event): 26 | if event.is_action_pressed("ui_accept"): 27 | generate_maze() 28 | 29 | ### MAZE GENERATION ### 30 | 31 | func generate_maze(): 32 | #Clear the maze 33 | visited_cells = [current_cell] 34 | stack.clear() 35 | # Create walls 36 | for x in MAZE_SIZE.x: 37 | for y in MAZE_SIZE.y: 38 | set_cell(x+MAZE_POS.x, y+MAZE_POS.y, WALL_ID) 39 | # Create limits 40 | for x in MAZE_SIZE.x+2: 41 | set_cell(x+MAZE_POS.x-1, MAZE_POS.y-1, LIMIT_ID) 42 | set_cell(x+MAZE_POS.x-1, MAZE_POS.y-2, LIMIT_ID) 43 | for x in MAZE_SIZE.x+2: 44 | set_cell(x+MAZE_POS.x-1, MAZE_SIZE.y + MAZE_POS.y, LIMIT_ID) 45 | set_cell(x+MAZE_POS.x-1, MAZE_SIZE.y + MAZE_POS.y+1, LIMIT_ID) 46 | for y in MAZE_SIZE.y: 47 | set_cell(MAZE_POS.x-1, MAZE_POS.y + y , LIMIT_ID) 48 | set_cell(MAZE_POS.x-2, MAZE_POS.y + y , LIMIT_ID) 49 | for y in MAZE_SIZE.y: 50 | set_cell(MAZE_SIZE.x + MAZE_POS.x, MAZE_POS.y + y , LIMIT_ID) 51 | set_cell(MAZE_SIZE.x + MAZE_POS.x+1, MAZE_POS.y + y , LIMIT_ID) 52 | #create cells 53 | for x in (MAZE_SIZE.x+1)/2: 54 | for y in (MAZE_SIZE.y + 1)/2: 55 | set_cell(MAZE_POS.x + 2 * x , MAZE_POS.y + 2 * y, PATH_ID) 56 | #get cells 57 | cells = get_used_cells_by_id(PATH_ID) 58 | #generate maze 59 | while visited_cells.size() < cells.size(): 60 | var neighbours = neighbours_have_not_been_visited(current_cell) 61 | if neighbours.size() > 0: 62 | var random_neighbour = neighbours[randi()%neighbours.size()] 63 | stack.push_front(current_cell) 64 | var wall = (random_neighbour - current_cell)/2 + current_cell 65 | set_cell(int(wall.x), int(wall.y), 1) 66 | current_cell = random_neighbour 67 | visited_cells.append(current_cell) 68 | elif stack.size() > 0: 69 | current_cell = stack[0] 70 | stack.pop_front() 71 | 72 | func neighbours_have_not_been_visited(cell): 73 | var neighbours = [] 74 | for dir in DIRECTIONS: 75 | if not visited_cells.has(cell + dir) and get_cell(int(cell.x + dir.x), int(cell.y + dir.y)) != LIMIT_ID: 76 | neighbours.append(cell + dir) 77 | return neighbours 78 | --------------------------------------------------------------------------------