Load spritesheet
This commit is contained in:
parent
d05e382063
commit
79eb52e282
20
game/BUILD
20
game/BUILD
@ -1,7 +1,23 @@
|
|||||||
|
load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "game",
|
name = "game",
|
||||||
srcs = glob(["*.c"]),
|
srcs = glob(["*.c"]) + [":art/game_demo_sprites.c"],
|
||||||
hdrs = glob(["*.h"]),
|
hdrs = glob(["*.h"]) + [":art/game_demo_sprites.h"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = ["//device:device", "//sys:sys"]
|
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",
|
||||||
|
)
|
8
game/art/game_demo_sprites.h
Normal file
8
game/art/game_demo_sprites.h
Normal 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
|
BIN
game/art/game_demo_sprites.png
Normal file
BIN
game/art/game_demo_sprites.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
@ -9,3 +9,13 @@ py_binary(
|
|||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
py_binary(
|
||||||
|
name = "spritesheet",
|
||||||
|
srcs = ["spritesheet.py", "shared.py"],
|
||||||
|
deps = [
|
||||||
|
requirement("pillow"),
|
||||||
|
requirement("Jinja2"),
|
||||||
|
],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
@ -26,7 +26,6 @@ def main(font_name, n_glyphs, fname_png, fname_c):
|
|||||||
|
|
||||||
def load_glyphs(fname_png: str):
|
def load_glyphs(fname_png: str):
|
||||||
width, height, data = shared.load_image(fname_png)
|
width, height, data = shared.load_image(fname_png)
|
||||||
monochrome = [pixel_to_monochrome(p) for p in data]
|
|
||||||
|
|
||||||
glyphs = []
|
glyphs = []
|
||||||
for gy in range(0, height, 8):
|
for gy in range(0, height, 8):
|
||||||
@ -36,7 +35,7 @@ def load_glyphs(fname_png: str):
|
|||||||
for px in range(0, 8):
|
for px in range(0, 8):
|
||||||
x = gx + px
|
x = gx + px
|
||||||
y = gy + py
|
y = gy + py
|
||||||
if monochrome[y * width + x]:
|
if pixel_to_monochrome(data[y * width + x]):
|
||||||
glyph |= 1 << (py * 8 + px)
|
glyph |= 1 << (py * 8 + px)
|
||||||
glyphs.append(glyph)
|
glyphs.append(glyph)
|
||||||
|
|
||||||
|
95
pytools/spritesheet.py
Normal file
95
pytools/spritesheet.py
Normal 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])
|
Loading…
Reference in New Issue
Block a user