Selaa lähdekoodia

Round and smooth the block segments, fade them out when broken

Segments keep their flat colours but are drawn with rounded,
antialiased corners and an even 4 px gap, instead of sharp edges with
hairline seams. The collision shapes are unchanged.

A broken segment now flashes towards white and fades out over 0.15 s
instead of vanishing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gabriel Capella 5 päivää sitten
vanhempi
sitoutus
f7cbe13e09
1 muutettua tiedostoa jossa 38 lisäystä ja 12 poistoa
  1. 38 12
      scripts/block.gd

+ 38 - 12
scripts/block.gd

@@ -2,9 +2,18 @@ class_name Block
 extends AnimatableBody2D
 ## One arc-shaped segment of a ring around the core.
 
+const GAP := 4.0 # px between neighbouring tiles, drawn only (collision has no gap)
+const CORNER := 4.0 # corner rounding radius in px
+const BREAK_SECONDS := 0.15 # fade-out time, after a short flash
+
 var indestructible := false
 var color := Params.COLOR_BLUE
 var _polygon := PackedVector2Array()
+## 0 to 1: how far the tile is washed towards white while breaking.
+var _flash := 0.0:
+	set(value):
+		_flash = value
+		queue_redraw()
 
 
 func _init(inner: float, outer: float, begin: float, end: float, is_indestructible: bool) -> void:
@@ -13,18 +22,12 @@ func _init(inner: float, outer: float, begin: float, end: float, is_indestructib
 	collision_mask = 0
 	indestructible = is_indestructible
 
-	# Leave a ~1px gap between neighbouring segments.
-	begin += 1.0 / outer
-	end -= 1.0 / outer
-	var steps := maxi(2, int((end - begin) * sqrt(outer) / 1.5))
-	var outer_arc := _arc(outer, begin, end, steps)
-	# The drawn shape stops 2px short of the inner radius to leave a gap between rings.
-	_polygon = outer_arc + _arc(inner + 2.0, end, begin, steps)
-
 	var collision := CollisionPolygon2D.new()
-	collision.polygon = outer_arc + _arc(inner, end, begin, steps)
+	collision.polygon = _sector(inner, outer, begin + 1.0 / outer, end - 1.0 / outer, 0.0)
 	add_child(collision)
 
+	_polygon = _round_corners(_sector(inner + GAP / 2.0, outer - GAP / 2.0, begin, end, GAP / 2.0))
+
 	if indestructible:
 		color = Params.COLOR_ORANGE
 	else:
@@ -34,17 +37,40 @@ func _init(inner: float, outer: float, begin: float, end: float, is_indestructib
 			int(239 * (randf() / 5.0 + 0.5)))
 
 
+## Flashes and fades out, then frees itself. Stops colliding right away.
 func destroy() -> void:
 	collision_layer = 0
-	queue_free()
+	var tween := create_tween()
+	tween.tween_property(self, "_flash", 0.8, BREAK_SECONDS / 3.0)
+	tween.tween_property(self, "modulate:a", 0.0, BREAK_SECONDS)
+	tween.parallel().tween_property(self, "scale", Vector2.ONE * 1.04, BREAK_SECONDS)
+	tween.tween_callback(queue_free)
 
 
 func _draw() -> void:
-	draw_colored_polygon(_polygon, color)
+	var fill := color.lerp(Color.WHITE, _flash)
+	draw_colored_polygon(_polygon, fill)
 	# Polygons have no antialiasing of their own; a smooth outline softens the edge.
 	var outline := _polygon.duplicate()
 	outline.append(_polygon[0])
-	draw_polyline(outline, color, 1.0, true)
+	draw_polyline(outline, fill, 1.0, true)
+
+
+## Ring segment between two radii. [param gap] trims each side by that many pixels,
+## so the space between neighbours has the same width at every radius.
+static func _sector(inner: float, outer: float, begin: float, end: float, gap: float) -> PackedVector2Array:
+	var steps := maxi(2, int((end - begin) * sqrt(outer) / 1.5))
+	var outer_arc := _arc(outer, begin + gap / outer, end - gap / outer, steps)
+	return outer_arc + _arc(inner, end - gap / inner, begin + gap / inner, steps)
+
+
+## Shrinks then regrows the polygon with round joins, which rounds its corners.
+static func _round_corners(polygon: PackedVector2Array) -> PackedVector2Array:
+	var shrunk := Geometry2D.offset_polygon(polygon, -CORNER)
+	if shrunk.is_empty():
+		return polygon
+	var rounded := Geometry2D.offset_polygon(shrunk[0], CORNER, Geometry2D.JOIN_ROUND)
+	return polygon if rounded.is_empty() else rounded[0]
 
 
 static func _arc(radius: float, from: float, to: float, steps: int) -> PackedVector2Array: