From a103f080c627a2ded68891950b613a89aabe7444 Mon Sep 17 00:00:00 2001 From: yuki Date: Tue, 18 Nov 2025 12:21:18 -0300 Subject: [PATCH] implement basic destructable block --- resources/tilesets/level.tres | 4 --- scenes/ball/ball.gd | 29 ++++++++++++++----- scenes/ball/ball.tscn | 2 ++ scenes/main.tscn | 14 +++++----- scenes/tilemaps/block_tile_layer.gd | 37 +++++++++++++++++++++++++ scenes/tilemaps/block_tile_layer.gd.uid | 1 + scenes/tilemaps/block_tile_layer.tscn | 9 ++++++ 7 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 scenes/tilemaps/block_tile_layer.gd create mode 100644 scenes/tilemaps/block_tile_layer.gd.uid create mode 100644 scenes/tilemaps/block_tile_layer.tscn diff --git a/resources/tilesets/level.tres b/resources/tilesets/level.tres index 7420977..74e3473 100644 --- a/resources/tilesets/level.tres +++ b/resources/tilesets/level.tres @@ -16,10 +16,6 @@ texture = ExtResource("1_br5dt") 0:0/0/physics_layer_2/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) 1:0/0 = 0 1:0/0/physics_layer_1/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -1:1/0 = 0 -1:1/0/physics_layer_1/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -0:1/0 = 0 -0:1/0/physics_layer_1/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_pdhcq"] resource_name = "prototype floor" diff --git a/scenes/ball/ball.gd b/scenes/ball/ball.gd index 74bbb48..f1b28e1 100644 --- a/scenes/ball/ball.gd +++ b/scenes/ball/ball.gd @@ -11,7 +11,7 @@ var is_hit: bool = false # Called when the node enters the scene tree for the first time. func _ready() -> void: - #connect("body_entered", _on_collision) + connect("body_shape_entered", _on_collision) hurtbox.connect("area_entered", _on_hit) launch() @@ -22,7 +22,7 @@ func launch(angle: float = 0, speed_override: float = 0) -> void: linear_velocity = Vector2(cos(angle), sin(angle)) * (randf_range(launch_speed.x, launch_speed.y) if speed_override == 0 else speed_override) var length: float = linear_velocity.length()/100 play_animation(length) - decelerate_to_stop(length*2) + _decelerate_to_stop(length*2) func play_animation(speed_scale: float = 0) -> void: @@ -31,7 +31,7 @@ func play_animation(speed_scale: float = 0) -> void: sprite.play("default") -func decelerate_to_stop(duration: float = 0.3) -> void: +func _decelerate_to_stop(duration: float = 0.3) -> void: if current_decel_tween: current_decel_tween.kill() @@ -64,7 +64,22 @@ func _on_hit(hitbox: Hit) -> void: func _on_hit_end() -> void: is_hit = false -func _on_collision(_body: Node) -> void: - var length: float = linear_velocity.length()/100 - play_animation(length) - decelerate_to_stop(length) +func _on_collision(body_rid: RID, body: Node, _body_shape_index: int, _local_shape_index: int) -> void: + #var length: float = linear_velocity.length()/100 + #play_animation(length) + #_decelerate_to_stop(length) + + print("ball collided: "+body.name) + + var blocks := body as BlockTileLayer + if blocks != null: + assert(body is BlockTileLayer, "BlockTileLayer isnt its own class??") + var tile_pos: Vector2i = blocks.get_coords_for_body_rid(body_rid) + assert(tile_pos != null, "tile position is null") + assert(tile_pos != Vector2i.ZERO, "tile position is zero") + print("tile position: "+str(tile_pos)) + if blocks.get_cell_source_id(tile_pos) != -1: + if blocks.hit_tile(tile_pos): + linear_velocity *= 1.15 + else: + linear_velocity *= 1.08 diff --git a/scenes/ball/ball.tscn b/scenes/ball/ball.tscn index ba50b06..a155040 100644 --- a/scenes/ball/ball.tscn +++ b/scenes/ball/ball.tscn @@ -87,6 +87,8 @@ physics_material_override = SubResource("PhysicsMaterial_oqv3d") gravity_scale = 0.0 lock_rotation = true continuous_cd = 1 +contact_monitor = true +max_contacts_reported = 1 script = ExtResource("1_nv6q1") [node name="HurtArea2D" type="Area2D" parent="."] diff --git a/scenes/main.tscn b/scenes/main.tscn index a2cf892..f2cf0bc 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=5 format=4 uid="uid://d3c6aioatcy20"] +[gd_scene load_steps=6 format=4 uid="uid://d3c6aioatcy20"] [ext_resource type="TileSet" uid="uid://doja61ouvb77l" path="res://resources/tilesets/level.tres" id="1_uu6xs"] [ext_resource type="PackedScene" uid="uid://642nm6c4mpxx" path="res://scenes/player/player.tscn" id="2_r0du0"] +[ext_resource type="PackedScene" uid="uid://c0kslsucl4xhy" path="res://scenes/tilemaps/block_tile_layer.tscn" id="2_tbgi4"] [ext_resource type="PackedScene" uid="uid://cmgwv41ht3q4j" path="res://scenes/ball/ball.tscn" id="3_r0du0"] [ext_resource type="PackedScene" uid="uid://7nljh05o8b8e" path="res://scenes/level_camera/level_camera_2d.tscn" id="4_jyhfs"] @@ -13,25 +14,24 @@ tile_set = ExtResource("1_uu6xs") collision_enabled = false metadata/_edit_lock_ = true -[node name="BlockTilemap" type="TileMapLayer" parent="."] -tile_map_data = PackedByteArray("AAADAA0AAwAEAAIAAAADAAwAAwAEAAIAAAADAAsAAwAEAAIAAAADAAoAAwAEAAIAAAADAAkAAwAEAAIAAAADAAgAAwAEAAIAAAADAAcAAwAEAAIAAAADAAYAAwAEAAIAAAADAAUAAwAEAAIAAAADAAQAAwAEAAIAAAADAAMAAwAEAAIAAAADAAIAAwAEAAIAAAADAAEAAwAEAAIAAAAQAA0AAwAEAAIAAAAQAAwAAwAEAAIAAAAQAAsAAwAEAAIAAAAQAAoAAwAEAAIAAAAQAAkAAwAEAAIAAAAQAAgAAwAEAAIAAAAQAAcAAwAEAAIAAAAQAAYAAwAEAAIAAAAQAAUAAwAEAAIAAAAQAAQAAwAEAAIAAAAQAAMAAwAEAAIAAAAQAAIAAwAEAAIAAAAQAAEAAwAEAAIAAAADAAAAAwAEAAEAAAAQAAAAAwAEAAEAAAADAA4AAwAEAAMAAAAQAA4AAwAEAAMAAAAEAAoAAwAHAAQAAAAEAAsAAwAFAAQAAAAEAAwAAwAHAAAAAAAEAA0AAwAGAAUAAAAEAA4AAwAGAAcAAAAFAAsAAwAHAAQAAAAFAAwAAwAFAAQAAAAFAA0AAwAHAAUAAAAFAA4AAwAHAAcAAAAGAAwAAwAHAAQAAAAGAA0AAwAEAAEAAAAGAA4AAwAEAAMAAAANAAwAAwAHAAMAAAANAA0AAwAEAAEAAAANAA4AAwAEAAMAAAAOAAsAAwAHAAMAAAAOAAwAAwAGAAMAAAAOAA0AAwAHAAIAAAAOAA4AAwAGAAcAAAAPAAoAAwAHAAMAAAAPAAsAAwAGAAMAAAAPAAwAAwAEAAEAAAAPAA0AAwAEAAMAAAAPAA4AAwAHAAcAAAAFAAAAAwAGAAUAAAAGAAAAAwAHAAUAAAANAAAAAwAEAAEAAAAOAAAAAwAGAAAAAAAGAAIAAwAGAAQAAAAFAAMAAwAGAAQAAAAEAAQAAwAGAAQAAAANAAIAAwAFAAMAAAAOAAMAAwAFAAMAAAAPAAQAAwAFAAMAAAAOAAIAAwAGAAMAAAAPAAMAAwAGAAMAAAAFAAIAAwAFAAIAAAAEAAMAAwAFAAIAAAANAAEAAwAEAAMAAAAGAAEAAwAHAAIAAAAEAAEAAwAEAAQAAAAFAAEAAwAHAAcAAAAEAAAAAwAEAAAAAAAPAAIAAwAEAAQAAAAOAAEAAwAHAAAAAAAEAAIAAwAEAAUAAAAPAAEAAwAGAAMAAAAPAAAAAwAGAAMAAAAHAA0AAAABAAEAAAAIAA0AAAABAAEAAAAJAA0AAAABAAEAAAAKAA0AAAABAAEAAAALAA0AAAABAAEAAAAMAA0AAAABAAEAAAAHAAEAAAABAAEAAAAIAAEAAAABAAEAAAAJAAEAAAABAAEAAAAKAAEAAAABAAEAAAALAAEAAAABAAEAAAAMAAEAAAABAAEAAAAEAAcAAAAAAAAAAAAEAAYAAAAAAAAAAAAFAAYAAAAAAAAAAAAGAAYAAAAAAAAAAAAHAAYAAAAAAAAAAAAIAAYAAAAAAAAAAAAJAAYAAAAAAAAAAAAKAAYAAAAAAAAAAAALAAYAAAAAAAAAAAAMAAYAAAAAAAAAAAANAAYAAAAAAAAAAAAOAAYAAAAAAAAAAAAPAAYAAAAAAAAAAAAPAAcAAAAAAAAAAAAOAAcAAAAAAAAAAAANAAcAAAAAAAAAAAAMAAcAAAAAAAAAAAALAAcAAAAAAAAAAAAKAAcAAAAAAAAAAAAJAAcAAAAAAAAAAAAIAAcAAAAAAAAAAAAHAAcAAAAAAAAAAAAGAAcAAAAAAAAAAAAFAAcAAAAAAAAAAAA=") +[node name="WallTilemap" type="TileMapLayer" parent="."] +tile_map_data = PackedByteArray("AAADAA0AAwAEAAIAAAADAAwAAwAEAAIAAAADAAsAAwAEAAIAAAADAAoAAwAEAAIAAAADAAkAAwAEAAIAAAADAAgAAwAEAAIAAAADAAcAAwAEAAIAAAADAAYAAwAEAAIAAAADAAUAAwAEAAIAAAADAAQAAwAEAAIAAAADAAMAAwAEAAIAAAADAAIAAwAEAAIAAAADAAEAAwAEAAIAAAAQAA0AAwAEAAIAAAAQAAwAAwAEAAIAAAAQAAsAAwAEAAIAAAAQAAoAAwAEAAIAAAAQAAkAAwAEAAIAAAAQAAgAAwAEAAIAAAAQAAcAAwAEAAIAAAAQAAYAAwAEAAIAAAAQAAUAAwAEAAIAAAAQAAQAAwAEAAIAAAAQAAMAAwAEAAIAAAAQAAIAAwAEAAIAAAAQAAEAAwAEAAIAAAADAAAAAwAEAAEAAAAQAAAAAwAEAAEAAAADAA4AAwAEAAMAAAAQAA4AAwAEAAMAAAAEAAoAAwAHAAQAAAAEAAsAAwAFAAQAAAAEAAwAAwAHAAAAAAAEAA0AAwAGAAUAAAAEAA4AAwAGAAcAAAAFAAsAAwAHAAQAAAAFAAwAAwAFAAQAAAAFAA0AAwAHAAUAAAAFAA4AAwAHAAcAAAAGAAwAAwAHAAQAAAAGAA0AAwAEAAEAAAAGAA4AAwAEAAMAAAANAAwAAwAHAAMAAAANAA0AAwAEAAEAAAANAA4AAwAEAAMAAAAOAAsAAwAHAAMAAAAOAAwAAwAGAAMAAAAOAA0AAwAHAAIAAAAOAA4AAwAGAAcAAAAPAAoAAwAHAAMAAAAPAAsAAwAGAAMAAAAPAAwAAwAEAAEAAAAPAA0AAwAEAAMAAAAPAA4AAwAHAAcAAAAFAAAAAwAGAAUAAAAGAAAAAwAHAAUAAAANAAAAAwAEAAEAAAAOAAAAAwAGAAAAAAAGAAIAAwAGAAQAAAAFAAMAAwAGAAQAAAAEAAQAAwAGAAQAAAANAAIAAwAFAAMAAAAOAAMAAwAFAAMAAAAPAAQAAwAFAAMAAAAOAAIAAwAGAAMAAAAPAAMAAwAGAAMAAAAFAAIAAwAFAAIAAAAEAAMAAwAFAAIAAAANAAEAAwAEAAMAAAAGAAEAAwAHAAIAAAAEAAEAAwAEAAQAAAAFAAEAAwAHAAcAAAAEAAAAAwAEAAAAAAAPAAIAAwAEAAQAAAAOAAEAAwAHAAAAAAAEAAIAAwAEAAUAAAAPAAEAAwAGAAMAAAAPAAAAAwAGAAMAAAAEAAcAAAAAAAAAAAAEAAYAAAAAAAAAAAAFAAYAAAAAAAAAAAAGAAYAAAAAAAAAAAAHAAYAAAAAAAAAAAAIAAYAAAAAAAAAAAAJAAYAAAAAAAAAAAAKAAYAAAAAAAAAAAALAAYAAAAAAAAAAAAMAAYAAAAAAAAAAAANAAYAAAAAAAAAAAAOAAYAAAAAAAAAAAAPAAYAAAAAAAAAAAAPAAcAAAAAAAAAAAAOAAcAAAAAAAAAAAANAAcAAAAAAAAAAAAMAAcAAAAAAAAAAAALAAcAAAAAAAAAAAAKAAcAAAAAAAAAAAAJAAcAAAAAAAAAAAAIAAcAAAAAAAAAAAAHAAcAAAAAAAAAAAAGAAcAAAAAAAAAAAAFAAcAAAAAAAAAAAA=") tile_set = ExtResource("1_uu6xs") metadata/_edit_lock_ = true +[node name="BlockTileLayer" parent="." instance=ExtResource("2_tbgi4")] +tile_map_data = PackedByteArray("AAAHAA0ABAAAAAcAAAAIAA0ABAAAAAcAAAAJAA0ABAAAAAcAAAAKAA0ABAAAAAcAAAALAA0ABAAAAAcAAAAMAA0ABAAAAAcAAAAHAAEABAAAAAcAAAAIAAEABAAAAAcAAAAJAAEABAAAAAcAAAAKAAEABAAAAAcAAAALAAEABAAAAAcAAAAMAAEABAAAAAcAAAA=") + [node name="Player1" parent="." instance=ExtResource("2_r0du0")] position = Vector2(141, 184) -id = 1 -max_speed = 90.0 [node name="Player2" parent="." instance=ExtResource("2_r0du0")] position = Vector2(167, 77) id = 2 -max_speed = 90.0 [node name="Ball" parent="." instance=ExtResource("3_r0du0")] position = Vector2(162, 115) launch_speed = Vector2(150, 300) -speed_mult = null [node name="LevelCamera2D" parent="." instance=ExtResource("4_jyhfs")] ball_weight = 0.4 diff --git a/scenes/tilemaps/block_tile_layer.gd b/scenes/tilemaps/block_tile_layer.gd new file mode 100644 index 0000000..dce0e69 --- /dev/null +++ b/scenes/tilemaps/block_tile_layer.gd @@ -0,0 +1,37 @@ +class_name BlockTileLayer extends TileMapLayer + + +signal block_hit(tile_pos: Vector2i, hits_left: int) +signal block_destroyed(tile_pos: Vector2i) + +## Atlas in which the destructable blocks are stored. +@export var block_source_id: int = 4 +@export var max_hits: int = 4 + +var hit_counts: Dictionary[Vector2i, int] = {} + + +## Returns true if block is destroyed. +func hit_tile(coords: Vector2i) -> bool: + var source_id: int = get_cell_source_id(coords) + if source_id != block_source_id: + return false # not destructible + + var current_atlas: Vector2i = get_cell_atlas_coords(coords) + var row: int = current_atlas.y + + var hits: int = hit_counts.get(coords, 0) + 1 + + if hits >= max_hits: + # destroy + set_cell(coords, -1) + hit_counts.erase(coords) + block_destroyed.emit(coords) + return true + else: + # damage + var new_atlas: Vector2i = Vector2i(hits, row) # column=hits, row=same color + set_cell(coords, block_source_id, new_atlas) + hit_counts[coords] = hits + block_hit.emit(coords, max_hits - hits) + return false diff --git a/scenes/tilemaps/block_tile_layer.gd.uid b/scenes/tilemaps/block_tile_layer.gd.uid new file mode 100644 index 0000000..bd3b9df --- /dev/null +++ b/scenes/tilemaps/block_tile_layer.gd.uid @@ -0,0 +1 @@ +uid://c2r3y6kehk0gy diff --git a/scenes/tilemaps/block_tile_layer.tscn b/scenes/tilemaps/block_tile_layer.tscn new file mode 100644 index 0000000..362e51c --- /dev/null +++ b/scenes/tilemaps/block_tile_layer.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=3 format=3 uid="uid://c0kslsucl4xhy"] + +[ext_resource type="TileSet" uid="uid://doja61ouvb77l" path="res://resources/tilesets/level.tres" id="1_8foy8"] +[ext_resource type="Script" uid="uid://c2r3y6kehk0gy" path="res://scenes/tilemaps/block_tile_layer.gd" id="2_dkvk0"] + +[node name="BlockTileLayer" type="TileMapLayer"] +tile_set = ExtResource("1_8foy8") +physics_quadrant_size = 1 +script = ExtResource("2_dkvk0")