feat: Initial commit Plants vs Zombies Web Edition v2.4
- 5 Biomes: Day, Night, Pool, Fog, Roof (25 Campaign levels) - Minigames: Wall-nut Bowling, I Zombie, Roguelike, Boss Rush & Dr. Zomboss - Systems: Zen Garden, Workshop Crafting, Almanac, Tree of Wisdom, Achievements - Backend: REST API + SQLite Accounts & Save Synchronization - Infrastructure: Nginx HTTPS & Docker deployment
This commit is contained in:
commit
6457a8904e
50 files changed
+14486
No files matched your search
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import zlib
|
||||
import struct
|
||||
import math
|
||||
|
||||
def make_png(w, h, get_pixel):
|
||||
def chunk(tag, data):
|
||||
return struct.pack('>I', len(data)) + tag + data + struct.pack('>I', zlib.crc32(tag + data) & 0xffffffff)
|
||||
|
||||
ihdr = struct.pack('>IIBBBBB', w, h, 8, 6, 0, 0, 0) # RGBA 8-bit
|
||||
raw_rows = []
|
||||
for y in range(h):
|
||||
row = [0] # filter type 0
|
||||
for x in range(w):
|
||||
r, g, b, a = get_pixel(x, y, w, h)
|
||||
row.extend([r, g, b, a])
|
||||
raw_rows.append(bytes(row))
|
||||
raw_data = b''.join(raw_rows)
|
||||
idat = zlib.compress(raw_data, 9)
|
||||
return b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', ihdr) + chunk(b'IDAT', idat) + chunk(b'IEND', b'')
|
||||
|
||||
def render_pvz_icon(x, y, w, h):
|
||||
# Normalized coords (-1 to 1)
|
||||
nx = (x - w / 2) / (w / 2)
|
||||
ny = (y - h / 2) / (h / 2)
|
||||
dist = math.hypot(nx, ny)
|
||||
|
||||
# Outer dark green circle border
|
||||
if dist > 0.96:
|
||||
return 0, 0, 0, 0
|
||||
if dist > 0.90:
|
||||
return 27, 94, 32, 255
|
||||
|
||||
# Background circle (lawn green gradient)
|
||||
if dist <= 0.90:
|
||||
# Sunflower petals or Peashooter head
|
||||
# Let's draw stylized bright yellow sunflower with green peashooter center!
|
||||
angle = math.atan2(ny, nx)
|
||||
petal_r = 0.55 + 0.15 * math.sin(angle * 8)
|
||||
|
||||
# Petal check
|
||||
if dist < petal_r and dist > 0.40:
|
||||
return 255, 213, 79, 255 # Yellow sunflower petals
|
||||
|
||||
# Peashooter green head in center
|
||||
center_dist = math.hypot(nx + 0.08, ny)
|
||||
if center_dist < 0.35:
|
||||
# Snout pointing right
|
||||
snout = (nx > 0.05 and nx < 0.35 and abs(ny) < 0.12)
|
||||
if snout:
|
||||
return 76, 175, 80, 255
|
||||
# Eye
|
||||
eye_dist = math.hypot(nx - (-0.05), ny - (-0.12))
|
||||
if eye_dist < 0.06:
|
||||
return 255, 255, 255, 255
|
||||
if eye_dist < 0.03:
|
||||
return 0, 0, 0, 255
|
||||
return 67, 160, 71, 255
|
||||
|
||||
# Green lawn background inside circle
|
||||
grad = int(46 + (1.0 - dist) * 60)
|
||||
return 27, min(255, grad + 80), 32, 255
|
||||
|
||||
def main():
|
||||
game_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "game")
|
||||
|
||||
# Generate 192x192
|
||||
p192 = make_png(192, 192, render_pvz_icon)
|
||||
with open(os.path.join(game_dir, "icon-192.png"), "wb") as f:
|
||||
f.write(p192)
|
||||
print("Generated icon-192.png:", len(p192), "bytes")
|
||||
|
||||
# Generate 512x512
|
||||
p512 = make_png(512, 512, render_pvz_icon)
|
||||
with open(os.path.join(game_dir, "icon-512.png"), "wb") as f:
|
||||
f.write(p512)
|
||||
print("Generated icon-512.png:", len(p512), "bytes")
|
||||
|
||||
# Generate favicon.ico (valid 32x32 PNG inside or 32x32 favicon)
|
||||
p32 = make_png(32, 32, render_pvz_icon)
|
||||
with open(os.path.join(game_dir, "favicon.ico"), "wb") as f:
|
||||
f.write(p32)
|
||||
print("Generated favicon.ico:", len(p32), "bytes")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user