|
|
@@ -14,6 +14,8 @@ const TILE := 16
|
|
|
|
const FACE := 6
|
|
|
|
const FACE := 6
|
|
|
|
## Images of a burst of chips, from the hit to its end.
|
|
|
|
## Images of a burst of chips, from the hit to its end.
|
|
|
|
const HIT_FRAMES := 6
|
|
|
|
const HIT_FRAMES := 6
|
|
|
|
|
|
|
|
## Stages of a growing plant, from the seed to the fibres.
|
|
|
|
|
|
|
|
const GROWTH_STAGES := 6
|
|
|
|
## Size of a figure: a tile wide and one and a half tiles tall.
|
|
|
|
## Size of a figure: a tile wide and one and a half tiles tall.
|
|
|
|
const FIGURE_SIZE := Vector2i(16, 24)
|
|
|
|
const FIGURE_SIZE := Vector2i(16, 24)
|
|
|
|
const CLEAR := Color(0, 0, 0, 0)
|
|
|
|
const CLEAR := Color(0, 0, 0, 0)
|
|
|
@@ -25,6 +27,9 @@ var players: Array[Color] = []
|
|
|
|
## True for outlines in a darker shade of what they surround, false for one
|
|
|
|
## True for outlines in a darker shade of what they surround, false for one
|
|
|
|
## dark outline colour.
|
|
|
|
## dark outline colour.
|
|
|
|
var tinted_outlines := false
|
|
|
|
var tinted_outlines := false
|
|
|
|
|
|
|
|
## How strongly living things glow, from 0 (not at all) to 1; the subclass
|
|
|
|
|
|
|
|
## chooses it.
|
|
|
|
|
|
|
|
var glow := 0.0
|
|
|
|
var _textures: Dictionary[String, Texture2D] = {}
|
|
|
|
var _textures: Dictionary[String, Texture2D] = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -471,3 +476,325 @@ func _figure_image(colour: int, frame: int, left: bool) -> Pixels:
|
|
|
|
if left:
|
|
|
|
if left:
|
|
|
|
pixels.image.flip_x()
|
|
|
|
pixels.image.flip_x()
|
|
|
|
return pixels
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Things of later milestones, shown in the showcase.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _dead_soil(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var shadow: int = state.get("solid", 0) & (TileShape.N | TileShape.W | TileShape.NW)
|
|
|
|
|
|
|
|
var variant: int = state.get("variant", 0) % 8
|
|
|
|
|
|
|
|
var key := "dead/%d/%d" % [shadow, variant]
|
|
|
|
|
|
|
|
_put(canvas, _image(key, func() -> Pixels: return _crack_soil(_earth(variant, shadow), variant)), rect.position)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Dry cracks in every other tile of dead soil. Returns `pixels`.
|
|
|
|
|
|
|
|
func _crack_soil(pixels: Pixels, variant: int) -> Pixels:
|
|
|
|
|
|
|
|
if variant % 2 == 0:
|
|
|
|
|
|
|
|
var at := _spot(12, variant, 3, 7)
|
|
|
|
|
|
|
|
for step in 5:
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y, _c("dead_crack"))
|
|
|
|
|
|
|
|
if step == 2:
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y + 1, _c("dead_crack"))
|
|
|
|
|
|
|
|
pixels.put(at.x - 1, at.y + 2, _c("dead_crack"))
|
|
|
|
|
|
|
|
at += Vector2i(1, -1 if _noise(step, 5, variant) < 0.4 else 0)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _living_soil(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var living := _shape(state.get("living", 0))
|
|
|
|
|
|
|
|
var variant: int = state.get("variant", 0) % 6
|
|
|
|
|
|
|
|
_ground(canvas, rect, {"variant": state.get("variant", 0)})
|
|
|
|
|
|
|
|
_put(canvas, _image("living/%d/%d" % [living, variant], func() -> Pixels: return _grass_image(living, variant)), rect.position)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Grass with blades and a few flowers, with a soft edge toward the sides
|
|
|
|
|
|
|
|
## that are not living.
|
|
|
|
|
|
|
|
func _grass_image(living: int, variant: int) -> Pixels:
|
|
|
|
|
|
|
|
var open_n := (living & TileShape.N) == 0
|
|
|
|
|
|
|
|
var open_e := (living & TileShape.E) == 0
|
|
|
|
|
|
|
|
var open_s := (living & TileShape.S) == 0
|
|
|
|
|
|
|
|
var open_w := (living & TileShape.W) == 0
|
|
|
|
|
|
|
|
var pixels := Pixels.new(TILE, TILE)
|
|
|
|
|
|
|
|
pixels.rect(0, 0, TILE, TILE, _c("grass"))
|
|
|
|
|
|
|
|
for tuft in 6:
|
|
|
|
|
|
|
|
var at := _spot(tuft + 10, variant, 2, 12)
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y, _c("grass_dark"))
|
|
|
|
|
|
|
|
pixels.put(at.x - 1, at.y - 1, _c("grass_dark"))
|
|
|
|
|
|
|
|
pixels.put(at.x + 1, at.y - 1, _c("grass_dark"))
|
|
|
|
|
|
|
|
for blade in 4:
|
|
|
|
|
|
|
|
var at := _spot(blade + 20, variant, 1, 14)
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y, _c("grass_light"))
|
|
|
|
|
|
|
|
if variant % 3 == 0:
|
|
|
|
|
|
|
|
var x := 4 + variant % 7
|
|
|
|
|
|
|
|
var y := 5 + variant % 5
|
|
|
|
|
|
|
|
var petal := _c("flower_b") if variant % 2 == 0 else _c("flower_c")
|
|
|
|
|
|
|
|
for side in Pixels.SIDES:
|
|
|
|
|
|
|
|
pixels.put(x + side.x, y + side.y, petal)
|
|
|
|
|
|
|
|
pixels.put(x, y, _c("flower_a"))
|
|
|
|
|
|
|
|
if glow > 0.0:
|
|
|
|
|
|
|
|
for spark in 2:
|
|
|
|
|
|
|
|
var light := _c("spore")
|
|
|
|
|
|
|
|
light.a = glow * 0.8
|
|
|
|
|
|
|
|
pixels.put(2 + int(_noise(spark, 21, variant) * 12.0), 2 + int(_noise(spark, 22, variant) * 12.0), light)
|
|
|
|
|
|
|
|
# A ragged edge toward bare ground.
|
|
|
|
|
|
|
|
for i in TILE:
|
|
|
|
|
|
|
|
var ragged := 1 if _noise(i, 23, variant) < 0.45 else 0
|
|
|
|
|
|
|
|
if open_n:
|
|
|
|
|
|
|
|
_edge(pixels, Vector2i(i, 0), Vector2i(0, 1), ragged)
|
|
|
|
|
|
|
|
if open_s:
|
|
|
|
|
|
|
|
_edge(pixels, Vector2i(i, TILE - 1), Vector2i(0, -1), ragged)
|
|
|
|
|
|
|
|
if open_w:
|
|
|
|
|
|
|
|
_edge(pixels, Vector2i(0, i), Vector2i(1, 0), ragged)
|
|
|
|
|
|
|
|
if open_e:
|
|
|
|
|
|
|
|
_edge(pixels, Vector2i(TILE - 1, i), Vector2i(-1, 0), ragged)
|
|
|
|
|
|
|
|
if open_n and open_w:
|
|
|
|
|
|
|
|
_round(pixels, Vector2i(0, 0), Vector2i(1, 1), _c("grass_edge"))
|
|
|
|
|
|
|
|
if open_n and open_e:
|
|
|
|
|
|
|
|
_round(pixels, Vector2i(TILE - 1, 0), Vector2i(-1, 1), _c("grass_edge"))
|
|
|
|
|
|
|
|
if open_s and open_w:
|
|
|
|
|
|
|
|
_round(pixels, Vector2i(0, TILE - 1), Vector2i(1, -1), _c("grass_edge"))
|
|
|
|
|
|
|
|
if open_s and open_e:
|
|
|
|
|
|
|
|
_round(pixels, Vector2i(TILE - 1, TILE - 1), Vector2i(-1, -1), _c("grass_edge"))
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Clears `cut` pixels at `at` and draws the darker edge of the grass behind
|
|
|
|
|
|
|
|
## them, one step further in the direction `inward`.
|
|
|
|
|
|
|
|
func _edge(pixels: Pixels, at: Vector2i, inward: Vector2i, cut: int) -> void:
|
|
|
|
|
|
|
|
for depth in cut:
|
|
|
|
|
|
|
|
var gone := at + inward * depth
|
|
|
|
|
|
|
|
pixels.put(gone.x, gone.y, CLEAR)
|
|
|
|
|
|
|
|
var edge := at + inward * cut
|
|
|
|
|
|
|
|
pixels.put(edge.x, edge.y, _c("grass_edge"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _moss(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var variant: int = state.get("variant", 0) % 3
|
|
|
|
|
|
|
|
var twinkle := int(float(state.get("time", 0.0)) * 2.5) % 4
|
|
|
|
|
|
|
|
var foot := Vector2(rect.get_center().x, rect.end.y)
|
|
|
|
|
|
|
|
_put(canvas, _image("moss/%d/%d" % [variant, twinkle], func() -> Pixels: return _moss_image(variant, twinkle)), foot - Vector2(8, 13))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## A cushion of moss whose spores twinkle one after another.
|
|
|
|
|
|
|
|
func _moss_image(variant: int, twinkle: int) -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(TILE, 13)
|
|
|
|
|
|
|
|
var shift := variant - 1
|
|
|
|
|
|
|
|
for bump: Vector4 in [Vector4(4.5 + shift, 9.5, 4, 3.2), Vector4(11, 9.2, 4.3, 3.5), Vector4(7.8 - shift, 6.8, 3.8, 3.4)]:
|
|
|
|
|
|
|
|
pixels.ellipse(bump.x, bump.y, bump.z, bump.w, _c("moss"))
|
|
|
|
|
|
|
|
for y in pixels.size.y:
|
|
|
|
|
|
|
|
for x in pixels.size.x:
|
|
|
|
|
|
|
|
if not pixels.filled(x, y):
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
if y >= 11:
|
|
|
|
|
|
|
|
pixels.put(x, y, _c("moss_dark"))
|
|
|
|
|
|
|
|
elif not pixels.filled(x, y - 1) or not pixels.filled(x, y - 2):
|
|
|
|
|
|
|
|
pixels.put(x, y, _c("moss_light"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(_c("moss")), tinted_outlines)
|
|
|
|
|
|
|
|
var spores: Array[Vector2i] = [Vector2i(4 + shift, 8), Vector2i(8 - shift, 5), Vector2i(12, 8)]
|
|
|
|
|
|
|
|
for index in spores.size():
|
|
|
|
|
|
|
|
var at := spores[index]
|
|
|
|
|
|
|
|
var bright := index == twinkle
|
|
|
|
|
|
|
|
var spore := _c("spore") if bright else _c("spore").darkened(0.2)
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y, spore)
|
|
|
|
|
|
|
|
pixels.put(at.x + 1, at.y, spore)
|
|
|
|
|
|
|
|
if bright:
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y - 1, _c("spore"))
|
|
|
|
|
|
|
|
if glow > 0.0:
|
|
|
|
|
|
|
|
var halo := _c("spore")
|
|
|
|
|
|
|
|
halo.a = 0.45 * glow
|
|
|
|
|
|
|
|
for side in Pixels.SIDES:
|
|
|
|
|
|
|
|
pixels.shade(at.x + side.x, at.y + side.y + 1, halo)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _vine(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var points: PackedVector2Array = state.get("points", PackedVector2Array())
|
|
|
|
|
|
|
|
if points.size() < 2:
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
var origin := (rect.position - Vector2(6, 6)).floor()
|
|
|
|
|
|
|
|
var size := Vector2i(ceili(rect.size.x) + 13, ceili(rect.size.y) + 13)
|
|
|
|
|
|
|
|
var key := "vine/%d/%d/%d" % [hash(points), size.x, size.y]
|
|
|
|
|
|
|
|
_put(canvas, _image(key, func() -> Pixels: return _vine_image(points, origin, size)), origin)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## A vine two pixels thick along `points`, with leaves on alternate sides.
|
|
|
|
|
|
|
|
func _vine_image(points: PackedVector2Array, origin: Vector2, size: Vector2i) -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(size.x, size.y)
|
|
|
|
|
|
|
|
for i in points.size() - 1:
|
|
|
|
|
|
|
|
var from := Vector2i((points[i] - origin).round())
|
|
|
|
|
|
|
|
var to := Vector2i((points[i + 1] - origin).round())
|
|
|
|
|
|
|
|
pixels.line(from.x, from.y - 1, to.x, to.y - 1, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.line(from.x, from.y, to.x, to.y, _c("vine"))
|
|
|
|
|
|
|
|
pixels.line(from.x, from.y + 1, to.x, to.y + 1, _c("vine_dark"))
|
|
|
|
|
|
|
|
var length := 0.0
|
|
|
|
|
|
|
|
for i in points.size() - 1:
|
|
|
|
|
|
|
|
length += points[i].distance_to(points[i + 1])
|
|
|
|
|
|
|
|
var leaves := int(length / 9.0)
|
|
|
|
|
|
|
|
for leaf in leaves:
|
|
|
|
|
|
|
|
var at := Vector2i((along(points, (leaf + 0.5) / leaves) - origin).round())
|
|
|
|
|
|
|
|
var up := leaf % 2 == 0
|
|
|
|
|
|
|
|
var dy := -2 if up else 2
|
|
|
|
|
|
|
|
var tip := -1 if up else 1
|
|
|
|
|
|
|
|
pixels.put(at.x, at.y + dy, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(at.x + 1, at.y + dy, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(at.x + 1, at.y + dy + tip, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(at.x + 2, at.y + dy + tip, _c("leaf_dark"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(_c("vine")), tinted_outlines)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _fiber_plant(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var stage := clampi(int(float(state.get("growth", 1.0)) * GROWTH_STAGES), 0, GROWTH_STAGES - 1)
|
|
|
|
|
|
|
|
var lean := clampi(roundi(sway(state.get("time", 0.0), 3) * 1.4), -1, 1)
|
|
|
|
|
|
|
|
var foot := Vector2(rect.get_center().x, rect.end.y)
|
|
|
|
|
|
|
|
_put(canvas, _image("plant/%d/%d" % [stage, lean], func() -> Pixels: return _plant_image(stage, lean)), foot - Vector2(8, 28))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## A fibre plant at growth stage `stage`, its top leaning by `lean` pixels:
|
|
|
|
|
|
|
|
## a seed in a small mound, a sprout, a stalk with leaves, buds and at last
|
|
|
|
|
|
|
|
## white tufts of fibre.
|
|
|
|
|
|
|
|
func _plant_image(stage: int, lean: int) -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(TILE, 28)
|
|
|
|
|
|
|
|
pixels.rect(5, 26, 6, 1, _c("ground_dark"))
|
|
|
|
|
|
|
|
pixels.rect(4, 27, 8, 1, _c("ground_dark"))
|
|
|
|
|
|
|
|
if stage == 0:
|
|
|
|
|
|
|
|
pixels.put(7, 25, _c("seed"))
|
|
|
|
|
|
|
|
pixels.put(8, 25, _c("seed"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(_c("seed")), tinted_outlines)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
var heights: Array[int] = [0, 4, 8, 13, 17, 19]
|
|
|
|
|
|
|
|
var height := heights[stage]
|
|
|
|
|
|
|
|
var top := Vector2i(8, 25)
|
|
|
|
|
|
|
|
for i in height:
|
|
|
|
|
|
|
|
var x := 8 + roundi(lean * 2.0 * i / 19.0)
|
|
|
|
|
|
|
|
top = Vector2i(x, 25 - i)
|
|
|
|
|
|
|
|
pixels.put(top.x, top.y, _c("stem"))
|
|
|
|
|
|
|
|
@warning_ignore("integer_division")
|
|
|
|
|
|
|
|
for pair in range(1, height / 3 + 1):
|
|
|
|
|
|
|
|
var y := 26 - pair * 3
|
|
|
|
|
|
|
|
var x := 8 + roundi(lean * 2.0 * (25 - y) / 19.0)
|
|
|
|
|
|
|
|
var side := 1 if pair % 2 == 0 else -1
|
|
|
|
|
|
|
|
pixels.put(x + side, y, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(x + side * 2, y, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(x + side * 2, y - 1, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(x + side * 3, y - 1, _c("leaf_dark"))
|
|
|
|
|
|
|
|
pixels.put(x - side, y - 1, _c("leaf_dark"))
|
|
|
|
|
|
|
|
if stage == 1:
|
|
|
|
|
|
|
|
pixels.put(top.x - 1, top.y, _c("leaf"))
|
|
|
|
|
|
|
|
pixels.put(top.x + 1, top.y, _c("leaf"))
|
|
|
|
|
|
|
|
if stage == 4:
|
|
|
|
|
|
|
|
pixels.ellipse(top.x + 0.5, top.y - 0.5, 1.6, 1.6, _c("bud"))
|
|
|
|
|
|
|
|
if stage == 5:
|
|
|
|
|
|
|
|
for tuft: Vector3 in [Vector3(0, -2, 2.3), Vector3(-3, 1, 1.8), Vector3(3, 2, 1.8)]:
|
|
|
|
|
|
|
|
pixels.ellipse(top.x + 0.5 + tuft.x, top.y + tuft.y, tuft.z, tuft.z, _c("fibre"))
|
|
|
|
|
|
|
|
pixels.put(top.x + int(tuft.x), top.y + int(tuft.y) + 1, _c("fibre_shade"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(_c("stem")), tinted_outlines)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _stone(canvas: CanvasItem, rect: Rect2, _state: Dictionary) -> void:
|
|
|
|
|
|
|
|
_put(canvas, _image("stone", func() -> Pixels: return _stone_image()), Vector2(rect.get_center().x - 4, rect.end.y - 8))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _stone_image() -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(8, 8)
|
|
|
|
|
|
|
|
pixels.ellipse(4, 4.2, 3.2, 2.7, _c("stone"))
|
|
|
|
|
|
|
|
pixels.rect(2, 6, 4, 1, _c("stone_dark"))
|
|
|
|
|
|
|
|
pixels.put(2, 3, _c("stone_light"))
|
|
|
|
|
|
|
|
pixels.put(3, 2, _c("stone_light"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(_c("stone")), tinted_outlines)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _grazer(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var height := roundi(sin(PI * clampf(state.get("hop", 0.0), 0.0, 1.0)) * 5.0)
|
|
|
|
|
|
|
|
var left: bool = float(state.get("facing", 1.0)) < 0.0
|
|
|
|
|
|
|
|
var foot := Vector2(rect.get_center().x, rect.end.y)
|
|
|
|
|
|
|
|
var width := 14 - height
|
|
|
|
|
|
|
|
_put(canvas, _image("shadow/%d" % width, func() -> Pixels: return _shadow_image(width)), foot - Vector2(width / 2.0, 2))
|
|
|
|
|
|
|
|
var tucked := height > 1
|
|
|
|
|
|
|
|
_put(canvas, _image("grazer/%s/%s" % [tucked, left], func() -> Pixels: return _grazer_image(tucked, left)), foot - Vector2(10, 16 + height))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## A woolly animal, facing right or, with `left`, left; in the air its legs
|
|
|
|
|
|
|
|
## are `tucked`.
|
|
|
|
|
|
|
|
func _grazer_image(tucked: bool, left: bool) -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(20, 16)
|
|
|
|
|
|
|
|
for leg in [5, 7, 11, 13]:
|
|
|
|
|
|
|
|
pixels.rect(leg, 12, 1, 1 if tucked else 3, _c("hoof"))
|
|
|
|
|
|
|
|
for puff: Vector4 in [Vector4(9, 8, 6.5, 4.5), Vector4(5.5, 9.5, 4, 3.5), Vector4(12.5, 9.5, 4.5, 3.5), Vector4(8, 5.8, 4, 3), Vector4(11.5, 6.3, 3.5, 3)]:
|
|
|
|
|
|
|
|
pixels.ellipse(puff.x, puff.y, puff.z, puff.w, _c("wool"))
|
|
|
|
|
|
|
|
for y in pixels.size.y:
|
|
|
|
|
|
|
|
for x in pixels.size.x:
|
|
|
|
|
|
|
|
if pixels.at(x, y) == _c("wool"):
|
|
|
|
|
|
|
|
if y >= 11:
|
|
|
|
|
|
|
|
pixels.put(x, y, _c("wool_shade"))
|
|
|
|
|
|
|
|
elif not pixels.filled(x, y - 1) and _noise(x, y, 4) < 0.6:
|
|
|
|
|
|
|
|
pixels.put(x, y, _c("wool_light"))
|
|
|
|
|
|
|
|
pixels.ellipse(16.2, 8.0, 2.6, 3.2, _c("face"))
|
|
|
|
|
|
|
|
pixels.put(14, 5, _c("face"))
|
|
|
|
|
|
|
|
pixels.put(15, 5, _c("face"))
|
|
|
|
|
|
|
|
pixels.put(17, 7, _c("wool_light"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(_c("wool")), tinted_outlines)
|
|
|
|
|
|
|
|
if left:
|
|
|
|
|
|
|
|
pixels.image.flip_x()
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ruin(canvas: CanvasItem, rect: Rect2, state: Dictionary) -> void:
|
|
|
|
|
|
|
|
var awake := clampf(state.get("awake", 0.0), 0.0, 1.0)
|
|
|
|
|
|
|
|
_put(canvas, _image("ruin", func() -> Pixels: return _ruin_image()), rect.position)
|
|
|
|
|
|
|
|
_put(canvas, _image("ruin_glow", func() -> Pixels: return _ruin_glow()), rect.position, Color(1, 1, 1, awake))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## A gate of old stone blocks, three tiles wide, with moss on top and a dark
|
|
|
|
|
|
|
|
## doorway.
|
|
|
|
|
|
|
|
func _ruin_image() -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(TILE * 3, TILE * 3)
|
|
|
|
|
|
|
|
var stone := _c("ruin")
|
|
|
|
|
|
|
|
pixels.rect(3, 12, 12, 34, stone)
|
|
|
|
|
|
|
|
pixels.rect(33, 12, 12, 34, stone)
|
|
|
|
|
|
|
|
pixels.rect(1, 6, 46, 9, stone)
|
|
|
|
|
|
|
|
pixels.rect(1, 3, 46, 3, _c("ruin_light"))
|
|
|
|
|
|
|
|
pixels.rect(15, 15, 18, 31, _c("door"))
|
|
|
|
|
|
|
|
pixels.rect(9, 44, 30, 2, _c("ruin_dark"))
|
|
|
|
|
|
|
|
pixels.rect(7, 46, 34, 2, stone)
|
|
|
|
|
|
|
|
# Blocks: a joint every five rows, and between the blocks of each row.
|
|
|
|
|
|
|
|
for course in 8:
|
|
|
|
|
|
|
|
var y := 8 + course * 5
|
|
|
|
|
|
|
|
for x in range(1, 47):
|
|
|
|
|
|
|
|
if pixels.at(x, y) == stone:
|
|
|
|
|
|
|
|
pixels.put(x, y, _c("ruin_dark"))
|
|
|
|
|
|
|
|
var offset := 0 if course % 2 == 0 else 4
|
|
|
|
|
|
|
|
for x in range(3 + offset, 47, 8):
|
|
|
|
|
|
|
|
for row in range(y + 1, y + 5):
|
|
|
|
|
|
|
|
if pixels.at(x, row) == stone:
|
|
|
|
|
|
|
|
pixels.put(x, row, _c("ruin_dark"))
|
|
|
|
|
|
|
|
for x in range(1, 47):
|
|
|
|
|
|
|
|
if _noise(x, 40, 1) < 0.45:
|
|
|
|
|
|
|
|
pixels.put(x, 3, _c("ruin_moss"))
|
|
|
|
|
|
|
|
if _noise(x, 41, 1) < 0.25:
|
|
|
|
|
|
|
|
pixels.put(x, 4, _c("ruin_moss"))
|
|
|
|
|
|
|
|
for strand: Vector2i in [Vector2i(5, 4), Vector2i(12, 3), Vector2i(36, 5), Vector2i(43, 2)]:
|
|
|
|
|
|
|
|
pixels.rect(strand.x, 15, 1, strand.y, _c("ruin_moss"))
|
|
|
|
|
|
|
|
pixels.outline(_ink(stone), tinted_outlines)
|
|
|
|
|
|
|
|
return pixels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## The light in the doorway and the runes above it, shown as the ruin wakes.
|
|
|
|
|
|
|
|
func _ruin_glow() -> Pixels:
|
|
|
|
|
|
|
|
var pixels := Pixels.new(TILE * 3, TILE * 3)
|
|
|
|
|
|
|
|
var center := Vector2(24, 31)
|
|
|
|
|
|
|
|
for y in range(15, 46):
|
|
|
|
|
|
|
|
for x in range(15, 33):
|
|
|
|
|
|
|
|
var distance := Vector2(x + 0.5, y + 0.5).distance_to(center)
|
|
|
|
|
|
|
|
var light := _c("glow_light") if distance < 4.0 else _c("glow")
|
|
|
|
|
|
|
|
light.a = clampf(1.0 - distance / 13.0, 0.0, 1.0) * (0.8 + 0.2 * glow)
|
|
|
|
|
|
|
|
if light.a > 0.05:
|
|
|
|
|
|
|
|
pixels.put(x, y, light)
|
|
|
|
|
|
|
|
for rune in 3:
|
|
|
|
|
|
|
|
var x := 16 + rune * 7
|
|
|
|
|
|
|
|
for dot: Vector2i in [Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 2), Vector2i(1, 2)]:
|
|
|
|
|
|
|
|
pixels.put(x + dot.x + (rune % 2), 8 + dot.y, _c("glow"))
|
|
|
|
|
|
|
|
return pixels
|
|
|
|