Spielfeld über Art zeichnen
Karte, Figuren und Zielmarke zeichnet jetzt Art. Die Karte zeichnet in Blöcken von 16 mal 16 Kacheln und nach einem Treffer nur die Blöcke um die Kachel neu; jede Kachel kennt ihre Nachbarn. Figuren stehen aufrecht in ihrer Kachel, schreiten und schauen in die Richtung, in die sie gehen. Der eigene Schlag zeigt seine Splitter sofort, auch als Gast, und die Namen über fremden Figuren werden in Bildschirmgröße gezeichnet und bleiben scharf. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,3 +31,26 @@ func test_without_a_map_the_figure_stays() -> void:
|
||||
avatar.walk(Vector2.LEFT, 0.1)
|
||||
check_eq(avatar.position, Vector2.ZERO, "no walkability callable")
|
||||
avatar.free()
|
||||
|
||||
|
||||
func test_a_walking_figure_steps_and_faces_the_way_it_goes() -> void:
|
||||
var avatar := Avatar.new()
|
||||
avatar.is_walkable = _open_field
|
||||
avatar.position = GridMotion.tile_center(Vector2i(50, 50))
|
||||
check(not avatar.moving, "standing at first")
|
||||
avatar.walk(Vector2.LEFT, 0.1)
|
||||
check(avatar.moving, "walking")
|
||||
check_eq(avatar.facing, -1.0, "facing left")
|
||||
check(avatar.step > 0.0, "the step turns")
|
||||
avatar.walk(Vector2.UP, 0.1)
|
||||
check_eq(avatar.facing, -1.0, "walking up keeps the way it faces")
|
||||
avatar.walk(Vector2.ZERO, 0.1)
|
||||
check(not avatar.moving, "standing again")
|
||||
avatar.free()
|
||||
|
||||
|
||||
func test_a_figure_stands_upright_in_its_tile() -> void:
|
||||
var rect := Avatar.figure_rect(Vector2(100, 100))
|
||||
check_eq(rect.size, Vector2(GridMotion.TILE_SIZE, GridMotion.TILE_SIZE * 1.5), "a tile wide, one and a half tall")
|
||||
check_eq(rect.get_center().x, 100.0, "centred on the figure")
|
||||
check_eq(rect.end.y, 100.0 + Avatar.RADIUS + 1.0, "its feet just below its body")
|
||||
|
||||
@@ -32,3 +32,13 @@ func test_figures_can_be_forgotten() -> void:
|
||||
figures.clear()
|
||||
check_eq(figures.shown_at(3), Vector2.INF, "all are gone")
|
||||
figures.free()
|
||||
|
||||
|
||||
func test_a_figure_faces_the_way_it_glides() -> void:
|
||||
var figures := Figures.new()
|
||||
figures.place(1, Vector2(100.0, 0.0))
|
||||
check_eq(figures.facing_of(1), 1.0, "facing right at first")
|
||||
figures.place(1, Vector2.ZERO)
|
||||
figures._process(0.02)
|
||||
check_eq(figures.facing_of(1), -1.0, "facing left while it glides to the left")
|
||||
figures.free()
|
||||
|
||||
@@ -381,3 +381,14 @@ func test_a_mistyped_address_is_reported() -> void:
|
||||
check(main.session == null, "nothing starts")
|
||||
check_eq(main.menu.status(), tr("ADDRESS_INVALID") % "host:port", "the menu says why")
|
||||
_clean_up([directory])
|
||||
|
||||
|
||||
func test_an_own_hit_shows_its_burst_at_once() -> void:
|
||||
var directory := TestFiles.temporary_dir("burst")
|
||||
var main := _start_main(directory)
|
||||
main.play(false)
|
||||
var rock: Vector2i = main.session.spawn_point() + Vector2i(7, -2)
|
||||
check_eq(main.session.terrain_at(rock.x, rock.y), GwSession.TERRAIN_SOFT_ROCK, "rock beside the clearing")
|
||||
main.dig_at(rock)
|
||||
check_eq(main.map_view.burst_count(), 1, "the burst shows before the hit lands in a tick")
|
||||
_clean_up([directory])
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
extends TestCase
|
||||
## The map view over a real world of the core.
|
||||
|
||||
var key := PackedByteArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
|
||||
|
||||
|
||||
func _session() -> GwSession:
|
||||
var session := GwSession.new()
|
||||
session.start_new(7)
|
||||
session.join(key, "Ada")
|
||||
session.step()
|
||||
return session
|
||||
|
||||
|
||||
func _view(session: GwSession) -> MapView:
|
||||
var view := MapView.new()
|
||||
view.art = Art.new()
|
||||
view.session = session
|
||||
tree.root.add_child(view)
|
||||
view.reload()
|
||||
return view
|
||||
|
||||
|
||||
func _free(view: MapView) -> void:
|
||||
tree.root.remove_child(view)
|
||||
view.free()
|
||||
|
||||
|
||||
## The first tile of the soft rock beside the spawn clearing.
|
||||
func _rock(session: GwSession) -> Vector2i:
|
||||
return session.spawn_point() + Vector2i(7, -2)
|
||||
|
||||
|
||||
func test_the_map_is_drawn_in_blocks_that_cover_it() -> void:
|
||||
var session := _session()
|
||||
var view := _view(session)
|
||||
var across := ceili(session.map_width() / float(MapView.BLOCK))
|
||||
var down := ceili(session.map_height() / float(MapView.BLOCK))
|
||||
check_eq(view.block_count(), across * down, "blocks over the whole map")
|
||||
for style in Art.style_keys():
|
||||
view.art.select(style)
|
||||
view.redraw()
|
||||
await tree.process_frame
|
||||
_free(view)
|
||||
|
||||
|
||||
func test_each_tile_is_drawn_to_fit_the_rock_around_it() -> void:
|
||||
var session := _session()
|
||||
var view := _view(session)
|
||||
var solid := TileShape.flags(session.terrain_codes(), MapView.SOLID)
|
||||
for tile: Vector2i in [Vector2i(0, 0), session.spawn_point(), _rock(session)]:
|
||||
var expected := TileShape.mask(solid, session.map_width(), session.map_height(), tile, true)
|
||||
check_eq(view.mask_at(tile), expected, "the neighbours of %s" % tile)
|
||||
_free(view)
|
||||
|
||||
|
||||
func test_a_broken_rock_no_longer_shapes_its_neighbours() -> void:
|
||||
var session := _session()
|
||||
var view := _view(session)
|
||||
var rock := _rock(session)
|
||||
var west := rock + Vector2i(-1, 0)
|
||||
check(view.mask_at(west) & TileShape.E != 0, "the rock lies east of its neighbour")
|
||||
for hit in 3:
|
||||
session.dig(rock.x, rock.y)
|
||||
session.step()
|
||||
for wait in GwSession.DIG_COOLDOWN_TICKS:
|
||||
session.step()
|
||||
check_eq(session.terrain_at(rock.x, rock.y), GwSession.TERRAIN_GROUND, "three hits break it")
|
||||
view.refresh_tile(rock)
|
||||
check(view.mask_at(west) & TileShape.E == 0, "now there is ground east of the neighbour")
|
||||
await tree.process_frame
|
||||
_free(view)
|
||||
|
||||
|
||||
func test_a_burst_of_chips_shows_for_a_moment() -> void:
|
||||
var view := _view(_session())
|
||||
view.hit(Vector2i(3, 3))
|
||||
check_eq(view.burst_count(), 1, "a burst")
|
||||
view._process(MapView.HIT_SECONDS * 0.5)
|
||||
check_eq(view.burst_count(), 1, "still in the air")
|
||||
await tree.process_frame
|
||||
view._process(MapView.HIT_SECONDS * 0.6)
|
||||
check_eq(view.burst_count(), 0, "gone after its time")
|
||||
_free(view)
|
||||
|
||||
|
||||
func test_without_a_world_nothing_is_drawn() -> void:
|
||||
var view := _view(_session())
|
||||
view.session = null
|
||||
view.reload()
|
||||
check_eq(view.block_count(), 0, "no blocks")
|
||||
view.refresh_tile(Vector2i(1, 1))
|
||||
await tree.process_frame
|
||||
_free(view)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bp0vlwfwtlh7h
|
||||
Reference in New Issue
Block a user