diff --git a/projects/sasch40/frontend/public/assets/characters/maja/portrait.jpg b/projects/sasch40/frontend/public/assets/characters/maja/portrait.jpg index 37794e9..5639a99 100644 Binary files a/projects/sasch40/frontend/public/assets/characters/maja/portrait.jpg and b/projects/sasch40/frontend/public/assets/characters/maja/portrait.jpg differ diff --git a/projects/sasch40/frontend/public/assets/characters/maja/portrait_v2.jpg b/projects/sasch40/frontend/public/assets/characters/maja/portrait_v2.jpg new file mode 100644 index 0000000..5639a99 Binary files /dev/null and b/projects/sasch40/frontend/public/assets/characters/maja/portrait_v2.jpg differ diff --git a/projects/sasch40/frontend/public/assets/characters/miriam/portrait.jpg b/projects/sasch40/frontend/public/assets/characters/miriam/portrait.jpg index f7a85ad..34102f7 100644 Binary files a/projects/sasch40/frontend/public/assets/characters/miriam/portrait.jpg and b/projects/sasch40/frontend/public/assets/characters/miriam/portrait.jpg differ diff --git a/projects/sasch40/frontend/public/assets/characters/miriam/portrait_v2.jpg b/projects/sasch40/frontend/public/assets/characters/miriam/portrait_v2.jpg new file mode 100644 index 0000000..34102f7 Binary files /dev/null and b/projects/sasch40/frontend/public/assets/characters/miriam/portrait_v2.jpg differ diff --git a/projects/sasch40/frontend/public/assets/characters/saskia/portrait.jpg b/projects/sasch40/frontend/public/assets/characters/saskia/portrait.jpg index c213fed..c7130d9 100644 Binary files a/projects/sasch40/frontend/public/assets/characters/saskia/portrait.jpg and b/projects/sasch40/frontend/public/assets/characters/saskia/portrait.jpg differ diff --git a/projects/sasch40/frontend/public/assets/characters/saskia/portrait_v2.jpg b/projects/sasch40/frontend/public/assets/characters/saskia/portrait_v2.jpg new file mode 100644 index 0000000..c7130d9 Binary files /dev/null and b/projects/sasch40/frontend/public/assets/characters/saskia/portrait_v2.jpg differ diff --git a/projects/sasch40/frontend/public/assets/scenes/schankraum_v5.jpg b/projects/sasch40/frontend/public/assets/scenes/schankraum_v5.jpg new file mode 100644 index 0000000..de618c3 Binary files /dev/null and b/projects/sasch40/frontend/public/assets/scenes/schankraum_v5.jpg differ diff --git a/projects/sasch40/frontend/src/components/PlatformerView.vue b/projects/sasch40/frontend/src/components/PlatformerView.vue index 0f4c1e5..a4a855f 100644 --- a/projects/sasch40/frontend/src/components/PlatformerView.vue +++ b/projects/sasch40/frontend/src/components/PlatformerView.vue @@ -542,36 +542,101 @@ function drawPlayer(ctx: CanvasRenderingContext2D) { ctx.restore() } +const sisterImages: Record = {} + +function preloadSisterImages() { + const sources: Record = { + 1: CHARACTERS.saskia.portrait, + 2: CHARACTERS.maja.portrait, + 3: CHARACTERS.miriam.portrait + } + for (const [lvl, src] of Object.entries(sources)) { + const img = new Image() + img.src = src + sisterImages[Number(lvl)] = img + } +} + function drawSisterSprite(ctx: CanvasRenderingContext2D, x: number, y: number, level: number) { - // Dirndl color per sister - const dirndlColor = level === 1 ? '#f43f5e' : level === 2 ? '#8b5cf6' : '#06b6d4' - const hairColor = level === 1 ? '#fde047' : level === 2 ? '#78350f' : '#b45309' + const img = sisterImages[level] + const wave = Math.sin(Date.now() / 160) * 3 - // Body - ctx.fillStyle = dirndlColor - ctx.fillRect(x + 2, y + 14, 18, 18) - // White apron - ctx.fillStyle = '#ffffff' - ctx.fillRect(x + 6, y + 18, 10, 14) + if (img && img.complete && img.naturalWidth > 0) { + const size = 32 + const drawX = x - 4 + const drawY = y - 4 + wave - // Head - ctx.fillStyle = '#fbcfe8' - ctx.fillRect(x + 4, y + 4, 14, 12) + ctx.save() + // Golden border + ctx.beginPath() + ctx.arc(drawX + size / 2, drawY + size / 2, size / 2 + 2, 0, Math.PI * 2) + ctx.fillStyle = '#ffd700' + ctx.fill() + ctx.lineWidth = 2 + ctx.strokeStyle = '#b45309' + ctx.stroke() - // Hair - ctx.fillStyle = hairColor - ctx.fillRect(x + 2, y, 18, 6) - ctx.fillRect(x + 1, y + 5, 4, 14) // Left braid - ctx.fillRect(x + 17, y + 5, 4, 14) // Right braid + // Circular portrait + ctx.beginPath() + ctx.arc(drawX + size / 2, drawY + size / 2, size / 2, 0, Math.PI * 2) + ctx.clip() + ctx.drawImage(img, drawX, drawY, size, size) + ctx.restore() - // Tiara / flowers - ctx.fillStyle = '#ffd700' - ctx.fillRect(x + 5, y - 2, 12, 3) + // Little waving hand + ctx.fillStyle = '#ffd700' + ctx.font = '10px monospace' + ctx.fillText('👋', drawX + size - 2, drawY + 8 + wave) + } else { + // Custom pixel-art styling per sister matching real photos + const dirndlColor = level === 1 ? '#f43f5e' : level === 2 ? '#8b5cf6' : '#06b6d4' + const hairColor = level === 1 ? '#3d2314' : level === 2 ? '#6b4226' : '#18181b' - // Waving arm - const wave = Math.sin(Date.now() / 150) * 4 - ctx.fillStyle = '#fbcfe8' - ctx.fillRect(x - 3, y + 6 + wave, 5, 5) + // Body + ctx.fillStyle = dirndlColor + ctx.fillRect(x + 2, y + 14, 18, 18) + // White apron + ctx.fillStyle = '#ffffff' + ctx.fillRect(x + 6, y + 18, 10, 14) + + // Head + ctx.fillStyle = '#fce7f3' + ctx.fillRect(x + 4, y + 4, 14, 12) + + // Hair + ctx.fillStyle = hairColor + if (level === 1) { + // Saskia: elegant bun updo with side strands + ctx.fillRect(x + 2, y, 18, 6) + ctx.fillRect(x + 5, y - 5, 12, 6) + ctx.fillRect(x + 1, y + 5, 2, 6) + ctx.fillRect(x + 19, y + 5, 2, 6) + } else if (level === 2) { + // Maja: short pixie cut with side bangs + ctx.fillRect(x + 2, y, 18, 6) + ctx.fillRect(x + 1, y + 3, 5, 8) + // Gold hoop earring + ctx.fillStyle = '#ffd700' + ctx.fillRect(x + 1, y + 9, 2, 2) + ctx.fillStyle = hairColor + } else { + // Miriam: long flowing dark hair with sunglasses on head + ctx.fillRect(x + 2, y, 18, 6) + ctx.fillRect(x + 1, y + 4, 4, 16) + ctx.fillRect(x + 17, y + 4, 4, 16) + // Sunglasses + ctx.fillStyle = '#0f172a' + ctx.fillRect(x + 5, y - 3, 12, 3) + } + + // Tiara + ctx.fillStyle = '#ffd700' + ctx.fillRect(x + 6, y - 2, 10, 3) + + // Waving arm + ctx.fillStyle = '#fce7f3' + ctx.fillRect(x - 3, y + 6 + wave, 5, 5) + } } function drawHUD(ctx: CanvasRenderingContext2D) { @@ -604,6 +669,7 @@ function gameLoop() { } onMounted(() => { + preloadSisterImages() window.addEventListener('keydown', handleKeyDown) window.addEventListener('keyup', handleKeyUp) ;(window as any).__platformer = { @@ -652,6 +718,28 @@ onUnmounted(() => { Gierige Kronkorken-Kobolde haben Saschas drei Schwestern Saskia, Maja und Miriam auf luftige Himmelszinnen entführt!

+ +
+
+
+ Saskia +
+ 1. Saskia 👑 +
+
+
+ Maja +
+ 2. Maja 🌸 +
+
+
+ Miriam +
+ 3. Miriam ✨ +
+
+
☁️
@@ -962,6 +1050,46 @@ onUnmounted(() => { font-size: 6.5px; } +/* Sisters Showcase in Act II Intro */ +.sisters-showcase { + display: flex; + justify-content: center; + gap: 12px; + margin: 10px 0 12px 0; + width: 100%; +} + +.sister-mini-card { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; +} + +.sister-mini-portrait { + width: 52px; + height: 52px; + border-radius: 8px; + border: 2px solid #ffd700; + box-shadow: 0 0 8px rgba(255, 215, 0, 0.4); + overflow: hidden; + background: #1e1b4b; +} + +.sister-mini-portrait img { + width: 100%; + height: 100%; + object-fit: cover; + image-rendering: crisp-edges; +} + +.sister-mini-label { + font-family: 'Press Start 2P', monospace; + font-size: 5.5px; + color: #ffd700; + text-align: center; +} + /* Animations */ .fade-enter-active, .fade-leave-active { transition: opacity 0.3s; diff --git a/projects/sasch40/frontend/src/components/TavernView.vue b/projects/sasch40/frontend/src/components/TavernView.vue index 9fc0bdb..3c356e7 100644 --- a/projects/sasch40/frontend/src/components/TavernView.vue +++ b/projects/sasch40/frontend/src/components/TavernView.vue @@ -580,10 +580,36 @@ function proceedToExpress() {