games: theme-specific symbol vocabulary (45 new shapes) replaces generic royals/cubes across the library; presentation exposed on game cards
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
21 changed files +1,672 −632
modified
apps/web/src/components/game/symbol-art.ts
+356 −0
@@ -310,6 +310,362 @@ export function drawSymbol(style: SymbolStyle, opts: SymbolArtOptions): Containe | ||
| 310 | 310 | g.poly([0, 0, r * 0.87, -r * 0.5, r * 0.87, r * 0.5, 0, r]).fill(darken(style.color, 0.3)); |
| 311 | 311 | break; |
| 312 | 312 | } |
| 313 | + /* ----------------------------------------------------------- themed set */ | |
| 314 | + case "lock": { | |
| 315 | + g.roundRect(-r * 0.75, -r * 0.1, r * 1.5, r * 1.1, r * 0.2).fill(main); | |
| 316 | + g.arc(0, -r * 0.15, r * 0.5, Math.PI, 0).stroke({ color: accent, width: size * 0.05 }); | |
| 317 | + g.circle(0, r * 0.35, r * 0.16).fill(0x0b0d14); | |
| 318 | + g.rect(-r * 0.06, r * 0.35, r * 0.12, r * 0.35).fill(0x0b0d14); | |
| 319 | + break; | |
| 320 | + } | |
| 321 | + case "key": { | |
| 322 | + g.circle(-r * 0.45, -r * 0.35, r * 0.42).stroke({ color: main, width: size * 0.06 }); | |
| 323 | + g.moveTo(-r * 0.15, -r * 0.05).lineTo(r * 0.85, r * 0.95).stroke({ color: main, width: size * 0.06 }); | |
| 324 | + g.moveTo(r * 0.45, r * 0.55).lineTo(r * 0.7, r * 0.3).stroke({ color: accent, width: size * 0.05 }); | |
| 325 | + g.moveTo(r * 0.65, r * 0.75).lineTo(r * 0.9, r * 0.5).stroke({ color: accent, width: size * 0.05 }); | |
| 326 | + break; | |
| 327 | + } | |
| 328 | + case "code": { | |
| 329 | + g.roundRect(-r, -r * 0.7, r * 2, r * 1.4, r * 0.15).fill({ color: darken(style.color, 0.45), alpha: 0.95 }); | |
| 330 | + g.roundRect(-r, -r * 0.7, r * 2, r * 1.4, r * 0.15).stroke({ color: main, width: size * 0.02 }); | |
| 331 | + c.addChild(label(style.label ?? "</>", size * 0.26, main, true)); | |
| 332 | + break; | |
| 333 | + } | |
| 334 | + case "badge": { | |
| 335 | + g.roundRect(-r * 0.7, -r, r * 1.4, r * 2, r * 0.18).fill(main); | |
| 336 | + g.circle(0, -r * 0.4, r * 0.28).fill(0x0b0d14); | |
| 337 | + g.roundRect(-r * 0.45, r * 0.05, r * 0.9, r * 0.14, r * 0.05).fill(accent); | |
| 338 | + g.roundRect(-r * 0.45, r * 0.35, r * 0.6, r * 0.14, r * 0.05).fill(accent); | |
| 339 | + break; | |
| 340 | + } | |
| 341 | + case "mask": { | |
| 342 | + g.ellipse(0, 0, r, r * 0.6).fill(main); | |
| 343 | + g.ellipse(-r * 0.4, -r * 0.05, r * 0.28, r * 0.18).fill(0x0b0d14); | |
| 344 | + g.ellipse(r * 0.4, -r * 0.05, r * 0.28, r * 0.18).fill(0x0b0d14); | |
| 345 | + g.moveTo(-r * 0.95, -r * 0.1).lineTo(-r * 1.3, -r * 0.6).stroke({ color: accent, width: size * 0.025 }); | |
| 346 | + g.moveTo(r * 0.95, -r * 0.1).lineTo(r * 1.3, -r * 0.6).stroke({ color: accent, width: size * 0.025 }); | |
| 347 | + break; | |
| 348 | + } | |
| 349 | + case "glove": { | |
| 350 | + g.roundRect(-r * 0.55, -r * 0.2, r * 1.1, r * 1.1, r * 0.25).fill(main); | |
| 351 | + for (let i = 0; i < 4; i++) g.roundRect(-r * 0.55 + i * r * 0.28, -r, r * 0.22, r * 0.9, r * 0.1).fill(main); | |
| 352 | + g.roundRect(-r * 0.9, -r * 0.1, r * 0.35, r * 0.7, r * 0.15).fill(main); | |
| 353 | + g.roundRect(-r * 0.55, r * 0.6, r * 1.1, r * 0.3, r * 0.08).fill(accent); | |
| 354 | + break; | |
| 355 | + } | |
| 356 | + case "rope": { | |
| 357 | + g.circle(0, 0, r * 0.75).stroke({ color: main, width: size * 0.09 }); | |
| 358 | + g.circle(0, 0, r * 0.75).stroke({ color: accent, width: size * 0.02, alpha: 0.6 }); | |
| 359 | + for (let i = 0; i < 10; i++) { | |
| 360 | + const a = (i / 10) * Math.PI * 2; | |
| 361 | + g.moveTo(Math.cos(a) * r * 0.62, Math.sin(a) * r * 0.62).lineTo(Math.cos(a + 0.3) * r * 0.88, Math.sin(a + 0.3) * r * 0.88).stroke({ color: darken(style.color, 0.3), width: size * 0.02 }); | |
| 362 | + } | |
| 363 | + break; | |
| 364 | + } | |
| 365 | + case "bag": { | |
| 366 | + g.moveTo(-r * 0.75, r * 0.9).bezierCurveTo(-r * 1.1, -r * 0.3, -r * 0.3, -r * 0.6, 0, -r * 0.55).bezierCurveTo(r * 0.3, -r * 0.6, r * 1.1, -r * 0.3, r * 0.75, r * 0.9).lineTo(-r * 0.75, r * 0.9).fill(main); | |
| 367 | + g.roundRect(-r * 0.3, -r * 0.95, r * 0.6, r * 0.35, r * 0.1).fill(accent); | |
| 368 | + g.moveTo(-r * 0.35, r * 0.3).lineTo(r * 0.35, r * 0.3).stroke({ color: darken(style.color, 0.3), width: size * 0.03 }); | |
| 369 | + break; | |
| 370 | + } | |
| 371 | + case "lantern": { | |
| 372 | + g.roundRect(-r * 0.7, -r * 0.6, r * 1.4, r * 1.2, r * 0.45).fill(main); | |
| 373 | + g.rect(-r * 0.35, -r * 0.9, r * 0.7, r * 0.2).fill(accent); | |
| 374 | + g.rect(-r * 0.35, r * 0.6, r * 0.7, r * 0.2).fill(accent); | |
| 375 | + g.moveTo(0, r * 0.8).lineTo(0, r).stroke({ color: accent, width: size * 0.03 }); | |
| 376 | + for (let i = -1; i <= 1; i++) g.moveTo(i * r * 0.3, -r * 0.55).lineTo(i * r * 0.3, r * 0.55).stroke({ color: darken(style.color, 0.3), width: size * 0.015 }); | |
| 377 | + break; | |
| 378 | + } | |
| 379 | + case "fan": { | |
| 380 | + for (let i = -3; i <= 3; i++) { | |
| 381 | + const a = -Math.PI / 2 + i * 0.28; | |
| 382 | + g.moveTo(0, r * 0.7).lineTo(Math.cos(a) * r * 1.05, r * 0.7 + Math.sin(a) * r * 1.05).stroke({ color: i % 2 ? main : accent, width: size * 0.07 }); | |
| 383 | + } | |
| 384 | + g.circle(0, r * 0.7, r * 0.14).fill(0x0b0d14); | |
| 385 | + break; | |
| 386 | + } | |
| 387 | + case "scroll": { | |
| 388 | + g.roundRect(-r * 0.7, -r * 0.85, r * 1.4, r * 1.7, r * 0.1).fill({ color: accent, alpha: 0.9 }); | |
| 389 | + g.roundRect(-r * 0.85, -r, r * 1.7, r * 0.3, r * 0.15).fill(main); | |
| 390 | + g.roundRect(-r * 0.85, r * 0.7, r * 1.7, r * 0.3, r * 0.15).fill(main); | |
| 391 | + for (let i = 0; i < 3; i++) g.rect(-r * 0.45, -r * 0.5 + i * r * 0.32, r * 0.9, r * 0.08).fill({ color: darken(style.color, 0.4), alpha: 0.7 }); | |
| 392 | + break; | |
| 393 | + } | |
| 394 | + case "cherry": { | |
| 395 | + g.moveTo(-r * 0.3, r * 0.3).bezierCurveTo(-r * 0.2, -r * 0.5, r * 0.2, -r * 0.9, r * 0.5, -r).stroke({ color: 0x3ddc97, width: size * 0.035 }); | |
| 396 | + g.moveTo(r * 0.45, r * 0.3).bezierCurveTo(r * 0.5, -r * 0.4, r * 0.5, -r * 0.8, r * 0.5, -r).stroke({ color: 0x3ddc97, width: size * 0.035 }); | |
| 397 | + g.circle(-r * 0.35, r * 0.45, r * 0.42).fill(main); | |
| 398 | + g.circle(r * 0.45, r * 0.45, r * 0.42).fill(main); | |
| 399 | + g.circle(-r * 0.5, r * 0.3, r * 0.12).fill({ color: 0xffffff, alpha: 0.6 }); | |
| 400 | + g.circle(r * 0.3, r * 0.3, r * 0.12).fill({ color: 0xffffff, alpha: 0.6 }); | |
| 401 | + break; | |
| 402 | + } | |
| 403 | + case "seven": { | |
| 404 | + g.poly([-r * 0.8, -r, r * 0.8, -r, r * 0.8, -r * 0.55, -r * 0.05, r, -r * 0.55, r, r * 0.2, -r * 0.55, -r * 0.8, -r * 0.55]).fill(main); | |
| 405 | + g.poly([-r * 0.8, -r, r * 0.8, -r, r * 0.8, -r * 0.55, -r * 0.05, r, -r * 0.55, r, r * 0.2, -r * 0.55, -r * 0.8, -r * 0.55]).stroke({ color: accent, width: size * 0.03 }); | |
| 406 | + break; | |
| 407 | + } | |
| 408 | + case "bell": { | |
| 409 | + g.moveTo(-r * 0.75, r * 0.5).bezierCurveTo(-r * 0.75, -r * 0.5, -r * 0.3, -r * 0.9, 0, -r * 0.9).bezierCurveTo(r * 0.3, -r * 0.9, r * 0.75, -r * 0.5, r * 0.75, r * 0.5).lineTo(-r * 0.75, r * 0.5).fill(main); | |
| 410 | + g.roundRect(-r * 0.9, r * 0.45, r * 1.8, r * 0.18, r * 0.09).fill(accent); | |
| 411 | + g.circle(0, r * 0.8, r * 0.15).fill(accent); | |
| 412 | + g.circle(0, -r * 0.95, r * 0.1).fill(accent); | |
| 413 | + break; | |
| 414 | + } | |
| 415 | + case "joystick": { | |
| 416 | + g.roundRect(-r * 0.9, r * 0.3, r * 1.8, r * 0.6, r * 0.15).fill(darken(style.color, 0.4)); | |
| 417 | + g.rect(-r * 0.08, -r * 0.4, r * 0.16, r * 0.8).fill(0x9aa3b5); | |
| 418 | + g.circle(0, -r * 0.55, r * 0.35).fill(main); | |
| 419 | + g.circle(-r * 0.12, -r * 0.65, r * 0.1).fill({ color: 0xffffff, alpha: 0.5 }); | |
| 420 | + g.circle(r * 0.5, r * 0.6, r * 0.12).fill(accent); | |
| 421 | + break; | |
| 422 | + } | |
| 423 | + case "torii": { | |
| 424 | + g.rect(-r, -r * 0.85, r * 2, r * 0.18).fill(main); | |
| 425 | + g.rect(-r * 0.8, -r * 0.5, r * 1.6, r * 0.12).fill(main); | |
| 426 | + g.rect(-r * 0.6, -r * 0.5, r * 0.16, r * 1.5).fill(main); | |
| 427 | + g.rect(r * 0.44, -r * 0.5, r * 0.16, r * 1.5).fill(main); | |
| 428 | + g.rect(-r * 0.08, -r * 0.5, r * 0.16, r * 0.35).fill(accent); | |
| 429 | + break; | |
| 430 | + } | |
| 431 | + case "katana": { | |
| 432 | + g.moveTo(-r * 0.9, r * 0.9).lineTo(r * 0.7, -r * 0.7).stroke({ color: 0xdfe6f0, width: size * 0.05 }); | |
| 433 | + g.moveTo(-r * 0.9, r * 0.9).lineTo(r * 0.7, -r * 0.7).stroke({ color: 0xffffff, width: size * 0.015, alpha: 0.7 }); | |
| 434 | + g.moveTo(-r * 0.55, r * 0.35).lineTo(-r * 0.25, r * 0.65).stroke({ color: accent, width: size * 0.05 }); | |
| 435 | + g.moveTo(-r * 0.9, r * 0.9).lineTo(-r * 0.6, r * 0.6).stroke({ color: main, width: size * 0.08 }); | |
| 436 | + break; | |
| 437 | + } | |
| 438 | + case "cassette": { | |
| 439 | + g.roundRect(-r, -r * 0.65, r * 2, r * 1.3, r * 0.12).fill(main); | |
| 440 | + g.roundRect(-r * 0.75, -r * 0.4, r * 1.5, r * 0.55, r * 0.08).fill(darken(style.color, 0.45)); | |
| 441 | + g.circle(-r * 0.4, -r * 0.12, r * 0.16).fill(0x0b0d14).circle(r * 0.4, -r * 0.12, r * 0.16).fill(0x0b0d14); | |
| 442 | + g.rect(-r * 0.6, r * 0.3, r * 1.2, r * 0.14).fill(accent); | |
| 443 | + break; | |
| 444 | + } | |
| 445 | + case "ankh": { | |
| 446 | + g.ellipse(0, -r * 0.55, r * 0.35, r * 0.42).stroke({ color: main, width: size * 0.06 }); | |
| 447 | + g.rect(-r * 0.08, -r * 0.1, r * 0.16, r * 1.1).fill(main); | |
| 448 | + g.rect(-r * 0.7, -r * 0.1, r * 1.4, r * 0.16).fill(main); | |
| 449 | + g.circle(0, -r * 0.55, r * 0.08).fill(accent); | |
| 450 | + break; | |
| 451 | + } | |
| 452 | + case "scarab": { | |
| 453 | + g.ellipse(0, r * 0.15, r * 0.6, r * 0.7).fill(main); | |
| 454 | + g.circle(0, -r * 0.6, r * 0.28).fill(darken(style.color, 0.25)); | |
| 455 | + g.moveTo(0, -r * 0.4).lineTo(0, r * 0.8).stroke({ color: accent, width: size * 0.02 }); | |
| 456 | + for (const sgn of [-1, 1]) { | |
| 457 | + g.moveTo(sgn * r * 0.55, -r * 0.1).lineTo(sgn * r * 0.95, -r * 0.5).stroke({ color: accent, width: size * 0.035 }); | |
| 458 | + g.moveTo(sgn * r * 0.6, r * 0.3).lineTo(sgn * r * 1.0, r * 0.4).stroke({ color: accent, width: size * 0.035 }); | |
| 459 | + } | |
| 460 | + break; | |
| 461 | + } | |
| 462 | + case "pyramid": { | |
| 463 | + g.poly([0, -r, r, r * 0.75, -r, r * 0.75]).fill(main); | |
| 464 | + g.poly([0, -r, r, r * 0.75, 0, r * 0.75]).fill(darken(style.color, 0.25)); | |
| 465 | + g.poly([0, -r, r * 0.25, -r * 0.55, -r * 0.25, -r * 0.55]).fill(accent); | |
| 466 | + break; | |
| 467 | + } | |
| 468 | + case "warning": { | |
| 469 | + g.poly([0, -r, r * 0.95, r * 0.75, -r * 0.95, r * 0.75]).fill(main); | |
| 470 | + g.poly([0, -r * 0.6, r * 0.55, r * 0.55, -r * 0.55, r * 0.55]).fill(0x0b0d14); | |
| 471 | + g.rect(-r * 0.08, -r * 0.3, r * 0.16, r * 0.5).fill(main); | |
| 472 | + g.circle(0, r * 0.38, r * 0.09).fill(main); | |
| 473 | + break; | |
| 474 | + } | |
| 475 | + case "valve": { | |
| 476 | + g.circle(0, 0, r * 0.85).stroke({ color: main, width: size * 0.07 }); | |
| 477 | + for (let i = 0; i < 4; i++) { | |
| 478 | + const a = (i / 4) * Math.PI * 2; | |
| 479 | + g.moveTo(0, 0).lineTo(Math.cos(a) * r * 0.85, Math.sin(a) * r * 0.85).stroke({ color: main, width: size * 0.05 }); | |
| 480 | + } | |
| 481 | + g.circle(0, 0, r * 0.25).fill(accent); | |
| 482 | + break; | |
| 483 | + } | |
| 484 | + case "gauge": { | |
| 485 | + g.arc(0, r * 0.2, r * 0.9, Math.PI, 0).stroke({ color: darken(style.color, 0.3), width: size * 0.09 }); | |
| 486 | + g.arc(0, r * 0.2, r * 0.9, Math.PI, Math.PI * 1.6).stroke({ color: main, width: size * 0.09 }); | |
| 487 | + g.moveTo(0, r * 0.2).lineTo(r * 0.45, -r * 0.5).stroke({ color: accent, width: size * 0.04 }); | |
| 488 | + g.circle(0, r * 0.2, r * 0.12).fill(accent); | |
| 489 | + break; | |
| 490 | + } | |
| 491 | + case "barrel": { | |
| 492 | + g.roundRect(-r * 0.65, -r * 0.9, r * 1.3, r * 1.8, r * 0.2).fill(main); | |
| 493 | + g.rect(-r * 0.65, -r * 0.45, r * 1.3, r * 0.12).fill(darken(style.color, 0.4)); | |
| 494 | + g.rect(-r * 0.65, r * 0.33, r * 1.3, r * 0.12).fill(darken(style.color, 0.4)); | |
| 495 | + polygon(g, 0, 0, r * 0.28, 3, -Math.PI / 2).fill(accent); | |
| 496 | + break; | |
| 497 | + } | |
| 498 | + case "wheel": { | |
| 499 | + g.circle(0, 0, r * 0.95).fill(0x0b0d14); | |
| 500 | + g.circle(0, 0, r * 0.95).stroke({ color: main, width: size * 0.05 }); | |
| 501 | + g.circle(0, 0, r * 0.6).stroke({ color: accent, width: size * 0.03 }); | |
| 502 | + for (let i = 0; i < 5; i++) { | |
| 503 | + const a = (i / 5) * Math.PI * 2; | |
| 504 | + g.moveTo(0, 0).lineTo(Math.cos(a) * r * 0.6, Math.sin(a) * r * 0.6).stroke({ color: accent, width: size * 0.035 }); | |
| 505 | + } | |
| 506 | + g.circle(0, 0, r * 0.14).fill(main); | |
| 507 | + break; | |
| 508 | + } | |
| 509 | + case "helmet": { | |
| 510 | + g.arc(0, r * 0.1, r * 0.85, Math.PI, 0).fill(main); | |
| 511 | + g.rect(-r * 0.85, r * 0.1, r * 1.7, r * 0.45).fill(main); | |
| 512 | + g.roundRect(-r * 0.6, -r * 0.05, r * 1.4, r * 0.4, r * 0.1).fill(0x0b0d14); | |
| 513 | + g.moveTo(-r * 0.3, -r * 0.7).lineTo(r * 0.3, -r * 0.7).stroke({ color: accent, width: size * 0.04 }); | |
| 514 | + break; | |
| 515 | + } | |
| 516 | + case "flag": { | |
| 517 | + g.rect(-r * 0.85, -r, r * 0.1, r * 2).fill(0x9aa3b5); | |
| 518 | + for (let i = 0; i < 4; i++) for (let j = 0; j < 3; j++) g.rect(-r * 0.75 + i * r * 0.4, -r + j * r * 0.33, r * 0.4, r * 0.33).fill((i + j) % 2 ? main : accent); | |
| 519 | + break; | |
| 520 | + } | |
| 521 | + case "trophy": { | |
| 522 | + g.moveTo(-r * 0.7, -r).lineTo(r * 0.7, -r).lineTo(r * 0.45, r * 0.15).lineTo(-r * 0.45, r * 0.15).fill(main); | |
| 523 | + g.arc(-r * 0.75, -r * 0.55, r * 0.3, Math.PI * 0.5, Math.PI * 1.5).stroke({ color: main, width: size * 0.04 }); | |
| 524 | + g.arc(r * 0.75, -r * 0.55, r * 0.3, -Math.PI * 0.5, Math.PI * 0.5).stroke({ color: main, width: size * 0.04 }); | |
| 525 | + g.rect(-r * 0.1, r * 0.15, r * 0.2, r * 0.4).fill(main); | |
| 526 | + g.roundRect(-r * 0.5, r * 0.55, r, r * 0.3, r * 0.06).fill(accent); | |
| 527 | + break; | |
| 528 | + } | |
| 529 | + case "idol": { | |
| 530 | + g.roundRect(-r * 0.55, -r * 0.9, r * 1.1, r * 1.8, r * 0.15).fill(main); | |
| 531 | + g.rect(-r * 0.4, -r * 0.55, r * 0.8, r * 0.14).fill(0x0b0d14); | |
| 532 | + g.rect(-r * 0.4, -r * 0.1, r * 0.8, r * 0.14).fill(0x0b0d14); | |
| 533 | + g.poly([-r * 0.3, r * 0.35, r * 0.3, r * 0.35, 0, r * 0.7]).fill(accent); | |
| 534 | + break; | |
| 535 | + } | |
| 536 | + case "totem": { | |
| 537 | + for (let i = 0; i < 3; i++) { | |
| 538 | + g.roundRect(-r * 0.55, -r + i * r * 0.68, r * 1.1, r * 0.6, r * 0.08).fill(i % 2 ? darken(style.color, 0.25) : main); | |
| 539 | + g.circle(-r * 0.22, -r * 0.7 + i * r * 0.68, r * 0.08).fill(accent); | |
| 540 | + g.circle(r * 0.22, -r * 0.7 + i * r * 0.68, r * 0.08).fill(accent); | |
| 541 | + } | |
| 542 | + break; | |
| 543 | + } | |
| 544 | + case "snake": { | |
| 545 | + g.moveTo(-r * 0.8, r * 0.8).bezierCurveTo(-r * 0.9, -r * 0.2, r * 0.9, r * 0.6, r * 0.6, -r * 0.5).bezierCurveTo(r * 0.4, -r * 1.0, -r * 0.2, -r * 0.6, 0, -r * 0.3).stroke({ color: main, width: size * 0.08 }); | |
| 546 | + g.circle(0, -r * 0.3, r * 0.2).fill(main); | |
| 547 | + g.circle(r * 0.06, -r * 0.36, r * 0.06).fill(accent); | |
| 548 | + break; | |
| 549 | + } | |
| 550 | + case "rocket": { | |
| 551 | + g.moveTo(0, -r).bezierCurveTo(r * 0.6, -r * 0.4, r * 0.5, r * 0.4, r * 0.35, r * 0.6).lineTo(-r * 0.35, r * 0.6).bezierCurveTo(-r * 0.5, r * 0.4, -r * 0.6, -r * 0.4, 0, -r).fill(main); | |
| 552 | + g.poly([-r * 0.35, r * 0.2, -r * 0.75, r * 0.8, -r * 0.35, r * 0.6]).fill(accent); | |
| 553 | + g.poly([r * 0.35, r * 0.2, r * 0.75, r * 0.8, r * 0.35, r * 0.6]).fill(accent); | |
| 554 | + g.circle(0, -r * 0.25, r * 0.18).fill(0x0b0d14); | |
| 555 | + g.poly([-r * 0.2, r * 0.6, r * 0.2, r * 0.6, 0, r]).fill(0xffb347); | |
| 556 | + break; | |
| 557 | + } | |
| 558 | + case "anchor": { | |
| 559 | + g.circle(0, -r * 0.75, r * 0.2).stroke({ color: main, width: size * 0.05 }); | |
| 560 | + g.rect(-r * 0.07, -r * 0.55, r * 0.14, r * 1.4).fill(main); | |
| 561 | + g.rect(-r * 0.55, -r * 0.35, r * 1.1, r * 0.12).fill(main); | |
| 562 | + g.arc(0, r * 0.15, r * 0.75, Math.PI * 0.15, Math.PI * 0.85).stroke({ color: main, width: size * 0.07 }); | |
| 563 | + g.circle(-r * 0.7, r * 0.4, r * 0.08).fill(accent).circle(r * 0.7, r * 0.4, r * 0.08).fill(accent); | |
| 564 | + break; | |
| 565 | + } | |
| 566 | + case "chest": { | |
| 567 | + g.roundRect(-r * 0.9, -r * 0.2, r * 1.8, r * 1.0, r * 0.1).fill(main); | |
| 568 | + g.roundRect(-r * 0.9, -r * 0.75, r * 1.8, r * 0.6, r * 0.3).fill(darken(style.color, 0.2)); | |
| 569 | + g.rect(-r * 0.9, -r * 0.2, r * 1.8, r * 0.12).fill(accent); | |
| 570 | + g.roundRect(-r * 0.15, -r * 0.2, r * 0.3, r * 0.35, r * 0.05).fill(accent); | |
| 571 | + break; | |
| 572 | + } | |
| 573 | + case "trident": { | |
| 574 | + g.rect(-r * 0.07, -r * 0.4, r * 0.14, r * 1.4).fill(main); | |
| 575 | + for (const dx of [-0.5, 0, 0.5]) { | |
| 576 | + g.moveTo(dx * r, -r * 0.3).lineTo(dx * r, -r).stroke({ color: main, width: size * 0.05 }); | |
| 577 | + g.poly([dx * r - r * 0.12, -r * 0.85, dx * r + r * 0.12, -r * 0.85, dx * r, -r * 1.1]).fill(accent); | |
| 578 | + } | |
| 579 | + g.rect(-r * 0.5, -r * 0.4, r, r * 0.12).fill(main); | |
| 580 | + break; | |
| 581 | + } | |
| 582 | + case "shell": { | |
| 583 | + g.arc(0, r * 0.4, r * 0.95, Math.PI, 0).fill(main); | |
| 584 | + for (let i = -3; i <= 3; i++) g.moveTo(0, r * 0.4).lineTo(Math.cos(-Math.PI / 2 + i * 0.38) * r * 0.95, r * 0.4 + Math.sin(-Math.PI / 2 + i * 0.38) * r * 0.95).stroke({ color: darken(style.color, 0.25), width: size * 0.02 }); | |
| 585 | + g.rect(-r * 0.95, r * 0.4, r * 1.9, r * 0.18).fill(accent); | |
| 586 | + break; | |
| 587 | + } | |
| 588 | + case "planet": { | |
| 589 | + g.circle(0, 0, r * 0.7).fill(main); | |
| 590 | + g.ellipse(0, r * 0.05, r * 1.05, r * 0.28).stroke({ color: accent, width: size * 0.04 }); | |
| 591 | + g.circle(-r * 0.25, -r * 0.25, r * 0.18).fill({ color: 0xffffff, alpha: 0.3 }); | |
| 592 | + g.ellipse(r * 0.15, r * 0.15, r * 0.3, r * 0.12).fill({ color: darken(style.color, 0.25), alpha: 0.8 }); | |
| 593 | + break; | |
| 594 | + } | |
| 595 | + case "comet": { | |
| 596 | + g.moveTo(r * 0.5, -r * 0.5).lineTo(-r * 1.0, r * 0.15).lineTo(-r * 0.6, r * 0.6).lineTo(r * 0.5, -r * 0.5).fill({ color: accent, alpha: 0.5 }); | |
| 597 | + g.moveTo(r * 0.5, -r * 0.5).lineTo(-r * 0.7, r * 0.7).stroke({ color: accent, alpha: 0.4, width: size * 0.05 }); | |
| 598 | + g.circle(r * 0.5, -r * 0.5, r * 0.4).fill(main); | |
| 599 | + g.circle(r * 0.4, -r * 0.6, r * 0.12).fill({ color: 0xffffff, alpha: 0.6 }); | |
| 600 | + break; | |
| 601 | + } | |
| 602 | + case "satellite": { | |
| 603 | + g.roundRect(-r * 0.3, -r * 0.3, r * 0.6, r * 0.6, r * 0.1).fill(main); | |
| 604 | + g.rect(-r * 1.0, -r * 0.18, r * 0.6, r * 0.36).fill(accent); | |
| 605 | + g.rect(r * 0.4, -r * 0.18, r * 0.6, r * 0.36).fill(accent); | |
| 606 | + for (const x of [-0.8, -0.6, 0.6, 0.8]) g.moveTo(x * r, -r * 0.18).lineTo(x * r, r * 0.18).stroke({ color: darken(style.color, 0.4), width: size * 0.012 }); | |
| 607 | + g.arc(0, -r * 0.55, r * 0.3, Math.PI, 0).stroke({ color: main, width: size * 0.03 }); | |
| 608 | + break; | |
| 609 | + } | |
| 610 | + case "pickaxe": { | |
| 611 | + g.moveTo(-r * 0.7, r * 0.9).lineTo(r * 0.5, -r * 0.4).stroke({ color: 0x8a6d2e, width: size * 0.06 }); | |
| 612 | + g.moveTo(r * 0.0, -r * 0.9).bezierCurveTo(r * 0.7, -r * 0.9, r * 1.0, -r * 0.4, r * 0.95, r * 0.15).lineTo(r * 0.55, -r * 0.35).fill(main); | |
| 613 | + g.moveTo(r * 0.0, -r * 0.9).lineTo(r * 0.55, -r * 0.35).stroke({ color: accent, width: size * 0.03 }); | |
| 614 | + break; | |
| 615 | + } | |
| 616 | + case "ore": { | |
| 617 | + polygon(g, 0, r * 0.1, r * 0.9, 7).fill(0x3a3f4a); | |
| 618 | + g.poly([-r * 0.3, -r * 0.1, 0, -r * 0.5, r * 0.35, -r * 0.05, r * 0.1, r * 0.35, -r * 0.25, r * 0.3]).fill(main); | |
| 619 | + g.poly([-r * 0.3, -r * 0.1, 0, -r * 0.5, 0, 0]).fill(accent); | |
| 620 | + break; | |
| 621 | + } | |
| 622 | + case "drill": { | |
| 623 | + g.rect(-r * 0.4, -r * 0.9, r * 0.8, r * 0.7).fill(main); | |
| 624 | + g.poly([-r * 0.4, -r * 0.2, r * 0.4, -r * 0.2, 0, r]).fill(0xc8d0dc); | |
| 625 | + for (let i = 0; i < 4; i++) g.moveTo(-r * 0.32 + i * r * 0.1, -r * 0.2 + i * r * 0.28).lineTo(r * 0.32 - i * r * 0.1, -r * 0.2 + i * r * 0.28).stroke({ color: 0x5c6270, width: size * 0.015 }); | |
| 626 | + g.rect(-r * 0.15, -r * 0.6, r * 0.3, r * 0.15).fill(accent); | |
| 627 | + break; | |
| 628 | + } | |
| 629 | + case "ingot": { | |
| 630 | + g.poly([-r * 0.7, -r * 0.3, r * 0.7, -r * 0.3, r * 0.95, r * 0.5, -r * 0.95, r * 0.5]).fill(main); | |
| 631 | + g.poly([-r * 0.7, -r * 0.3, r * 0.7, -r * 0.3, r * 0.5, 0, -r * 0.5, 0]).fill(accent); | |
| 632 | + g.moveTo(-r * 0.5, r * 0.15).lineTo(r * 0.5, r * 0.15).stroke({ color: darken(style.color, 0.3), width: size * 0.02 }); | |
| 633 | + break; | |
| 634 | + } | |
| 635 | + case "hourglass": { | |
| 636 | + g.poly([-r * 0.7, -r, r * 0.7, -r, r * 0.1, 0, r * 0.7, r, -r * 0.7, r, -r * 0.1, 0]).stroke({ color: main, width: size * 0.04 }); | |
| 637 | + g.poly([-r * 0.45, -r * 0.8, r * 0.45, -r * 0.8, 0, -r * 0.1]).fill({ color: accent, alpha: 0.8 }); | |
| 638 | + g.poly([-r * 0.55, r * 0.9, r * 0.55, r * 0.9, 0, r * 0.35]).fill({ color: accent, alpha: 0.8 }); | |
| 639 | + break; | |
| 640 | + } | |
| 641 | + case "igloo": { | |
| 642 | + g.arc(0, r * 0.4, r * 0.95, Math.PI, 0).fill(main); | |
| 643 | + g.rect(-r * 0.95, r * 0.4, r * 1.9, r * 0.2).fill(main); | |
| 644 | + g.arc(-r * 0.3, r * 0.5, r * 0.35, Math.PI, 0).fill(0x0b0d14); | |
| 645 | + for (let i = 0; i < 3; i++) g.arc(0, r * 0.4, r * (0.35 + i * 0.25), Math.PI, 0).stroke({ color: accent, width: size * 0.015, alpha: 0.6 }); | |
| 646 | + break; | |
| 647 | + } | |
| 648 | + case "paw": { | |
| 649 | + g.ellipse(0, r * 0.35, r * 0.55, r * 0.45).fill(main); | |
| 650 | + for (const [dx, dy] of [[-0.6, -0.25], [-0.22, -0.6], [0.22, -0.6], [0.6, -0.25]]) g.circle(dx * r, dy * r, r * 0.2).fill(main); | |
| 651 | + g.ellipse(0, r * 0.4, r * 0.3, r * 0.22).fill({ color: accent, alpha: 0.6 }); | |
| 652 | + break; | |
| 653 | + } | |
| 654 | + case "fish": { | |
| 655 | + g.ellipse(-r * 0.1, 0, r * 0.7, r * 0.42).fill(main); | |
| 656 | + g.poly([r * 0.5, 0, r, -r * 0.45, r, r * 0.45]).fill(accent); | |
| 657 | + g.circle(-r * 0.5, -r * 0.1, r * 0.08).fill(0x0b0d14); | |
| 658 | + g.moveTo(-r * 0.2, -r * 0.4).bezierCurveTo(0, -r * 0.7, r * 0.2, -r * 0.5, r * 0.25, -r * 0.3).fill({ color: accent, alpha: 0.8 }); | |
| 659 | + break; | |
| 660 | + } | |
| 661 | + case "meteor": { | |
| 662 | + polygon(g, r * 0.2, r * 0.2, r * 0.6, 7, 0.3).fill(main); | |
| 663 | + g.circle(r * 0.35, 0, r * 0.12).fill({ color: darken(style.color, 0.3) }); | |
| 664 | + g.circle(0, r * 0.4, r * 0.1).fill({ color: darken(style.color, 0.3) }); | |
| 665 | + g.moveTo(-r * 0.2, -r * 0.3).lineTo(-r * 1.0, -r * 1.0).stroke({ color: accent, alpha: 0.6, width: size * 0.06 }); | |
| 666 | + g.moveTo(r * 0.1, -r * 0.55).lineTo(-r * 0.5, -r * 1.05).stroke({ color: accent, alpha: 0.4, width: size * 0.04 }); | |
| 667 | + break; | |
| 668 | + } | |
| 313 | 669 | } |
| 314 | 670 | c.addChild(g); |
| 315 | 671 | return c; |
modified
apps/web/src/components/lobby/game-art.tsx
+1167 −533
Large diff (1,892 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/arctic-fortune/index.ts
+3 −3
Large diff (17 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/cosmic-collapse/index.ts
+3 −3
Large diff (12 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/deep-treasure/index.ts
+4 −4
Large diff (18 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/diamond-heist/index.ts
+10 −10
Large diff (28 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/dragon-core/index.ts
+1 −1
Large diff (8 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/golden-emperor/index.ts
+7 −7
Large diff (20 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/inferno-reels/index.ts
+3 −3
Large diff (16 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/lucky-circuit/index.ts
+4 −4
Large diff (16 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/midnight-tokyo/index.ts
+8 −8
Large diff (23 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/moonbase-77/index.ts
+6 −6
Large diff (18 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/neon-vault/index.ts
+7 −7
Large diff (24 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/pharaoh-protocol/index.ts
+8 −8
Large diff (25 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/quantum-jackpot/index.ts
+4 −4
Large diff (15 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/reel-reactor/index.ts
+5 −5
Large diff (17 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/royal-circuit/index.ts
+10 −10
Large diff (27 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/void-miner/index.ts
+4 −4
Large diff (20 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/wild-temple/index.ts
+8 −8
Large diff (24 lines) is not loaded by default to keep the page fast.Load diff
modified
games/src/zero-gravity/index.ts
+3 −3
Large diff (17 lines) is not loaded by default to keep the page fast.Load diff
modified
packages/game-core/src/types.ts
+51 −1
Large diff (59 lines) is not loaded by default to keep the page fast.Load diff