From 6d920e47e7b576a70411a00dfcdb703202dc4542 Mon Sep 17 00:00:00 2001 From: veclav talica Date: Sun, 26 Nov 2023 04:16:46 +0500 Subject: [PATCH] TileMapTileDescriptor and building of tileset from them --- nodes/TileMapObject.gd | 34 +++++++++++++++++++++++++++++ nodes/TileMapTileDescriptor.gd | 13 +++++++++++ project.godot | 8 ++++++- scenes/Game.tscn | 40 +++++++++------------------------- scenes/tiles/Brickwall.tscn | 9 ++++++++ 5 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 nodes/TileMapTileDescriptor.gd create mode 100644 scenes/tiles/Brickwall.tscn diff --git a/nodes/TileMapObject.gd b/nodes/TileMapObject.gd index 4f841ec..f6f5b4b 100644 --- a/nodes/TileMapObject.gd +++ b/nodes/TileMapObject.gd @@ -1,17 +1,51 @@ tool extends TileMap +# todo: Give care about descriptor swaps being loseless / non introducing artifacts. + ## Dictates whether tileset collision information should be exposed to game context. export var expose_collisions: bool = true +var _descriptor_name_to_id: Dictionary # String to int + +func change_tile_texture(p_tile: String, p_texture: Texture) -> void: + if not p_tile in _descriptor_name_to_id: + push_error("Invalid tile name") + return + + var id := _descriptor_name_to_id[p_tile] as int + tile_set.tile_set_texture(id, p_texture) + func _enter_tree() -> void: + tile_set = TileSet.new() + # It's okay to fail here for non-grid contexts. if get_parent().connect("cell_size_changed", self, "_update_cell_size"): _update_cell_size(get_parent().cell_size, get_parent().cell_size) + if connect("child_entered_tree", self, "_on_child_entered_tree") != OK: + assert(false) + + if connect("child_exiting_tree", self, "_on_child_exiting_tree") != OK: + assert(false) + func _update_cell_size(_p_old_cell_size: Vector2, p_new_cell_size: Vector2) -> void: # We're assuming that all tile textures are of same dimensions. # todo: Diagnose mismatch by walking over all textures? var tileset_texture_size := tile_set.tile_get_texture(0).get_size() scale = p_new_cell_size / tileset_texture_size cell_size = p_new_cell_size / scale + +func _on_child_entered_tree(p_node: Node) -> void: + var id := tile_set.get_last_unused_tile_id() + _descriptor_name_to_id[p_node.name] = id + tile_set.create_tile(id) + tile_set.tile_set_texture(id, p_node.texture) + +func _on_child_exiting_tree(p_node: Node) -> void: + var id := _descriptor_name_to_id[p_node.name] as int + for cell in get_used_cells_by_id(id): + set_cell(cell.x, cell.y, -1) + tile_set.remove_tile(id) + if not _descriptor_name_to_id.erase(p_node.name): + assert(false) diff --git a/nodes/TileMapTileDescriptor.gd b/nodes/TileMapTileDescriptor.gd new file mode 100644 index 0000000..b9265d1 --- /dev/null +++ b/nodes/TileMapTileDescriptor.gd @@ -0,0 +1,13 @@ +tool +extends Node +class_name TK_TileMapTileDescriptor + +export var texture: Texture setget _set_texture + +# todo: More layer customizeability. +export var is_solid: bool + +func _set_texture(p_texture: Texture) -> void: + texture = p_texture + if is_inside_tree(): + get_parent().change_tile_texture(name, p_texture) diff --git a/project.godot b/project.godot index b0321cd..6f8c846 100644 --- a/project.godot +++ b/project.godot @@ -138,6 +138,11 @@ _global_script_classes=[ { "class": "TK_GridContext", "language": "GDScript", "path": "res://nodes/GridContext.gd" +}, { +"base": "Node", +"class": "TK_TileMapTileDescriptor", +"language": "GDScript", +"path": "res://nodes/TileMapTileDescriptor.gd" } ] _global_script_class_icons={ "BrushPrefabs": "", @@ -165,7 +170,8 @@ _global_script_class_icons={ "TK_Controller": "", "TK_FittingSprite": "", "TK_GameObject": "", -"TK_GridContext": "" +"TK_GridContext": "", +"TK_TileMapTileDescriptor": "" } [application] diff --git a/scenes/Game.tscn b/scenes/Game.tscn index 20289c7..cd455f4 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://nodes/FittingSprite.gd" type="Script" id=1] [ext_resource path="res://art/entities/fiend.png" type="Texture" id=2] @@ -7,59 +7,39 @@ [ext_resource path="res://nodes/GameObject.tscn" type="PackedScene" id=5] [ext_resource path="res://art/tiles/brickwall.png" type="Texture" id=6] [ext_resource path="res://nodes/TileMapObject.gd" type="Script" id=7] - -[sub_resource type="OccluderPolygon2D" id=2] -polygon = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 ) - -[sub_resource type="ConvexPolygonShape2D" id=3] -points = PoolVector2Array( 16, 16, 0, 16, 0, 16, 16, 16 ) - -[sub_resource type="ConvexPolygonShape2D" id=4] -points = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 ) +[ext_resource path="res://scenes/tiles/Brickwall.tscn" type="PackedScene" id=8] [sub_resource type="TileSet" id=1] -0/name = "brickwall.png 0" +0/name = "" 0/texture = ExtResource( 6 ) 0/tex_offset = Vector2( 0, 0 ) 0/modulate = Color( 1, 1, 1, 1 ) -0/region = Rect2( 0, 0, 16, 16 ) +0/region = Rect2( 0, 0, 0, 0 ) 0/tile_mode = 0 0/occluder_offset = Vector2( 0, 0 ) -0/occluder = SubResource( 2 ) 0/navigation_offset = Vector2( 0, 0 ) 0/shape_offset = Vector2( 0, 0 ) 0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) -0/shape = SubResource( 3 ) 0/shape_one_way = false -0/shape_one_way_margin = 1.0 -0/shapes = [ { -"autotile_coord": Vector2( 0, 0 ), -"one_way": false, -"one_way_margin": 1.0, -"shape": SubResource( 3 ), -"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) -}, { -"autotile_coord": Vector2( 0, 0 ), -"one_way": false, -"one_way_margin": 1.0, -"shape": SubResource( 4 ), -"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) -} ] +0/shape_one_way_margin = 0.0 +0/shapes = [ ] 0/z_index = 0 [node name="Gauntlet" type="Node"] [node name="GridContext" parent="." instance=ExtResource( 4 )] -[node name="TileMap" type="TileMap" parent="GridContext"] +[node name="TileMapObject" type="TileMap" parent="GridContext"] scale = Vector2( 4, 4 ) tile_set = SubResource( 1 ) cell_size = Vector2( 16, 16 ) bake_navigation = true format = 1 -tile_data = PoolIntArray( 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 0, 12, 0, 0, 13, 0, 0, 14, 0, 0, 15, 0, 0, 65536, 0, 0, 65542, 0, 0, 65551, 0, 0, 131072, 0, 0, 131082, 0, 0, 131087, 0, 0, 196608, 0, 0, 196618, 0, 0, 196623, 0, 0, 262144, 0, 0, 262145, 0, 0, 262146, 0, 0, 262147, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 0, 0, 262153, 0, 0, 262154, 0, 0, 262156, 0, 0, 262157, 0, 0, 262158, 0, 0, 262159, 0, 0, 327680, 0, 0, 327683, 0, 0, 327695, 0, 0, 393216, 0, 0, 393226, 0, 0, 393227, 0, 0, 393229, 0, 0, 393231, 0, 0, 458752, 0, 0, 458761, 0, 0, 458762, 0, 0, 458767, 0, 0, 524288, 0, 0, 524289, 0, 0, 524290, 0, 0, 524291, 0, 0, 524292, 0, 0, 524293, 0, 0, 524294, 0, 0, 524295, 0, 0, 524296, 0, 0, 524297, 0, 0, 524298, 0, 0, 524299, 0, 0, 524300, 0, 0, 524301, 0, 0, 524302, 0, 0, 524303, 0, 0 ) +tile_data = PoolIntArray( 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 0, 12, 0, 0, 13, 0, 0, 14, 0, 0, 15, 0, 0, 65536, 0, 0, 65551, 0, 0, 131072, 0, 0, 131074, 0, 0, 131085, 0, 0, 131087, 0, 0, 196608, 0, 0, 196623, 0, 0, 262144, 0, 0, 262146, 0, 0, 262157, 0, 0, 262159, 0, 0, 327680, 0, 0, 327695, 0, 0, 393216, 0, 0, 393218, 0, 0, 393219, 0, 0, 393220, 0, 0, 393221, 0, 0, 393222, 0, 0, 393223, 0, 0, 393224, 0, 0, 393225, 0, 0, 393226, 0, 0, 393227, 0, 0, 393228, 0, 0, 393229, 0, 0, 393231, 0, 0, 458752, 0, 0, 458767, 0, 0, 524288, 0, 0, 524289, 0, 0, 524290, 0, 0, 524291, 0, 0, 524292, 0, 0, 524293, 0, 0, 524294, 0, 0, 524295, 0, 0, 524296, 0, 0, 524297, 0, 0, 524298, 0, 0, 524299, 0, 0, 524300, 0, 0, 524301, 0, 0, 524302, 0, 0, 524303, 0, 0 ) script = ExtResource( 7 ) +[node name="Brickwall" parent="GridContext/TileMapObject" instance=ExtResource( 8 )] + [node name="GameObject" parent="GridContext" instance=ExtResource( 5 )] position = Vector2( 384, 128 ) diff --git a/scenes/tiles/Brickwall.tscn b/scenes/tiles/Brickwall.tscn new file mode 100644 index 0000000..0b65570 --- /dev/null +++ b/scenes/tiles/Brickwall.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://art/tiles/brickwall.png" type="Texture" id=1] +[ext_resource path="res://nodes/TileMapTileDescriptor.gd" type="Script" id=2] + +[node name="Brickwall" type="Node"] +script = ExtResource( 2 ) +texture = ExtResource( 1 ) +is_solid = true