feat(render): hud overlay and audio backend
This commit is contained in:
1 parent
38c53fb531
commit
6d121a9652
2 files changed
+122
No files matched your search
@@ -0,0 +1,71 @@
|
||||
import array
|
||||
import math
|
||||
|
||||
import pygame
|
||||
|
||||
toneTable = {
|
||||
"jump": (660, 90),
|
||||
"doubleJump": (820, 90),
|
||||
"dash": (300, 80),
|
||||
"stomp": (200, 120),
|
||||
"pickup": (900, 70),
|
||||
"hurt": (160, 160),
|
||||
"die": (110, 300),
|
||||
"shoot": (420, 70),
|
||||
"checkpoint": (1040, 120),
|
||||
"levelComplete": (760, 260),
|
||||
"spark": (520, 40),
|
||||
}
|
||||
|
||||
|
||||
def synthTone(frequency, milliseconds, volume=0.25):
|
||||
mixerInfo = pygame.mixer.get_init()
|
||||
if mixerInfo is None:
|
||||
return None
|
||||
sampleRate, _, channels = mixerInfo
|
||||
frames = int(sampleRate * milliseconds / 1000.0)
|
||||
amplitude = int(32767 * volume)
|
||||
samples = array.array("h")
|
||||
for index in range(frames):
|
||||
envelope = 1.0 - index / frames
|
||||
value = int(amplitude * envelope * (1.0 if math.sin(2.0 * math.pi * frequency * index / sampleRate) >= 0 else -1.0))
|
||||
for _ in range(max(1, channels)):
|
||||
samples.append(value)
|
||||
return pygame.mixer.Sound(buffer=samples.tobytes())
|
||||
|
||||
|
||||
class PygameAudio:
|
||||
def __init__(self):
|
||||
self.enabled = False
|
||||
self.sounds = {}
|
||||
try:
|
||||
if pygame.mixer.get_init() is None:
|
||||
pygame.mixer.init()
|
||||
for name, (frequency, duration) in toneTable.items():
|
||||
sound = synthTone(frequency, duration)
|
||||
if sound is not None:
|
||||
self.sounds[name] = sound
|
||||
self.enabled = bool(self.sounds)
|
||||
except pygame.error:
|
||||
self.enabled = False
|
||||
|
||||
def sink(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
sound = self.sounds.get(event.name)
|
||||
if sound is not None:
|
||||
sound.play()
|
||||
|
||||
|
||||
class NullAudio:
|
||||
enabled = False
|
||||
|
||||
def sink(self, event):
|
||||
pass
|
||||
|
||||
|
||||
def buildAudioSink():
|
||||
backend = PygameAudio()
|
||||
if backend.enabled:
|
||||
return backend.sink
|
||||
return NullAudio().sink
|
||||
@@ -0,0 +1,51 @@
|
||||
import pygame
|
||||
|
||||
from .theme import hudTextColor, hudShadowColor, heartFull, heartEmpty
|
||||
|
||||
|
||||
class Hud:
|
||||
def __init__(self):
|
||||
self.font = pygame.font.Font(None, 22)
|
||||
self.bigFont = pygame.font.Font(None, 48)
|
||||
|
||||
def drawText(self, surf, text, pos, color=hudTextColor):
|
||||
shadow = self.font.render(text, True, hudShadowColor)
|
||||
label = self.font.render(text, True, color)
|
||||
surf.blit(shadow, (pos[0] + 1, pos[1] + 1))
|
||||
surf.blit(label, pos)
|
||||
|
||||
def drawCentered(self, surf, text, y, color=hudTextColor):
|
||||
label = self.bigFont.render(text, True, color)
|
||||
shadow = self.bigFont.render(text, True, hudShadowColor)
|
||||
x = (surf.get_width() - label.get_width()) // 2
|
||||
surf.blit(shadow, (x + 2, y + 2))
|
||||
surf.blit(label, (x, y))
|
||||
|
||||
def drawHearts(self, surf, hp, maxHp):
|
||||
for index in range(maxHp):
|
||||
color = heartFull if index < hp else heartEmpty
|
||||
x = 10 + index * 16
|
||||
y = 30
|
||||
pygame.draw.circle(surf, color, (x + 3, y + 3), 3)
|
||||
pygame.draw.circle(surf, color, (x + 8, y + 3), 3)
|
||||
pygame.draw.polygon(surf, color, [(x, y + 4), (x + 11, y + 4), (x + 5, y + 11)])
|
||||
|
||||
def draw(self, surf, world):
|
||||
self.drawText(surf, "SCORE %06d" % world.score, (10, 8))
|
||||
self.drawText(surf, "COINS x%02d" % world.coins, (surf.get_width() - 130, 8))
|
||||
self.drawText(surf, "LIVES %d" % world.lives, (surf.get_width() - 130, 30))
|
||||
self.drawHearts(surf, world.player.hp, world.player.maxHp)
|
||||
|
||||
def drawOverlay(self, surf, mode):
|
||||
veil = pygame.Surface(surf.get_size(), pygame.SRCALPHA)
|
||||
veil.fill((0, 0, 0, 140))
|
||||
surf.blit(veil, (0, 0))
|
||||
messages = {
|
||||
"menu": "PIXEL PLATFORMER",
|
||||
"paused": "PAUSED",
|
||||
"gameover": "GAME OVER",
|
||||
"complete": "LEVEL CLEAR",
|
||||
"victory": "YOU WIN",
|
||||
}
|
||||
self.drawCentered(surf, messages.get(mode, ""), surf.get_height() // 2 - 40)
|
||||
self.drawCentered(surf, "PRESS ENTER", surf.get_height() // 2 + 12)
|
||||
Reference in new issue
Block a user