├── .gitignore ├── Chest.tscn ├── InteractiveTileMap.tscn ├── InteractiveTilemap.gd ├── LICENSE ├── Level.tscn ├── README.md ├── default_env.tres ├── icon.png ├── icon.png.import ├── project.godot └── tileset ├── CREDITS.txt ├── tiles.png └── tiles.png.import /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Godot-specific ignores 3 | .import/ 4 | export.cfg 5 | export_presets.cfg 6 | 7 | # Mono-specific ignores 8 | .mono/ 9 | data_*/ 10 | -------------------------------------------------------------------------------- /Chest.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://tileset/tiles.png" type="Texture" id=1] 4 | 5 | [node name="Chest" type="StaticBody2D"] 6 | 7 | [node name="Sprite" type="Sprite" parent="."] 8 | position = Vector2( 0, -9 ) 9 | texture = ExtResource( 1 ) 10 | region_enabled = true 11 | region_rect = Rect2( 80, 80, 16, 32 ) 12 | -------------------------------------------------------------------------------- /InteractiveTileMap.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://InteractiveTilemap.gd" type="Script" id=1] 4 | [ext_resource path="res://tileset/tiles.png" type="Texture" id=2] 5 | 6 | [sub_resource type="TileSet" id=1] 7 | 0/name = "Rock" 8 | 0/texture = ExtResource( 2 ) 9 | 0/tex_offset = Vector2( 0, 0 ) 10 | 0/modulate = Color( 1, 1, 1, 1 ) 11 | 0/region = Rect2( 96, 96, 16, 16 ) 12 | 0/tile_mode = 0 13 | 0/occluder_offset = Vector2( 0, 0 ) 14 | 0/navigation_offset = Vector2( 0, 0 ) 15 | 0/shape_offset = Vector2( 0, 0 ) 16 | 0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 17 | 0/shape_one_way = false 18 | 0/shape_one_way_margin = 0.0 19 | 0/shapes = [ ] 20 | 0/z_index = 0 21 | 1/name = "Chest" 22 | 1/texture = ExtResource( 2 ) 23 | 1/tex_offset = Vector2( 0, 0 ) 24 | 1/modulate = Color( 1, 1, 1, 1 ) 25 | 1/region = Rect2( 64, 96, 16, 16 ) 26 | 1/tile_mode = 0 27 | 1/occluder_offset = Vector2( 0, 0 ) 28 | 1/navigation_offset = Vector2( 0, 0 ) 29 | 1/shape_offset = Vector2( 0, 0 ) 30 | 1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 31 | 1/shape_one_way = false 32 | 1/shape_one_way_margin = 0.0 33 | 1/shapes = [ ] 34 | 1/z_index = 0 35 | 36 | [node name="InteractiveTilemap" type="TileMap"] 37 | tile_set = SubResource( 1 ) 38 | cell_size = Vector2( 16, 16 ) 39 | format = 1 40 | script = ExtResource( 1 ) 41 | -------------------------------------------------------------------------------- /InteractiveTilemap.gd: -------------------------------------------------------------------------------- 1 | extends TileMap 2 | class_name InteractiveTilemap 3 | 4 | # In TILE_SCENES dictionary, a key-value pair makes the link between 5 | # the tile's ID in the TileMap (key) and this object's scene (value) 6 | # This way, by referring to TILE_SCENES with a certain ID we will receive this tile's 7 | # individual scene 8 | export(Dictionary) var TILE_SCENES := { 9 | 1: preload("res://Chest.tscn") 10 | } 11 | 12 | onready var half_cell_size := cell_size * 0.5 13 | 14 | 15 | func _ready(): 16 | yield(get_tree(), "idle_frame") 17 | _replace_tiles_with_scenes() 18 | 19 | func _replace_tiles_with_scenes(scene_dictionary: Dictionary = TILE_SCENES): 20 | for tile_pos in get_used_cells(): 21 | var tile_id = get_cell(tile_pos.x, tile_pos.y) 22 | 23 | if scene_dictionary.has(tile_id): 24 | var object_scene = scene_dictionary[tile_id] 25 | _replace_tile_with_object(tile_pos, object_scene) 26 | 27 | func _replace_tile_with_object(tile_pos: Vector2, object_scene: PackedScene, parent: Node = get_tree().current_scene): 28 | # Clear the cell in TileMap 29 | if get_cellv(tile_pos) != INVALID_CELL: 30 | set_cellv(tile_pos, -1) 31 | update_bitmask_region() 32 | 33 | # Spawn the object 34 | if object_scene: 35 | var obj = object_scene.instance() 36 | var ob_pos = map_to_world(tile_pos) + half_cell_size 37 | 38 | parent.add_child(obj) 39 | obj.global_position = to_global(ob_pos) 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 IvessJohn 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 | -------------------------------------------------------------------------------- /Level.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://InteractiveTilemap.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Chest.tscn" type="PackedScene" id=2] 5 | 6 | [node name="Level" type="Node2D"] 7 | 8 | [node name="InteractiveTilemap" parent="." instance=ExtResource( 1 )] 9 | tile_data = PoolIntArray( 65548, 0, 0, 131072, 1, 0, 131080, 0, 0, 196608, 1, 0, 196621, 0, 0, 262144, 1, 0, 262152, 0, 0, 262157, 0, 0, 327680, 1, 0, 327681, 1, 0, 327682, 1, 0, 327689, 0, 0, 393216, 1, 0, 393217, 1, 0, 393218, 1, 0, 393226, 0, 0, 393229, 0, 0 ) 10 | TILE_SCENES = { 11 | 0: ExtResource( 2 ) 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # godot-interactive-tilemaps-tutorial 2 | 3 | This is a repository containing the source code of the project shown in [John Ivess's tutorial on Interactive TileMaps in Godot](https://youtu.be/O4AQtCWNQmo). 4 | 5 | ## Legal 6 | The code is written under the MIT license. 7 | 8 | Art: [forest_](https://analogstudios.itch.io/forest) by [analogStudios_](https://twitter.com/analogstudios_) under CC-0 license and the author's approval. 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvessJohn/godot-interactive-tilemaps-tutorial/e29466fd4f0a58de63386e5f870918f029cab0d9/icon.png -------------------------------------------------------------------------------- /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 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=true 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /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 | "base": "TileMap", 13 | "class": "InteractiveTilemap", 14 | "language": "GDScript", 15 | "path": "res://InteractiveTilemap.gd" 16 | } ] 17 | _global_script_class_icons={ 18 | "InteractiveTilemap": "" 19 | } 20 | 21 | [application] 22 | 23 | config/name="InteractiveTileMap" 24 | run/main_scene="res://Level.tscn" 25 | config/icon="res://icon.png" 26 | 27 | [display] 28 | 29 | window/size/width=320 30 | window/size/height=180 31 | window/size/test_width=1280 32 | window/size/test_height=720 33 | window/stretch/mode="2d" 34 | window/stretch/aspect="keep" 35 | 36 | [importer_defaults] 37 | 38 | texture={ 39 | "compress/bptc_ldr": 0, 40 | "compress/hdr_mode": 0, 41 | "compress/lossy_quality": 0.7, 42 | "compress/mode": 0, 43 | "compress/normal_map": 0, 44 | "detect_3d": false, 45 | "flags/anisotropic": false, 46 | "flags/filter": false, 47 | "flags/mipmaps": false, 48 | "flags/repeat": 0, 49 | "flags/srgb": 2, 50 | "process/HDR_as_SRGB": false, 51 | "process/fix_alpha_border": true, 52 | "process/invert_color": false, 53 | "process/normal_map_invert_y": false, 54 | "process/premult_alpha": false, 55 | "size_limit": 0, 56 | "stream": false, 57 | "svg/scale": 1.0 58 | } 59 | 60 | [physics] 61 | 62 | common/enable_pause_aware_picking=true 63 | 64 | [rendering] 65 | 66 | environment/default_environment="res://default_env.tres" 67 | -------------------------------------------------------------------------------- /tileset/CREDITS.txt: -------------------------------------------------------------------------------- 1 | Art provided is a part of forest_ asset pack by @analogstudios_. The asset pack is used under author's agreement. 2 | 3 | Download the full tileset here: https://analogstudios.itch.io/forest 4 | 5 | Artist pages: 6 | Twitter: https://twitter.com/analogstudios_ 7 | Instagram: https://www.instagram.com/analogstudios_/ 8 | Pinterest: https://www.pinterest.dk/analogstudios_/ -------------------------------------------------------------------------------- /tileset/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvessJohn/godot-interactive-tilemaps-tutorial/e29466fd4f0a58de63386e5f870918f029cab0d9/tileset/tiles.png -------------------------------------------------------------------------------- /tileset/tiles.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tiles.png-af7c84ecaa7961b5a732d88da7d3ec06.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://tileset/tiles.png" 13 | dest_files=[ "res://.import/tiles.png-af7c84ecaa7961b5a732d88da7d3ec06.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 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | --------------------------------------------------------------------------------