- 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
36 lines
1.6 KiB
Python
36 lines
1.6 KiB
Python
"""Normalize the generated ensemble; native MASM owns timing and staging."""
|
|
from pathlib import Path
|
|
import struct
|
|
from PIL import Image
|
|
from pack_guest_cast import isolate
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def main():
|
|
sheet = Image.open(ROOT / "assets/sprites/hall/cabaret-ensemble-v1.png").convert("RGBA")
|
|
frames = []
|
|
for column in range(3):
|
|
cells = [isolate(sheet.crop((column*sheet.width//3, row*sheet.height//4,
|
|
(column+1)*sheet.width//3,(row+1)*sheet.height//4)))
|
|
for row in range(4)]
|
|
scale = min(142/max(cell.width for cell in cells),
|
|
(180 if column == 1 else 242)/max(cell.height for cell in cells))
|
|
for cell in cells:
|
|
size = (round(cell.width*scale),round(cell.height*scale))
|
|
canvas = Image.new("RGBA",(160,256))
|
|
canvas.alpha_composite(cell.resize(size,Image.Resampling.LANCZOS),
|
|
((160-size[0])//2,250-size[1]))
|
|
frames.append(canvas)
|
|
raw = b"".join(frame.tobytes("raw","BGRA") for frame in frames)
|
|
(ROOT / "assets/animations/hall/cabaret-ensemble-v1.bin").write_bytes(
|
|
struct.pack("<4s4I",b"ANM1",160,256,len(frames),len(raw))+raw)
|
|
preview = Image.new("RGBA",(480,1024),(24,28,29,255))
|
|
for index,frame in enumerate(frames):
|
|
preview.alpha_composite(frame,((index//4)*160,(index%4)*256))
|
|
preview.save(ROOT / "build/cabaret-ensemble-preview.png")
|
|
print("Packed three performers, four poses each")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|