From ec1c99ebb4bde85f6ef81582b5e779954b931463 Mon Sep 17 00:00:00 2001 From: veclav talica Date: Sun, 26 Nov 2023 05:17:35 +0500 Subject: [PATCH] contextual collisions, tilemap support for collision of tiles --- nodes/Context.gd | 2 +- nodes/GridContext.gd | 22 ++++++++++++++++++---- nodes/TileMapObject.gd | 15 +++++++++++++++ nodes/TileMapTileDescriptor.gd | 3 +++ scenes/Game.tscn | 8 ++++---- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/nodes/Context.gd b/nodes/Context.gd index 5f5a493..c0f63ba 100644 --- a/nodes/Context.gd +++ b/nodes/Context.gd @@ -9,7 +9,7 @@ func local_position_to_context_position(_p_position: Vector2) -> Vector2: push_error("Abstract class method is unimplemented") return Vector2.ZERO -func is_path_traversible(_p_from: Vector2, _p_to: Vector2) -> bool: +func is_path_traversible(_p_game_object: Node2D, _p_from: Vector2, _p_to: Vector2) -> bool: push_error("Abstract class method is unimplemented") return false diff --git a/nodes/GridContext.gd b/nodes/GridContext.gd index 559b3e7..825d15f 100644 --- a/nodes/GridContext.gd +++ b/nodes/GridContext.gd @@ -9,20 +9,34 @@ export var cell_size: Vector2 = Vector2(64, 64) setget _set_cell_size signal cell_size_changed(p_old_cell_size, p_new_cell_size) +var _colliders: Dictionary # Node to null (set) + func local_position_to_context_position(p_position: Vector2) -> Vector2: return p_position / cell_size -func is_path_traversible(p_from: Vector2, p_to: Vector2) -> bool: - # todo: +func is_path_traversible(p_game_object: Node2D, p_from: Vector2, p_to: Vector2) -> bool: + for collider in _colliders: + if not collider.is_path_traversible(p_game_object, p_from, p_to): + return false return true +# todo: Effectful traversal. func try_moving(p_game_object: Node2D, p_from: Vector2, p_to: Vector2) -> bool: - if not is_path_traversible(p_from, p_to): + if not is_path_traversible(p_game_object, p_from, p_to): return false - + p_game_object.position = cell_size * p_to return true +func register_collider(p_collider: Node) -> void: + _colliders[p_collider] = null + if p_collider.connect("child_exiting_tree", self, "_on_collider_exiting_tree") != OK: + assert(false) + +func _on_collider_exiting_tree(p_collider) -> void: + if not _colliders.erase(p_collider): + pass + func _set_cell_size(p_new_cell_size: Vector2) -> void: if p_new_cell_size.x == 0 or p_new_cell_size.y == 0: push_error("Cell size cannot be zero") diff --git a/nodes/TileMapObject.gd b/nodes/TileMapObject.gd index 59bc088..58b41ea 100644 --- a/nodes/TileMapObject.gd +++ b/nodes/TileMapObject.gd @@ -7,6 +7,7 @@ extends TileMap export var expose_collisions: bool = true var _descriptor_name_to_id: Dictionary # String to int +var _id_to_descriptor_name: Dictionary # int to String func change_tile_texture(p_tile: String, p_texture: Texture) -> void: if not p_tile in _descriptor_name_to_id: @@ -16,8 +17,19 @@ func change_tile_texture(p_tile: String, p_texture: Texture) -> void: var id := _descriptor_name_to_id[p_tile] as int tile_set.tile_set_texture(id, p_texture) +func is_path_traversible(p_game_object: Node2D, p_from: Vector2, p_to: Vector2) -> bool: + if p_from.distance_squared_to(p_to) == 1: + var id := get_cell(int(p_to.x), int(p_to.y)) + if id == -1: return true + var descriptor = _id_to_descriptor_name[id] as String + return get_node(descriptor).is_traversible_for(p_game_object) + else: + print_debug("Unimplemented") + return false + func _enter_tree() -> void: tile_set = TileSet.new() + get_parent().register_collider(self) # It's okay to fail here for non-grid contexts. if get_parent().connect("cell_size_changed", self, "_update_cell_size"): @@ -41,6 +53,7 @@ func _update_cell_size(_p_old_cell_size: Vector2, p_new_cell_size: Vector2) -> v 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 + _id_to_descriptor_name[id] = p_node.name tile_set.create_tile(id) tile_set.tile_set_texture(id, p_node.texture) @@ -51,3 +64,5 @@ func _on_child_exiting_tree(p_node: Node) -> void: tile_set.remove_tile(id) if not _descriptor_name_to_id.erase(p_node.name): assert(false) + if not _id_to_descriptor_name.erase(id): + assert(false) diff --git a/nodes/TileMapTileDescriptor.gd b/nodes/TileMapTileDescriptor.gd index b9265d1..9b695c0 100644 --- a/nodes/TileMapTileDescriptor.gd +++ b/nodes/TileMapTileDescriptor.gd @@ -7,6 +7,9 @@ export var texture: Texture setget _set_texture # todo: More layer customizeability. export var is_solid: bool +func is_traversible_for(_p_game_object: Node2D) -> bool: + return not is_solid + func _set_texture(p_texture: Texture) -> void: texture = p_texture if is_inside_tree(): diff --git a/scenes/Game.tscn b/scenes/Game.tscn index cd455f4..9a57c5d 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -40,10 +40,10 @@ script = ExtResource( 7 ) [node name="Brickwall" parent="GridContext/TileMapObject" instance=ExtResource( 8 )] -[node name="GameObject" parent="GridContext" instance=ExtResource( 5 )] +[node name="Player" parent="GridContext" instance=ExtResource( 5 )] position = Vector2( 384, 128 ) -[node name="Visual" type="Sprite" parent="GridContext/GameObject"] +[node name="Visual" type="Sprite" parent="GridContext/Player"] scale = Vector2( 4, 4 ) texture = ExtResource( 2 ) centered = false @@ -53,9 +53,9 @@ __meta__ = { } target_size = Vector2( 64, 64 ) -[node name="4WayController" parent="GridContext/GameObject" instance=ExtResource( 3 )] +[node name="4WayController" parent="GridContext/Player" instance=ExtResource( 3 )] -[node name="Camera2D" type="Camera2D" parent="GridContext/GameObject"] +[node name="Camera2D" type="Camera2D" parent="GridContext/Player"] position = Vector2( 32, 32 ) __meta__ = { "_edit_lock_": true