Skip to content

Commit 8f0f5ef

Browse files
committed
add gameover and play again functionality. add license.
1 parent 6f3542c commit 8f0f5ef

File tree

1 file changed

+135
-74
lines changed
  • Metro/Metro_RP2350_FlappyNyanCat

1 file changed

+135
-74
lines changed

Metro/Metro_RP2350_FlappyNyanCat/code.py

Lines changed: 135 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
13
import random
24
import sys
35
import terminalio
@@ -222,6 +224,16 @@ def recycle_post(self, post):
222224
self.pool.append(post)
223225

224226

227+
class GameOverException(Exception):
228+
"""
229+
Exception that will be raised when the player loses the game.
230+
"""
231+
232+
def __init__(self, msg):
233+
self.msg = msg
234+
super().__init__(self.msg)
235+
236+
225237
# palette of colors for the trail
226238
trail_palette = Palette(10)
227239
# rainbow colors
@@ -326,14 +338,30 @@ def recycle_post(self, post):
326338
nyan_tg.y = 50
327339

328340
# text label for the current score
329-
score_lbl = Label(terminalio.FONT, text="0", color=0xFFFFFF, scale=2)
341+
score_lbl = Label(terminalio.FONT, text="Spacebar", color=0xFFFFFF, scale=2)
330342
# move it to the bottom left corner
331343
score_lbl.anchor_point = (0, 1)
332344
score_lbl.anchored_position = (2, display.height - 2)
333345

334346
# add it to the main_group
335347
main_group.append(score_lbl)
336348

