Load spritesheet

This commit is contained in:
Pyrex 2024-02-26 17:04:37 -08:00
parent d05e382063
commit 79eb52e282
6 changed files with 132 additions and 4 deletions

View File

@ -1,7 +1,23 @@
load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
cc_library(
name = "game",
srcs = glob(["*.c"]),
hdrs = glob(["*.h"]),
srcs = glob(["*.c"]) + [":art/game_demo_sprites.c"],
hdrs = glob(["*.h"]) + [":art/game_demo_sprites.h"],
visibility = ["//visibility:public"],
deps = ["//device:device", "//sys:sys"]
)
run_binary(
name = "game_demo_sprites",
args = [
"game_demo_sprites",
"256", # n sprites
"0", # key color
"$(location :art/game_demo_sprites.png)",
"$(location :art/game_demo_sprites.c)"
],
srcs = [":art/game_demo_sprites.png"],
outs = [":art/game_demo_sprites.c"],
tool = "//pytools:spritesheet",
)

View File

@ -0,0 +1,8 @@
#ifndef CROCPARTY_GAME_DEMO_SPRITES_H
#define CROCPARTY_GAME_DEMO_SPRITES_H
#include "sys/sys.h"
sys_sprite game_demo_sprites[256];
#endif // CROCPARTY_GAME_DEMO_SPRITES_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -9,3 +9,13 @@ py_binary(
],
visibility = ["//visibility:public"],
)
py_binary(
name = "spritesheet",
srcs = ["spritesheet.py", "shared.py"],
deps = [
requirement("pillow"),
requirement("Jinja2"),
],
visibility = ["//visibility:public"],
)

View File

@ -26,7 +26,6 @@ def main(font_name, n_glyphs, fname_png, fname_c):
def load_glyphs(fname_png: str):
width, height, data = shared.load_image(fname_png)
monochrome = [pixel_to_monochrome(p) for p in data]
glyphs = []
for gy in range(0, height, 8):
@ -36,7 +35,7 @@ def load_glyphs(fname_png: str):
for px in range(0, 8):
x = gx + px
y = gy + py
if monochrome[y * width + x]:
if pixel_to_monochrome(data[y * width + x]):
glyph |= 1 << (py * 8 + px)
glyphs.append(glyph)

95
pytools/spritesheet.py Normal file
View File

@ -0,0 +1,95 @@
from typing import Tuple
from PIL import Image
import sys
import shared
TEMPLATE = """
// generated code! be nice!
#include "sys/sys.h"
sys_sprite {{spritesheet_name}}[{{n_sprites}}] = {
{% for sprite in sprites -%}
{ .pixels={
{% for row in sprite -%}
{ {{ row|join(",") }} }{% if not loop.last %},{% endif %}
{% endfor %}
} }{% if not loop.last %},{% endif %}
{%- endfor %}
};
""".lstrip()
def main(spritesheet_name, n_sprites, key_color, fname_png, fname_c):
sprites = load_sprites(fname_png, key_color)
assert(len(sprites) == n_sprites), f"must be exactly {n_sprites} sprites"
with open(fname_c, "wt") as output:
output.write(
shared.templates.from_string(TEMPLATE).render(
spritesheet_name=spritesheet_name,
n_sprites=n_sprites,
sprites=sprites,
)
)
def load_sprites(fname_png: str, key_color: int):
width, height, data = shared.load_image(fname_png)
sprites = []
for gy in range(0, height, 8):
for gx in range(0, width, 8):
pixels = []
for py in range(0, 8):
row = []
for px in range(0, 8):
x = gx + px
y = gy + py
pal = pixel_to_palette(data[y * width + x], key_color, x, y)
row.append(pal)
pixels.append(row)
sprites.append(pixels)
return sprites
palette_colors = {
(0, 0, 0): 0,
(29, 43, 83): 1,
(126, 37, 83): 2,
(0, 135, 81): 3,
(171, 82, 54): 4,
(95, 87, 79): 5,
(194, 195, 199): 6,
(255, 241, 232): 7,
(255, 0, 77): 8,
(255, 163, 0): 9,
(255, 236, 39): 10,
(0, 228, 54): 11,
(41, 173, 255): 12,
(131, 118, 156): 13,
(255, 119, 168): 14,
(255, 204, 170): 15,
}
def pixel_to_palette(rgba, key_color, x, y):
(r, g, b, a) = rgba
if a < 128:
return 255
rgb = (r, g, b)
ix = palette_colors.get(rgb)
if ix is None:
raise ValueError(f"unrecognized color at ({x}, {y}): {rgb}")
if ix == key_color:
return 255
return ix
if __name__ == "__main__":
assert len(sys.argv) == 6, \
"there must be five args (spritesheet name, n sprites, key color, src png, out c)"
main(sys.argv[1], int(sys.argv[2]), int(sys.argv[3]), sys.argv[4], sys.argv[5])