This demo requires a font file, replace "B612-Regular.ttf" with the font file you have in the same folder.
Created
February 7, 2024 03:23
-
-
Save pathunstrom/9b1e8aa7ed250a69bfa8b66ebb88e731 to your computer and use it in GitHub Desktop.
PyTexas Meetup 02/06/2024 Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
import dataclasses | |
import ppb | |
import ppb.keycodes | |
import ppb.systemslib | |
font = ppb.Font("B612-Regular.ttf", size=120) | |
class ScoringSystem(ppb.systemslib.System): | |
score = 0 | |
high_score = 0 | |
def __init__(self, *, engine: ppb.GameEngine, **kwargs): | |
super().__init__(engine=engine, **kwargs) | |
engine.register(ppb.events.PreRender, self.add_scores) | |
def on_scene_started(self, event: ppb.events.SceneStarted, signal: ppb.Signal): | |
if isinstance(event.scene, Game): | |
self.score = 0 | |
def on_scored(self, event: Scored, signal: ppb.Signal): | |
self.score += event.value | |
if self.score > self.high_score: | |
self.high_score = self.score | |
def add_scores(self, event): | |
event.score = self.score | |
event.high_score = self.high_score | |
@dataclasses.dataclass | |
class Scored: | |
value: int | |
scene: ppb.Scene = None | |
@dataclasses.dataclass | |
class ScoredPreRender: | |
time_delta: float | |
scene: ppb.Scene | |
score: int | |
high_score: int | |
class Player(ppb.Sprite): | |
image = ppb.Triangle(150, 200, 80) | |
position = ppb.Vector(0, -8) | |
intent = ppb.Vector(0, 0) | |
speed = 5 | |
# image = ppb.Image("player.png") | |
def on_update(self, event: ppb.events.Update, signal: ppb.Signal): | |
if self.intent: | |
self.position += self.intent * self.speed * event.time_delta | |
def on_key_pressed(self, event: ppb.events.KeyPressed, signal: ppb.Signal): | |
if event.key is ppb.keycodes.A: | |
self.intent += ppb.directions.Left | |
elif event.key is ppb.keycodes.D: | |
self.intent += ppb.directions.Right | |
elif event.key is ppb.keycodes.Space: | |
event.scene.add(Bullet(position=self.top_middle), tags=["player_bullets"]) | |
def on_key_released(self, event: ppb.events.KeyReleased, signal: ppb.Signal): | |
if event.key is ppb.keycodes.A: | |
self.intent -= ppb.directions.Left | |
elif event.key is ppb.keycodes.D: | |
self.intent -= ppb.directions.Right | |
class Target(ppb.Sprite): | |
image = ppb.Circle(200, 20, 60) | |
class Bullet(ppb.Sprite): | |
image = ppb.Triangle(150, 190, 220) | |
size = 0.35 | |
intent = ppb.directions.Up | |
speed = 10 | |
def on_update(self, event: ppb.events.Update, signal: ppb.Signal): | |
if self.intent: | |
self.position += self.intent * self.speed * event.time_delta | |
for target in event.scene.get(kind=Target): | |
delta: ppb.Vector = target.position - self.position | |
distance = delta.length | |
combined_radii = (self.size + target.size) / 2 | |
if distance <= combined_radii: | |
event.scene.remove(self) | |
event.scene.remove(target) | |
signal(Scored(10)) | |
break | |
class ScorePanel(ppb.Sprite): | |
layer = 100 | |
color = (200, 200, 200) | |
text_template = "Score: {score}" | |
def on_pre_render(self, event: ScoredPreRender, signal: ppb.Signal): | |
context = { | |
"score": event.score, | |
"high_score": event.high_score | |
} | |
self.image = ppb.Text(self.text_template.format(**context), font=font, color=self.color) | |
class Game(ppb.Scene): | |
background_color = (25, 25, 25) | |
def on_update(self, event: ppb.events.Update, signal: ppb.Signal): | |
if not any(self.get(kind=Target)): | |
signal(ppb.events.StopScene()) | |
class Title(ppb.Scene): | |
background_color = (161, 102, 204) | |
def __init__(self, **kwargs): | |
super().__init__(**kwargs) | |
self.add( | |
ppb.Sprite( | |
image=ppb.Text("Our Cool Game", font=font, color=(25, 75, 25)), | |
size=3, | |
position=ppb.Vector(0, 6) | |
) | |
) | |
self.add(ScorePanel(text_template="High Score: {high_score}", color=(25, 75, 25))) | |
def on_key_released(self, event: ppb.events.KeyReleased, signal: ppb.Signal): | |
signal(ppb.events.StartScene(Game, {"set_up": setup})) | |
def setup(scene: ppb.Scene): | |
scene.add(Player()) | |
for x in range(-10, 11, 6): | |
scene.add(Target(position=ppb.Vector(x, 7))) | |
scene.add(ScorePanel(position=ppb.Vector(-10.5, 8.5), size=0.75)) | |
scene.add(ScorePanel(text_template="High Score: {high_score}", position=ppb.Vector(9, 8.5), size=0.75)) | |
ppb.run(starting_scene=Title, systems=[ScoringSystem]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment