d2a7973022
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>
93 lines
3.3 KiB
GDScript
93 lines
3.3 KiB
GDScript
class_name Figures
|
|
extends Node2D
|
|
## The figures of the other players, with their names, drawn by `art`. A new
|
|
## position comes over the network about ten times a second; in between,
|
|
## each figure glides toward the latest one, stepping and facing the way it
|
|
## goes.
|
|
|
|
## How quickly a figure closes the gap to its latest position, per second.
|
|
const GLIDE := 15.0
|
|
## Pixels per frame below which a gliding figure counts as standing.
|
|
const STANDING := 0.05
|
|
## Size and width of the names, in pixels of the playing field. The names
|
|
## are drawn at the size they have on screen, so that they stay sharp.
|
|
const NAME_SIZE := 8
|
|
const NAME_WIDTH := 80.0
|
|
const NAME_OUTLINE := Color(0.05, 0.05, 0.06)
|
|
|
|
var session: GwSession
|
|
var art: Art
|
|
var _shown: Dictionary[int, Vector2] = {}
|
|
var _latest: Dictionary[int, Vector2] = {}
|
|
var _facing: Dictionary[int, float] = {}
|
|
var _step: Dictionary[int, float] = {}
|
|
var _moving: Dictionary[int, bool] = {}
|
|
|
|
|
|
## Moves the figure of `player` toward `position`. A figure that was not
|
|
## shown yet appears there at once.
|
|
func place(player: int, position: Vector2) -> void:
|
|
if not _shown.has(player):
|
|
_shown[player] = position
|
|
_latest[player] = position
|
|
queue_redraw()
|
|
|
|
|
|
## Removes the figure of `player`.
|
|
func forget(player: int) -> void:
|
|
for figures: Dictionary in [_shown, _latest, _facing, _step, _moving]:
|
|
figures.erase(player)
|
|
queue_redraw()
|
|
|
|
|
|
func clear() -> void:
|
|
for figures: Dictionary in [_shown, _latest, _facing, _step, _moving]:
|
|
figures.clear()
|
|
queue_redraw()
|
|
|
|
|
|
## Where the figure of `player` is shown, or Vector2.INF if it is not.
|
|
func shown_at(player: int) -> Vector2:
|
|
return _shown.get(player, Vector2.INF)
|
|
|
|
|
|
## 1.0 if the figure of `player` faces right, -1.0 if it faces left.
|
|
func facing_of(player: int) -> float:
|
|
return _facing.get(player, 1.0)
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
if _shown.is_empty():
|
|
return
|
|
var weight := minf(1.0, GLIDE * delta)
|
|
for player in _shown:
|
|
var before := _shown[player]
|
|
_shown[player] = before.lerp(_latest[player], weight)
|
|
var moved := _shown[player] - before
|
|
if absf(moved.x) > STANDING:
|
|
_facing[player] = signf(moved.x)
|
|
_step[player] = _step.get(player, 0.0) + moved.length() * Avatar.STEP_PER_PIXEL
|
|
_moving[player] = moved.length() > STANDING
|
|
queue_redraw()
|
|
|
|
|
|
func _draw() -> void:
|
|
if art == null:
|
|
return
|
|
var font := ThemeDB.fallback_font
|
|
# The camera enlarges the field. Text drawn at its size on screen and then
|
|
# shrunk stays sharp; text drawn small and enlarged would blur.
|
|
var zoom := maxf(1.0, get_global_transform_with_canvas().get_scale().x)
|
|
for player in _shown:
|
|
var at := _shown[player]
|
|
var state := {"player": player, "facing": facing_of(player), "step": _step.get(player, 0.0), "moving": _moving.get(player, false)}
|
|
art.draw(self, Art.FIGURE, Avatar.figure_rect(at), state)
|
|
if session != null:
|
|
var label := Vector2(at.x - NAME_WIDTH / 2.0, Avatar.figure_rect(at).position.y - 2.0)
|
|
var text := session.player_name(player)
|
|
var size := roundi(NAME_SIZE * zoom)
|
|
draw_set_transform(label, 0.0, Vector2.ONE / zoom)
|
|
draw_string_outline(font, Vector2.ZERO, text, HORIZONTAL_ALIGNMENT_CENTER, NAME_WIDTH * zoom, size, maxi(2, roundi(zoom * 1.5)), NAME_OUTLINE)
|
|
draw_string(font, Vector2.ZERO, text, HORIZONTAL_ALIGNMENT_CENTER, NAME_WIDTH * zoom, size)
|
|
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|