Cosmic Candy Pinball: procedural 8-bit pinball game
Native pygame-ce game with fully procedural pixel art and chiptune audio (no asset files). Pure-logic physics module with flipper angular momentum, plus headless autoplay/screenshot/probe dev tools.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
"""Tiny hand-rolled 5x5 pixel bitmap font, rendered chunky for an 8-bit look."""
|
||||
|
||||
import pygame
|
||||
|
||||
|
||||
GLYPHS = {
|
||||
"A": [".###.", "#...#", "#####", "#...#", "#...#"],
|
||||
"B": ["####.", "#...#", "####.", "#...#", "####."],
|
||||
"C": [".###.", "#....", "#....", "#....", ".###."],
|
||||
"D": ["####.", "#...#", "#...#", "#...#", "####."],
|
||||
"E": ["#####", "#....", "####.", "#....", "#####"],
|
||||
"F": ["#####", "#....", "####.", "#....", "#...."],
|
||||
"G": [".###.", "#....", "#.###", "#...#", ".###."],
|
||||
"H": ["#...#", "#...#", "#####", "#...#", "#...#"],
|
||||
"I": ["#####", "..#..", "..#..", "..#..", "#####"],
|
||||
"J": ["..###", "...#.", "...#.", "#..#.", ".##.."],
|
||||
"K": ["#...#", "#..#.", "###..", "#..#.", "#...#"],
|
||||
"L": ["#....", "#....", "#....", "#....", "#####"],
|
||||
"M": ["#...#", "##.##", "#.#.#", "#...#", "#...#"],
|
||||
"N": ["#...#", "##..#", "#.#.#", "#..##", "#...#"],
|
||||
"O": [".###.", "#...#", "#...#", "#...#", ".###."],
|
||||
"P": ["####.", "#...#", "####.", "#....", "#...."],
|
||||
"Q": [".###.", "#...#", "#...#", "#..#.", ".##.#"],
|
||||
"R": ["####.", "#...#", "####.", "#..#.", "#...#"],
|
||||
"S": [".###.", "#....", ".###.", "....#", "####."],
|
||||
"T": ["#####", "..#..", "..#..", "..#..", "..#.."],
|
||||
"U": ["#...#", "#...#", "#...#", "#...#", ".###."],
|
||||
"V": ["#...#", "#...#", "#...#", ".#.#.", "..#.."],
|
||||
"W": ["#...#", "#...#", "#.#.#", "##.##", "#...#"],
|
||||
"X": ["#...#", ".#.#.", "..#..", ".#.#.", "#...#"],
|
||||
"Y": ["#...#", ".#.#.", "..#..", "..#..", "..#.."],
|
||||
"Z": ["#####", "...#.", "..#..", ".#...", "#####"],
|
||||
"0": [".###.", "#..##", "#.#.#", "##..#", ".###."],
|
||||
"1": ["..#..", ".##..", "..#..", "..#..", ".###."],
|
||||
"2": ["####.", "....#", ".###.", "#....", "#####"],
|
||||
"3": ["####.", "....#", ".###.", "....#", "####."],
|
||||
"4": ["#...#", "#...#", "#####", "....#", "....#"],
|
||||
"5": ["#####", "#....", "####.", "....#", "####."],
|
||||
"6": [".###.", "#....", "####.", "#...#", ".###."],
|
||||
"7": ["#####", "....#", "...#.", "..#..", ".#..."],
|
||||
"8": [".###.", "#...#", ".###.", "#...#", ".###."],
|
||||
"9": [".###.", "#...#", ".####", "....#", ".###."],
|
||||
" ": [".....", ".....", ".....", ".....", "....."],
|
||||
".": [".....", ".....", ".....", "..##.", "..##."],
|
||||
",": [".....", ".....", "..#..", "..#..", ".#..."],
|
||||
"!": ["..#..", "..#..", "..#..", ".....", "..#.."],
|
||||
"?": [".###.", "#...#", "..#..", ".....", "..#.."],
|
||||
"'": ["..#..", "..#..", ".....", ".....", "....."],
|
||||
'"': [".#.#.", ".#.#.", ".....", ".....", "....."],
|
||||
":": [".....", "..#..", ".....", "..#..", "....."],
|
||||
";": [".....", "..#..", ".....", "..#..", ".#..."],
|
||||
"-": [".....", ".....", "#####", ".....", "....."],
|
||||
"+": ["..#..", "..#..", "#####", "..#..", "..#.."],
|
||||
"*": ["#...#", ".#.#.", "..#..", ".#.#.", "#...#"],
|
||||
"/": ["....#", "...#.", "..#..", ".#...", "#...."],
|
||||
"=": [".....", "#####", ".....", "#####", "....."],
|
||||
"<": ["...#.", "..#..", ".#...", "..#..", "...#."],
|
||||
">": [".#...", "..#..", "...#.", "..#..", ".#..."],
|
||||
"(": ["...#.", "..#..", ".#...", "..#..", "...#."],
|
||||
")": [".#...", "..#..", "...#.", "..#..", ".#..."],
|
||||
"~": [".....", ".#.#.", ".#.#.", ".....", "....."],
|
||||
"|": ["..#..", "..#..", "..#..", "..#..", "..#.."],
|
||||
"%": ["##..#", "##.#.", "..#..", ".#.##", "#..##"],
|
||||
"&": [".##..", "#..#.", ".#...", "#.#.#", ".##.#"],
|
||||
"@": [".###.", "#.#.#", "#.###", "#....", ".###."],
|
||||
"#": [".#.#.", "#####", ".#.#.", "#####", ".#.#."],
|
||||
"^": ["..#..", ".#.#.", "#...#", ".....", "....."],
|
||||
"_": [".....", ".....", ".....", ".....", "#####"],
|
||||
}
|
||||
|
||||
_text_cache = {}
|
||||
|
||||
|
||||
def text_width(text, scale=1, spacing=1):
|
||||
if not text:
|
||||
return 0
|
||||
return (len(text) * 5 + (len(text) - 1) * spacing) * scale
|
||||
|
||||
|
||||
def render_text(text, color, scale=1, spacing=1, shadow=None):
|
||||
"""Return a Surface with the pixel text drawn."""
|
||||
key = (text, color, scale, spacing, shadow)
|
||||
if key in _text_cache:
|
||||
return _text_cache[key]
|
||||
w = text_width(text, scale, spacing)
|
||||
h = 5 * scale
|
||||
surf = pygame.Surface((w, h), pygame.SRCALPHA)
|
||||
if shadow is not None:
|
||||
_draw_into(surf, text, shadow, scale, spacing, (scale, scale))
|
||||
_draw_into(surf, text, color, scale, spacing, (0, 0))
|
||||
_text_cache[key] = surf
|
||||
return surf
|
||||
|
||||
|
||||
def _draw_into(surf, text, color, scale, spacing, off):
|
||||
x0 = off[0]
|
||||
for ch in text.upper():
|
||||
g = GLYPHS.get(ch, GLYPHS[" "])
|
||||
for row in range(5):
|
||||
for col in range(5):
|
||||
if g[row][col] == "#":
|
||||
surf.fill(color, (x0 + col * scale, off[1] + row * scale, scale, scale))
|
||||
x0 += (5 + spacing) * scale
|
||||
|
||||
|
||||
def draw_text(surf, x, y, text, color, scale=1, spacing=1, align="left", shadow=(20, 12, 40, 180)):
|
||||
"""Draw text. align in {'left','center','right'}. Shadow color or None."""
|
||||
t = render_text(text, color, scale, spacing, shadow)
|
||||
if align == "center":
|
||||
x -= t.get_width() // 2
|
||||
elif align == "right":
|
||||
x -= t.get_width()
|
||||
surf.blit(t, (round(x), round(y)))
|
||||
return t.get_width(), t.get_height()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user