Refactoring: Project structure, sprite stairs & fog masks rendering fix
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import numpy as np
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
PALETTE = [
|
||||
224, 248, 207, # 0
|
||||
134, 192, 108, # 1
|
||||
48, 104, 80, # 2
|
||||
7, 24, 33 # 3
|
||||
] + [0] * (256 * 3 - 12)
|
||||
|
||||
# Based on peasant_preview3, but looking down-right
|
||||
GRID_DR_STAND = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032321111232300",
|
||||
"0032312112132300",
|
||||
"0032313113132300",
|
||||
"0032311111132300",
|
||||
"0032313333132300",
|
||||
"0003331111333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000323003230000",
|
||||
"0003333003333000",
|
||||
"0003333003333000"
|
||||
]
|
||||
|
||||
def draw_frame(draw, grid, x_off):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
val = int(grid[y][x])
|
||||
draw.point((x_off + x, y), fill=val)
|
||||
|
||||
img = Image.new("P", (16, 16), 0)
|
||||
img.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(img), GRID_DR_STAND, 0)
|
||||
img.save("test_peasant.png")
|
||||
@@ -0,0 +1,583 @@
|
||||
import os
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Standard Game Boy palette
|
||||
# 0: White, 1: Light Gray, 2: Dark Gray, 3: Black
|
||||
PALETTE = [
|
||||
224, 248, 207, # 0
|
||||
134, 192, 108, # 1
|
||||
48, 104, 80, # 2
|
||||
7, 24, 33 # 3
|
||||
] + [0] * (256 * 3 - 12)
|
||||
|
||||
def draw_corner(draw, corner_type, state, is_alt):
|
||||
if state == 0:
|
||||
fill_color = 3
|
||||
neigh_inner = None
|
||||
elif state == 1:
|
||||
fill_color = 0 if is_alt else 1
|
||||
neigh_inner = 1 if is_alt else 0
|
||||
neigh_outline = 2
|
||||
else:
|
||||
fill_color = 1 if is_alt else 2
|
||||
neigh_inner = 2 if is_alt else 1
|
||||
neigh_outline = 3
|
||||
|
||||
if corner_type == 'tl':
|
||||
draw.polygon([(0, 0), (15, 0), (0, 7)], fill=fill_color)
|
||||
if state != 0:
|
||||
draw.polygon([(-1, -4), (11, -1), (0, 3), (-12, 0)], fill=neigh_inner, outline=neigh_outline)
|
||||
elif corner_type == 'tr':
|
||||
draw.polygon([(16, 0), (31, 0), (31, 7)], fill=fill_color)
|
||||
if state != 0:
|
||||
draw.polygon([(31, -4), (43, -1), (32, 3), (20, 0)], fill=neigh_inner, outline=neigh_outline)
|
||||
elif corner_type == 'bl':
|
||||
draw.polygon([(0, 8), (0, 15), (15, 15)], fill=fill_color)
|
||||
if state != 0:
|
||||
draw.polygon([(-1, 12), (11, 15), (0, 19), (-12, 16)], fill=neigh_inner, outline=neigh_outline)
|
||||
elif corner_type == 'br':
|
||||
draw.polygon([(31, 8), (31, 15), (16, 15)], fill=fill_color)
|
||||
if state != 0:
|
||||
draw.polygon([(31, 12), (43, 15), (32, 19), (20, 16)], fill=neigh_inner, outline=neigh_outline)
|
||||
|
||||
def draw_autotile(img, y_offset, is_alt, mask, is_dark=False):
|
||||
temp_img = Image.new("P", (32, 16), 3)
|
||||
temp_img.putpalette(PALETTE)
|
||||
draw = ImageDraw.Draw(temp_img)
|
||||
|
||||
tl_state = mask % 3
|
||||
tr_state = mask // 3
|
||||
body_color = 2 if is_dark else (1 if is_alt else 0)
|
||||
outer = [(15, 0), (31, 7), (16, 15), (0, 8)]
|
||||
draw.polygon(outer, fill=body_color)
|
||||
draw_corner(draw, 'tl', tl_state, is_alt)
|
||||
draw_corner(draw, 'tr', tr_state, is_alt)
|
||||
draw_corner(draw, 'bl', 0, is_alt)
|
||||
draw_corner(draw, 'br', 0, is_alt)
|
||||
inner_color = 3 if is_dark else (0 if is_alt else 1)
|
||||
if is_dark:
|
||||
inner_color = 1 if is_alt else 2
|
||||
outline_color = 3 if is_dark else 2
|
||||
inner = [(15, 4), (27, 7), (16, 11), (4, 8)]
|
||||
draw.polygon(inner, fill=inner_color, outline=outline_color)
|
||||
|
||||
img.paste(temp_img, (0, y_offset))
|
||||
|
||||
def generate_tiles():
|
||||
img = Image.new("P", (32, 5768), 3)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
for mask in range(9): draw_autotile(img, 8 + mask * 16, False, mask, False)
|
||||
for mask in range(9): draw_autotile(img, 152 + mask * 16, True, mask, False)
|
||||
for mask in range(9): draw_autotile(img, 296 + mask * 16, False, mask, True)
|
||||
for mask in range(9): draw_autotile(img, 440 + mask * 16, True, mask, True)
|
||||
|
||||
stairs_pattern = [
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3311111133TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT330033TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3300000033TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT330033TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3311111133TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT330033TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3300000033TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT330033TTTTTTTTTTTTT",
|
||||
]
|
||||
dark_stairs_pattern = [
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT332233TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3322222233TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT332233TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3311111133TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT332233TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3322222233TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT332233TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTTTT33TTTTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
"TTTTTTTTTTT3311111133TTTTTTTTTTT",
|
||||
"TTTTTTTTTTTTT331133TTTTTTTTTTTTT",
|
||||
]
|
||||
|
||||
for v_set, base_offset, pattern in [
|
||||
(0, 584, stairs_pattern),
|
||||
(1, 1880, stairs_pattern),
|
||||
(2, 3176, dark_stairs_pattern),
|
||||
(3, 4472, dark_stairs_pattern)
|
||||
]:
|
||||
is_alt_vic = (v_set == 1 or v_set == 3)
|
||||
is_dark_vic = (v_set == 2 or v_set == 3)
|
||||
for mask in range(81):
|
||||
y_offset = base_offset + mask * 16
|
||||
|
||||
tl_state = mask % 3
|
||||
tr_state = (mask // 3) % 3
|
||||
bl_state = (mask // 9) % 3
|
||||
br_state = (mask // 27) % 3
|
||||
|
||||
temp_img = Image.new("P", (32, 16), 3)
|
||||
temp_img.putpalette(PALETTE)
|
||||
draw = ImageDraw.Draw(temp_img)
|
||||
|
||||
body_color = 2 if is_dark_vic else (1 if is_alt_vic else 0)
|
||||
outer = [(15, 0), (31, 7), (16, 15), (0, 8)]
|
||||
draw.polygon(outer, fill=body_color)
|
||||
|
||||
draw_corner(draw, 'tl', tl_state, is_alt_vic)
|
||||
draw_corner(draw, 'tr', tr_state, is_alt_vic)
|
||||
draw_corner(draw, 'bl', bl_state, is_alt_vic)
|
||||
draw_corner(draw, 'br', br_state, is_alt_vic)
|
||||
|
||||
for py in range(16):
|
||||
for px in range(32):
|
||||
char = pattern[py][px]
|
||||
if char != 'T':
|
||||
temp_img.putpixel((px, py), int(char))
|
||||
|
||||
img.paste(temp_img, (0, y_offset))
|
||||
|
||||
img.save("tiles.png")
|
||||
|
||||
def generate_stamina():
|
||||
# 13 variants of 8x16 tiles = 104x16 pixels
|
||||
img = Image.new("P", (104, 16), 0) # Fill with 0 (transparent)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
def draw_sprite_bar_tile(x_off, filled_px, cap=None):
|
||||
for y in range(8):
|
||||
for x in range(8):
|
||||
color = 3 # black inside
|
||||
if y == 0 or y == 7:
|
||||
color = 3 # black border
|
||||
elif y == 1 or y == 6:
|
||||
color = 2 # dark gray inner border
|
||||
else:
|
||||
if x < filled_px:
|
||||
color = 1 # light gray (filled)
|
||||
else:
|
||||
color = 3 # black (empty)
|
||||
|
||||
if cap == 'L' and x == 0:
|
||||
color = 2 # left border
|
||||
elif cap == 'R' and x == 7:
|
||||
color = 2 # right border
|
||||
|
||||
img.putpixel((x_off + x, y), color)
|
||||
|
||||
# Also fill bottom 8 rows with transparent color 0
|
||||
for y in range(8, 16):
|
||||
for x in range(104):
|
||||
img.putpixel((x, y), 0)
|
||||
|
||||
for i in range(9):
|
||||
draw_sprite_bar_tile(i * 8, i)
|
||||
|
||||
draw_sprite_bar_tile(9 * 8, 0, 'L')
|
||||
draw_sprite_bar_tile(10 * 8, 0, 'R')
|
||||
draw_sprite_bar_tile(11 * 8, 8, 'L')
|
||||
draw_sprite_bar_tile(12 * 8, 8, 'R')
|
||||
|
||||
img.save("stamina.png")
|
||||
|
||||
# Grids for player frames
|
||||
# 0 = White, 1 = Light Gray, 2 = Dark Gray, 3 = Black
|
||||
|
||||
# Down-Right Stand (Frame 0)
|
||||
GRID_DR_STAND = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032321111232300",
|
||||
"0032311211232300",
|
||||
"0032311311332300",
|
||||
"0032311111132300",
|
||||
"0032311333332300",
|
||||
"0003331111333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000323003230000",
|
||||
"0003333003333000",
|
||||
"0003333003333000"
|
||||
]
|
||||
|
||||
# Down-Right Walk (Frame 1)
|
||||
GRID_DR_WALK = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032321111232300",
|
||||
"0032311211232300",
|
||||
"0032311311332300",
|
||||
"0032311111132300",
|
||||
"0032311333332300",
|
||||
"0003331111333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000320002300000",
|
||||
"0003330033300000",
|
||||
"0003330033300000"
|
||||
]
|
||||
|
||||
# Up-Right Stand (Frame 4 in final list)
|
||||
GRID_UR_STAND = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0003333333333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000323003230000",
|
||||
"0003333003333000",
|
||||
"0003333003333000"
|
||||
]
|
||||
|
||||
# Up-Right Walk (Frame 5 in final list)
|
||||
GRID_UR_WALK = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0003333333333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000320002300000",
|
||||
"0003330033300000",
|
||||
"0003330033300000"
|
||||
]
|
||||
|
||||
def draw_frame(draw, grid, x_off):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
val = int(grid[y][x])
|
||||
draw.point((x_off + x, y), fill=val)
|
||||
|
||||
def generate_player():
|
||||
# 8 frames in total (128x16 pixels)
|
||||
player_img = Image.new("P", (128, 16), 0)
|
||||
player_img.putpalette(PALETTE)
|
||||
|
||||
dr_stand = Image.new("P", (16, 16), 0)
|
||||
dr_stand.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(dr_stand), GRID_DR_STAND, 0)
|
||||
|
||||
dr_walk = Image.new("P", (16, 16), 0)
|
||||
dr_walk.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(dr_walk), GRID_DR_WALK, 0)
|
||||
|
||||
ur_stand = Image.new("P", (16, 16), 0)
|
||||
ur_stand.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(ur_stand), GRID_UR_STAND, 0)
|
||||
|
||||
ur_walk = Image.new("P", (16, 16), 0)
|
||||
ur_walk.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(ur_walk), GRID_UR_WALK, 0)
|
||||
|
||||
dl_stand = dr_stand.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
dl_walk = dr_walk.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_stand = ur_stand.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_walk = ur_walk.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
|
||||
player_img.paste(dr_stand, (0 * 16, 0))
|
||||
player_img.paste(dr_walk, (1 * 16, 0))
|
||||
player_img.paste(dl_stand, (2 * 16, 0))
|
||||
player_img.paste(dl_walk, (3 * 16, 0))
|
||||
player_img.paste(ul_stand, (4 * 16, 0))
|
||||
player_img.paste(ul_walk, (5 * 16, 0))
|
||||
player_img.paste(ur_stand, (6 * 16, 0))
|
||||
player_img.paste(ur_walk, (7 * 16, 0))
|
||||
|
||||
player_img.save("player.png")
|
||||
|
||||
def generate_gameover():
|
||||
# 80x16 pixels
|
||||
img = Image.new("P", (80, 16), 3)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
# We can design each letter on an 8x16 grid
|
||||
# Let's specify the pixel grids (16 rows of 8 chars)
|
||||
# 0: White (text body), 2: Dark Gray (text outline/shadow), 3: Black (background)
|
||||
grids = {
|
||||
'G': [
|
||||
"33322223",
|
||||
"33200002",
|
||||
"32002222",
|
||||
"32023333",
|
||||
"32023222",
|
||||
"32023202",
|
||||
"32002202",
|
||||
"33200002",
|
||||
"33322223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'A': [
|
||||
"33322333",
|
||||
"33200233",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32233223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'M': [
|
||||
"32233223",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32233223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'E': [
|
||||
"32222223",
|
||||
"32000002",
|
||||
"32022222",
|
||||
"32000023",
|
||||
"32022222",
|
||||
"32023333",
|
||||
"32000002",
|
||||
"32222223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
' ': [
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'O': [
|
||||
"33222233",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"33222233",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'V': [
|
||||
"32233223",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"33200233",
|
||||
"33322333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'R': [
|
||||
"32222233",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32000233",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32233223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
]
|
||||
}
|
||||
|
||||
text = "GAME OVER"
|
||||
for i, char in enumerate(text):
|
||||
grid = grids[char]
|
||||
for y in range(16):
|
||||
for x in range(8):
|
||||
val = int(grid[y][x])
|
||||
target_x = i * 8 + x + 4
|
||||
target_y = y + 3
|
||||
if target_x < 80 and target_y < 16:
|
||||
img.putpixel((target_x, target_y), val)
|
||||
|
||||
img.save("gameover.png")
|
||||
|
||||
def generate_victory():
|
||||
img = Image.new("P", (56, 16), 3)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
grids = {
|
||||
'V': [
|
||||
"32223222",
|
||||
"32023202",
|
||||
"32023202",
|
||||
"32023202",
|
||||
"33202023",
|
||||
"33200023",
|
||||
"33320233",
|
||||
"33332333"
|
||||
],
|
||||
'I': [
|
||||
"33222233",
|
||||
"33200233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33200233",
|
||||
"33222233"
|
||||
],
|
||||
'C': [
|
||||
"33222233",
|
||||
"32000023",
|
||||
"32022233",
|
||||
"32023333",
|
||||
"32023333",
|
||||
"32022233",
|
||||
"32000023",
|
||||
"33222233"
|
||||
],
|
||||
'T': [
|
||||
"32222223",
|
||||
"32000002",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33322233"
|
||||
],
|
||||
'O': [
|
||||
"33222233",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"33222233"
|
||||
],
|
||||
'R': [
|
||||
"32222233",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32023023",
|
||||
"32023023",
|
||||
"32233223"
|
||||
],
|
||||
'Y': [
|
||||
"32233223",
|
||||
"32023202",
|
||||
"33202023",
|
||||
"33200023",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33320233",
|
||||
"33322233"
|
||||
]
|
||||
}
|
||||
|
||||
text = "VICTORY"
|
||||
for i, char in enumerate(text):
|
||||
grid = grids[char]
|
||||
for y in range(8):
|
||||
for x in range(8):
|
||||
val = int(grid[y][x])
|
||||
target_x = i * 8 + x
|
||||
target_y = y + 4
|
||||
if target_x < 56 and target_y < 16:
|
||||
img.putpixel((target_x, target_y), val)
|
||||
|
||||
img.save("victory.png")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_tiles()
|
||||
generate_player()
|
||||
generate_gameover()
|
||||
generate_stamina()
|
||||
generate_victory()
|
||||
print("PNG assets generated (tiles, player, gameover, stamina, victory).")
|
||||
@@ -0,0 +1,118 @@
|
||||
import numpy as np
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Game Boy Hardware Colors (Green Palette)
|
||||
PALETTE = [
|
||||
224, 248, 207, # 0
|
||||
134, 192, 108, # 1
|
||||
48, 104, 80, # 2
|
||||
7, 24, 33 # 3
|
||||
] + [0] * (256 * 3 - 12)
|
||||
|
||||
# Scarier diagonal ghost
|
||||
GHOST_DR_STAND = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003113113130000",
|
||||
"0003112221130000",
|
||||
"0031113331130000",
|
||||
"0032111211133000",
|
||||
"0003211111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000321330000000",
|
||||
"0000033000000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_DR_WALK = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003113113130000",
|
||||
"0003112221130000",
|
||||
"0003113331130000",
|
||||
"0032111211133000",
|
||||
"0032211111111300",
|
||||
"0003221111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000003213000000",
|
||||
"0000000330000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_UR_STAND = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003211111133000",
|
||||
"0000321111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000321330000000",
|
||||
"0000033000000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_UR_WALK = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003211111133000",
|
||||
"0000321111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000003213000000",
|
||||
"0000000330000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
def draw_frame(draw, grid, x_off):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
val = int(grid[y][x])
|
||||
draw.point((x_off + x, y), fill=val)
|
||||
|
||||
ghost_img = Image.new("P", (128, 16), 0)
|
||||
ghost_img.putpalette(PALETTE)
|
||||
|
||||
dr_s = Image.new("P", (16, 16), 0); dr_s.putpalette(PALETTE); draw_frame(ImageDraw.Draw(dr_s), GHOST_DR_STAND, 0)
|
||||
dr_w = Image.new("P", (16, 16), 0); dr_w.putpalette(PALETTE); draw_frame(ImageDraw.Draw(dr_w), GHOST_DR_WALK, 0)
|
||||
ur_s = Image.new("P", (16, 16), 0); ur_s.putpalette(PALETTE); draw_frame(ImageDraw.Draw(ur_s), GHOST_UR_STAND, 0)
|
||||
ur_w = Image.new("P", (16, 16), 0); ur_w.putpalette(PALETTE); draw_frame(ImageDraw.Draw(ur_w), GHOST_UR_WALK, 0)
|
||||
|
||||
dl_s = dr_s.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
dl_w = dr_w.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_s = ur_s.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_w = ur_w.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
|
||||
ghost_img.paste(dr_s, (0 * 16, 0))
|
||||
ghost_img.paste(dr_w, (1 * 16, 0))
|
||||
ghost_img.paste(dl_s, (2 * 16, 0))
|
||||
ghost_img.paste(dl_w, (3 * 16, 0))
|
||||
ghost_img.paste(ul_s, (4 * 16, 0))
|
||||
ghost_img.paste(ul_w, (5 * 16, 0))
|
||||
ghost_img.paste(ur_s, (6 * 16, 0))
|
||||
ghost_img.paste(ur_w, (7 * 16, 0))
|
||||
|
||||
ghost_img.save('enemy.png')
|
||||
print("Saved enemy.png")
|
||||
@@ -0,0 +1,128 @@
|
||||
import numpy as np
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Game Boy Hardware Colors (Green Palette)
|
||||
C0 = (224, 248, 207, 255)
|
||||
C1 = (134, 192, 108, 255)
|
||||
C2 = (48, 104, 80, 255)
|
||||
C3 = (7, 24, 33, 255)
|
||||
TR = (224, 248, 207, 0) # Transparent
|
||||
|
||||
# Scarier diagonal ghost
|
||||
# Down-Right Stand
|
||||
GHOST_DR_STAND = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003113113130000",
|
||||
"0003112221130000",
|
||||
"0031113331130000",
|
||||
"0032111211133000",
|
||||
"0003211111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000321330000000",
|
||||
"0000033000000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_DR_WALK = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003113113130000",
|
||||
"0003112221130000",
|
||||
"0003113331130000",
|
||||
"0032111211133000",
|
||||
"0032211111111300",
|
||||
"0003221111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000003213000000",
|
||||
"0000000330000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_UR_STAND = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003211111133000",
|
||||
"0000321111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000321330000000",
|
||||
"0000033000000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_UR_WALK = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003211111133000",
|
||||
"0000321111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000003213000000",
|
||||
"0000000330000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
def draw_frame(draw, grid, x_off):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
val = int(grid[y][x])
|
||||
draw.point((x_off + x, y), fill=val)
|
||||
|
||||
ghost_img = Image.new("P", (128, 16), 0)
|
||||
PALETTE = [C0[0], C0[1], C0[2], C1[0], C1[1], C1[2], C2[0], C2[1], C2[2], C3[0], C3[1], C3[2]] + [0]*756
|
||||
ghost_img.putpalette(PALETTE)
|
||||
|
||||
dr_s = Image.new("P", (16, 16), 0); draw_frame(ImageDraw.Draw(dr_s), GHOST_DR_STAND, 0)
|
||||
dr_w = Image.new("P", (16, 16), 0); draw_frame(ImageDraw.Draw(dr_w), GHOST_DR_WALK, 0)
|
||||
ur_s = Image.new("P", (16, 16), 0); draw_frame(ImageDraw.Draw(ur_s), GHOST_UR_STAND, 0)
|
||||
ur_w = Image.new("P", (16, 16), 0); draw_frame(ImageDraw.Draw(ur_w), GHOST_UR_WALK, 0)
|
||||
|
||||
dl_s = dr_s.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
dl_w = dr_w.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_s = ur_s.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_w = ur_w.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
|
||||
ghost_img.paste(dr_s, (0 * 16, 0))
|
||||
ghost_img.paste(dr_w, (1 * 16, 0))
|
||||
ghost_img.paste(dl_s, (2 * 16, 0))
|
||||
ghost_img.paste(dl_w, (3 * 16, 0))
|
||||
ghost_img.paste(ul_s, (4 * 16, 0))
|
||||
ghost_img.paste(ul_w, (5 * 16, 0))
|
||||
ghost_img.paste(ur_s, (6 * 16, 0))
|
||||
ghost_img.paste(ur_w, (7 * 16, 0))
|
||||
|
||||
# Resize by 4x for easier previewing
|
||||
ghost_preview = Image.new('RGBA', ghost_img.size)
|
||||
preview_palette = [TR, C1, C2, C3]
|
||||
for y in range(ghost_img.size[1]):
|
||||
for x in range(ghost_img.size[0]):
|
||||
p = ghost_img.getpixel((x, y))
|
||||
ghost_preview.putpixel((x, y), preview_palette[p])
|
||||
|
||||
ghost_preview = ghost_preview.resize((128*4, 16*4), Image.Resampling.NEAREST)
|
||||
ghost_preview.save('ghost_enemy.png')
|
||||
print("Saved scary diagonal ghost_enemy.png")
|
||||
@@ -0,0 +1,44 @@
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
palette = [
|
||||
(224, 248, 207, 0), # 0: Transparent (alpha 0, but Game Boy color 0)
|
||||
(134, 192, 108, 255), # 1: Light
|
||||
(48, 104, 80, 255), # 2: Dark
|
||||
(7, 24, 33, 255) # 3: Black
|
||||
]
|
||||
|
||||
sprite = [
|
||||
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], # 00
|
||||
[0,0,0,3,1,3,0,0,0,0,0,0,0,0,0,0], # 01 flame tip
|
||||
[0,0,3,1,2,1,3,0,0,3,3,3,3,3,0,0], # 02 flame / head top
|
||||
[0,0,3,1,2,1,3,0,3,2,2,2,2,2,3,0], # 03 flame / hood
|
||||
[0,0,0,3,1,3,0,0,3,1,1,1,1,1,3,0], # 04 flame base / face top
|
||||
[0,0,0,3,2,3,0,0,3,1,3,1,3,1,3,0], # 05 stick / scared eyes (wide)
|
||||
[0,0,0,3,2,3,0,0,3,1,1,3,1,1,3,0], # 06 stick / scared open mouth
|
||||
[0,0,0,3,2,3,0,0,0,3,1,1,1,3,0,0], # 07 stick / chin
|
||||
[0,0,0,3,2,3,0,0,3,2,2,2,2,2,3,0], # 08 stick / shoulders
|
||||
[0,0,3,1,1,1,3,3,2,2,2,2,2,3,0,0], # 09 hand holding stick / body
|
||||
[0,0,0,3,3,3,0,3,2,2,2,2,2,3,1,3], # 10 hand bottom / body / right hand
|
||||
[0,0,0,0,0,0,0,0,3,2,2,2,2,3,3,3], # 11 body lower
|
||||
[0,0,0,0,0,0,0,0,3,2,3,0,3,2,3,0], # 12 legs
|
||||
[0,0,0,0,0,0,0,0,3,2,3,0,3,2,3,0], # 13 legs
|
||||
[0,0,0,0,0,0,0,3,3,2,3,0,3,2,3,3], # 14 shoes
|
||||
[0,0,0,0,0,0,0,3,3,3,0,0,0,3,3,3], # 15 shoes bottom
|
||||
]
|
||||
|
||||
img = Image.new('RGBA', (16, 16))
|
||||
pixels = img.load()
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
pixels[x, y] = palette[sprite[y][x]]
|
||||
|
||||
# Save 16x16 with transparency (for the actual asset generation)
|
||||
img.save('peasant_16x16.png')
|
||||
|
||||
# Upscale for preview
|
||||
preview = img.resize((160, 160), Image.Resampling.NEAREST)
|
||||
bg = Image.new('RGBA', (160, 160), (224, 248, 207, 255))
|
||||
bg.paste(preview, (0,0), preview)
|
||||
bg.save('peasant_preview.png')
|
||||
print("Generated peasant_16x16.png and peasant_preview.png")
|
||||
@@ -0,0 +1,65 @@
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
palette = [
|
||||
(224, 248, 207, 0), # 0: Transparent
|
||||
(134, 192, 108, 255), # 1: Light (Skin)
|
||||
(48, 104, 80, 255), # 2: Dark (Clothes/Hood)
|
||||
(7, 24, 33, 255) # 3: Black (Outlines/Eyes)
|
||||
]
|
||||
|
||||
sprite = [
|
||||
[0,0,0,0, 3,3,3,3,3,3,3,3, 0,0,0,0], # 00 hat top
|
||||
[0,0,0,3, 2,2,2,2,2,2,2,2, 3,0,0,0], # 01 hat
|
||||
[0,0,3,2, 2,3,3,3,3,3,3,2, 2,3,0,0], # 02 hat brim
|
||||
[0,0,3,2, 3,2,1,1,1,1,2,3, 2,3,0,0], # 03 eyebrows outer
|
||||
[0,0,3,2, 3,1,2,1,1,2,1,3, 2,3,0,0], # 04 eyebrows inner
|
||||
[0,0,3,2, 3,1,3,1,1,3,1,3, 2,3,0,0], # 05 eyes
|
||||
[0,0,3,2, 3,1,1,3,3,1,1,3, 2,3,0,0], # 06 mouth
|
||||
[0,0,3,2, 3,1,1,3,3,1,1,3, 2,3,0,0], # 07 mouth
|
||||
[0,0,0,3, 3,3,1,1,1,1,3,3, 3,0,0,0], # 08 chin
|
||||
[0,0,3,2, 2,3,3,3,3,3,3,2, 2,3,0,0], # 09 shoulders
|
||||
[0,0,3,2, 2,3,1,1,1,1,3,2, 2,3,0,0], # 10 hands clasped
|
||||
[0,0,3,2, 2,3,3,3,3,3,3,2, 2,3,0,0], # 11 belt/lower arms
|
||||
[0,0,3,2, 2,2,2,2,2,2,2,2, 2,3,0,0], # 12 tunic
|
||||
[0,0,0,3, 2,2,2,3,3,2,2,2, 3,0,0,0], # 13 tunic split
|
||||
[0,0,0,0, 3,2,3,0,0,3,2,3, 0,0,0,0], # 14 legs
|
||||
[0,0,0,3, 3,3,3,0,0,3,3,3, 3,0,0,0], # 15 shoes
|
||||
]
|
||||
|
||||
# We need to replace the first frame of player.png which is 128x16
|
||||
# We will create a new 128x16 image, paste this frame into the first slot
|
||||
# For now, we just copy this frame 8 times so the animation doesn't break,
|
||||
# although we only designed the first frame.
|
||||
img_sheet = Image.new('P', (128, 16))
|
||||
# Create palette flat array
|
||||
flat_palette = []
|
||||
for p in palette:
|
||||
flat_palette.extend([p[0], p[1], p[2]])
|
||||
# Pad palette to 256 colors
|
||||
flat_palette.extend([0] * (768 - len(flat_palette)))
|
||||
img_sheet.putpalette(flat_palette)
|
||||
|
||||
pixels = img_sheet.load()
|
||||
|
||||
for frame in range(8):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
pixels[x + frame*16, y] = sprite[y][x]
|
||||
|
||||
# Save the game asset
|
||||
img_sheet.save('player.png', transparency=0)
|
||||
|
||||
# Save the preview
|
||||
preview = Image.new('RGBA', (16, 16))
|
||||
p_pixels = preview.load()
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
p_pixels[x, y] = palette[sprite[y][x]]
|
||||
|
||||
preview = preview.resize((160, 160), Image.Resampling.NEAREST)
|
||||
bg = Image.new('RGBA', (160, 160), (224, 248, 207, 255))
|
||||
bg.paste(preview, (0,0), preview)
|
||||
bg.save('peasant_preview2.png')
|
||||
|
||||
print("Generated player.png and peasant_preview2.png")
|
||||
@@ -0,0 +1,55 @@
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
palette = [
|
||||
(224, 248, 207, 0), # 0: Transparent
|
||||
(134, 192, 108, 255), # 1: Light (Skin)
|
||||
(48, 104, 80, 255), # 2: Dark (Clothes/Hood)
|
||||
(7, 24, 33, 255) # 3: Black (Outlines/Eyes)
|
||||
]
|
||||
|
||||
sprite = [
|
||||
[0,0,0,0, 3,3,3,3,3,3,3,3, 0,0,0,0], # 00 hat top
|
||||
[0,0,0,3, 2,2,2,2,2,2,2,2, 3,0,0,0], # 01 hat
|
||||
[0,0,3,2, 2,3,3,3,3,3,3,2, 2,3,0,0], # 02 hat brim
|
||||
[0,0,3,2, 3,2,1,1,1,1,2,3, 2,3,0,0], # 03 eyebrows outer
|
||||
[0,0,3,2, 3,1,2,1,1,2,1,3, 2,3,0,0], # 04 eyebrows inner
|
||||
[0,0,3,2, 3,1,3,1,1,3,1,3, 2,3,0,0], # 05 eyes
|
||||
[0,0,3,2, 3,1,1,1,1,1,1,3, 2,3,0,0], # 06 cheeks
|
||||
[0,0,3,2, 3,1,3,3,3,3,1,3, 2,3,0,0], # 07 mouth (tense)
|
||||
[0,0,0,3, 3,3,1,1,1,1,3,3, 3,0,0,0], # 08 chin
|
||||
[0,0,3,2, 3,3,3,3,3,3,3,3, 2,3,0,0], # 09 shoulders/neck
|
||||
[0,0,3,2, 3,2,2,2,2,2,2,3, 2,3,0,0], # 10 arms/body
|
||||
[0,0,3,1, 3,2,2,2,2,2,2,3, 1,3,0,0], # 11 hands/body
|
||||
[0,0,3,3, 3,3,2,2,2,2,3,3, 3,3,0,0], # 12 hands bottom / tunic
|
||||
[0,0,0,0, 3,2,3,0,0,3,2,3, 0,0,0,0], # 13 legs
|
||||
[0,0,0,3, 3,3,3,0,0,3,3,3, 3,0,0,0], # 14 shoes
|
||||
[0,0,0,3, 3,3,3,0,0,3,3,3, 3,0,0,0], # 15 shoes
|
||||
]
|
||||
|
||||
img_sheet = Image.new('P', (128, 16))
|
||||
flat_palette = []
|
||||
for p in palette:
|
||||
flat_palette.extend([p[0], p[1], p[2]])
|
||||
flat_palette.extend([0] * (768 - len(flat_palette)))
|
||||
img_sheet.putpalette(flat_palette)
|
||||
pixels = img_sheet.load()
|
||||
|
||||
for frame in range(8):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
pixels[x + frame*16, y] = sprite[y][x]
|
||||
|
||||
img_sheet.save('player.png', transparency=0)
|
||||
|
||||
preview = Image.new('RGBA', (16, 16))
|
||||
p_pixels = preview.load()
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
p_pixels[x, y] = palette[sprite[y][x]]
|
||||
|
||||
preview = preview.resize((160, 160), Image.Resampling.NEAREST)
|
||||
bg = Image.new('RGBA', (160, 160), (224, 248, 207, 255))
|
||||
bg.paste(preview, (0,0), preview)
|
||||
bg.save('peasant_preview3.png')
|
||||
print("Generated peasant_preview3.png")
|
||||
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Standard Game Boy palette
|
||||
# 0: White, 1: Light Gray, 2: Dark Gray, 3: Black
|
||||
PALETTE = [
|
||||
224, 248, 207, # 0
|
||||
134, 192, 108, # 1
|
||||
48, 104, 80, # 2
|
||||
7, 24, 33 # 3
|
||||
] + [0] * (256 * 3 - 12)
|
||||
|
||||
stairs_pattern = [
|
||||
"00000000000000033000000000000000",
|
||||
"00000000000003311330000000000000",
|
||||
"00000000000331111113300000000000",
|
||||
"00000000000003311330000000000000",
|
||||
"00000000000000033000000000000000",
|
||||
"00000000000003300330000000000000",
|
||||
"00000000000330000003300000000000",
|
||||
"00000000000003300330000000000000",
|
||||
"00000000000000033000000000000000",
|
||||
"00000000000003311330000000000000",
|
||||
"00000000000331111113300000000000",
|
||||
"00000000000003311330000000000000",
|
||||
"00000000000000033000000000000000",
|
||||
"00000000000003300330000000000000",
|
||||
"00000000000330000003300000000000",
|
||||
"00000000000003300330000000000000",
|
||||
]
|
||||
|
||||
def generate_stairs_sprite():
|
||||
img = Image.new("P", (32, 16), 0)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
for py in range(16):
|
||||
for px in range(32):
|
||||
char = stairs_pattern[py][px]
|
||||
if char != '0':
|
||||
img.putpixel((px, py), int(char))
|
||||
|
||||
img.save("stairs_sprite.png")
|
||||
print("stairs_sprite.png generated.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_stairs_sprite()
|
||||
@@ -0,0 +1,141 @@
|
||||
import sys
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
PALETTE = [
|
||||
224, 248, 207, # 0
|
||||
134, 192, 108, # 1
|
||||
48, 104, 80, # 2
|
||||
7, 24, 33 # 3
|
||||
] + [0] * (256 * 3 - 12)
|
||||
|
||||
def generate_victory():
|
||||
# 64x16 pixels
|
||||
img = Image.new("P", (64, 16), 3)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
grids = {
|
||||
'V': [
|
||||
"32233223",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"33200233",
|
||||
"33322333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'I': [
|
||||
"33322333",
|
||||
"33322333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33322333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'T': [
|
||||
"32222223",
|
||||
"32000002",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33300333",
|
||||
"33322333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'O': [
|
||||
"33222233",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"33222233",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'R': [
|
||||
"32222233",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32000233",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32233223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
],
|
||||
'A': [
|
||||
"33322333",
|
||||
"33200233",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32000023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32022023",
|
||||
"32233223",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333",
|
||||
"33333333"
|
||||
]
|
||||
}
|
||||
|
||||
text = "VITTORIA"
|
||||
for i, char in enumerate(text):
|
||||
grid = grids[char]
|
||||
for y in range(16):
|
||||
for x in range(8):
|
||||
val = int(grid[y][x])
|
||||
target_x = i * 8 + x
|
||||
target_y = y
|
||||
if target_x < 64 and target_y < 16:
|
||||
img.putpixel((target_x, target_y), val)
|
||||
|
||||
img.save("victory.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_victory()
|
||||
@@ -0,0 +1,56 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
def main():
|
||||
img = cv2.imread('hello_iso_gb.png')
|
||||
if img is None:
|
||||
print("Error: Could not load hello_iso_gb.png")
|
||||
return
|
||||
|
||||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
h, w = gray.shape
|
||||
|
||||
# Create a markup copy of the image
|
||||
markup = img.copy()
|
||||
|
||||
# We want to detect the rendering glitches (black V-shapes or gaps cutting into the floor tiles)
|
||||
# The floor tiles are White (255) and Light Gray (153) with Dark Gray (85) lines.
|
||||
# The empty background is Black (0).
|
||||
# Inside the walkable path, any Black (0) pixel that is surrounded by floor tile colors
|
||||
# represents a cutout glitch.
|
||||
# Let's use morphological operations to find these black cutouts inside the tiles.
|
||||
|
||||
# Threshold to find floor tiles (value > 50, so anything not black)
|
||||
_, floor_mask = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)
|
||||
|
||||
# Invert to find black pixels
|
||||
black_mask = cv2.bitwise_not(floor_mask)
|
||||
|
||||
# Find contours of the black regions
|
||||
contours, _ = cv2.findContours(black_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||||
|
||||
glitch_count = 0
|
||||
for cnt in contours:
|
||||
x, y, rw, rh = cv2.boundingRect(cnt)
|
||||
|
||||
# The screen border is black, so we ignore black regions touching the screen boundaries
|
||||
if x <= 2 or y <= 2 or (x + rw) >= w - 2 or (y + rh) >= h - 2:
|
||||
continue
|
||||
|
||||
# Glitches are small black gaps/triangles. Typically small (e.g. area between 4 and 40 pixels)
|
||||
area = cv2.contourArea(cnt)
|
||||
if 2 <= area <= 50:
|
||||
# Check if it's inside the checkerboard area
|
||||
# (which is roughly centered on the screen)
|
||||
cv2.rectangle(markup, (x, y), (x + rw, y + rh), (0, 0, 255), 1) # Red box
|
||||
glitch_count += 1
|
||||
|
||||
print(f"Detected {glitch_count} rendering glitches (black cutouts/gaps) inside the floor map.")
|
||||
|
||||
# Save the marked-up image to the artifacts directory
|
||||
output_path = '/home/enne2/.gemini/antigravity-ide/brain/dd9e728a-93c4-49f8-90b6-3f72fcc47f04/analyzed_tiles.png'
|
||||
cv2.imwrite(output_path, markup)
|
||||
print(f"Saved analysis markup to: {output_path}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,30 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
def main():
|
||||
img = cv2.imread('hello_iso_gb.png')
|
||||
if img is None:
|
||||
print("Error: Could not load hello_iso_gb.png")
|
||||
return
|
||||
|
||||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
h, w = gray.shape
|
||||
print(f"Image dimensions: {w}x{h}")
|
||||
|
||||
# Print all unique gray values on screen
|
||||
unique_vals = np.unique(gray)
|
||||
print(f"Unique gray values: {unique_vals}")
|
||||
|
||||
# Find all contours in the image
|
||||
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||||
|
||||
print("\nAll non-trivial contours:")
|
||||
for idx, cnt in enumerate(contours):
|
||||
x, y, rw, rh = cv2.boundingRect(cnt)
|
||||
area = cv2.contourArea(cnt)
|
||||
# Filter out screen-sized or tiny noise contours
|
||||
if 4 <= area <= 10000:
|
||||
print(f"Contour {idx}: x={x}, y={y}, w={rw}, h={rh}, area={area}, center=({x + rw/2}, {y + rh/2})")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,43 @@
|
||||
from PIL import Image
|
||||
|
||||
# Open the new cover image
|
||||
img = Image.open('bg.png')
|
||||
|
||||
# Convert to grayscale first to get raw intensity values
|
||||
img_gray = img.convert('L')
|
||||
|
||||
# Create a new indexed image with the exact Game Boy palette mapping
|
||||
# 0 = White, 1 = Light Gray, 2 = Dark Gray, 3 = Black
|
||||
final_img = Image.new('P', img_gray.size)
|
||||
|
||||
# Set the palette
|
||||
palette = [
|
||||
255, 255, 255, # 0: White
|
||||
170, 170, 170, # 1: Light Gray
|
||||
85, 85, 85, # 2: Dark Gray
|
||||
0, 0, 0 # 3: Black
|
||||
]
|
||||
palette += [0] * (256 * 3 - len(palette))
|
||||
final_img.putpalette(palette)
|
||||
|
||||
# Map the grayscale pixels to palette indices (0-3)
|
||||
# Darker pixels get higher indices (closer to 3/Black), lighter get lower indices (closer to 0/White)
|
||||
raw_pixels = list(img_gray.getdata())
|
||||
mapped_pixels = []
|
||||
for p in raw_pixels:
|
||||
if p > 200:
|
||||
mapped_pixels.append(0) # White
|
||||
elif p > 120:
|
||||
mapped_pixels.append(1) # Light Gray
|
||||
elif p > 55:
|
||||
mapped_pixels.append(2) # Dark Gray
|
||||
else:
|
||||
mapped_pixels.append(3) # Black
|
||||
|
||||
final_img.putdata(mapped_pixels)
|
||||
|
||||
# Save the resulting image
|
||||
final_img.save('title_bg.png')
|
||||
print("title_bg.png created successfully with correct color indexing.")
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
from pyboy import PyBoy
|
||||
import sys
|
||||
|
||||
def take_screenshot():
|
||||
# Initialize PyBoy in headless mode to not block or require X11
|
||||
pyboy = PyBoy('hello_iso.gb', window_type="headless")
|
||||
|
||||
# Run for 300 frames to let the PyBoy boot screen finish and the title screen render fully
|
||||
for _ in range(300):
|
||||
pyboy.tick()
|
||||
|
||||
# Take screenshot
|
||||
pyboy.screen.image.save('screenshot.png')
|
||||
print("Screenshot saved to screenshot.png")
|
||||
pyboy.stop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
take_screenshot()
|
||||
@@ -0,0 +1,75 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
from pyboy import PyBoy
|
||||
|
||||
def main():
|
||||
# Load PyBoy with the test gameover ROM
|
||||
pyboy = PyBoy('test_gameover.gb', window='null', cgb=False)
|
||||
|
||||
# Tick for 120 frames to let the game boot and sprites render
|
||||
for _ in range(120):
|
||||
pyboy.tick()
|
||||
|
||||
# Grab screen buffer and convert it to OpenCV format
|
||||
screen_image = pyboy.screen.image
|
||||
# screen_image is a PIL Image. Convert to numpy array (RGB)
|
||||
img_np = np.array(screen_image)
|
||||
# Convert RGB to BGR for OpenCV
|
||||
img_bgr = cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR)
|
||||
# Save the screenshot
|
||||
cv2.imwrite('gameover_rendering.png', img_bgr)
|
||||
print("Screenshot saved to gameover_rendering.png")
|
||||
|
||||
# Analyze alignment using OpenCV
|
||||
gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
|
||||
h, w = gray.shape
|
||||
print(f"Screen size: {w}x{h}")
|
||||
|
||||
# The background is white/light (value 255). The text has black/dark pixels.
|
||||
# We use BINARY_INV to detect dark objects.
|
||||
_, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
|
||||
|
||||
# Find all contours in the thresholded image
|
||||
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||
|
||||
# Find the bounding box of elements in the lower half of the screen (y > 100) where "GAME OVER" is rendered
|
||||
gameover_boxes = []
|
||||
player_boxes = []
|
||||
|
||||
for cnt in contours:
|
||||
x, y, rw, rh = cv2.boundingRect(cnt)
|
||||
if y > 80:
|
||||
gameover_boxes.append((x, y, rw, rh))
|
||||
else:
|
||||
player_boxes.append((x, y, rw, rh))
|
||||
|
||||
# Combine bounding boxes of GAME OVER parts
|
||||
if len(gameover_boxes) > 0:
|
||||
min_x = min(box[0] for box in gameover_boxes)
|
||||
max_x = max(box[0] + box[2] for box in gameover_boxes)
|
||||
min_y = min(box[1] for box in gameover_boxes)
|
||||
max_y = max(box[1] + box[3] for box in gameover_boxes)
|
||||
|
||||
text_width = max_x - min_x
|
||||
text_height = max_y - min_y
|
||||
center_x = min_x + text_width / 2.0
|
||||
|
||||
print("\n--- OpenCV Alignment Verification ---")
|
||||
print(f"GAME OVER text bounding box: x={min_x}, y={min_y}, w={text_width}, h={text_height}")
|
||||
print(f"GAME OVER text horizontal center: {center_x}")
|
||||
print(f"Target screen center: {w / 2.0}")
|
||||
|
||||
# Verify alignment within 2 pixels tolerance
|
||||
offset = abs(center_x - (w / 2.0))
|
||||
print(f"Alignment offset: {offset} pixels")
|
||||
if offset <= 2.0:
|
||||
print("SUCCESS: The GAME OVER text is absolutely aligned (perfectly centered)!")
|
||||
else:
|
||||
print(f"WARNING: The GAME OVER text is off-center by {offset} pixels.")
|
||||
else:
|
||||
print("Error: Could not detect the GAME OVER text in the lower half of the screen.")
|
||||
|
||||
pyboy.stop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,75 @@
|
||||
from pyboy import PyBoy
|
||||
from pyboy.utils import WindowEvent
|
||||
|
||||
def get_symbol_address(symbol_name):
|
||||
try:
|
||||
with open('hello_iso.noi', 'r') as f:
|
||||
for line in f:
|
||||
parts = line.strip().split()
|
||||
if len(parts) >= 3 and parts[0] == 'DEF' and parts[1] == symbol_name:
|
||||
return int(parts[2], 16)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
raise ValueError(f"Symbol {symbol_name} not found in hello_iso.noi")
|
||||
|
||||
def main():
|
||||
pyboy = PyBoy('hello_iso.gb', window='null', cgb=False)
|
||||
# Let the game boot and generate the maze
|
||||
for _ in range(60 * 2):
|
||||
pyboy.tick()
|
||||
|
||||
# Dynamically look up addresses
|
||||
player_lx_addr = get_symbol_address('_player_lx')
|
||||
player_ly_addr = get_symbol_address('_player_ly')
|
||||
maze_addr = get_symbol_address('_maze')
|
||||
|
||||
# Read player position from RAM
|
||||
lx = pyboy.memory[player_lx_addr]
|
||||
ly = pyboy.memory[player_ly_addr]
|
||||
print(f"Initial player coordinates in RAM: lx={lx}, ly={ly}")
|
||||
|
||||
# Read maze array from RAM (7x7 starting at maze_addr)
|
||||
map_size = 7
|
||||
maze = []
|
||||
for y in range(map_size):
|
||||
row = []
|
||||
for x in range(map_size):
|
||||
val = pyboy.memory[maze_addr + y * map_size + x]
|
||||
row.append(val)
|
||||
maze.append(row)
|
||||
|
||||
print("\nMaze layout in RAM (0=wall, 1=path):")
|
||||
for y, row in enumerate(maze):
|
||||
row_str = f"{y:02d}: "
|
||||
for x, val in enumerate(row):
|
||||
if x == lx and y == ly:
|
||||
row_str += "P" # Player
|
||||
else:
|
||||
row_str += str(val)
|
||||
print(row_str)
|
||||
|
||||
# Check neighbors of player
|
||||
print(f"\nPlayer neighbors: Up={maze[ly-1][lx]}, Down={maze[ly+1][lx]}, Left={maze[ly][lx-1]}, Right={maze[ly][lx+1]}")
|
||||
|
||||
# Try pressing Down (Down-Left)
|
||||
print("\nSimulating pressing DOWN...")
|
||||
pyboy.send_input(WindowEvent.PRESS_ARROW_DOWN)
|
||||
pyboy.tick()
|
||||
pyboy.send_input(WindowEvent.RELEASE_ARROW_DOWN)
|
||||
for _ in range(30):
|
||||
pyboy.tick()
|
||||
print(f"Player coordinates after DOWN: lx={pyboy.memory[player_lx_addr]}, ly={pyboy.memory[player_ly_addr]}")
|
||||
|
||||
# Try pressing Right (Down-Right)
|
||||
print("\nSimulating pressing RIGHT...")
|
||||
pyboy.send_input(WindowEvent.PRESS_ARROW_RIGHT)
|
||||
pyboy.tick()
|
||||
pyboy.send_input(WindowEvent.RELEASE_ARROW_RIGHT)
|
||||
for _ in range(30):
|
||||
pyboy.tick()
|
||||
print(f"Player coordinates after RIGHT: lx={pyboy.memory[player_lx_addr]}, ly={pyboy.memory[player_ly_addr]}")
|
||||
|
||||
pyboy.stop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1 @@
|
||||
# Music script generator
|
||||
@@ -0,0 +1,14 @@
|
||||
from pyboy import PyBoy
|
||||
|
||||
def main():
|
||||
pyboy = PyBoy('hello_iso.gb', window='null', cgb=False)
|
||||
# Tick a few frames to let the map render
|
||||
for _ in range(60 * 2):
|
||||
pyboy.tick()
|
||||
|
||||
pyboy.screen.image.save('hello_iso_gb.png')
|
||||
pyboy.stop()
|
||||
print("Screenshot saved to hello_iso_gb.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,78 @@
|
||||
GRID_DR_STAND = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032321111232300",
|
||||
"0032311211232300",
|
||||
"0032311311332300",
|
||||
"0032311111132300",
|
||||
"0032311333332300",
|
||||
"0003331111333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000323003230000",
|
||||
"0003333003333000",
|
||||
"0003333003333000"
|
||||
]
|
||||
|
||||
GRID_DR_WALK = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032321111232300",
|
||||
"0032311211232300",
|
||||
"0032311311332300",
|
||||
"0032311111132300",
|
||||
"0032311333332300",
|
||||
"0003331111333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000320002300000",
|
||||
"0003330033300000",
|
||||
"0003330033300000"
|
||||
]
|
||||
|
||||
GRID_UR_STAND = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0003333333333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000323003230000",
|
||||
"0003333003333000",
|
||||
"0003333003333000"
|
||||
]
|
||||
|
||||
GRID_UR_WALK = [
|
||||
"0000333333330000",
|
||||
"0003222222223000",
|
||||
"0032233333322300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0032222222222300",
|
||||
"0003333333333000",
|
||||
"0032333333332300",
|
||||
"0032322222232300",
|
||||
"0031322222231300",
|
||||
"0033332222333300",
|
||||
"0000320002300000",
|
||||
"0003330033300000",
|
||||
"0003330033300000"
|
||||
]
|
||||
|
||||
import sys
|
||||
print("Done")
|
||||
@@ -0,0 +1,126 @@
|
||||
import os
|
||||
|
||||
with open('generate_assets.py', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
GHOST_GRIDS = """
|
||||
# Ghost Grids
|
||||
GHOST_DR_STAND = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003113113130000",
|
||||
"0003112221130000",
|
||||
"0031113331130000",
|
||||
"0032111211133000",
|
||||
"0003211111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000321330000000",
|
||||
"0000033000000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_DR_WALK = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003113113130000",
|
||||
"0003112221130000",
|
||||
"0003113331130000",
|
||||
"0032111211133000",
|
||||
"0032211111111300",
|
||||
"0003221111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000003213000000",
|
||||
"0000000330000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_UR_STAND = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003211111133000",
|
||||
"0000321111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000321330000000",
|
||||
"0000033000000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
GHOST_UR_WALK = [
|
||||
"0000033333000000",
|
||||
"0000322222300000",
|
||||
"0003211111230000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003111111130000",
|
||||
"0003211111133000",
|
||||
"0000321111111300",
|
||||
"0000322111113000",
|
||||
"0000322111330000",
|
||||
"0000032213000000",
|
||||
"0000032213000000",
|
||||
"0000032113000000",
|
||||
"0000003213000000",
|
||||
"0000000330000000",
|
||||
"0000000000000000"
|
||||
]
|
||||
|
||||
def generate_enemy():
|
||||
img = Image.new("P", (128, 16), 0)
|
||||
img.putpalette(PALETTE)
|
||||
|
||||
dr_s = Image.new("P", (16, 16), 0)
|
||||
dr_s.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(dr_s), GHOST_DR_STAND, 0)
|
||||
|
||||
dr_w = Image.new("P", (16, 16), 0)
|
||||
dr_w.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(dr_w), GHOST_DR_WALK, 0)
|
||||
|
||||
ur_s = Image.new("P", (16, 16), 0)
|
||||
ur_s.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(ur_s), GHOST_UR_STAND, 0)
|
||||
|
||||
ur_w = Image.new("P", (16, 16), 0)
|
||||
ur_w.putpalette(PALETTE)
|
||||
draw_frame(ImageDraw.Draw(ur_w), GHOST_UR_WALK, 0)
|
||||
|
||||
dl_s = dr_s.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
dl_w = dr_w.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_s = ur_s.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
ul_w = ur_w.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
|
||||
img.paste(dr_s, (0 * 16, 0))
|
||||
img.paste(dr_w, (1 * 16, 0))
|
||||
img.paste(dl_s, (2 * 16, 0))
|
||||
img.paste(dl_w, (3 * 16, 0))
|
||||
img.paste(ul_s, (4 * 16, 0))
|
||||
img.paste(ul_w, (5 * 16, 0))
|
||||
img.paste(ur_s, (6 * 16, 0))
|
||||
img.paste(ur_w, (7 * 16, 0))
|
||||
|
||||
img.save("enemy.png")
|
||||
"""
|
||||
|
||||
content = content.replace("def generate_player():", GHOST_GRIDS + "\ndef generate_player():")
|
||||
content = content.replace("generate_player()", "generate_player()\n generate_enemy()")
|
||||
content = content.replace("player, gameover", "player, enemy, gameover")
|
||||
|
||||
with open('generate_assets.py', 'w') as f:
|
||||
f.write(content)
|
||||
Reference in New Issue
Block a user