started using level select object, added preview of animated alien
This commit is contained in:
parent
7036ea9ed0
commit
62831ade79
101
NS.py
101
NS.py
|
@ -1,5 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- 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
|
import argparse
|
||||||
from random import randint, choice, random
|
from random import randint, choice, random
|
||||||
from math import pi
|
from math import pi
|
||||||
|
@ -34,6 +41,13 @@ from lib.pgfw.pgfw.extension import (
|
||||||
from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon
|
from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon
|
||||||
|
|
||||||
class NS(Game, Animation):
|
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)
|
LNW, LNE, LSE, LSW = range(4)
|
||||||
N, NE, E, NW, S, W = range(6)
|
N, NE, E, NW, S, W = range(6)
|
||||||
|
@ -130,6 +144,7 @@ class NS(Game, Animation):
|
||||||
ds = self.get_display_surface()
|
ds = self.get_display_surface()
|
||||||
self.background = Surface(ds.get_size())
|
self.background = Surface(ds.get_size())
|
||||||
self.background.fill((0, 0, 0))
|
self.background.fill((0, 0, 0))
|
||||||
|
self.level_select = LevelSelect(self)
|
||||||
self.platform = Platform(self)
|
self.platform = Platform(self)
|
||||||
self.tony = Tony(self)
|
self.tony = Tony(self)
|
||||||
self.logo = Logo(self)
|
self.logo = Logo(self)
|
||||||
|
@ -202,6 +217,7 @@ class NS(Game, Animation):
|
||||||
self.score_hidden = False
|
self.score_hidden = False
|
||||||
self.idle_elapsed = 0
|
self.idle_elapsed = 0
|
||||||
self.suppressing_input = False
|
self.suppressing_input = False
|
||||||
|
self.level_select.reset()
|
||||||
self.title.reset()
|
self.title.reset()
|
||||||
if not leave_wipe_running:
|
if not leave_wipe_running:
|
||||||
self.wipe.reset()
|
self.wipe.reset()
|
||||||
|
@ -276,6 +292,7 @@ class NS(Game, Animation):
|
||||||
self.reset_arduino()
|
self.reset_arduino()
|
||||||
self.no_reset_elapsed = 0
|
self.no_reset_elapsed = 0
|
||||||
self.title.update()
|
self.title.update()
|
||||||
|
self.level_select.update()
|
||||||
self.ending.update()
|
self.ending.update()
|
||||||
self.boss.update()
|
self.boss.update()
|
||||||
if not self.title.active:
|
if not self.title.active:
|
||||||
|
@ -288,6 +305,44 @@ class NS(Game, Animation):
|
||||||
self.reset()
|
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):
|
class Button(Sprite):
|
||||||
|
|
||||||
MARGIN = 2
|
MARGIN = 2
|
||||||
|
@ -559,9 +614,13 @@ class Title(Animation):
|
||||||
self.halt()
|
self.halt()
|
||||||
|
|
||||||
def start_game(self):
|
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.deactivate()
|
||||||
self.get_game().set_most_recent_time(None)
|
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):
|
def draw_scores(self):
|
||||||
step = 75
|
step = 75
|
||||||
|
@ -610,19 +669,18 @@ class Title(Animation):
|
||||||
self.get_game().tony.set_frameset("board")
|
self.get_game().tony.set_frameset("board")
|
||||||
|
|
||||||
def update(self):
|
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)
|
Animation.update(self)
|
||||||
if self.active:
|
if self.active:
|
||||||
ds = self.get_display_surface()
|
ds = self.get_display_surface()
|
||||||
dsr = ds.get_rect()
|
dsr = ds.get_rect()
|
||||||
self.get_game().logo.update()
|
self.get_game().logo.update()
|
||||||
# advance unlock pattern
|
# Advance through the unlock pattern
|
||||||
platform = self.get_game().platform
|
platform = self.get_game().platform
|
||||||
if not self.get_game().wipe.is_playing() and platform.get_edge_pressed() == self.UNLOCK_MOVES[self.unlock_index]:
|
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:
|
if self.unlock_index == len(self.UNLOCK_MOVES) - 1:
|
||||||
platform.set_glowing([])
|
platform.set_glowing([])
|
||||||
self.get_game().wipe.start(self.start_game)
|
self.get_game().wipe.start(self.start_game)
|
||||||
|
@ -631,13 +689,8 @@ class Title(Animation):
|
||||||
self.unlock_index += 1
|
self.unlock_index += 1
|
||||||
platform.set_glowing(platform.get_buttons_from_edges([self.UNLOCK_MOVES[self.unlock_index]]))
|
platform.set_glowing(platform.get_buttons_from_edges([self.UNLOCK_MOVES[self.unlock_index]]))
|
||||||
self.get_audio().play_sfx("land_0")
|
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()
|
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:
|
if self.video.location.right > dsr.right or self.video.location.left < dsr.left:
|
||||||
self.angle = reflect_angle(self.angle, 0)
|
self.angle = reflect_angle(self.angle, 0)
|
||||||
if self.video.location.right > dsr.right:
|
if self.video.location.right > dsr.right:
|
||||||
|
@ -1159,11 +1212,6 @@ class Light(Animation):
|
||||||
shifted = []
|
shifted = []
|
||||||
for point in self.get_points():
|
for point in self.get_points():
|
||||||
shifted.append((point[0], point[1] - y))
|
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:
|
if self.position == NS.LSW:
|
||||||
saturation = 0
|
saturation = 0
|
||||||
else:
|
else:
|
||||||
|
@ -1179,7 +1227,6 @@ class Light(Animation):
|
||||||
),
|
),
|
||||||
True, shifted, 3
|
True, shifted, 3
|
||||||
)
|
)
|
||||||
# ds.blit(intermediate, (0, 0))
|
|
||||||
|
|
||||||
def in_orientation(self, orientation):
|
def in_orientation(self, orientation):
|
||||||
if self.position == NS.LNW:
|
if self.position == NS.LNW:
|
||||||
|
@ -1346,20 +1393,28 @@ class Boys(Meter):
|
||||||
|
|
||||||
|
|
||||||
class Boss(Animation):
|
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):
|
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)
|
Animation.__init__(self, parent)
|
||||||
if self.get_configuration("display", "effects"):
|
if self.get_configuration("display", "effects"):
|
||||||
self.kool_man = RainbowSprite(self, load(self.get_resource("Kool_man_waah.png")).convert_alpha(), hue_shift)
|
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)
|
self.spoopy = RainbowSprite(self, load(self.get_resource("Spoopy.png")).convert_alpha(), hue_shift)
|
||||||
else:
|
else:
|
||||||
self.kool_man = Sprite(self)
|
self.kool_man = Sprite(self)
|
||||||
self.kool_man.load_from_path("Kool_man_waah.png", True)
|
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 = Sprite(self)
|
||||||
self.spoopy.load_from_path("Spoopy.png", True)
|
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:
|
for sprite in self.kool_man, self.visitor, self.spoopy:
|
||||||
sprite.location.topleft = 100, 0
|
sprite.location.topleft = 100, 0
|
||||||
self.health = Health(self)
|
self.health = Health(self)
|
||||||
|
@ -1367,7 +1422,7 @@ class Boss(Animation):
|
||||||
self.register(self.brandish, self.cancel_flash, self.show_introduction_dialogue,
|
self.register(self.brandish, self.cancel_flash, self.show_introduction_dialogue,
|
||||||
self.show_end_dialogue, self.end_dialogue)
|
self.show_end_dialogue, self.end_dialogue)
|
||||||
self.kool_man.add_frameset([0], name="normal", switch=True)
|
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.spoopy.add_frameset([0], name="normal", switch=True)
|
||||||
self.kool_man_avatar = load(self.get_resource("Kool_man_avatar.png")).convert()
|
self.kool_man_avatar = load(self.get_resource("Kool_man_avatar.png")).convert()
|
||||||
self.visitor_avatar = load(self.get_resource("Visitor_avatar.png")).convert()
|
self.visitor_avatar = load(self.get_resource("Visitor_avatar.png")).convert()
|
||||||
|
|
40
OPEN-GAME
40
OPEN-GAME
|
@ -1,33 +1,19 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from os import environ, execvp, chdir, getcwd
|
#
|
||||||
from os.path import exists, join, dirname
|
# Scrapeboard is an arcade game in development by Frank DeMarco (@diskmem) and Blake Andrews (@snakesandrews).
|
||||||
from sys import version_info, argv
|
# 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):
|
from sys import argv
|
||||||
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]))
|
|
||||||
|
|
||||||
if "--go-to-dir" in argv:
|
if "--go-to-dir" in argv:
|
||||||
move_to_executable()
|
move_to_executable()
|
||||||
|
|
12
config
12
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]
|
[setup]
|
||||||
license = Public Domain
|
license = Public Domain
|
||||||
title = Scrapeboard
|
title = Scrapeboard
|
||||||
|
|
2
lib/pgfw
2
lib/pgfw
|
@ -1 +1 @@
|
||||||
Subproject commit 285181d23b789492b4b0186be1cacf160e89672a
|
Subproject commit 6693ca45140aa67df7a6b0622a98d8d5b59079a3
|
Loading…
Reference in New Issue