|
@@ -2,9 +2,18 @@ class_name Block
|
|
|
extends AnimatableBody2D
|
|
extends AnimatableBody2D
|
|
|
## One arc-shaped segment of a ring around the core.
|
|
## 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 indestructible := false
|
|
|
var color := Params.COLOR_BLUE
|
|
var color := Params.COLOR_BLUE
|
|
|
var _polygon := PackedVector2Array()
|
|
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:
|
|
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
|
|
collision_mask = 0
|
|
|
indestructible = is_indestructible
|
|
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()
|
|
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)
|
|
add_child(collision)
|
|
|
|
|
|
|
|
|
|
+ _polygon = _round_corners(_sector(inner + GAP / 2.0, outer - GAP / 2.0, begin, end, GAP / 2.0))
|
|
|
|
|
+
|
|
|
if indestructible:
|
|
if indestructible:
|
|
|
color = Params.COLOR_ORANGE
|
|
color = Params.COLOR_ORANGE
|
|
|
else:
|
|
else:
|
|
@@ -34,17 +37,40 @@ func _init(inner: float, outer: float, begin: float, end: float, is_indestructib
|
|
|
int(239 * (randf() / 5.0 + 0.5)))
|
|
int(239 * (randf() / 5.0 + 0.5)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+## Flashes and fades out, then frees itself. Stops colliding right away.
|
|
|
func destroy() -> void:
|
|
func destroy() -> void:
|
|
|
collision_layer = 0
|
|
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:
|
|
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.
|
|
# Polygons have no antialiasing of their own; a smooth outline softens the edge.
|
|
|
var outline := _polygon.duplicate()
|
|
var outline := _polygon.duplicate()
|
|
|
outline.append(_polygon[0])
|
|
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:
|
|
static func _arc(radius: float, from: float, to: float, steps: int) -> PackedVector2Array:
|