├── global.gd ├── icon.png ├── example.gif ├── assets ├── grid.png ├── tile.png ├── frame.png ├── grid.png.import ├── tile.png.import └── frame.png.import ├── .import ├── frame.png-3ac25dcfa39cb943440d117e36cbfa2f.md5 ├── frame.png-b49da370ab5b416325f31bcd38e64bfc.md5 ├── grid.png-0e5acf495abafdc7f64f9b213a44aa0e.md5 ├── grid.png-9bb66f80dbdd793fb4bb275a0d999fdf.md5 ├── icon.png-487276ed1e3a0c39cad0279d744ee560.md5 ├── tile.png-455dd1073ac41712b0ee435e5393be66.md5 ├── tile.png-b6edd167b3cc7ec58612b18f9a6dce92.md5 ├── grid (copy).png-731c6171a096204586102852bc690e07.md5 ├── frame.png-3ac25dcfa39cb943440d117e36cbfa2f.stex ├── frame.png-b49da370ab5b416325f31bcd38e64bfc.stex ├── grid.png-0e5acf495abafdc7f64f9b213a44aa0e.stex ├── grid.png-9bb66f80dbdd793fb4bb275a0d999fdf.stex ├── icon.png-487276ed1e3a0c39cad0279d744ee560.stex ├── tile.png-455dd1073ac41712b0ee435e5393be66.stex └── tile.png-b6edd167b3cc7ec58612b18f9a6dce92.stex ├── scenes ├── DelaunayTest.tscn ├── Main.tscn ├── LittleGodot.tscn ├── Room.tscn ├── Graph.gd ├── DelaunayTest.gd ├── Room.gd ├── LittleGodot.gd └── Main.gd ├── default_env.tres ├── README.md ├── icon.png.import ├── LICENSE ├── kruskal.gd ├── delaunay_triangulation.gd ├── project.godot └── export_presets.cfg /global.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | onready var max_movement = 100.0 -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/icon.png -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/example.gif -------------------------------------------------------------------------------- /assets/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/assets/grid.png -------------------------------------------------------------------------------- /assets/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/assets/tile.png -------------------------------------------------------------------------------- /assets/frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/assets/frame.png -------------------------------------------------------------------------------- /.import/frame.png-3ac25dcfa39cb943440d117e36cbfa2f.md5: -------------------------------------------------------------------------------- 1 | source_md5="1f30b871341c5a7067ff23c889aa86c1" 2 | dest_md5="37359d0c3c494241a52bb88a98b8eafd" 3 | 4 | -------------------------------------------------------------------------------- /.import/frame.png-b49da370ab5b416325f31bcd38e64bfc.md5: -------------------------------------------------------------------------------- 1 | source_md5="1f30b871341c5a7067ff23c889aa86c1" 2 | dest_md5="37359d0c3c494241a52bb88a98b8eafd" 3 | 4 | -------------------------------------------------------------------------------- /.import/grid.png-0e5acf495abafdc7f64f9b213a44aa0e.md5: -------------------------------------------------------------------------------- 1 | source_md5="623968271621a67e54c6ad6f74c64082" 2 | dest_md5="3ac394c8b30e6c0003f86f5f69cccadf" 3 | 4 | -------------------------------------------------------------------------------- /.import/grid.png-9bb66f80dbdd793fb4bb275a0d999fdf.md5: -------------------------------------------------------------------------------- 1 | source_md5="623968271621a67e54c6ad6f74c64082" 2 | dest_md5="3ac394c8b30e6c0003f86f5f69cccadf" 3 | 4 | -------------------------------------------------------------------------------- /.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5: -------------------------------------------------------------------------------- 1 | source_md5="ae7e641067601e2184afcade49abd283" 2 | dest_md5="84511021bbc8c9d37c7f0f4d181de883" 3 | 4 | -------------------------------------------------------------------------------- /.import/tile.png-455dd1073ac41712b0ee435e5393be66.md5: -------------------------------------------------------------------------------- 1 | source_md5="5a0f6ea453c45e4d326c7fa62ec98b1f" 2 | dest_md5="1b83e41b42121f35d01d308efde99ddc" 3 | 4 | -------------------------------------------------------------------------------- /.import/tile.png-b6edd167b3cc7ec58612b18f9a6dce92.md5: -------------------------------------------------------------------------------- 1 | source_md5="5a0f6ea453c45e4d326c7fa62ec98b1f" 2 | dest_md5="1b83e41b42121f35d01d308efde99ddc" 3 | 4 | -------------------------------------------------------------------------------- /.import/grid (copy).png-731c6171a096204586102852bc690e07.md5: -------------------------------------------------------------------------------- 1 | source_md5="623968271621a67e54c6ad6f74c64082" 2 | dest_md5="3ac394c8b30e6c0003f86f5f69cccadf" 3 | 4 | -------------------------------------------------------------------------------- /.import/frame.png-3ac25dcfa39cb943440d117e36cbfa2f.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/frame.png-3ac25dcfa39cb943440d117e36cbfa2f.stex -------------------------------------------------------------------------------- /.import/frame.png-b49da370ab5b416325f31bcd38e64bfc.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/frame.png-b49da370ab5b416325f31bcd38e64bfc.stex -------------------------------------------------------------------------------- /.import/grid.png-0e5acf495abafdc7f64f9b213a44aa0e.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/grid.png-0e5acf495abafdc7f64f9b213a44aa0e.stex -------------------------------------------------------------------------------- /.import/grid.png-9bb66f80dbdd793fb4bb275a0d999fdf.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/grid.png-9bb66f80dbdd793fb4bb275a0d999fdf.stex -------------------------------------------------------------------------------- /.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex -------------------------------------------------------------------------------- /.import/tile.png-455dd1073ac41712b0ee435e5393be66.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/tile.png-455dd1073ac41712b0ee435e5393be66.stex -------------------------------------------------------------------------------- /.import/tile.png-b6edd167b3cc7ec58612b18f9a6dce92.stex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriquelalves/Godot-ProcGen-Dungeon-Generator/HEAD/.import/tile.png-b6edd167b3cc7ec58612b18f9a6dce92.stex -------------------------------------------------------------------------------- /scenes/DelaunayTest.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://scenes/DelaunayTest.gd" type="Script" id=1] 4 | 5 | [node name="DelaunayTest" type="Node2D"] 6 | script = ExtResource( 1 ) 7 | 8 | -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | sky_top_color = Color( 0.647059, 0.839216, 0.945098, 1 ) 6 | sky_horizon_color = Color( 0.839216, 0.917647, 0.980392, 1 ) 7 | sky_curve = 0.25 8 | ground_bottom_color = Color( 0.156863, 0.184314, 0.211765, 1 ) 9 | ground_horizon_color = Color( 0.423529, 0.396078, 0.372549, 1 ) 10 | ground_curve = 0.01 11 | 12 | [resource] 13 | 14 | background_mode = 2 15 | background_sky = SubResource( 1 ) 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Godot-ProcGen-Dungeon-Generator 2 | A simple Dungeon Procedural Generator using Godot (v3.0). 3 | 4 | ![Dungeon Example](/example.gif) 5 | 6 | This project is based on this gamasutra article: https://www.gamasutra.com/blogs/AAdonaac/20150903/252889/Procedural_Dungeon_Generation_Algorithm.php 7 | 8 | ## WIP 9 | 10 | This project is still under development! Some of the tasks are: 11 | 12 | - Code cleaning. 13 | - Little fixes (rooms intersecting, LittleGodot getting drunk). 14 | - Lots of polish! 15 | - Integrating to an actual Zelda-Like Godot project. 16 | -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | 7 | [deps] 8 | 9 | source_file="res://icon.png" 10 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 11 | 12 | [params] 13 | 14 | compress/mode=0 15 | compress/lossy_quality=0.7 16 | compress/hdr_mode=0 17 | compress/normal_map=0 18 | flags/repeat=0 19 | flags/filter=true 20 | flags/mipmaps=false 21 | flags/anisotropic=false 22 | flags/srgb=2 23 | process/fix_alpha_border=true 24 | process/premult_alpha=false 25 | process/HDR_as_SRGB=false 26 | stream=false 27 | size_limit=0 28 | detect_3d=true 29 | svg/scale=1.0 30 | -------------------------------------------------------------------------------- /scenes/Main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://scenes/Main.gd" type="Script" id=1] 4 | [ext_resource path="res://scenes/Graph.gd" type="Script" id=2] 5 | [ext_resource path="res://scenes/LittleGodot.tscn" type="PackedScene" id=3] 6 | 7 | [node name="Main" type="Node2D"] 8 | script = ExtResource( 1 ) 9 | 10 | [node name="Rooms" type="Node2D" parent="."] 11 | position = Vector2( 496, 288 ) 12 | 13 | [node name="GraphLayer" type="CanvasLayer" parent="."] 14 | 15 | [node name="Graph" type="Control" parent="GraphLayer"] 16 | margin_right = 40.0 17 | margin_bottom = 40.0 18 | script = ExtResource( 2 ) 19 | 20 | [node name="LittleGodot" parent="." instance=ExtResource( 3 )] 21 | visible = false 22 | z_index = 1 23 | 24 | -------------------------------------------------------------------------------- /assets/grid.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/grid.png-0e5acf495abafdc7f64f9b213a44aa0e.stex" 6 | 7 | [deps] 8 | 9 | source_file="res://assets/grid.png" 10 | dest_files=[ "res://.import/grid.png-0e5acf495abafdc7f64f9b213a44aa0e.stex" ] 11 | 12 | [params] 13 | 14 | compress/mode=0 15 | compress/lossy_quality=0.7 16 | compress/hdr_mode=0 17 | compress/bptc_ldr=0 18 | compress/normal_map=0 19 | flags/repeat=0 20 | flags/filter=true 21 | flags/mipmaps=false 22 | flags/anisotropic=false 23 | flags/srgb=2 24 | process/fix_alpha_border=true 25 | process/premult_alpha=false 26 | process/HDR_as_SRGB=false 27 | process/invert_color=false 28 | stream=false 29 | size_limit=0 30 | detect_3d=true 31 | svg/scale=1.0 32 | -------------------------------------------------------------------------------- /assets/tile.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tile.png-455dd1073ac41712b0ee435e5393be66.stex" 6 | 7 | [deps] 8 | 9 | source_file="res://assets/tile.png" 10 | dest_files=[ "res://.import/tile.png-455dd1073ac41712b0ee435e5393be66.stex" ] 11 | 12 | [params] 13 | 14 | compress/mode=0 15 | compress/lossy_quality=0.7 16 | compress/hdr_mode=0 17 | compress/bptc_ldr=0 18 | compress/normal_map=0 19 | flags/repeat=0 20 | flags/filter=true 21 | flags/mipmaps=false 22 | flags/anisotropic=false 23 | flags/srgb=2 24 | process/fix_alpha_border=true 25 | process/premult_alpha=false 26 | process/HDR_as_SRGB=false 27 | process/invert_color=false 28 | stream=false 29 | size_limit=0 30 | detect_3d=true 31 | svg/scale=1.0 32 | -------------------------------------------------------------------------------- /assets/frame.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/frame.png-b49da370ab5b416325f31bcd38e64bfc.stex" 6 | 7 | [deps] 8 | 9 | source_file="res://assets/frame.png" 10 | dest_files=[ "res://.import/frame.png-b49da370ab5b416325f31bcd38e64bfc.stex" ] 11 | 12 | [params] 13 | 14 | compress/mode=0 15 | compress/lossy_quality=0.7 16 | compress/hdr_mode=0 17 | compress/bptc_ldr=0 18 | compress/normal_map=0 19 | flags/repeat=0 20 | flags/filter=true 21 | flags/mipmaps=false 22 | flags/anisotropic=false 23 | flags/srgb=2 24 | process/fix_alpha_border=true 25 | process/premult_alpha=false 26 | process/HDR_as_SRGB=false 27 | process/invert_color=false 28 | stream=false 29 | size_limit=0 30 | detect_3d=true 31 | svg/scale=1.0 32 | -------------------------------------------------------------------------------- /scenes/LittleGodot.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://scenes/LittleGodot.gd" type="Script" id=1] 4 | [ext_resource path="res://icon.png" type="Texture" id=2] 5 | 6 | [sub_resource type="RectangleShape2D" id=1] 7 | 8 | custom_solver_bias = 0.0 9 | extents = Vector2( 0.735598, 0.72707 ) 10 | 11 | [node name="LittleGodot" type="Node2D"] 12 | script = ExtResource( 1 ) 13 | _sections_unfolded = [ "Transform" ] 14 | 15 | [node name="Sprite" type="Sprite" parent="."] 16 | position = Vector2( 8, 8 ) 17 | scale = Vector2( 0.25, 0.25 ) 18 | texture = ExtResource( 2 ) 19 | _sections_unfolded = [ "Region", "Transform" ] 20 | 21 | [node name="Area2D" type="Area2D" parent="."] 22 | position = Vector2( 8, 8 ) 23 | input_pickable = true 24 | gravity_vec = Vector2( 0, 1 ) 25 | gravity = 98.0 26 | linear_damp = 0.1 27 | angular_damp = 1.0 28 | audio_bus_override = false 29 | audio_bus_name = "Master" 30 | 31 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] 32 | shape = SubResource( 1 ) 33 | _sections_unfolded = [ "Transform" ] 34 | 35 | -------------------------------------------------------------------------------- /scenes/Room.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://scenes/Room.gd" type="Script" id=1] 4 | [ext_resource path="res://assets/tile.png" type="Texture" id=2] 5 | [ext_resource path="res://assets/frame.png" type="Texture" id=3] 6 | 7 | [sub_resource type="RectangleShape2D" id=1] 8 | 9 | extents = Vector2( 32, 32 ) 10 | 11 | [node name="Room" type="RigidBody2D"] 12 | collision_layer = 0 13 | mode = 2 14 | gravity_scale = 0.0 15 | script = ExtResource( 1 ) 16 | 17 | [node name="Tile" type="TextureRect" parent="."] 18 | margin_right = 64.0 19 | margin_bottom = 64.0 20 | texture = ExtResource( 2 ) 21 | expand = true 22 | stretch_mode = 2 23 | 24 | [node name="Frame" type="NinePatchRect" parent="."] 25 | visible = false 26 | margin_right = 64.0 27 | margin_bottom = 64.0 28 | texture = ExtResource( 3 ) 29 | patch_margin_left = 16 30 | patch_margin_top = 16 31 | patch_margin_right = 16 32 | patch_margin_bottom = 16 33 | 34 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 35 | position = Vector2( 32, 32 ) 36 | shape = SubResource( 1 ) 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Henrique Lacreta Alves 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 | -------------------------------------------------------------------------------- /scenes/Graph.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | enum DRAWING {NO_DRAW, TRIANGLES, SPANNING_TREE} 4 | onready var current_state = DRAWING.NO_DRAW 5 | 6 | onready var triangles = [] 7 | onready var spanning_tree = [] 8 | 9 | func clean(): 10 | current_state = DRAWING.NO_DRAW 11 | update() 12 | 13 | func draw_triangles(tri): 14 | triangles = tri 15 | current_state = DRAWING.TRIANGLES 16 | update() 17 | 18 | func draw_spanning_tree(st): 19 | spanning_tree = st 20 | current_state = DRAWING.SPANNING_TREE 21 | update() 22 | 23 | func _draw(): 24 | 25 | if current_state == DRAWING.TRIANGLES: 26 | for triangle in triangles: 27 | # print(triangle.points[0], triangle.points[1], triangle.points[2]) 28 | draw_line(triangle.points[0]*1000, triangle.points[1]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) 29 | draw_line(triangle.points[1]*1000, triangle.points[2]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) 30 | draw_line(triangle.points[2]*1000, triangle.points[0]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) 31 | elif current_state == DRAWING.SPANNING_TREE: 32 | for edge in spanning_tree: 33 | draw_line(edge[0]*1000, edge[1]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) -------------------------------------------------------------------------------- /scenes/DelaunayTest.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var Delaunay = preload("res://delaunay_triangulation.gd") 4 | onready var delaunay = null 5 | 6 | onready var positions = [] 7 | onready var triangles = [] 8 | 9 | func _ready(): 10 | delaunay = Delaunay.new() 11 | 12 | func _draw(): 13 | for p in positions: 14 | draw_circle(p, 3.0, Color(1.0, 1.0, 0.0)) 15 | 16 | for triangle in triangles: 17 | print(triangle.points[0]*1000, triangle.points[1]*1000, triangle.points[2]*1000) 18 | draw_line(triangle.points[0]*1000, triangle.points[1]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) 19 | draw_line(triangle.points[1]*1000, triangle.points[2]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) 20 | draw_line(triangle.points[2]*1000, triangle.points[0]*1000, Color(1.0, 0.2, 1.0, 1.0), 2.0, true) 21 | 22 | 23 | func _input(event): 24 | if event is InputEventMouseButton and event.is_pressed(): 25 | if event.button_index == BUTTON_LEFT: 26 | positions.push_back(event.position) 27 | update() 28 | 29 | if event is InputEventKey and event.is_pressed(): 30 | print("====== STARTING ======") 31 | triangles = delaunay.bowyer_watson(positions) 32 | # triangles = Geometry.triangulate_polygon(PoolVector2Array(positions)) 33 | print("====== ENDED ======") 34 | print(triangles) 35 | update() -------------------------------------------------------------------------------- /scenes/Room.gd: -------------------------------------------------------------------------------- 1 | extends RigidBody2D 2 | 3 | var size = Vector2() 4 | var last_pos = position 5 | var selected = false 6 | 7 | func _ready(): 8 | pass 9 | 10 | func create(s = null): 11 | if s == null: 12 | size = Vector2(64 * (0.5 + randf()), 64 * (0.5 + randf())).snapped(Vector2(16,16)) 13 | else: 14 | size = s 15 | disable() 16 | enable_collision_box() 17 | choose() 18 | set_physics_process(false) 19 | $Frame.rect_size = size 20 | $Tile.rect_size = size 21 | $CollisionShape2D.shape = $CollisionShape2D.shape.duplicate() 22 | $CollisionShape2D.shape.extents = Vector2(size.x/2.0, size.y/2.0) 23 | $CollisionShape2D.position = size/2.0 24 | 25 | func choose(): 26 | selected = true 27 | modulate = Color(1.0, 0.5, 0.8, 1.0) 28 | 29 | func enable_collision_box(): 30 | # pass 31 | $CollisionShape2D.disabled = false 32 | collision_mask = 0 33 | collision_layer = 1 34 | 35 | func disable(): 36 | $CollisionShape2D.disabled = true 37 | collision_layer = 0 38 | sleeping = true 39 | 40 | func get_tile_size(): 41 | return size/16.0 42 | 43 | func select_main(): 44 | modulate = Color(1.0, 0.1, 0.1, 1.0) 45 | 46 | func get_movement(): 47 | global.max_movement = max(global.max_movement, (position-last_pos).length()) 48 | last_pos = position 49 | 50 | func _physics_process(delta): 51 | position = position.snapped(Vector2(16,16)) 52 | -------------------------------------------------------------------------------- /kruskal.gd: -------------------------------------------------------------------------------- 1 | var vertices_tree_idx = {} 2 | var vertices = [] 3 | var edges_dic = {} 4 | var edges = [] 5 | 6 | var tree_id_counter = 0 7 | 8 | class KeySorter: 9 | static func sort(a, b): 10 | # print(a, b) 11 | if a.x < b.x: 12 | return true 13 | elif a.x == b.x and a.y < a.y: 14 | return true 15 | return false 16 | 17 | class EdgeSorter: 18 | static func sort(a, b): 19 | if a["distance"] < b["distance"]: 20 | return true 21 | return false 22 | 23 | func start(points): # Receive a dictionary of points {vec2:{vec2:true, vec2:true...} ...} 24 | var ret_edges = [] 25 | vertices = points 26 | 27 | # First, get an array of edges {distance, v1, v2}, in distance order 28 | for p in points.keys(): 29 | vertices_tree_idx[p] = tree_id_counter 30 | tree_id_counter += 1 31 | for ps in points[p].keys(): 32 | var key = [p,ps] 33 | key.sort_custom(KeySorter, "sort") 34 | edges_dic[key] = {"v1": p, "v2": ps, "distance": p.distance_to(ps)} 35 | 36 | edges = edges_dic.values() 37 | edges.sort_custom(EdgeSorter, "sort") 38 | 39 | # For each edge, check if it can connect vertices 40 | for edge in edges: 41 | if vertices_tree_idx[edge["v1"]] != vertices_tree_idx[edge["v2"]]: 42 | change_tree_idx(vertices_tree_idx[edge["v1"]], vertices_tree_idx[edge["v2"]]) 43 | ret_edges.push_back([edge["v1"], edge["v2"]]) 44 | 45 | print(ret_edges) 46 | return ret_edges 47 | 48 | func change_tree_idx(id_from, id_to): 49 | for vertice in vertices: 50 | if vertices_tree_idx[vertice] == id_from: 51 | vertices_tree_idx[vertice] = id_to 52 | 53 | #func _ready(): 54 | # edges.sort_custom(EdgeSorter, "sort") -------------------------------------------------------------------------------- /scenes/LittleGodot.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const MIN_DISTANCE = 0.05 4 | 5 | onready var target_pos = Vector2() 6 | onready var target_tile = Vector2() 7 | 8 | onready var begin_passage = Vector2() 9 | onready var end_passage = Vector2() 10 | onready var moving_empty = false 11 | onready var last_room_ref = null 12 | 13 | onready var moving = false 14 | onready var moving_y = false 15 | 16 | signal intersected_room 17 | signal create_passage 18 | signal finished 19 | 20 | func next_tile(): 21 | 22 | 23 | # Is area2d intersecting something? 24 | if $Area2D.get_overlapping_bodies().empty(): 25 | emit_signal("create_passage", target_tile) 26 | elif last_room_ref != $Area2D.get_overlapping_bodies()[0]: 27 | last_room_ref = $Area2D.get_overlapping_bodies()[0] 28 | emit_signal("intersected_room", last_room_ref) 29 | # if not $Area2D.get_overlapping_bodies().empty(): 30 | # if last_room_ref != $Area2D.get_overlapping_bodies()[0]: 31 | # last_room_ref = $Area2D.get_overlapping_bodies()[0] 32 | # emit_signal("intersected_room", last_room_ref) 33 | # 34 | # if moving_empty: # Was moving on empty space 35 | # moving_empty = false 36 | # emit_signal("create_passage", begin_passage, end_passage) 37 | # else: 38 | # if moving_empty == false: # Just got out of a room 39 | # moving_empty = true 40 | # begin_passage.x = target_tile.x # Deep copy vector, why do I need to do this tho 41 | # begin_passage.y = target_tile.y 42 | # end_passage.x = target_tile.x 43 | # end_passage.y = target_tile.y 44 | 45 | # Has finished moving? 46 | if target_tile == target_pos: 47 | moving = false 48 | emit_signal("finished") 49 | return 50 | 51 | # New tile to lerp position to 52 | if target_tile.y == target_pos.y: 53 | # if not moving_y: # started moving horizontally, checks if needs to create passage 54 | # if moving_empty: 55 | # emit_signal("create_passage", begin_passage, end_passage) 56 | # begin_passage.x = target_tile.x 57 | # begin_passage.y = target_tile.y 58 | # end_passage.x = target_tile.x 59 | # end_passage.y = target_tile.y 60 | # 61 | # moving_y = true 62 | target_tile.x += 16 * sign(target_pos.x - position.x) 63 | else: 64 | target_tile.y += 16 * sign(target_pos.y - position.y) 65 | 66 | func move_to(pos): 67 | moving = true 68 | moving_empty = false 69 | moving_y = false 70 | target_pos = pos.snapped(Vector2(16,16)) 71 | position = position.snapped(Vector2(16,16)) 72 | target_tile = position 73 | 74 | func _physics_process(delta): 75 | if moving: 76 | position.x = lerp(position.x, target_tile.x, 0.5) 77 | position.y = lerp(position.y, target_tile.y, 0.5) 78 | if position.distance_to(target_tile) < MIN_DISTANCE: 79 | call_deferred("next_tile") 80 | 81 | func _ready(): 82 | pass # Replace with function body. -------------------------------------------------------------------------------- /delaunay_triangulation.gd: -------------------------------------------------------------------------------- 1 | var triangle_id = 0 2 | 3 | func test(): 4 | var new_triangle = triangle.new(0, Vector2(0, 10), Vector2(10, 0), Vector2(10, 10)) 5 | 6 | func bowyer_watson(pl): 7 | test() 8 | 9 | var point_list = pl.duplicate() 10 | for i in range(point_list.size()): 11 | point_list[i] /= 1000.0 12 | 13 | var triangulation = [] 14 | var super_triangle = triangle.new(triangle_id, Vector2(0.4, -0.4), Vector2(-0.8, 1), Vector2(1.6, 1)) 15 | triangle_id += 1 16 | triangulation.push_back(super_triangle) 17 | 18 | for point in point_list: 19 | var bad_triangles = [] 20 | for tri in triangulation: 21 | if tri.is_in_circumcircle(point): 22 | bad_triangles.push_back(tri) 23 | var polygon = [] 24 | for tri in bad_triangles: 25 | for edge in tri.edges: 26 | if is_edge_shared(bad_triangles, edge) <= 1: 27 | polygon.push_back(edge) 28 | 29 | for tri in bad_triangles: 30 | remove_triangle(triangulation, tri) 31 | 32 | for edge in polygon: 33 | var new_tri = triangle.new(triangle_id, edge[0],edge[1],point) 34 | triangle_id += 1 35 | triangulation.push_back(new_tri) 36 | 37 | var idx = 0 38 | for tri_idx in range(triangulation.size()): 39 | var tri = triangulation[idx] 40 | if contain_vertex_from_triangle(tri, super_triangle): 41 | triangulation.remove(idx) 42 | else: 43 | idx += 1 44 | return triangulation 45 | 46 | func contain_vertex_from_triangle(tri1, tri2): 47 | if contain_vertex_from_point(tri1.points[0], tri2) or\ 48 | contain_vertex_from_point(tri1.points[1], tri2) or\ 49 | contain_vertex_from_point(tri1.points[2], tri2): 50 | return true 51 | return false 52 | 53 | func contain_vertex_from_point(p, tri): 54 | if p == tri.points[0] or p == tri.points[1] or p == tri.points[2]: 55 | return true 56 | return false 57 | 58 | func remove_triangle(triangulation, tri): 59 | for t in range(len(triangulation)): 60 | if triangulation[t].id == tri.id: 61 | triangulation.remove(t) 62 | return 63 | 64 | func is_edge_equal(edge1, edge2): 65 | if ((edge1[0] == edge2[0]) and (edge1[1] == edge2[1])) or \ 66 | ((edge1[0] == edge2[1]) and (edge1[1] == edge2[0])): 67 | return true 68 | return false 69 | 70 | func is_edge_shared(triangles, edge): 71 | var counter = 0 72 | for tri in triangles: 73 | if (is_edge_equal(tri.edges[0], edge) or \ 74 | is_edge_equal(tri.edges[1], edge) or \ 75 | is_edge_equal(tri.edges[2], edge)): 76 | counter += 1 77 | return counter 78 | 79 | # Helper class 80 | class triangle: 81 | var id = 0 82 | 83 | var points = [] 84 | var edges = [] 85 | 86 | func _init(triangle_id, p1, p2, p3): 87 | id = triangle_id 88 | set_points(p1, p2, p3) 89 | 90 | func set_points(p1, p2, p3): 91 | if not ccw(p1,p2,p3): 92 | var temp = p2 93 | p2 = p3 94 | p3 = temp 95 | 96 | points = [p1, p2, p3] 97 | edges = [[p1,p2],[p2,p3],[p3,p1]] 98 | 99 | func ccw(a, b, c): 100 | return (b.x - a.x)*(c.y - a.y)-(c.x - a.x)*(b.y - a.y) > 0 101 | 102 | func is_in_circumcircle(point): 103 | var col1 = Vector3(points[0].x - point.x, points[1].x - point.x, points[2].x - point.x) 104 | var col2 = Vector3(points[0].y - point.y, points[1].y - point.y, points[2].y - point.y) 105 | var col3 = Vector3(\ 106 | pow((points[0].x - point.x),2.0) + pow((points[0].y - point.y), 2.0),\ 107 | pow((points[1].x - point.x),2.0) + pow((points[1].y - point.y), 2.0),\ 108 | pow((points[2].x - point.x),2.0) + pow((points[2].y - point.y), 2.0)) 109 | var basis = Basis(col1, col2, col3) 110 | if basis.determinant() > 0.0: 111 | return true 112 | return false -------------------------------------------------------------------------------- /scenes/Main.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var Room = preload("res://scenes/Room.tscn") 4 | 5 | enum STATE {STATE_IDLE, STATE_CREATING_ROOMS, STATE_SEPARATING, STATE_MAIN_ROOMS, STATE_TRIANGULATION, STATE_MIN_SPANNING_TREE, STATE_LITTLE_GODOT, STATE_FINISH} 6 | onready var current_state = STATE.STATE_IDLE 7 | onready var last_working_state = STATE.STATE_IDLE 8 | 9 | onready var creating_rooms_tick = 0.0 10 | onready var creating_rooms_tick_limit = 0.01 11 | onready var number_rooms_generating = 40 12 | onready var room_minimum_size = 6.0 13 | 14 | onready var main_rooms = [] 15 | 16 | onready var graph_points = {} 17 | 18 | onready var Delaunay = preload("res://delaunay_triangulation.gd") 19 | onready var delaunay = null 20 | onready var triangles = [] 21 | 22 | onready var Kruskal = preload("res://kruskal.gd") 23 | onready var kruskal = null 24 | onready var min_spanning_tree = [] 25 | 26 | onready var edge_idx = 0 27 | 28 | func _ready(): 29 | randomize() 30 | 31 | delaunay = Delaunay.new() 32 | kruskal = Kruskal.new() 33 | $LittleGodot.connect("finished", self, "on_littlegodot_finished") 34 | $LittleGodot.connect("create_passage", self, "on_littlegodot_passage") 35 | $LittleGodot.connect("intersected_room", self, "on_littlegodot_room") 36 | 37 | func on_littlegodot_finished(): 38 | printt("Finished") 39 | if edge_idx < min_spanning_tree.size(): 40 | $LittleGodot.position = min_spanning_tree[edge_idx][0] * 1000 41 | $LittleGodot.move_to(min_spanning_tree[edge_idx][1] * 1000) 42 | edge_idx += 1 43 | else: 44 | $LittleGodot.hide() 45 | idle() 46 | 47 | func on_littlegodot_passage(pos): 48 | printt("Passage", pos) 49 | var new_room = Room.instance() 50 | $Rooms.add_child(new_room) 51 | new_room.position = pos - $Rooms.position 52 | new_room.create(Vector2(16,16)) 53 | # var new_room = Room.instance() 54 | # $Rooms.add_child(new_room) 55 | # if begin.x == end.x: 56 | # new_room.position = Vector2(begin.x, min(begin.y, end.y)) - $Rooms.position 57 | # new_room.create(Vector2(32, abs(begin.y - end.y) + 16)) 58 | # else: 59 | # new_room.position = Vector2(min(begin.x, end.x), begin.y) - $Rooms.position 60 | # new_room.create(Vector2(abs(begin.x - end.x) + 16, 32)) 61 | 62 | func on_littlegodot_room(room_ref): 63 | printt("Room ref", room_ref) 64 | room_ref.choose() 65 | 66 | func _input(event): 67 | if event is InputEventMouseButton and event.is_pressed(): 68 | next_state() 69 | 70 | if event is InputEventKey: 71 | if event.is_pressed(): 72 | if event.scancode == KEY_SPACE: 73 | next_state() 74 | elif event.scancode == KEY_R and event.is_pressed(): 75 | get_tree().change_scene("res://scenes/Main.tscn") 76 | 77 | func idle(): 78 | last_working_state = current_state 79 | current_state = STATE.STATE_IDLE 80 | 81 | func next_state(): 82 | if current_state != STATE.STATE_IDLE: 83 | return 84 | 85 | current_state = last_working_state + 1 86 | 87 | match current_state: 88 | STATE.STATE_SEPARATING: 89 | for child in $Rooms.get_children(): 90 | child.collision_layer = 1 91 | 92 | STATE.STATE_MAIN_ROOMS: 93 | var children = $Rooms.get_children() 94 | children.shuffle() 95 | var min_size = round(children.size()*0.5) 96 | while children.size() > min_size: 97 | children[0].queue_free() 98 | children.pop_front() 99 | 100 | for child in children: 101 | child.position = child.position.snapped(Vector2(16.0,16.0)) 102 | if child.get_tile_size().length() > room_minimum_size: 103 | child.select_main() 104 | child.raise() 105 | main_rooms.append(child) 106 | idle() 107 | 108 | STATE.STATE_TRIANGULATION: 109 | var positions = [] 110 | for room in main_rooms: 111 | positions.push_back(room.global_position + room.size/2.0) 112 | triangles = delaunay.bowyer_watson(positions) 113 | 114 | # Godot delaunay triangulation implementation is not working, but this 115 | # is how it's called 116 | # triangles = Geometry.triangulate_polygon(PoolVector2Array(positions)) 117 | 118 | $GraphLayer/Graph.draw_triangles(triangles) 119 | 120 | for triangle in triangles: 121 | for point in triangle.points: 122 | if not graph_points.has(point): 123 | graph_points[point] = {} 124 | graph_points[triangle.points[0]][triangle.points[1]] = true 125 | graph_points[triangle.points[0]][triangle.points[2]] = true 126 | graph_points[triangle.points[1]][triangle.points[0]] = true 127 | graph_points[triangle.points[1]][triangle.points[2]] = true 128 | graph_points[triangle.points[2]][triangle.points[0]] = true 129 | graph_points[triangle.points[2]][triangle.points[1]] = true 130 | idle() 131 | 132 | STATE.STATE_MIN_SPANNING_TREE: 133 | min_spanning_tree = kruskal.start(graph_points) 134 | $GraphLayer/Graph.draw_spanning_tree(min_spanning_tree) 135 | idle() 136 | 137 | STATE.STATE_LITTLE_GODOT: 138 | $LittleGodot.show() 139 | for room in $Rooms.get_children(): 140 | room.enable_collision_box() 141 | 142 | edge_idx = 0 143 | $LittleGodot.position = min_spanning_tree[edge_idx][0] * 1000 144 | $LittleGodot.move_to(min_spanning_tree[edge_idx][1] * 1000) 145 | edge_idx += 1 146 | 147 | STATE.STATE_FINISH: 148 | for room in $Rooms.get_children(): 149 | if not room.selected: 150 | room.queue_free() 151 | $GraphLayer/Graph.clean() 152 | 153 | func _physics_process(delta): 154 | match current_state: 155 | 156 | STATE.STATE_CREATING_ROOMS: 157 | creating_rooms_tick += delta 158 | if creating_rooms_tick > creating_rooms_tick_limit: 159 | creating_rooms_tick -= creating_rooms_tick_limit 160 | var new_room = Room.instance() 161 | $Rooms.add_child(new_room) 162 | new_room.create() 163 | new_room.position = Vector2(randi()%200 - 100, randi()%100 - 50) 164 | if $Rooms.get_child_count() >= number_rooms_generating: 165 | idle() 166 | 167 | STATE.STATE_SEPARATING: 168 | global.max_movement = 0.0 169 | for room in $Rooms.get_children(): 170 | room.get_movement() 171 | 172 | if global.max_movement < 0.01: 173 | for child in $Rooms.get_children(): 174 | child.disable() 175 | idle() -------------------------------------------------------------------------------- /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="Physics Procedural Room Generator" 19 | run/main_scene="res://scenes/Main.tscn" 20 | config/icon="res://icon.png" 21 | 22 | [autoload] 23 | 24 | global="*res://global.gd" 25 | 26 | [display] 27 | 28 | window/stretch/mode="viewport" 29 | window/stretch/aspect="keep_height" 30 | 31 | [input] 32 | 33 | ui_accept={ 34 | "deadzone": 0.5, 35 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"unicode":0,"echo":false,"script":null) 36 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777222,"unicode":0,"echo":false,"script":null) 37 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) 38 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null) 39 | ] 40 | } 41 | ui_select={ 42 | "deadzone": 0.5, 43 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) 44 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":3,"pressure":0.0,"pressed":false,"script":null) 45 | ] 46 | } 47 | ui_cancel={ 48 | "deadzone": 0.5, 49 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"unicode":0,"echo":false,"script":null) 50 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null) 51 | ] 52 | } 53 | ui_focus_next={ 54 | "deadzone": 0.5, 55 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777218,"unicode":0,"echo":false,"script":null) 56 | ] 57 | } 58 | ui_focus_prev={ 59 | "deadzone": 0.5, 60 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":true,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777218,"unicode":0,"echo":false,"script":null) 61 | ] 62 | } 63 | ui_left={ 64 | "deadzone": 0.5, 65 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null) 66 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) 67 | ] 68 | } 69 | ui_right={ 70 | "deadzone": 0.5, 71 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) 72 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null) 73 | ] 74 | } 75 | ui_up={ 76 | "deadzone": 0.5, 77 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null) 78 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) 79 | ] 80 | } 81 | ui_down={ 82 | "deadzone": 0.5, 83 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) 84 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) 85 | ] 86 | } 87 | ui_page_up={ 88 | "deadzone": 0.5, 89 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777235,"unicode":0,"echo":false,"script":null) 90 | ] 91 | } 92 | ui_page_down={ 93 | "deadzone": 0.5, 94 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777236,"unicode":0,"echo":false,"script":null) 95 | ] 96 | } 97 | ui_home={ 98 | "deadzone": 0.5, 99 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777229,"unicode":0,"echo":false,"script":null) 100 | ] 101 | } 102 | ui_end={ 103 | "deadzone": 0.5, 104 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777230,"unicode":0,"echo":false,"script":null) 105 | ] 106 | } 107 | 108 | [rendering] 109 | 110 | environment/default_environment="res://default_env.tres" 111 | -------------------------------------------------------------------------------- /export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Android" 4 | platform="Android" 5 | runnable=true 6 | custom_features="" 7 | export_filter="all_resources" 8 | include_filter="" 9 | exclude_filter="" 10 | export_path="" 11 | patch_list=PoolStringArray( ) 12 | 13 | [preset.0.options] 14 | 15 | graphics/32_bits_framebuffer=true 16 | one_click_deploy/clear_previous_install=true 17 | custom_package/debug="/home/peronio/Dev/godot/godot-master/bin/android_debug.apk" 18 | custom_package/release="/home/peronio/Dev/godot/godot-master/bin/android_release.apk" 19 | command_line/extra_args="" 20 | version/code=1 21 | version/name="1.0" 22 | package/unique_name="org.godotengine.proceduraldungeon" 23 | package/name="Dungeon test" 24 | package/signed=true 25 | screen/immersive_mode=true 26 | screen/orientation=0 27 | screen/support_small=true 28 | screen/support_normal=true 29 | screen/support_large=true 30 | screen/support_xlarge=true 31 | screen/opengl_debug=false 32 | launcher_icons/xxxhdpi_192x192="" 33 | launcher_icons/xxhdpi_144x144="" 34 | launcher_icons/xhdpi_96x96="" 35 | launcher_icons/hdpi_72x72="" 36 | launcher_icons/mdpi_48x48="" 37 | keystore/release="" 38 | keystore/release_user="" 39 | keystore/release_password="" 40 | apk_expansion/enable=false 41 | apk_expansion/SALT="" 42 | apk_expansion/public_key="" 43 | architectures/armeabi-v7a=true 44 | architectures/arm64-v8a=false 45 | architectures/x86=false 46 | architectures/x86_64=false 47 | permissions/access_checkin_properties=false 48 | permissions/access_coarse_location=false 49 | permissions/access_fine_location=false 50 | permissions/access_location_extra_commands=false 51 | permissions/access_mock_location=false 52 | permissions/access_network_state=false 53 | permissions/access_surface_flinger=false 54 | permissions/access_wifi_state=false 55 | permissions/account_manager=false 56 | permissions/add_voicemail=false 57 | permissions/authenticate_accounts=false 58 | permissions/battery_stats=false 59 | permissions/bind_accessibility_service=false 60 | permissions/bind_appwidget=false 61 | permissions/bind_device_admin=false 62 | permissions/bind_input_method=false 63 | permissions/bind_nfc_service=false 64 | permissions/bind_notification_listener_service=false 65 | permissions/bind_print_service=false 66 | permissions/bind_remoteviews=false 67 | permissions/bind_text_service=false 68 | permissions/bind_vpn_service=false 69 | permissions/bind_wallpaper=false 70 | permissions/bluetooth=false 71 | permissions/bluetooth_admin=false 72 | permissions/bluetooth_privileged=false 73 | permissions/brick=false 74 | permissions/broadcast_package_removed=false 75 | permissions/broadcast_sms=false 76 | permissions/broadcast_sticky=false 77 | permissions/broadcast_wap_push=false 78 | permissions/call_phone=false 79 | permissions/call_privileged=false 80 | permissions/camera=false 81 | permissions/capture_audio_output=false 82 | permissions/capture_secure_video_output=false 83 | permissions/capture_video_output=false 84 | permissions/change_component_enabled_state=false 85 | permissions/change_configuration=false 86 | permissions/change_network_state=false 87 | permissions/change_wifi_multicast_state=false 88 | permissions/change_wifi_state=false 89 | permissions/clear_app_cache=false 90 | permissions/clear_app_user_data=false 91 | permissions/control_location_updates=false 92 | permissions/delete_cache_files=false 93 | permissions/delete_packages=false 94 | permissions/device_power=false 95 | permissions/diagnostic=false 96 | permissions/disable_keyguard=false 97 | permissions/dump=false 98 | permissions/expand_status_bar=false 99 | permissions/factory_test=false 100 | permissions/flashlight=false 101 | permissions/force_back=false 102 | permissions/get_accounts=false 103 | permissions/get_package_size=false 104 | permissions/get_tasks=false 105 | permissions/get_top_activity_info=false 106 | permissions/global_search=false 107 | permissions/hardware_test=false 108 | permissions/inject_events=false 109 | permissions/install_location_provider=false 110 | permissions/install_packages=false 111 | permissions/install_shortcut=false 112 | permissions/internal_system_window=false 113 | permissions/internet=false 114 | permissions/kill_background_processes=false 115 | permissions/location_hardware=false 116 | permissions/manage_accounts=false 117 | permissions/manage_app_tokens=false 118 | permissions/manage_documents=false 119 | permissions/master_clear=false 120 | permissions/media_content_control=false 121 | permissions/modify_audio_settings=false 122 | permissions/modify_phone_state=false 123 | permissions/mount_format_filesystems=false 124 | permissions/mount_unmount_filesystems=false 125 | permissions/nfc=false 126 | permissions/persistent_activity=false 127 | permissions/process_outgoing_calls=false 128 | permissions/read_calendar=false 129 | permissions/read_call_log=false 130 | permissions/read_contacts=false 131 | permissions/read_external_storage=false 132 | permissions/read_frame_buffer=false 133 | permissions/read_history_bookmarks=false 134 | permissions/read_input_state=false 135 | permissions/read_logs=false 136 | permissions/read_phone_state=false 137 | permissions/read_profile=false 138 | permissions/read_sms=false 139 | permissions/read_social_stream=false 140 | permissions/read_sync_settings=false 141 | permissions/read_sync_stats=false 142 | permissions/read_user_dictionary=false 143 | permissions/reboot=false 144 | permissions/receive_boot_completed=false 145 | permissions/receive_mms=false 146 | permissions/receive_sms=false 147 | permissions/receive_wap_push=false 148 | permissions/record_audio=false 149 | permissions/reorder_tasks=false 150 | permissions/restart_packages=false 151 | permissions/send_respond_via_message=false 152 | permissions/send_sms=false 153 | permissions/set_activity_watcher=false 154 | permissions/set_alarm=false 155 | permissions/set_always_finish=false 156 | permissions/set_animation_scale=false 157 | permissions/set_debug_app=false 158 | permissions/set_orientation=false 159 | permissions/set_pointer_speed=false 160 | permissions/set_preferred_applications=false 161 | permissions/set_process_limit=false 162 | permissions/set_time=false 163 | permissions/set_time_zone=false 164 | permissions/set_wallpaper=false 165 | permissions/set_wallpaper_hints=false 166 | permissions/signal_persistent_processes=false 167 | permissions/status_bar=false 168 | permissions/subscribed_feeds_read=false 169 | permissions/subscribed_feeds_write=false 170 | permissions/system_alert_window=false 171 | permissions/transmit_ir=false 172 | permissions/uninstall_shortcut=false 173 | permissions/update_device_stats=false 174 | permissions/use_credentials=false 175 | permissions/use_sip=false 176 | permissions/vibrate=false 177 | permissions/wake_lock=false 178 | permissions/write_apn_settings=false 179 | permissions/write_calendar=false 180 | permissions/write_call_log=false 181 | permissions/write_contacts=false 182 | permissions/write_external_storage=false 183 | permissions/write_gservices=false 184 | permissions/write_history_bookmarks=false 185 | permissions/write_profile=false 186 | permissions/write_secure_settings=false 187 | permissions/write_settings=false 188 | permissions/write_sms=false 189 | permissions/write_social_stream=false 190 | permissions/write_sync_settings=false 191 | permissions/write_user_dictionary=false 192 | user_permissions/0=false 193 | user_permissions/1=false 194 | user_permissions/2=false 195 | user_permissions/3=false 196 | user_permissions/4=false 197 | user_permissions/5=false 198 | user_permissions/6=false 199 | user_permissions/7=false 200 | user_permissions/8=false 201 | user_permissions/9=false 202 | user_permissions/10=false 203 | user_permissions/11=false 204 | user_permissions/12=false 205 | user_permissions/13=false 206 | user_permissions/14=false 207 | user_permissions/15=false 208 | user_permissions/16=false 209 | user_permissions/17=false 210 | user_permissions/18=false 211 | user_permissions/19=false 212 | --------------------------------------------------------------------------------