From 62831ade7947b9027a561bb3eef5f96caf6662fe Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Sat, 29 Jan 2022 17:52:14 -0500 Subject: [PATCH] started using level select object, added preview of animated alien --- NS.py | 101 +++++++++++++++++++++++++++++++++++++++++------------- OPEN-GAME | 40 +++++++-------------- config | 12 +++++++ lib/pgfw | 2 +- 4 files changed, 104 insertions(+), 51 deletions(-) diff --git a/NS.py b/NS.py index 99a823d..b7fd43f 100644 --- a/NS.py +++ b/NS.py @@ -1,5 +1,12 @@ # -*- coding: utf-8 -*- +# +# Scrapeboard is an arcade game in development by Frank DeMarco (@diskmem) and Blake Andrews (@snakesandrews). +# It requires custom hardware to play, but it can be tested in keyboard mode with just the code in this +# repository. For more information on setting up and running the game, see the README. For more information +# on the game in general, visit https://scrape.nugget.fun +# + import argparse from random import randint, choice, random from math import pi @@ -34,6 +41,13 @@ from lib.pgfw.pgfw.extension import ( from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon class NS(Game, Animation): + """ + The main game object for Scrapeboard. It initializes and manages most of the other game objects that only have a single + object like the title screen, boss manager, platform, dialog manager, screen wipe manager, main character, and more (see + the objects initialized in __init__). It initializes and manages the serial input from the Arduino, and it listens for and + responds to keyboard input. Its update method is called once per frame by the PGFW code. In its update method it calls the + update methods of its child objects. + """ LNW, LNE, LSE, LSW = range(4) N, NE, E, NW, S, W = range(6) @@ -130,6 +144,7 @@ class NS(Game, Animation): ds = self.get_display_surface() self.background = Surface(ds.get_size()) self.background.fill((0, 0, 0)) + self.level_select = LevelSelect(self) self.platform = Platform(self) self.tony = Tony(self) self.logo = Logo(self) @@ -202,6 +217,7 @@ class NS(Game, Animation): self.score_hidden = False self.idle_elapsed = 0 self.suppressing_input = False + self.level_select.reset() self.title.reset() if not leave_wipe_running: self.wipe.reset() @@ -276,6 +292,7 @@ class NS(Game, Animation): self.reset_arduino() self.no_reset_elapsed = 0 self.title.update() + self.level_select.update() self.ending.update() self.boss.update() if not self.title.active: @@ -288,6 +305,44 @@ class NS(Game, Animation): self.reset() +class LevelSelect(GameChild): + """ + Display the available levels. Initialize a platform for each level and display each platform beneath its level glowing + with a pair of pads to press to start that level. Wait for user input, then launch the level of the pair that gets + pressed by the user. + """ + + def __init__(self, parent): + GameChild.__init__(self, parent) + self.subscribe(self.respond, KEYDOWN) + + def activate(self): + self.active = True + + def deactivate(self): + self.active = False + + def reset(self): + self.deactivate() + + def respond(self, event): + if self.active: + launch_level = None + if event.key == K_1: + launch_level = 0 + elif event.key == K_2: + launch_level = 1 + elif event.key == K_3: + launch_level = 2 + if launch_level is not None: + self.deactivate() + self.get_game().boss.start_level(launch_level) + + def update(self): + if self.active: + self.get_display_surface().fill((255, 255, 0)) + + class Button(Sprite): MARGIN = 2 @@ -559,9 +614,13 @@ class Title(Animation): self.halt() def start_game(self): + """ + Turn off the title screen and display the level select. Set the most recent time to None so the most + recent high score stops blinking. + """ self.deactivate() self.get_game().set_most_recent_time(None) - self.get_game().boss.start_level(0) + self.get_game().level_select.activate() def draw_scores(self): step = 75 @@ -610,19 +669,18 @@ class Title(Animation): self.get_game().tony.set_frameset("board") def update(self): - ''' - Move title, check button presses, and draw screen - ''' + """ + Scroll the background, check for button presses for the unlock pattern, handle switching between attract mode + with the GIFs active and unlocking pattern mode, and draw the screen + """ Animation.update(self) if self.active: ds = self.get_display_surface() dsr = ds.get_rect() self.get_game().logo.update() - # advance unlock pattern + # Advance through the unlock pattern platform = self.get_game().platform if not self.get_game().wipe.is_playing() and platform.get_edge_pressed() == self.UNLOCK_MOVES[self.unlock_index]: - # self.first_pressed = True - # self.first_pressed_elapsed = 0 if self.unlock_index == len(self.UNLOCK_MOVES) - 1: platform.set_glowing([]) self.get_game().wipe.start(self.start_game) @@ -631,13 +689,8 @@ class Title(Animation): self.unlock_index += 1 platform.set_glowing(platform.get_buttons_from_edges([self.UNLOCK_MOVES[self.unlock_index]])) self.get_audio().play_sfx("land_0") - # reset unlock pattern if idle - # if self.first_pressed: - # self.first_pressed_elapsed += self.get_game().time_filter.get_last_frame_duration() - # if self.first_pressed_elapsed > 1000 * 10: - # self.reset() self.get_game().tony.update() - # bounce the gif around the screen + # Bounce the GIF around the screen if self.video.location.right > dsr.right or self.video.location.left < dsr.left: self.angle = reflect_angle(self.angle, 0) if self.video.location.right > dsr.right: @@ -1159,11 +1212,6 @@ class Light(Animation): shifted = [] for point in self.get_points(): shifted.append((point[0], point[1] - y)) - # ratio = 1 - float(y + 1) / (self.MAX_GLOW_INDEX + 1) - # alpha = int(ratio * 255) - # color = Color(self.color.r, self.color.g, self.color.b, alpha) - # ds = self.get_display_surface() - # intermediate = Surface(ds.get_size(), SRCALPHA) if self.position == NS.LSW: saturation = 0 else: @@ -1179,7 +1227,6 @@ class Light(Animation): ), True, shifted, 3 ) - # ds.blit(intermediate, (0, 0)) def in_orientation(self, orientation): if self.position == NS.LNW: @@ -1346,20 +1393,28 @@ class Boys(Meter): class Boss(Animation): + """ + The Boss object also serves as the level object, and it is expected that only one of these objects is initialized. + Its drawing, animations, timings, etc will be determined by the level_index member variable. For example, if + level_index is 0, the kool man sprite will be drawn, but if level_index is 2, the spoopy sprite will be drawn. + """ def __init__(self, parent): + """ + Load graphics for boss sprites, avatars, and backgrounds. Initialize boss health and swords objects. Register + animations that control attacks, effects, and dialog. + """ Animation.__init__(self, parent) if self.get_configuration("display", "effects"): self.kool_man = RainbowSprite(self, load(self.get_resource("Kool_man_waah.png")).convert_alpha(), hue_shift) - self.visitor = RainbowSprite(self, load(self.get_resource("Visitor.png")).convert_alpha(), hue_shift) self.spoopy = RainbowSprite(self, load(self.get_resource("Spoopy.png")).convert_alpha(), hue_shift) else: self.kool_man = Sprite(self) self.kool_man.load_from_path("Kool_man_waah.png", True) - self.visitor = Sprite(self) - self.visitor.load_from_path("Visitor.png", True) self.spoopy = Sprite(self) self.spoopy.load_from_path("Spoopy.png", True) + self.visitor = Sprite(self, 42) + self.visitor.load_from_path("alienAnimations/alienBoil", True) for sprite in self.kool_man, self.visitor, self.spoopy: sprite.location.topleft = 100, 0 self.health = Health(self) @@ -1367,7 +1422,7 @@ class Boss(Animation): self.register(self.brandish, self.cancel_flash, self.show_introduction_dialogue, self.show_end_dialogue, self.end_dialogue) self.kool_man.add_frameset([0], name="normal", switch=True) - self.visitor.add_frameset([0], name="normal", switch=True) + self.visitor.add_frameset(list(range(0, len(self.visitor.frames))), name="normal", switch=True) self.spoopy.add_frameset([0], name="normal", switch=True) self.kool_man_avatar = load(self.get_resource("Kool_man_avatar.png")).convert() self.visitor_avatar = load(self.get_resource("Visitor_avatar.png")).convert() diff --git a/OPEN-GAME b/OPEN-GAME index edc2ee2..4b828e9 100755 --- a/OPEN-GAME +++ b/OPEN-GAME @@ -1,33 +1,19 @@ #!/usr/bin/env python3 -from os import environ, execvp, chdir, getcwd -from os.path import exists, join, dirname -from sys import version_info, argv +# +# Scrapeboard is an arcade game in development by Frank DeMarco (@diskmem) and Blake Andrews (@snakesandrews). +# It requires custom hardware to play, but it can be tested in keyboard mode with just the code in this +# repository. For more information on setting up and running the game, see the README. For more information +# on the game in general, visit https://scrape.nugget.fun +# +# This is the launcher script that creates a main game object and runs it. If you're running Python 3 with +# the pygame module installed, you should be able to run this script with the --no-serial flag to get it +# running even without the custom hardware: +# +# ./OPEN-GAME --no-serial +# -def can_import(module_name): - try: - __import__(module_name) - except ImportError: - return False - else: - return True - -def is_python_3(): - return version_info[0] >= 3 - -def is_current_version(file_name): - version = map(int, file_name.replace("python", "").split(".")) - return version == list(version_info)[:2] - -def launch_alternative(alternatives): - for alternative in alternatives: - if not is_current_version(alternative): - for root in environ["PATH"].split(":"): - if exists(join(root, alternative)): - execvp(alternative, [alternative] + argv) - -def move_to_executable(): - chdir(dirname(argv[0])) +from sys import argv if "--go-to-dir" in argv: move_to_executable() diff --git a/config b/config index 7dd5013..18a3a7c 100644 --- a/config +++ b/config @@ -1,3 +1,15 @@ +# +# Scrapeboard is an arcade game in development by Frank DeMarco (@diskmem) and Blake Andrews (@snakesandrews). +# It requires custom hardware to play, but it can be tested in keyboard mode with just the code in this +# repository. For more information on setting up and running the game, see the README. For more information +# on the game in general, visit https://scrape.nugget.fun +# +# This file contains configurable values that can adjust things like visual effects, performance, and audio. +# A lot of these values are closely tied to how the game is expected to run (for example, the screen resolution), +# but they can still be played around with. There are also a lot of values currently hardcoded in NS.py that +# should be moved into here eventually. +# + [setup] license = Public Domain title = Scrapeboard diff --git a/lib/pgfw b/lib/pgfw index 285181d..6693ca4 160000 --- a/lib/pgfw +++ b/lib/pgfw @@ -1 +1 @@ -Subproject commit 285181d23b789492b4b0186be1cacf160e89672a +Subproject commit 6693ca45140aa67df7a6b0622a98d8d5b59079a3