diff options
Diffstat (limited to 'test-client')
| -rw-r--r-- | test-client/main.ts | 27 | ||||
| -rw-r--r-- | test-client/protocol.ts | 5 | ||||
| -rw-r--r-- | test-client/visual.ts | 55 | 
3 files changed, 57 insertions, 30 deletions
| diff --git a/test-client/main.ts b/test-client/main.ts index a3bf0105..5d3a6d11 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -88,6 +88,7 @@ export interface PlayerData extends MovementBase {      character: number,      anim_position: V2,      message_persist?: MessageData, +    message_pinned?: MessageData,      message?: MessageData,  } @@ -97,8 +98,9 @@ export interface TileData {      kind: TileIndex      item?: ItemData  } +export type MessageStyle = "hint" | "normal" | "error" | "pinned"  export interface MessageData { -    style: "hint" | "normal" | "error" +    style: MessageStyle      inner: Message      anim_position: V2,      anim_size: number, @@ -120,7 +122,7 @@ export let camera_scale = 0.05;  export const interact_target_anim: V2 = { x: 0, y: 0 }  export let interact_possible_anim: number = 0  export let interact_active_anim: number = 0 -export let nametag_scale_anim: number = 0 +export let overlay_vis_anim: number = 0  export let is_lobby = false  let interacting: V2 | undefined;  let last_server_sent_position: V2 = { x: 0, y: 0 } @@ -226,11 +228,18 @@ function packet(p: PacketC) {                      inner: p.message,                      anim_size: 0.,                      anim_position: player.anim_position, -                    timeout: p.timeout ?? { initial: 5, remaining: 5 }, +                    timeout: p.timeout ?? { initial: 5, remaining: 5, pinned: false },                      style: "normal" as const                  };                  if (p.timeout === undefined) player.message = message                  else player.message_persist = message +                if (p.timeout?.pinned) player.message_pinned = { +                    inner: p.message, +                    anim_size: 0, +                    anim_position: { x: 20, y: 0 }, +                    style: "pinned", +                    timeout: p.timeout +                }              } else if (p.timeout !== undefined) {                  delete player.message_persist              } @@ -248,7 +257,7 @@ function packet(p: PacketC) {                  style: p.error ? "error" : "normal",                  anim_size: 0.,                  anim_position: { x: 0, y: 0 }, -                timeout: { initial: 5, remaining: 5 } +                timeout: { initial: 5, remaining: 5, pinned: false }              }              break;          case "set_ingame": @@ -286,7 +295,7 @@ function packet(p: PacketC) {                  case "book": open("https://s.metamuffin.org/static/hurrycurry/book.pdf"); break                  case "score":                      global_message = { -                        timeout: { initial: 5, remaining: 5 }, +                        timeout: { initial: 5, remaining: 5, pinned: false },                          inner: { text: `Score: ${JSON.stringify(p.data, null, 4)}` },                          anim_position: { x: 0, y: 0 },                          anim_size: 0, @@ -391,16 +400,18 @@ function frame_update(dt: number) {          if (item.active) item.active.position += item.active.speed * dt      } +    let pin_xo = 0      for (const [pid, player] of players) {          if (pid == my_id) player.anim_position.x = player.position.x, player.anim_position.y = player.position.y          else lerp_exp_v2_mut(player.anim_position, player.position, dt * 15)          if (player.item !== undefined && player.item !== null) update_item(player.item)          if (player.message && tick_message(player.message, dt)) delete player.message          if (player.message_persist && tick_message(player.message_persist, dt)) delete player.message_persist +        if (player.message_pinned && tick_message(player.message_pinned, dt)) delete player.message_pinned +        if (player.message_pinned) lerp_exp_v2_mut(player.message_pinned.anim_position, { x: pin_xo++, y: 0 }, dt * 5)      } -    for (const [_, tile] of tiles) { +    for (const [_, tile] of tiles)          if (tile.item !== undefined && tile.item !== null) update_item(tile.item) -    }      const remove: ItemData[] = []      for (const item of items_removed) { @@ -426,7 +437,7 @@ function frame_update(dt: number) {      const zoom_target = Math.min(canvas.width, canvas.height) * (keys_down.has("KeyL") ? 0.05 : 0.1)      camera_scale = lerp_exp(camera_scale, zoom_target, dt * 5) -    nametag_scale_anim = lerp_exp(nametag_scale_anim, +keys_down.has("KeyL"), dt * 10) +    overlay_vis_anim = lerp_exp(overlay_vis_anim, +keys_down.has("KeyL"), dt * 10)      tick_particles(dt)  } diff --git a/test-client/protocol.ts b/test-client/protocol.ts index c8c59ed2..64d740c3 100644 --- a/test-client/protocol.ts +++ b/test-client/protocol.ts @@ -40,7 +40,7 @@ export type PacketS =      | { type: "leave", player: PlayerID } // Despawns a character      | { type: "movement", player: PlayerID, pos: Vec2, dir: Vec2, boost: boolean }      | { type: "interact", player: PlayerID, pos?: Vec2 } // Interact with some tile. pos is a position when pressing and null when releasing interact button -    | { type: "communicate", player: PlayerID, message?: Message, timeout?: number } // Sends a message +    | { type: "communicate", player: PlayerID, message?: Message, timeout?: number, pin?: boolean } // Sends a message      | { type: "effect", player: PlayerID, name: string } // Sends an effect      | { type: "replay_tick", dt: number } // Steps forward in replay. @@ -73,7 +73,8 @@ export type Menu =  export interface MessageTimeout {      initial: number, -    remaining: number +    remaining: number, +    pinned: boolean,  }  export interface Score { diff --git a/test-client/visual.ts b/test-client/visual.ts index 9a267da0..784a36a3 100644 --- a/test-client/visual.ts +++ b/test-client/visual.ts @@ -16,7 +16,7 @@  */  import { tr } from "./locale.ts"; -import { ItemData, MessageData, PlayerData, TileData, camera, camera_scale, canvas, ctx, data, get_interact_target, global_message, interact_active_anim, interact_possible_anim, interact_target_anim, is_lobby, items_removed, keys_down, my_id, nametag_scale_anim, players, score, server_hints, tiles } from "./main.ts"; +import { ItemData, MessageData, MessageStyle, PlayerData, TileData, camera, camera_scale, canvas, ctx, data, get_interact_target, global_message, interact_active_anim, interact_possible_anim, interact_target_anim, is_lobby, items_removed, keys_down, my_id, overlay_vis_anim, players, score, server_hints, tiles } from "./main.ts";  import { PLAYER_SIZE } from "./movement.ts";  import { draw_item_sprite, draw_tile_sprite, ItemName, TileName } from "./tiles.ts";  import { V2, ceil_v2, floor_v2 } from "./util.ts"; @@ -67,16 +67,24 @@ export function draw_ingame() {      draw_interact_target()      for (const [_, player] of players) -        if (player.message) draw_message(player.message) +        if (player.message) draw_message(player.message, true)      for (const [_, player] of players) -        if (player.message_persist) draw_message(player.message_persist) +        if (player.message_persist) draw_message(player.message_persist, true)      for (const [_, player] of players)          draw_player_nametag(player)      for (const [_, message] of server_hints) -        draw_message(message) +        draw_message(message, true) + +    ctx.restore() +    ctx.save() +    ctx.translate(50, 50) +    ctx.scale(80, 80) + +    for (const [_, player] of players) +        if (player.message_pinned) draw_message(player.message_pinned, false)      ctx.restore() @@ -143,13 +151,13 @@ function draw_player(player: PlayerData) {  }  function draw_player_nametag(player: PlayerData) { -    if (nametag_scale_anim > 0.01) { +    if (overlay_vis_anim > 0.01) {          ctx.save()          ctx.translate(player.anim_position.x, player.anim_position.y)          ctx.translate(0, -1)          ctx.textAlign = "center"          ctx.font = "15px sans-serif" -        ctx.scale(nametag_scale_anim / camera_scale, nametag_scale_anim / camera_scale) +        ctx.scale(overlay_vis_anim / camera_scale, overlay_vis_anim / camera_scale)          const w = ctx.measureText(player.name).width + 20          ctx.fillStyle = "#fffa"          ctx.beginPath() @@ -221,20 +229,27 @@ function message_str(m: Message): string {      return "[unknown message type]"  } -const MESSAGE_BG = { "normal": "#fff", "hint": "#111", "error": "#fff" } -const MESSAGE_FG = { "normal": "#000", "hint": "#fff", "error": "#a00" } -function draw_message(m: MessageData, server?: boolean) { +const MESSAGE_BG: { [key in MessageStyle]: string } = { normal: "#fff", hint: "#111", error: "#fff", pinned: "rgb(4, 32, 0)" } +const MESSAGE_FG: { [key in MessageStyle]: string } = { normal: "#000", hint: "#fff", error: "#a00", pinned: "#000" } +function draw_message(m: MessageData, world: boolean) {      ctx.save()      ctx.translate(m.anim_position.x, m.anim_position.y) -    const scale = Math.min(m.anim_size, 1 - nametag_scale_anim); +    const scale = Math.min(m.anim_size, 1 - overlay_vis_anim);      ctx.scale(scale, scale)      if ("item" in m.inner) { -        ctx.fillStyle = "#fffa" -        ctx.beginPath() -        ctx.moveTo(0, -0.3) -        ctx.arc(0, -1, 0.5, Math.PI / 4, Math.PI - Math.PI / 4, true) -        ctx.closePath() -        ctx.fill() +        ctx.fillStyle = MESSAGE_BG[m.style] +        if (m.style == "pinned") { +            ctx.translate(0, 1) +            ctx.beginPath() +            ctx.arc(0, -1, 0.5, 0, Math.PI * 2) +            ctx.fill() +        } else { +            ctx.beginPath() +            ctx.moveTo(0, -0.3) +            ctx.arc(0, -1, 0.5, Math.PI / 4, Math.PI - Math.PI / 4, true) +            ctx.closePath() +            ctx.fill() +        }          if (m.timeout) {              const t = m.timeout.remaining / m.timeout.initial; @@ -253,13 +268,13 @@ function draw_message(m: MessageData, server?: boolean) {          ctx.translate(0, -1)          ctx.textAlign = "center" -        ctx.font = "15px " + (server ? "monospace" : "sans-serif") -        if (!server) ctx.scale(2 / camera_scale, 2 / camera_scale) +        ctx.font = "15px " + (world ? "sans-serif" : "monospace") +        if (world) ctx.scale(2 / camera_scale, 2 / camera_scale)          const lines = message_str(m.inner).split("\n")          const w = lines.reduce((a, v) => Math.max(a, ctx.measureText(v).width), 0) + 10 -        if (!server) ctx.translate(0, -lines.length * 15 / 2) +        if (world) ctx.translate(0, -lines.length * 15 / 2)          ctx.fillStyle = MESSAGE_BG[m.style]          ctx.beginPath() @@ -282,7 +297,7 @@ function draw_global_message() {      ctx.save()      ctx.translate(canvas.width / 2, canvas.height / 6)      ctx.scale(2, 2) -    draw_message(global_message, true) +    draw_message(global_message, false)      ctx.restore()  } | 