349+
game_over_label = Label(
350+
terminalio.FONT,
351+
text="",
352+
color=0xFFFFFF,
353+
background_color=0x000000,
354+
padding_top=10,
355+
padding_bottom=10,
356+
padding_left=10,
357+
padding_right=10,
358+
)
359+
game_over_label.anchor_point = (0.5, 0.5)
360+
game_over_label.anchored_position = (display.width // 2, display.height // 2)
361+
game_over_label.hidden = True
362+
363+
main_group.append(game_over_label)
364+
337365
# set the main_group to show on the display
338366
display.root_group = main_group
339367

@@ -450,96 +478,129 @@ def shift_post(post):
450478
playing = False
451479

452480
while True:
481+
try:
482+
# if the player hasn't started yet
483+
if not playing:
484+
while True:
485+
# check if any keys were pressed
486+
available = supervisor.runtime.serial_bytes_available
487+
488+
# if one or more keys was pressed
489+
if available:
490+
# read the value
491+
cur_btn_val = sys.stdin.read(available)
492+
else:
493+
cur_btn_val = None
494+
495+
# if spacebar was pressed
496+
if cur_btn_val == " ":
497+
# do the first jump
498+
cat_speed = -JUMP_SPEED
499+
500+
# set playing to true and breakout of the pause loop
501+
playing = True
502+
break
503+
504+
# check if the cat is touching the first post
505+
if first_post.check_collision(nyan_tg):
506+
raise GameOverException(
507+
f"Kitty got distracted by the scratchers post.\nScore: {score}"
508+
)
509+
510+
# check if the cat is touching the second post
511+
if second_post.check_collision(nyan_tg):
512+
raise GameOverException(
513+
f"Kitty got distracted by the scratchers post.\nScore: {score}"
514+
)
515+
516+
# check if any keyboard data is available
517+
available = supervisor.runtime.serial_bytes_available
518+
if available:
519+
# read the data if there is some available
520+
cur_btn_val = sys.stdin.read(available)
521+
else:
522+
cur_btn_val = None
453523

454-
# if the player hasn't started yet
455-
if not playing:
456-
while True:
457-
# check if any keys were pressed
458-
available = supervisor.runtime.serial_bytes_available
524+
# apply gravity to the cat, maxing out at terminal velocity
525+
cat_speed = min(cat_speed + FALL_SPEED, TERMINAL_VELOCITY)
459526

460-
# if one or more keys was pressed
461-
if available:
462-
# read the value
463-
cur_btn_val = sys.stdin.read(available)
464-
else:
465-
cur_btn_val = None
527+
# if there is keyboard data and spacebar was pressed
528+
if cur_btn_val is not None and " " in cur_btn_val:
529+
cat_speed = -JUMP_SPEED
466530

467-
# if spacebar was pressed
468-
if cur_btn_val == " ":
469-
# do the first jump
470-
cat_speed = -JUMP_SPEED
531+
# award a point for each jump
532+
score += 1
533+
elif cur_btn_val is not None and "s" in cur_btn_val:
534+
swap_trail()
535+
# award a point for swapping the trail
536+
score += 1
471537

472-
# set playing to true and breakout of the pause loop
473-
playing = True
474-
break
538+
# move the cat down by cat_speed amount of pixels
539+
nyan_tg.y += cat_speed
475540

476-
# check if the cat is touching the first post
477-
if first_post.check_collision(nyan_tg):
478-
raise KeyboardInterrupt(
479-
f"Kitty got distracted by the scratchers post. Score: {score}"
480-
)
541+
# if the cat has touched the top or bottom edge
542+
if nyan_tg.y > display.height // 2 or nyan_tg.y < 0:
543+
raise GameOverException(f"Kitty wandered away.\nScore: {score}")
481544

482-
# check if the cat is touching the second post
483-
if second_post.check_collision(nyan_tg):
484-
raise KeyboardInterrupt(
485-
f"Kitty got distracted by the scratchers post. Score: {score}"
486-
)
487-
488-
# check if any keyboard data is available
489-
available = supervisor.runtime.serial_bytes_available
490-
if available:
491-
# read the data if there is some available
492-
cur_btn_val = sys.stdin.read(available)
493-
else:
494-
cur_btn_val = None
545+
# current coordinates of the cat
546+
draw_coords = [nyan_tg.x // 2, nyan_tg.y // 2]
495547

496-
# apply gravity to the cat, maxing out at terminal velocity
497-
cat_speed = min(cat_speed + FALL_SPEED, TERMINAL_VELOCITY)
548+
try:
549+
# erase the trail
550+
erase_trail()
551+
except ValueError as exc:
552+
raise GameOverException(f"Kitty wandered away.\nScore: {score}") from exc
498553

499-
# if there is keyboard data and spacebar was pressed
500-
if cur_btn_val is not None and " " in cur_btn_val:
501-
cat_speed = -JUMP_SPEED
554+
# shift the trail coordinates over
555+
shift_trail()
502556

503-
# award a point for each jump
504-
score += 1
505-
elif cur_btn_val is not None and "s" in cur_btn_val:
506-
swap_trail()
507-
# award a point for swapping the trail
508-
score += 1
557+
# add new coordinates to the trail at the cats current location
558+
trail_coords.append(draw_coords)
509559

510-
# move the cat down by cat_speed amount of pixels
511-
nyan_tg.y += cat_speed
560+
# if the trail is at its maximum length
561+
if len(trail_coords) > TRAIL_LENGTH:
562+
# remove the oldest coordinate from the trail coordinates list.
563+
trail_coords.pop(0)
512564

513-
# if the cat has touched the top or bottom edge
514-
if nyan_tg.y > display.height // 2 or nyan_tg.y < 0:
515-
raise KeyboardInterrupt(f"Kitty wandered away. Score: {score}")
565+
# draw the trail
566+
draw_trail()
516567

517-
# current coordinates of the cat
518-
draw_coords = [nyan_tg.x // 2, nyan_tg.y // 2]
568+
# shift the posts over
569+
first_post = shift_post(first_post)
570+
second_post = shift_post(second_post)
519571

520-
# erase the trail
521-
erase_trail()
572+
# update the score label
573+
score_lbl.text = str(score)
522574

523-
# shift the trail coordinates over
524-
shift_trail()
575+
# refresh the display
576+
display.refresh(target_frames_per_second=30)
525577

526-
# add new coordinates to the trail at the cats current location
527-
trail_coords.append(draw_coords)
578+
except GameOverException as e:
579+
# update the game over message
580+
game_over_label.text = str(f"{e.msg}\nPress P to play again\nPress Q to quit")
581+
# make the game over message visible
582+
game_over_label.hidden = False
528583

529-
# if the trail is at its maximum length
530-
if len(trail_coords) > TRAIL_LENGTH:
531-
# remove the oldest coordinate from the trail coordinates list.
532-
trail_coords.pop(0)
584+
# refresh display so the message shows
585+
display.refresh()
586+
break
533587

534-
# draw the trail
535-
draw_trail()
588+
# wait for the player to press a key
589+
while True:
590+
# check if any keys were pressed
591+
available = supervisor.runtime.serial_bytes_available
536592

537-
# shift the posts over
538-
first_post = shift_post(first_post)
539-
second_post = shift_post(second_post)
593+
# if one or more keys was pressed
594+
if available:
595+
# read the value
596+
cur_btn_val = sys.stdin.read(available)
540597

541-
# update the score label
542-
score_lbl.text = str(score)
598+
# if player pressed p
599+
if "p" in cur_btn_val:
600+
supervisor.set_next_code_file(__file__)
601+
supervisor.reload()
543602

544-
# refresh the display
545-
display.refresh(target_frames_per_second=30)
603+
# if player pressed q
604+
elif "q" in cur_btn_val:
605+
print("exiting")
606+
break

0 commit comments

Comments
 (0)