Phase 6 done: see-through cores, faint on sacrifice and rebirth; Phase 7 design

Adrian (2026-11-02): the cores should be transparent so the Pokémon
shows; the Pokémon's death sound when a sacrifice is made or a rebirth
ends; then start the next phase (Phase 6 approved).

- Cores drawn as a solid frame around tinted glass, rendered
  translucent, no occlusion (tools/machine_assets.py).
- The shown Pokémon plays Cobblemon's faint animation and its cry
  pitched down (Cobblemon has no death sounds), vanishes after 2 s; a
  reborn Pokémon then shows in its new form. Tests check the new form.
- Phase 7 decisions (every guardian gets area attacks, Groudon for the
  Basalt Furnace, Giratina replaces the Ender Dragon, dying or leaving
  the arena loses) and design in docs/design.md; README status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
claudeandClaude Opus 5.5 committed 2026-11-02 15:58:01 +01:00
1 parent c2a87f178e
commit dc4568e023
29 files changed
+116 -42

No files matched your search

+36 -30
View File
@@ -3,6 +3,8 @@
Each core is an "orientable" block (front, side, top) facing the player who placed it. The 16x16 textures are drawn
here, from a palette and an emblem per machine, so they can be redrawn after a change. Our own art (pack license).
The cores are see-through (Adrian, 2026-11-02: the Pokémon in the chamber behind the core must be visible): a solid
frame around tinted glass, the emblem faint on the front; the models render translucent.
Usage: tools/machine_assets.py
"""
@@ -83,51 +85,54 @@ EMBLEMS = {
}
def frame(image, dark, light):
GLASS_ALPHA = 70
EMBLEM_ALPHA = 150
def frame(image, dark, mid, light):
"""A two-pixel frame: light top-left edge, dark bottom-right edge, mid inner ring."""
for i in range(16):
image.putpixel((i, 0), light)
image.putpixel((0, i), light)
image.putpixel((i, 15), dark)
image.putpixel((15, i), dark)
for a, b in ((i, 0), (0, i)):
image.putpixel((a, b), light + (255,))
for a, b in ((i, 15), (15, i)):
image.putpixel((a, b), dark + (255,))
for i in range(1, 15):
for a, b in ((i, 1), (1, i), (i, 14), (14, i)):
image.putpixel((a, b), mid + (255,))
def side(dark, mid, light):
image = Image.new("RGBA", (16, 16), mid + (255,))
for y in range(16):
for x in range(16):
# Plates of 8x4 with a seam, offset every other row, like bricks or panels.
if y % 4 == 0 or (x + (4 if (y // 4) % 2 else 0)) % 8 == 0:
image.putpixel((x, y), dark + (255,))
elif (x + y) % 7 == 0:
image.putpixel((x, y), light + (255,))
frame(image, dark + (255,), light + (255,))
def glass(dark, mid, light, accent):
"""Tinted glass inside the frame, with a few lighter streaks so the face still reads as a surface."""
image = Image.new("RGBA", (16, 16), (0, 0, 0, 0))
tint = tuple((m + a) // 2 for m, a in zip(mid, accent))
for y in range(2, 14):
for x in range(2, 14):
streak = (x - y) in (3, 4) or (x - y) == -6
image.putpixel((x, y), (light if streak else tint) + (GLASS_ALPHA + (50 if streak else 0),))
frame(image, dark, mid, light)
return image
def side(dark, mid, light, accent):
return glass(dark, mid, light, accent)
def top(dark, mid, light, accent):
image = side(dark, mid, light)
for y in range(5, 11):
for x in range(5, 11):
edge = x in (5, 10) or y in (5, 10)
image.putpixel((x, y), (dark if edge else accent) + (255,))
image = glass(dark, mid, light, accent)
for x, y in ((2, 2), (13, 2), (2, 13), (13, 13)):
image.putpixel((x, y), accent + (255,))
return image
def front(dark, mid, light, accent, emblem):
image = Image.new("RGBA", (16, 16), dark + (255,))
for y in range(2, 14):
for x in range(2, 14):
image.putpixel((x, y), (mid if (x + y) % 2 else dark) + (255,))
frame(image, dark + (255,), light + (255,))
image = glass(dark, mid, light, accent)
rows = EMBLEMS[emblem]
top_row = (16 - len(rows)) // 2
glow = tuple(min(255, c + 60) for c in accent)
for y, row in enumerate(rows):
for x, c in enumerate(row):
if c == "#":
image.putpixel((x, top_row + y), accent + (255,))
elif c == "+":
image.putpixel((x, top_row + y), glow + (255,))
if 2 <= x <= 13 and 2 <= top_row + y <= 13 and c in "#+":
image.putpixel((x, top_row + y), (accent if c == "#" else glow) + (EMBLEM_ALPHA,))
return image
@@ -140,11 +145,12 @@ def main():
textures = ASSETS / "textures/block"
textures.mkdir(parents=True, exist_ok=True)
for name, (dark, mid, light, accent, emblem) in CORES.items():
side(dark, mid, light).save(textures / f"{name}_side.png")
side(dark, mid, light, accent).save(textures / f"{name}_side.png")
top(dark, mid, light, accent).save(textures / f"{name}_top.png")
front(dark, mid, light, accent, emblem).save(textures / f"{name}_front.png")
write_json(ASSETS / f"models/block/{name}.json", {
"parent": "minecraft:block/orientable",
"render_type": "minecraft:translucent",
"textures": {"top": f"cobblesurvival:block/{name}_top", "front": f"cobblesurvival:block/{name}_front",
"side": f"cobblesurvival:block/{name}_side"},
})