- Native player-controlled stairs, upper lounge bar, and Hell Tower infernal portal - Cabaret stage with musical acts, audience seating, and interaction - Dedicated cash/trophy wall terminals with native balance and achievement screens - Projecting 3D wall lanterns with ray/plane intersection - Six roaming guests with seated poses and card rank rendering updates - Synchronized launcher hash and updated binaries
47 lines
2.1 KiB
Python
47 lines
2.1 KiB
Python
"""Pack the approved piano/pianist and guitarist cutouts for the MASM stage."""
|
|
from pathlib import Path
|
|
import struct
|
|
from PIL import Image
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def pack(sheet, left, right, width, name):
|
|
cells = [sheet.crop((left, row * 384, right, (row + 1) * 384))
|
|
for row in range(4)]
|
|
bounds = [cell.getchannel("A").point(lambda a: 255 if a >= 128 else 0).getbbox()
|
|
for cell in cells]
|
|
assert all(bounds), "each playing pose must contain opaque pixels"
|
|
box = (min(b[0] for b in bounds), min(b[1] for b in bounds),
|
|
max(b[2] for b in bounds), max(b[3] for b in bounds))
|
|
scale = min((width - 12) / (box[2] - box[0]), 244 / (box[3] - box[1]))
|
|
size = (round((box[2] - box[0]) * scale), round((box[3] - box[1]) * scale))
|
|
frames = []
|
|
for cell in cells:
|
|
sprite = cell.crop(box).resize(size, Image.Resampling.LANCZOS)
|
|
# The native sprite rasterizer uses a binary alpha test.
|
|
sprite.putalpha(sprite.getchannel("A").point(lambda a: 255 if a >= 128 else 0))
|
|
canvas = Image.new("RGBA", (width, 256))
|
|
canvas.alpha_composite(sprite, ((width - size[0]) // 2, 250 - size[1]))
|
|
frames.append(canvas)
|
|
raw = b"".join(frame.tobytes("raw", "BGRA") for frame in frames)
|
|
(ROOT / f"assets/animations/hall/{name}-v1.bin").write_bytes(
|
|
struct.pack("<4s4I", b"ANM1", width, 256, 4, len(raw)) + raw)
|
|
return frames
|
|
|
|
|
|
def main():
|
|
sheet = Image.open(ROOT / "assets/sprites/hall/cabaret-musicians-v1.png").convert("RGBA")
|
|
assert sheet.size == (1024, 1536)
|
|
piano = pack(sheet, 0, 640, 384, "cabaret-piano")
|
|
guitar = pack(sheet, 640, 1024, 160, "cabaret-guitar")
|
|
preview = Image.new("RGBA", (544, 1024), (24, 28, 29, 255))
|
|
for row in range(4):
|
|
preview.alpha_composite(piano[row], (0, row * 256))
|
|
preview.alpha_composite(guitar[row], (384, row * 256))
|
|
preview.save(ROOT / "build/cabaret-musicians-preview.png")
|
|
print("Packed coherent grand piano/pianist and guitarist: four anchored poses each")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|