Skip to content

Instantly share code, notes, and snippets.

@EncodeTheCode
Created May 11, 2025 22:29
Show Gist options
  • Save EncodeTheCode/692ed2320ca95b8107d6b1178f86eb4f to your computer and use it in GitHub Desktop.
Save EncodeTheCode/692ed2320ca95b8107d6b1178f86eb4f to your computer and use it in GitHub Desktop.
import pygame
fps = 60
x0 = (0,0,0)
grey = (30,30,30)
res = [(256,224),(256,240),(320,224),(320,240),(352,240),(368,240),(384,224),(384,240),(512,224),(512,240),(640,224),(640,240),(320,480),(640,480),(800,600),(1024,768),(1280,800),(1280,900),(1366,768)]
cur_res = res[18]
class BitmapFont:
def __init__(self, font_image, char_width, char_height):
self.font_image = pygame.image.load(font_image).convert()
self.char_width = char_width
self.char_height = char_height
self.font_image.set_colorkey(x0) # Transparency for black
self.char_map = self.build_char_map()
self.character_images = self.extract_characters()
def build_char_map(self):
char_map = {}
for i in range(26): # A-Z
char_map[chr(ord('A') + i)] = i
for i in range(10): # 0–9
char_map[str(i)] = 26 + i
char_map[' '] = 36
char_map['.'] = 37
char_map['!'] = 38
char_map['?'] = 39
char_map[','] = 40
char_map['-'] = 41
char_map['_'] = 42
char_map['('] = 43
char_map[')'] = 44
char_map['['] = 45
char_map[']'] = 46
char_map['@'] = 47
char_map[':'] = 48
char_map[';'] = 49
char_map['*'] = 50
char_map["'"] = 51
char_map['"'] = 52
char_map['1'] = 53
char_map['2'] = 54
char_map['3'] = 55
char_map['4'] = 56
char_map['5'] = 57
char_map['6'] = 58
char_map['7'] = 59
char_map['8'] = 60
char_map['9'] = 61
char_map['0'] = 62
return char_map
def extract_characters(self):
characters = {}
total_slots = max(self.char_map.values()) + 1
for index in range(total_slots):
x = index * self.char_width
rect = pygame.Rect(x, 0, self.char_width, self.char_height)
char_surface = self.font_image.subsurface(rect).copy()
char_surface.set_colorkey(x0)
characters[index] = char_surface
return characters
def render_text(self, text, surface, x, y, letter_spacing=0, color=(255, 255, 255)):
for char in text.upper():
index = self.char_map.get(char)
if index is not None and index in self.character_images:
image = self.character_images[index]
tinted = image.copy()
tinted.fill(color, special_flags=pygame.BLEND_RGB_MULT)
surface.blit(tinted, (x, y))
x += self.char_width + letter_spacing
class TextObject:
def __init__(self, text, x, y, spacing=0, color=(255, 255, 255)):
self.text = text
self.x = x
self.y = y
self.spacing = spacing
self.color = color
class TextGroupManager:
def __init__(self, font_renderer):
self.font_renderer = font_renderer
self.groups = {}
def add_text(self, group_name, text, x, y, spacing=0, color=(255, 255, 255)):
if group_name not in self.groups:
self.groups[group_name] = []
self.groups[group_name].append(TextObject(text, x, y, spacing, color))
def render_all(self, surface):
for group in self.groups.values():
for text_obj in group:
self.font_renderer.render_text(
text_obj.text, surface,
text_obj.x, text_obj.y,
text_obj.spacing,
text_obj.color
)
def delete_group(self, group_name):
if group_name in self.groups:
del self.groups[group_name]
def clear_all(self):
self.groups.clear()
if __name__ == "__main__":
pygame.init()
screen = pygame.display.set_mode(cur_res)
clock = pygame.time.Clock()
# \x30 = 0
# \x31 = 1
# \x32 = 2
# \x33 = 3
# \x34 = 4
# \x35 = 5
# \x36 = 6
# \x37 = 7
# \x38 = 8
# \x39 = Custom Space Character, or Digit 9
# \x2E = .
# \x2C = ,
# \x2A = *
# \x2D = -
# \x21 = !
# \x27 = '
# \x28 = (
# \x29 = )
# \x3A = :
# \x3B = ;
# \x3F = ?
# \x41 = A
# \x42 = B
# \x43 = C
# \x44 = D
# \x45 = E
# \x46 = F
# \x47 = G
# \x48 = H
# \x49 = I
# \x4A = J
# \x4B = K
# \x4C = L
# \x4D = M
# \x4E = N
# \x4F = O
# \x50 = P
# \x51 = Q
# \x52 = R
# \x53 = S
# \x54 = T
# \x55 = U
# \x56 = V
# \x57 = W
# \x58 = X
# \x59 = Y
# \x5A = Z
# \x5B = [
# \x5D = ]
# \x5F = _
# \x61 = A
# \x62 = B
# \x63 = C
# \x64 = D
# \x65 = E
# \x66 = F
# \x67 = G
# \x68 = H
# \x69 = I
# \x6A = J
# \x6B = K
# \x6C = L
# \x6D = M
# \x6E = N
# \x6F = O
# \x70 = P
# \x71 = Q
# \x72 = R
# \x73 = S
# \x74 = T
# \x75 = U
# \x76 = V
# \x77 = W
# \x78 = X
# \x79 = Y
# \x7A = Z
font_renderer = BitmapFont("font_extended_bw.bmp", 30, 30)
manager = TextGroupManager(font_renderer)
manager.add_text("hud", "SCORE 123", 50, 50, spacing=2, color=(255, 255, 0)) # Yellow
manager.add_text("hud", "LEVEL 7", 50, 90, spacing=2, color=(0, 255, 0)) # Green
manager.add_text("notification", "MISSION COMPLETE!", 200, 200, spacing=-15, color=(255, 0, 0)) # Red
running = True
timer = 0
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(x0)
if (pygame.time.get_ticks() // 500) % 2 == 0: # toggle every 500ms
manager.delete_group("notification")
manager.add_text("notification", "MISSION COMPLETE!", 200, 200, spacing=-15, color=(255, 0, 0)) # Red
if (pygame.time.get_ticks() // 1500) % 2 == 0: # toggle every 1500ms
manager.delete_group("notification")
manager.render_all(screen)
pygame.display.flip()
clock.tick(fps)
timer += 1
if timer == 180:
manager.delete_group("notification") # Remove red text after 3 seconds
pygame.quit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment