Round 2: 16-facing rotating vehicles, projectile/explosion effects, death booms, real terrain + wax crystal art, Pressing District 4-player map
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BIN
assets_src/renders_topdown/basscannon.png
Normal file
|
After Width: | Height: | Size: 684 KiB |
BIN
assets_src/renders_topdown/basscannon_raw.png
Normal file
|
After Width: | Height: | Size: 594 KiB |
BIN
assets_src/renders_topdown/digger.png
Normal file
|
After Width: | Height: | Size: 609 KiB |
BIN
assets_src/renders_topdown/digger_raw.png
Normal file
|
After Width: | Height: | Size: 532 KiB |
BIN
assets_src/renders_topdown/drmwalker.png
Normal file
|
After Width: | Height: | Size: 745 KiB |
BIN
assets_src/renders_topdown/drmwalker_raw.png
Normal file
|
After Width: | Height: | Size: 660 KiB |
BIN
assets_src/renders_topdown/popupvan.png
Normal file
|
After Width: | Height: | Size: 782 KiB |
BIN
assets_src/renders_topdown/popupvan_raw.png
Normal file
|
After Width: | Height: | Size: 681 KiB |
BIN
assets_src/renders_topdown/scraper.png
Normal file
|
After Width: | Height: | Size: 809 KiB |
BIN
assets_src/renders_topdown/scraper_raw.png
Normal file
|
After Width: | Height: | Size: 716 KiB |
BIN
assets_src/renders_topdown/spinner.png
Normal file
|
After Width: | Height: | Size: 474 KiB |
BIN
assets_src/renders_topdown/spinner_raw.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
assets_src/renders_topdown/stacktank.png
Normal file
|
After Width: | Height: | Size: 788 KiB |
BIN
assets_src/renders_topdown/stacktank_raw.png
Normal file
|
After Width: | Height: | Size: 680 KiB |
BIN
assets_src/renders_topdown/streamvan.png
Normal file
|
After Width: | Height: | Size: 785 KiB |
BIN
assets_src/renders_topdown/streamvan_raw.png
Normal file
|
After Width: | Height: | Size: 694 KiB |
BIN
assets_src/renders_topdown/terrain_raw.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
assets_src/renders_topdown/wax.png
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
assets_src/renders_topdown/wax_raw.png
Normal file
|
After Width: | Height: | Size: 547 KiB |
BIN
mods/vinylgod/maps/district/map.bin
Normal file
BIN
mods/vinylgod/maps/district/map.png
Normal file
|
After Width: | Height: | Size: 937 B |
62
mods/vinylgod/maps/district/map.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
MapFormat: 12
|
||||
|
||||
RequiresMod: vinylgod
|
||||
|
||||
Title: Pressing District
|
||||
|
||||
Author: Monster Robot Party
|
||||
|
||||
Tileset: VINYLGOD
|
||||
|
||||
MapSize: 66,66
|
||||
|
||||
Bounds: 1,1,64,64
|
||||
|
||||
Visibility: Lobby
|
||||
|
||||
Categories: Maps
|
||||
|
||||
Players:
|
||||
PlayerReference@Neutral:
|
||||
Name: Neutral
|
||||
OwnsWorld: True
|
||||
NonCombatant: True
|
||||
Faction: Random
|
||||
PlayerReference@Creeps:
|
||||
Name: Creeps
|
||||
NonCombatant: True
|
||||
Faction: Random
|
||||
PlayerReference@Multi0:
|
||||
Name: Multi0
|
||||
Playable: True
|
||||
Faction: Random
|
||||
Enemies: Creeps
|
||||
PlayerReference@Multi1:
|
||||
Name: Multi1
|
||||
Playable: True
|
||||
Faction: Random
|
||||
Enemies: Creeps
|
||||
PlayerReference@Multi2:
|
||||
Name: Multi2
|
||||
Playable: True
|
||||
Faction: Random
|
||||
Enemies: Creeps
|
||||
PlayerReference@Multi3:
|
||||
Name: Multi3
|
||||
Playable: True
|
||||
Faction: Random
|
||||
Enemies: Creeps
|
||||
|
||||
Actors:
|
||||
Actor0: mpspawn
|
||||
Owner: Multi0
|
||||
Location: 8,8
|
||||
Actor1: mpspawn
|
||||
Owner: Multi1
|
||||
Location: 57,8
|
||||
Actor2: mpspawn
|
||||
Owner: Multi2
|
||||
Location: 8,57
|
||||
Actor3: mpspawn
|
||||
Owner: Multi3
|
||||
Location: 57,57
|
||||
@ -9,6 +9,8 @@
|
||||
|
||||
spinner:
|
||||
Inherits: ^ArmedUnit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 40
|
||||
@ -29,6 +31,8 @@ spinner:
|
||||
|
||||
stacktank:
|
||||
Inherits: ^ArmedUnit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 50
|
||||
@ -49,6 +53,8 @@ stacktank:
|
||||
|
||||
basscannon:
|
||||
Inherits: ^ArmedUnit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 60
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
^Unit:
|
||||
Inherits: ^EconSprite
|
||||
FireWarheadsOnDeath:
|
||||
Weapon: UnitExplode
|
||||
Targetable:
|
||||
TargetTypes: GroundActor
|
||||
MustBeDestroyed:
|
||||
@ -22,6 +24,8 @@
|
||||
|
||||
digger:
|
||||
Inherits: ^Unit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 20
|
||||
@ -49,6 +53,8 @@ digger:
|
||||
|
||||
popupvan:
|
||||
Inherits: ^Unit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 30
|
||||
@ -91,6 +97,8 @@ djgrunt:
|
||||
|
||||
^EconBuilding:
|
||||
Inherits: ^EconSprite
|
||||
FireWarheadsOnDeath:
|
||||
Weapon: BuildingExplode
|
||||
Targetable:
|
||||
TargetTypes: GroundActor, Structure
|
||||
MustBeDestroyed:
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
streamvan:
|
||||
Inherits: ^Unit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 31
|
||||
@ -121,6 +123,8 @@ printfarm:
|
||||
|
||||
scraper:
|
||||
Inherits: ^Unit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 21
|
||||
@ -168,6 +172,8 @@ bufferbot:
|
||||
|
||||
drmwalker:
|
||||
Inherits: ^ArmedUnit
|
||||
-WithSpriteBody:
|
||||
WithFacingSpriteBody:
|
||||
Buildable:
|
||||
Queue: Vehicle
|
||||
BuildPaletteOrder: 51
|
||||
|
||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 19 KiB |
BIN
mods/vinylgod/sequences/assets/bigboom.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 33 KiB |
BIN
mods/vinylgod/sequences/assets/pop.png
Normal file
|
After Width: | Height: | Size: 529 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 17 KiB |
BIN
mods/vinylgod/sequences/assets/seven_inch_proj.png
Normal file
|
After Width: | Height: | Size: 208 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 582 B After Width: | Height: | Size: 4.2 KiB |
@ -9,12 +9,14 @@ clock:
|
||||
digger:
|
||||
idle:
|
||||
Filename: sequences/assets/digger.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_digger.png
|
||||
|
||||
popupvan:
|
||||
idle:
|
||||
Filename: sequences/assets/popupvan.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_popupvan.png
|
||||
|
||||
@ -63,18 +65,21 @@ garage:
|
||||
spinner:
|
||||
idle:
|
||||
Filename: sequences/assets/spinner.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_spinner.png
|
||||
|
||||
stacktank:
|
||||
idle:
|
||||
Filename: sequences/assets/stacktank.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_stacktank.png
|
||||
|
||||
basscannon:
|
||||
idle:
|
||||
Filename: sequences/assets/basscannon.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_basscannon.png
|
||||
|
||||
@ -93,6 +98,7 @@ mastering:
|
||||
streamvan:
|
||||
idle:
|
||||
Filename: sequences/assets/streamvan.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_streamvan.png
|
||||
|
||||
@ -129,6 +135,7 @@ printfarm:
|
||||
scraper:
|
||||
idle:
|
||||
Filename: sequences/assets/scraper.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_scraper.png
|
||||
|
||||
@ -141,5 +148,19 @@ bufferbot:
|
||||
drmwalker:
|
||||
idle:
|
||||
Filename: sequences/assets/drmwalker.png
|
||||
Facings: 16
|
||||
icon:
|
||||
Filename: sequences/assets/icon_drmwalker.png
|
||||
|
||||
seven_inch_proj:
|
||||
idle:
|
||||
Filename: sequences/assets/seven_inch_proj.png
|
||||
Length: 4
|
||||
|
||||
explosion:
|
||||
pop:
|
||||
Filename: sequences/assets/pop.png
|
||||
Length: 8
|
||||
bigboom:
|
||||
Filename: sequences/assets/bigboom.png
|
||||
Length: 12
|
||||
|
||||
|
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 1.9 KiB |
@ -7,6 +7,9 @@
|
||||
|
||||
tonearm_blade:
|
||||
Inherits: ^GroundWeapon
|
||||
Warhead@2Eff: CreateEffect
|
||||
Explosions: pop
|
||||
ValidTargets: Ground, GroundActor
|
||||
ReloadDelay: 12
|
||||
Range: 1c512
|
||||
Warhead@1Dam: SpreadDamage
|
||||
@ -21,11 +24,16 @@ tonearm_blade:
|
||||
|
||||
seven_inch:
|
||||
Inherits: ^GroundWeapon
|
||||
Warhead@2Eff: CreateEffect
|
||||
Explosions: pop
|
||||
ValidTargets: Ground, GroundActor
|
||||
ReloadDelay: 30
|
||||
Range: 4c0
|
||||
Projectile: Bullet
|
||||
Speed: 512
|
||||
LaunchAngle: 30
|
||||
Image: seven_inch_proj
|
||||
Sequences: idle
|
||||
Warhead@1Dam: SpreadDamage
|
||||
Spread: 96
|
||||
Damage: 3000
|
||||
@ -38,6 +46,9 @@ seven_inch:
|
||||
|
||||
feedback_burst:
|
||||
Inherits: ^GroundWeapon
|
||||
Warhead@2Eff: CreateEffect
|
||||
Explosions: pop
|
||||
ValidTargets: Ground, GroundActor
|
||||
ReloadDelay: 50
|
||||
Range: 5c0
|
||||
Warhead@1Dam: SpreadDamage
|
||||
@ -52,6 +63,9 @@ feedback_burst:
|
||||
|
||||
bass_ring:
|
||||
Inherits: ^GroundWeapon
|
||||
Warhead@2Eff: CreateEffect
|
||||
Explosions: bigboom
|
||||
ValidTargets: Ground, GroundActor
|
||||
ReloadDelay: 120
|
||||
Range: 9c0
|
||||
MinRange: 2c0
|
||||
@ -71,6 +85,9 @@ bass_ring:
|
||||
|
||||
ping:
|
||||
Inherits: ^GroundWeapon
|
||||
Warhead@2Eff: CreateEffect
|
||||
Explosions: pop
|
||||
ValidTargets: Ground, GroundActor
|
||||
ReloadDelay: 15
|
||||
Range: 3c512
|
||||
Warhead@1Dam: SpreadDamage
|
||||
@ -82,3 +99,13 @@ ping:
|
||||
Wood: 35
|
||||
Light: 45
|
||||
Heavy: 15
|
||||
|
||||
UnitExplode:
|
||||
Warhead@Eff: CreateEffect
|
||||
Explosions: pop
|
||||
ValidTargets: Ground, GroundActor
|
||||
|
||||
BuildingExplode:
|
||||
Warhead@Eff: CreateEffect
|
||||
Explosions: bigboom
|
||||
ValidTargets: Ground, GroundActor
|
||||
|
||||
82
tools/gen_map.py
Normal file
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate 'Pressing District' — 64x64 4-player skirmish map (yaml + bin + preview)."""
|
||||
import os, struct
|
||||
from PIL import Image
|
||||
|
||||
W = H = 66 # 64 playable + 1 border each side
|
||||
MAP = os.path.join(os.path.dirname(__file__), '..', 'mods', 'vinylgod', 'maps', 'district')
|
||||
os.makedirs(MAP, exist_ok=True)
|
||||
|
||||
SPAWNS = [(8, 8), (57, 8), (8, 57), (57, 57)]
|
||||
WAX = [(16, 16, 5), (49, 16, 5), (16, 49, 5), (49, 49, 5), (32, 32, 7), (32, 10, 3), (32, 55, 3), (10, 32, 3), (55, 32, 3)]
|
||||
|
||||
# map.bin: fmt2 header, tiles (template 255 idx 0), resources
|
||||
data = bytearray()
|
||||
data += struct.pack('<BHH', 2, W, H)
|
||||
data += struct.pack('<III', 17, 0, 3 * W * H + 17)
|
||||
data += b'\xff\x00\x00' * (W * H)
|
||||
res = bytearray(2 * W * H)
|
||||
for cx, cy, r in WAX:
|
||||
for x in range(cx - r, cx + r + 1):
|
||||
for y in range(cy - r, cy + r + 1):
|
||||
d2 = (x - cx) ** 2 + (y - cy) ** 2
|
||||
if d2 <= r * r and 0 < x < W - 1 and 0 < y < H - 1:
|
||||
o = 2 * (x * H + y)
|
||||
res[o], res[o + 1] = 1, max(2, round(12 * (1 - (d2 ** 0.5) / (r + 1))))
|
||||
data += res
|
||||
open(os.path.join(MAP, 'map.bin'), 'wb').write(data)
|
||||
|
||||
players = '\n'.join(f""" PlayerReference@Multi{i}:
|
||||
Name: Multi{i}
|
||||
Playable: True
|
||||
Faction: Random
|
||||
Enemies: Creeps""" for i in range(4))
|
||||
actors = '\n'.join(f""" Actor{i}: mpspawn
|
||||
Owner: Multi{i}
|
||||
Location: {x},{y}""" for i, (x, y) in enumerate(SPAWNS))
|
||||
|
||||
open(os.path.join(MAP, 'map.yaml'), 'w').write(f"""MapFormat: 12
|
||||
|
||||
RequiresMod: vinylgod
|
||||
|
||||
Title: Pressing District
|
||||
|
||||
Author: Monster Robot Party
|
||||
|
||||
Tileset: VINYLGOD
|
||||
|
||||
MapSize: {W},{H}
|
||||
|
||||
Bounds: 1,1,64,64
|
||||
|
||||
Visibility: Lobby
|
||||
|
||||
Categories: Maps
|
||||
|
||||
Players:
|
||||
PlayerReference@Neutral:
|
||||
Name: Neutral
|
||||
OwnsWorld: True
|
||||
NonCombatant: True
|
||||
Faction: Random
|
||||
PlayerReference@Creeps:
|
||||
Name: Creeps
|
||||
NonCombatant: True
|
||||
Faction: Random
|
||||
{players}
|
||||
|
||||
Actors:
|
||||
{actors}
|
||||
""")
|
||||
|
||||
# preview
|
||||
im = Image.new('RGB', (W, H), (55, 50, 52))
|
||||
for cx, cy, r in WAX:
|
||||
for x in range(cx - r, cx + r + 1):
|
||||
for y in range(cy - r, cy + r + 1):
|
||||
if (x - cx) ** 2 + (y - cy) ** 2 <= r * r and 0 <= x < W and 0 <= y < H:
|
||||
im.putpixel((x, y), (255, 45, 150))
|
||||
for x, y in SPAWNS:
|
||||
im.putpixel((x, y), (255, 255, 255))
|
||||
im.resize((W * 3, H * 3), Image.NEAREST).save(os.path.join(MAP, 'map.png'))
|
||||
print('district map written')
|
||||
88
tools/mbfacings.py
Normal file
@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Top-down vehicle renders -> 16-facing rotation sheets.
|
||||
|
||||
flux renders each vehicle facing NORTH from directly above; PIL rotates into 16
|
||||
frames (OpenRA facing order: north first, counter-clockwise), packed into one
|
||||
horizontal strip with FrameSize metadata. Geometrically correct, unlike rotating
|
||||
a 3/4-view sprite. Also: terrain tile + wax crystal density sheet.
|
||||
"""
|
||||
import os, sys
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
from mbgen import run, upload # noqa: E402
|
||||
from PIL import Image # noqa: E402
|
||||
from PIL.PngImagePlugin import PngInfo # noqa: E402
|
||||
|
||||
ROOT = os.path.join(os.path.dirname(__file__), '..')
|
||||
RENDERS = os.path.join(ROOT, 'assets_src', 'renders_topdown')
|
||||
ASSETS = os.path.join(ROOT, 'mods', 'vinylgod', 'sequences', 'assets')
|
||||
os.makedirs(RENDERS, exist_ok=True)
|
||||
|
||||
MRP = 'rusty junkyard robot aesthetic, rust metal with hot pink trim, '
|
||||
STR = 'glossy seamless white tech aesthetic, soft blue ring lights, '
|
||||
SUF = ', viewed from directly above, top-down aerial view, vehicle pointing straight up toward the top of the image, single object centered, video game sprite, plain flat grey background, no text, no shadow'
|
||||
|
||||
VEHICLES = [
|
||||
('digger', 26, MRP + 'forklift harvester truck carrying crates of vinyl records'),
|
||||
('popupvan', 26, MRP + 'delivery truck covered in band stickers with roof loudspeaker'),
|
||||
('spinner', 20, MRP + 'small round robot riding a single vinyl record wheel with blade arms'),
|
||||
('stacktank', 30, MRP + 'heavy tracked tank made of stacked speaker cabinets with subwoofer turret'),
|
||||
('basscannon', 30, MRP + 'long six-wheeled flatbed truck with one colossal subwoofer cannon'),
|
||||
('streamvan', 26, STR + 'sleek white autonomous delivery van with blue play-button roof logo'),
|
||||
('scraper', 24, STR + 'white autonomous street sweeper vehicle with glowing blue front intake'),
|
||||
('drmwalker', 30, STR + 'white quad-legged mech with one blue ring light, seen from above'),
|
||||
]
|
||||
|
||||
|
||||
def sheet16(im, size, out):
|
||||
im = im.crop(im.getbbox() or (0, 0, im.width, im.height))
|
||||
im.thumbnail((size * 4, size * 4), Image.LANCZOS) # rotate at 4x, downscale after
|
||||
strip = Image.new('RGBA', (size * 16, size), (0, 0, 0, 0))
|
||||
for i in range(16):
|
||||
fr = im.rotate(i * 22.5, expand=False, resample=Image.BICUBIC)
|
||||
fr.thumbnail((size, size), Image.LANCZOS)
|
||||
strip.paste(fr, (i * size + (size - fr.width) // 2, (size - fr.height) // 2), fr)
|
||||
meta = PngInfo()
|
||||
meta.add_text('FrameSize', f'{size},{size}')
|
||||
strip.save(out, pnginfo=meta)
|
||||
print(f'[facings] {out}', flush=True)
|
||||
|
||||
|
||||
for name, size, prompt in VEHICLES:
|
||||
raw = os.path.join(RENDERS, f'{name}_raw.png')
|
||||
cut = os.path.join(RENDERS, f'{name}.png')
|
||||
if not os.path.exists(cut):
|
||||
run('flux_local', {'prompt': prompt + SUF}, raw)
|
||||
run('bg_remove_local', {}, cut, asset_id=upload(raw))
|
||||
sheet16(Image.open(cut).convert('RGBA'), size, os.path.join(ASSETS, f'{name}.png'))
|
||||
|
||||
# terrain tile: seamless ground texture -> 32x32
|
||||
traw = os.path.join(RENDERS, 'terrain_raw.png')
|
||||
if not os.path.exists(traw):
|
||||
run('flux_local', {'prompt': 'seamless tileable texture, cracked dark asphalt with faint dust and tiny speckles, muted grey brown, flat even lighting, top down, no objects'}, traw)
|
||||
t = Image.open(traw).convert('RGBA').resize((64, 64), Image.LANCZOS).crop((16, 16, 48, 48))
|
||||
t.save(os.path.join(ROOT, 'mods', 'vinylgod', 'tilesets', 'vinylgod', 'vinylgod.png'))
|
||||
print('[terrain] tile written', flush=True)
|
||||
|
||||
# wax crystals: one cluster render -> 12 density frames
|
||||
wraw = os.path.join(RENDERS, 'wax_raw.png')
|
||||
wcut = os.path.join(RENDERS, 'wax.png')
|
||||
if not os.path.exists(wcut):
|
||||
run('flux_local', {'prompt': 'cluster of jagged black vinyl crystal shards glowing hot pink from the cracks, viewed from directly above, top down, video game resource sprite, single cluster centered, plain flat grey background'}, wraw)
|
||||
run('bg_remove_local', {}, wcut, asset_id=upload(wraw))
|
||||
w = Image.open(wcut).convert('RGBA')
|
||||
w = w.crop(w.getbbox() or (0, 0, w.width, w.height))
|
||||
strip = Image.new('RGBA', (32 * 12, 32), (0, 0, 0, 0))
|
||||
spots = [(16, 16), (7, 9), (24, 10), (9, 24), (24, 24), (16, 6), (5, 17), (27, 18), (16, 26), (11, 13), (21, 15), (16, 20)]
|
||||
for f in range(12):
|
||||
for i in range(f + 1):
|
||||
s = 10 + (6 if i == 0 else 0)
|
||||
c = w.copy()
|
||||
c.thumbnail((s, s), Image.LANCZOS)
|
||||
c = c.rotate(i * 47, expand=False)
|
||||
x, y = spots[i]
|
||||
strip.paste(c, (f * 32 + x - c.width // 2, y - c.height // 2), c)
|
||||
meta = PngInfo()
|
||||
meta.add_text('FrameSize', '32,32')
|
||||
strip.save(os.path.join(ASSETS, 'wax.png'), pnginfo=meta)
|
||||
print('[wax] density sheet written', flush=True)
|
||||
print('ALL DONE')
|
||||