generate_frames.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #!/usr/bin/env python3
  2. """
  3. Generate boot animation frames: ONLY the nucleus expanding.
  4. The orbiting electrons are handled by Swift after the kernel boots.
  5. Output: animation.bin (concatenated raw 32-bit BGRA frames, 200x200 each)
  6. """
  7. import math
  8. import os
  9. import struct
  10. import sys
  11. FRAME_COUNT = 60
  12. WIDTH = 200
  13. HEIGHT = 200
  14. CX = WIDTH / 2.0
  15. CY = HEIGHT / 2.0
  16. NUCLEUS_MAX_R = 28.0
  17. def main():
  18. if len(sys.argv) < 2:
  19. print("Usage: generate_frames.py <output-dir>")
  20. sys.exit(1)
  21. out_dir = sys.argv[1]
  22. os.makedirs(out_dir, exist_ok=True)
  23. out_path = os.path.join(out_dir, "animation.bin")
  24. all_frames = bytearray()
  25. for f in range(FRAME_COUNT):
  26. # Ease-out cubic expansion
  27. p = f / float(FRAME_COUNT - 1)
  28. p = 1.0 - (1.0 - p) ** 3
  29. radius = p * NUCLEUS_MAX_R
  30. frame = bytearray()
  31. for y in range(HEIGHT):
  32. for x in range(WIDTH):
  33. dx = x - CX
  34. dy = y - CY
  35. dist = math.sqrt(dx * dx + dy * dy)
  36. if dist < radius:
  37. val = 255
  38. elif dist < radius + 1.5:
  39. val = int(255 * (1.0 - (dist - radius) / 1.5))
  40. else:
  41. val = 0
  42. # 32-bit BGRA
  43. frame.extend(struct.pack('BBBB', val, val, val, 0xFF))
  44. all_frames.extend(frame)
  45. with open(out_path, 'wb') as fp:
  46. fp.write(all_frames)
  47. size_kb = len(all_frames) // 1024
  48. print(f" Generated {FRAME_COUNT} frames ({WIDTH}x{HEIGHT}x32bpp) "
  49. f"-> animation.bin ({size_kb} KB)")
  50. if __name__ == '__main__':
  51. main()