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:
1 parent
c2a87f178e
commit
dc4568e023
29 files changed
+116
-42
No files matched your search
+36
-30
@@ -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"},
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user