class_name Figures extends Node2D ## The figures of the other players, with their names. A new position comes ## over the network about ten times a second; in between, each figure glides ## toward the latest one. ## How quickly a figure closes the gap to its latest position, per second. const GLIDE := 15.0 const COLOR := Color(0.55, 0.8, 0.95) const OUTLINE := Color(0.05, 0.1, 0.15) const NAME_SIZE := 8 const NAME_WIDTH := 80.0 var session: GwSession var _shown: Dictionary[int, Vector2] = {} var _latest: Dictionary[int, Vector2] = {} ## 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: _shown.erase(player) _latest.erase(player) queue_redraw() func clear() -> void: _shown.clear() _latest.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) func _process(delta: float) -> void: if _shown.is_empty(): return var weight := minf(1.0, GLIDE * delta) for player in _shown: _shown[player] = _shown[player].lerp(_latest[player], weight) queue_redraw() func _draw() -> void: var font := ThemeDB.fallback_font for player in _shown: var at := _shown[player] draw_circle(at, Avatar.RADIUS + 1.0, OUTLINE) draw_circle(at, Avatar.RADIUS, COLOR) if session != null: var label := Vector2(at.x - NAME_WIDTH / 2.0, at.y - Avatar.RADIUS - 3.0) draw_string(font, label, session.player_name(player), HORIZONTAL_ALIGNMENT_CENTER, NAME_WIDTH, NAME_SIZE)