Kennungen, Kachelformen und Platzhalter für die Grafik
Jede Grafik auf dem Spielfeld bekommt eine Kennung. Art zeichnet sie im gewählten Stil oder aus einem Bild gleichen Namens unter game/art. ArtStyle zeichnet vorerst schlichte Platzhalter. TileShape beschreibt die Nachbarn einer Kachel, damit Felsmassen außen rund und innen geschlossen gezeichnet werden können. Die drei Stile Warm, Pastell und Glimmen gibt es schon mit Namen, noch ohne eigene Zeichnungen. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
extends TestCase
|
||||
|
||||
## Draws every graphic of `art` twice, with `state` and with nothing, while
|
||||
## it draws.
|
||||
class Probe extends Node2D:
|
||||
var art: Art
|
||||
var state: Dictionary
|
||||
var drawn := 0
|
||||
|
||||
func _draw() -> void:
|
||||
for id in Art.IDS:
|
||||
var rect := Rect2(0, 0, 48, 48) if id == Art.RUIN else Rect2(16, 16, 16, 16)
|
||||
art.draw(self, id, rect, state)
|
||||
art.draw(self, id, rect, {})
|
||||
drawn += 1
|
||||
|
||||
|
||||
## Everything a graphic can be asked to show, so that each drawing runs
|
||||
## through all its parts.
|
||||
static func _full_state() -> Dictionary:
|
||||
return {
|
||||
"solid": TileShape.N | TileShape.W | TileShape.NE, "living": TileShape.E | TileShape.S,
|
||||
"variant": 123456, "hits": 2, "age": 0.5, "player": 1, "facing": -1.0, "step": 1.0,
|
||||
"moving": true, "reachable": true, "time": 2.5, "growth": 0.9, "hop": 0.5, "awake": 0.7,
|
||||
"points": PackedVector2Array([Vector2(0, 8), Vector2(10, 4), Vector2(24, 9)]),
|
||||
}
|
||||
|
||||
|
||||
## Lets `art` draw every graphic once and returns how many were drawn.
|
||||
func _draw_everything(art: Art) -> int:
|
||||
var probe := Probe.new()
|
||||
probe.art = art
|
||||
probe.state = _full_state()
|
||||
tree.root.add_child(probe)
|
||||
await tree.process_frame
|
||||
await tree.process_frame
|
||||
var drawn := probe.drawn
|
||||
tree.root.remove_child(probe)
|
||||
probe.free()
|
||||
return drawn
|
||||
|
||||
|
||||
func test_every_style_draws_every_graphic() -> void:
|
||||
var art := Art.new()
|
||||
for style in art.styles:
|
||||
art.select(style.key())
|
||||
check_eq(await _draw_everything(art), Art.IDS.size(), "%s draws them all" % style.key())
|
||||
art.style = ArtStyle.new()
|
||||
check_eq(await _draw_everything(art), Art.IDS.size(), "the placeholders too")
|
||||
|
||||
|
||||
func test_the_styles_are_offered_in_a_fixed_order() -> void:
|
||||
var art := Art.new()
|
||||
var keys: Array[StringName] = []
|
||||
for style in art.styles:
|
||||
keys.append(style.key())
|
||||
check_eq(keys, Art.style_keys(), "the keys in the order of the styles")
|
||||
check_eq(keys, [WarmStyle.KEY, PastelStyle.KEY, GlowStyle.KEY], "warm, pastel, glow")
|
||||
check_eq(art.style, art.styles[0], "the first one is chosen at first")
|
||||
|
||||
|
||||
func test_a_style_is_chosen_by_its_key() -> void:
|
||||
var art := Art.new()
|
||||
var changes := [0]
|
||||
art.changed.connect(func() -> void: changes[0] += 1)
|
||||
check(art.select(PastelStyle.KEY), "the pastel style exists")
|
||||
check_eq(art.style.key(), PastelStyle.KEY, "and is chosen")
|
||||
check(art.select(PastelStyle.KEY), "choosing it again works")
|
||||
check_eq(changes[0], 1, "only a real change is announced")
|
||||
check(not art.select(&"watercolour"), "an unknown key is refused")
|
||||
check_eq(art.style.key(), PastelStyle.KEY, "and changes nothing")
|
||||
|
||||
|
||||
func test_the_next_style_follows_and_the_first_comes_after_the_last() -> void:
|
||||
var art := Art.new()
|
||||
var seen: Array[StringName] = []
|
||||
for i in art.styles.size() + 1:
|
||||
seen.append(art.style.key())
|
||||
art.select_next()
|
||||
check_eq(seen, [WarmStyle.KEY, PastelStyle.KEY, GlowStyle.KEY, WarmStyle.KEY], "round and round")
|
||||
|
||||
|
||||
func test_every_style_has_a_name_in_every_language() -> void:
|
||||
for translation in I18n.load_translations(I18n.TEXTS_FILE):
|
||||
for style in Art.new().styles:
|
||||
var title := String(translation.get_message(style.title_key()))
|
||||
check(not title.is_empty(), "%s in %s" % [style.title_key(), translation.locale])
|
||||
|
||||
|
||||
func test_a_picture_named_after_an_id_replaces_its_drawing() -> void:
|
||||
var directory := TestFiles.temporary_dir("art")
|
||||
DirAccess.make_dir_recursive_absolute(directory.path_join("terrain"))
|
||||
var image := Image.create(16, 16, false, Image.FORMAT_RGBA8)
|
||||
image.fill(Color.RED)
|
||||
image.save_png(directory.path_join("terrain/ground.png"))
|
||||
var art := Art.new()
|
||||
art.load_overrides(directory)
|
||||
check(art.has_override(Art.GROUND), "the ground has a picture")
|
||||
check(not art.has_override(Art.SOFT_ROCK), "soft rock has none")
|
||||
check_eq(await _draw_everything(art), Art.IDS.size(), "the picture is drawn like the rest")
|
||||
art.load_overrides(directory.path_join("missing"))
|
||||
check(not art.has_override(Art.GROUND), "loading again drops the picture")
|
||||
TestFiles.remove_dir(directory)
|
||||
|
||||
|
||||
func test_without_the_folder_of_pictures_everything_is_drawn() -> void:
|
||||
var art := Art.new()
|
||||
art.load_overrides(Art.OVERRIDE_DIR)
|
||||
for id in Art.IDS:
|
||||
check(not art.has_override(id), "no picture for %s" % id)
|
||||
@@ -0,0 +1 @@
|
||||
uid://dmuqgq1uvws3x
|
||||
@@ -0,0 +1,26 @@
|
||||
extends TestCase
|
||||
## The helpers that every style draws with.
|
||||
|
||||
|
||||
func test_a_point_can_be_found_along_a_path() -> void:
|
||||
var path := PackedVector2Array([Vector2(0, 0), Vector2(10, 0), Vector2(10, 10)])
|
||||
check_eq(ArtStyle.along(path, 0.0), Vector2(0, 0), "the start")
|
||||
check_eq(ArtStyle.along(path, 0.5), Vector2(10, 0), "halfway is the bend")
|
||||
check_eq(ArtStyle.along(path, 0.75), Vector2(10, 5), "three quarters")
|
||||
check_eq(ArtStyle.along(path, 1.0), Vector2(10, 10), "the end")
|
||||
check_eq(ArtStyle.along(path, 2.0), Vector2(10, 10), "never beyond the end")
|
||||
|
||||
|
||||
func test_shares_lie_between_zero_and_one_and_stay_the_same() -> void:
|
||||
for variant in [0, 1, 99, 123456, 2147483647]:
|
||||
for salt in 4:
|
||||
var share := ArtStyle.share(variant, salt)
|
||||
check(share >= 0.0 and share < 1.0, "share of %d and %d: %f" % [variant, salt, share])
|
||||
check_eq(ArtStyle.share(variant, salt), share, "the same again")
|
||||
|
||||
|
||||
func test_a_sway_swings_gently_and_differs_between_things() -> void:
|
||||
for tenth in 100:
|
||||
var swing := ArtStyle.sway(tenth * 0.1, 7)
|
||||
check(swing >= -1.0 and swing <= 1.0, "between left and right at %.1f s: %f" % [tenth * 0.1, swing])
|
||||
check(ArtStyle.sway(0.0, 1) != ArtStyle.sway(0.0, 2), "two things do not swing alike")
|
||||
@@ -0,0 +1 @@
|
||||
uid://cbkbq72ph6wdn
|
||||
@@ -0,0 +1,38 @@
|
||||
extends TestCase
|
||||
|
||||
## A map of three by three tiles, row by row, with rock (1) in the middle and
|
||||
## in the top right corner.
|
||||
const CODES := [0, 0, 1, 0, 1, 0, 0, 0, 0]
|
||||
|
||||
|
||||
func _flags() -> PackedByteArray:
|
||||
return TileShape.flags(PackedByteArray(CODES), [1])
|
||||
|
||||
|
||||
func test_flags_mark_the_tiles_of_the_given_codes() -> void:
|
||||
check_eq(_flags(), PackedByteArray([0, 0, 1, 0, 1, 0, 0, 0, 0]), "rock is marked")
|
||||
check_eq(TileShape.flags(PackedByteArray([0, 1, 2]), [1, 2]), PackedByteArray([0, 1, 1]), "several codes")
|
||||
|
||||
|
||||
func test_a_mask_holds_the_marked_neighbours_clockwise_from_north() -> void:
|
||||
check_eq(TileShape.mask(_flags(), 3, 3, Vector2i(1, 1), false), TileShape.NE, "the middle sees the corner")
|
||||
check_eq(TileShape.mask(_flags(), 3, 3, Vector2i(1, 2), false), TileShape.N, "below the middle")
|
||||
check_eq(TileShape.mask(_flags(), 3, 3, Vector2i(2, 1), false), TileShape.N | TileShape.W, "right of the middle")
|
||||
check_eq(TileShape.mask(_flags(), 3, 3, Vector2i(0, 0), false), TileShape.SE, "the top left corner")
|
||||
|
||||
|
||||
func test_beyond_the_edge_neighbours_count_as_marked_if_asked() -> void:
|
||||
var corner := TileShape.mask(_flags(), 3, 3, Vector2i(0, 0), true)
|
||||
var outside := TileShape.N | TileShape.NE | TileShape.NW | TileShape.W | TileShape.SW
|
||||
check_eq(corner, outside | TileShape.SE, "five neighbours lie outside")
|
||||
|
||||
|
||||
func test_variants_stay_the_same_and_differ_between_neighbours() -> void:
|
||||
check_eq(TileShape.variant(Vector2i(4, 7)), TileShape.variant(Vector2i(4, 7)), "the same every time")
|
||||
var seen := {}
|
||||
for y in 4:
|
||||
for x in 4:
|
||||
var variant := TileShape.variant(Vector2i(x, y))
|
||||
check(variant >= 0, "never negative: %d" % variant)
|
||||
seen[variant] = true
|
||||
check_eq(seen.size(), 16, "sixteen tiles, sixteen variants")
|
||||
@@ -0,0 +1 @@
|
||||
uid://c4ecwk4sri50q
|
||||
Reference in New Issue
Block a user