implement basic destructable block

This commit is contained in:
yuki 2025-11-18 12:21:18 -03:00
parent fd4c08975d
commit a103f080c6
7 changed files with 78 additions and 18 deletions

View file

@ -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"

View file

@ -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

View file

@ -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="."]

View file

@ -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

View file

@ -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

View file

@ -0,0 +1 @@
uid://c2r3y6kehk0gy

View file

@ -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")