Workers P2: Regie 1 (Agenten, Snapshot ohne Animation, Posen, Leerlauf)
Dazu drawSideBubble in sprites.js: Ottos seitliche Blase braucht das Raster des Kontexts. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1aabbef3ab
commit
e69c4355bd
5 files changed
+619
-1
No files matched your search
@@ -253,6 +253,9 @@ function deviceRect(ctx, x, y, w, h, color) {
|
||||
ctx.fillRect(x, y, w, h)
|
||||
}
|
||||
|
||||
// Breite der Zeichenfläche in Geräte-Pixeln (ohne Canvas 960, wie die Welt bei Raster 3)
|
||||
const canvasWidth = (ctx) => (ctx.canvas && ctx.canvas.width > 0 ? ctx.canvas.width : 960)
|
||||
|
||||
/* Sprechblase über einem Worker: (x, y) = Spitze der Blase (logisch). Maße wachsen mit dem Raster; die Blase
|
||||
wird in Geräte-Pixeln in die Breite von ctx.canvas geklemmt (Rand 2 bei k = 3, ohne Canvas 960). */
|
||||
export function drawBubble(ctx, x, y, text) {
|
||||
@@ -270,7 +273,7 @@ export function drawBubble(ctx, x, y, text) {
|
||||
const bh = u(22)
|
||||
const tipX = Math.round(x * k + ox)
|
||||
const by = Math.round(y * k + oy) - bh - u(6)
|
||||
const maxW = ctx.canvas && ctx.canvas.width > 0 ? ctx.canvas.width : 960
|
||||
const maxW = canvasWidth(ctx)
|
||||
const bx = Math.max(edge, Math.min(maxW - bw - edge, Math.round(tipX - bw / 2)))
|
||||
// Die Spitze bleibt am Kasten, auch wenn der Kasten wegen des Rands verschoben wurde
|
||||
const tailW = u(6)
|
||||
@@ -282,3 +285,38 @@ export function drawBubble(ctx, x, y, text) {
|
||||
ctx.fillStyle = PAL.ink
|
||||
ctx.fillText(str, bx + pad, by + u(5))
|
||||
}
|
||||
|
||||
/* Sprechblase neben einem Worker, für Otto an der Oberkante der Welt, wo über dem Kopf kein Platz ist (Vorlage: sideBubble).
|
||||
leftX/rightX = linke und rechte Körperkante (logisch), y = Oberkante der Blase. Die Blase steht links vom Körper und ihre
|
||||
Spitze zeigt nach rechts auf leftX; fehlt links der Platz (Rand 4), steht sie rechts davon mit der Spitze auf rightX,
|
||||
in die Breite von ctx.canvas geklemmt. Maße und Schrift wachsen mit dem Raster. */
|
||||
export function drawSideBubble(ctx, text, { leftX, rightX, y }) {
|
||||
const str = String(text ?? '')
|
||||
if (str === '') return
|
||||
const { k, ox, oy } = gridOf(ctx)
|
||||
const f = k / 3
|
||||
const u = (n) => Math.max(1, Math.round(n * f))
|
||||
ctx.font = fontOf(500, 12 * f)
|
||||
ctx.textBaseline = 'top'
|
||||
ctx.textAlign = 'left'
|
||||
const pad = u(7)
|
||||
const edge = u(2)
|
||||
const gap = u(9) // Blasenrand bis Körperkante: Rahmen, Spitze (8) und ein Pixel Luft
|
||||
const bw = Math.ceil(ctx.measureText(str).width) + 2 * pad
|
||||
const bh = u(22)
|
||||
const by = Math.round(y * k + oy)
|
||||
let bx = Math.round(leftX * k + ox) - gap - bw
|
||||
const onLeft = bx >= u(4)
|
||||
if (!onLeft) bx = Math.max(edge, Math.min(canvasWidth(ctx) - bw - edge, Math.round(rightX * k + ox) + gap))
|
||||
deviceRect(ctx, bx - edge, by - edge, bw + 2 * edge, bh + 2 * edge, PAL.o)
|
||||
deviceRect(ctx, bx, by, bw, bh, PAL.w)
|
||||
if (onLeft) {
|
||||
deviceRect(ctx, bx + bw + edge, by + u(7), u(4), u(4), PAL.o)
|
||||
deviceRect(ctx, bx + bw + u(6), by + u(8), u(2), u(2), PAL.o)
|
||||
} else {
|
||||
deviceRect(ctx, bx - u(6), by + u(7), u(4), u(4), PAL.o)
|
||||
deviceRect(ctx, bx - u(8), by + u(8), u(2), u(2), PAL.o)
|
||||
}
|
||||
ctx.fillStyle = PAL.ink
|
||||
ctx.fillText(str, bx + pad, by + u(5))
|
||||
}
|
||||
Reference in new issue
Block a user