This commit is contained in:
Frank DeMarco 2018-09-20 04:57:06 -04:00
parent 41c647b1e9
commit eec39049fa
7 changed files with 103 additions and 131 deletions

230
NS.py
View File

@ -7,7 +7,6 @@ from glob import iglob
from os.path import basename, join from os.path import basename, join
from threading import Thread from threading import Thread
from serial import Serial from serial import Serial
from PIL import Image, ImageDraw
from pygame import Surface, Color from pygame import Surface, Color
from pygame.event import clear from pygame.event import clear
@ -27,7 +26,8 @@ from lib.pgfw.pgfw.Animation import Animation
from lib.pgfw.pgfw.Audio import SoundEffect from lib.pgfw.pgfw.Audio import SoundEffect
from lib.pgfw.pgfw.extension import ( from lib.pgfw.pgfw.extension import (
get_step, get_step_relative, get_delta, reflect_angle, get_step, get_step_relative, get_delta, reflect_angle,
render_box, get_hsla_color, get_hue_shifted_surface render_box, get_hsla_color, get_hue_shifted_surface,
get_color_swapped_surface
) )
from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon
@ -44,6 +44,17 @@ class NS(Game, Animation):
def __init__(self): def __init__(self):
Game.__init__(self) Game.__init__(self)
self.get_configuration().type_declarations.add_chart(
{
"time":
{
"int": ["timer-max-time", "timer-start-time", "timer-addition", "sword-delay"]
},
"input":
{
"bool": "serial"
}
})
Animation.__init__(self, self) Animation.__init__(self, self)
self.load_sfx() self.load_sfx()
self.subscribe(self.respond, KEYDOWN) self.subscribe(self.respond, KEYDOWN)
@ -60,17 +71,6 @@ class NS(Game, Animation):
self.dialogue = Dialogue(self) self.dialogue = Dialogue(self)
self.chemtrails = Chemtrails(self) self.chemtrails = Chemtrails(self)
self.boss = Boss(self) self.boss = Boss(self)
self.get_configuration().type_declarations.add_chart(
{
"time":
{
"int": ["timer-max-time", "timer-start-time", "timer-addition", "sword-delay"]
},
"input":
{
"bool": "serial"
}
})
if self.serial_enabled(): if self.serial_enabled():
self.serial_kill = False self.serial_kill = False
self.serial_data = 0 self.serial_data = 0
@ -222,6 +222,50 @@ class Button(Sprite):
self.add_frame(frame) self.add_frame(frame)
class Meter(GameChild):
SPACING = 12
def __init__(self, parent):
GameChild.__init__(self, parent)
def setup(self, background, rect, indent, color, units):
self.background = background
self.rect = rect
self.icons = []
x = rect.left + indent
base = get_color_swapped_surface(
load(self.get_resource("HUD_circle.png")).convert_alpha(),
(0, 0, 0), color)
while x <= self.rect.right - base.get_width() - self.SPACING:
icon = Sprite(self)
icon.add_frame(base)
icon.location.midleft = x, self.rect.centery
self.icons.append(icon)
x += icon.location.w + self.SPACING
self.units = units
def reset(self):
self.amount = self.units
for icon in self.icons:
icon.unhide()
def change(self, delta):
self.amount += delta
cutoff = float(self.amount) / self.units * len(self.icons)
for ii, icon in enumerate(self.icons):
if ii < cutoff:
icon.unhide()
else:
icon.hide()
def update(self):
ds = self.get_display_surface()
ds.blit(self.background, self.rect)
for icon in self.icons:
icon.update()
class Title(GameChild): class Title(GameChild):
def __init__(self, parent): def __init__(self, parent):
@ -1010,11 +1054,13 @@ class Chemtrails(Sprite):
for direction in (NS.N, NS.NE, NS.E, NS.NW, NS.S, NS.W): for direction in (NS.N, NS.NE, NS.E, NS.NW, NS.S, NS.W):
self.add_frameset([direction], switch=(direction == NS.N)) self.add_frameset([direction], switch=(direction == NS.N))
self.life = Life(self) self.life = Life(self)
self.boys = Boys(self)
self.timer = Timer(self) self.timer = Timer(self)
def reset(self): def reset(self):
self.deactivate() self.deactivate()
self.life.reset() self.life.reset()
self.boys.reset()
self.timer.reset() self.timer.reset()
def deactivate(self): def deactivate(self):
@ -1036,13 +1082,15 @@ class Chemtrails(Sprite):
if boss.queue: if boss.queue:
self.timer.tick() self.timer.tick()
self.attack() self.attack()
if self.timer.time_remaining < 0: if self.timer.amount < 0:
self.life.decrease() self.life.decrease()
if not boss.is_playing(boss.show_end_dialogue): if not boss.is_playing(boss.show_end_dialogue):
self.timer.reset() self.timer.reset()
boss.combo() boss.combo()
# self.timer.update() if not boss.is_playing(boss.show_introduction_dialogue):
self.life.update() self.timer.update()
self.life.update()
self.boys.update()
def attack(self): def attack(self):
boss = self.get_game().boss boss = self.get_game().boss
@ -1103,94 +1151,52 @@ class Chemtrails(Sprite):
self.orientation = None self.orientation = None
class Timer(GameChild): class Timer(Meter):
TEXT = u"\u25F7"
BAR_POSITION = 448, 11
SIZE = 160
TOP = 120
RING_OFFSET = 8
def __init__(self, parent): def __init__(self, parent):
GameChild.__init__(self, parent) Meter.__init__(self, parent)
self.background = Sprite(self)
image = load(self.get_resource("HUD_background.png")).convert_alpha()
image = flip(image, True, False)
self.background.add_frame(image)
self.background.location.topright = self.get_display_surface().get_rect().topright
self.bar = load(self.get_resource("HUD_bar.png")).convert_alpha()
self.bar = flip(self.bar, True, False)
self.hourglass = Sprite(self)
self.hourglass.load_from_path(self.get_resource("Hourglass.png"), True)
dsr = self.get_display_surface().get_rect() dsr = self.get_display_surface().get_rect()
self.hourglass.location.midright = dsr.right, self.TOP + self.SIZE / 2 background = load(self.get_resource("HUD_timer.png")).convert()
rect = background.get_rect()
def reset(self): rect.bottomright = dsr.right - 6, dsr.bottom - 4
self.time_remaining = self.get_configuration("time", "timer-start-time") self.setup(background, rect, 53, (0, 0, 255),
self.get_configuration("time", "timer-start-time"))
def add_time(self, amount): def add_time(self, amount):
self.time_remaining += amount self.change(amount)
def tick(self): def tick(self):
self.time_remaining -= self.get_game().time_filter.get_last_frame_duration() self.change(-self.get_game().time_filter.get_last_frame_duration())
def update(self):
self.hourglass.update()
if self.time_remaining > 5500:
hue = 120
elif self.time_remaining > 3000:
hue = 30
else:
hue = 0
ds = self.get_display_surface()
max_time = self.get_configuration("time", "timer-max-time")
remaining_ratio = float(self.time_remaining) / max_time
left = ds.get_width() - self.SIZE / 2
ds.blit(self.get_ring(get_hsla_color(hue, lightness=20, alpha=67), remaining_ratio),
(left, self.TOP + self.RING_OFFSET))
ds.blit(self.get_ring(get_hsla_color(hue, lightness=80, alpha=67), remaining_ratio),
(left, self.TOP - self.RING_OFFSET))
ds.blit(self.get_ring(get_hsla_color(hue, alpha=67), remaining_ratio), (left, self.TOP))
def get_ring(self, color, remaining):
image = Image.new("RGBA", (self.SIZE, self.SIZE))
draw = ImageDraw.Draw(image)
draw.pieslice((0, 0, self.SIZE - 1, self.SIZE - 1), 90, remaining * 180 + 90,
fill=(color.r, color.g, color.b, color.a))
draw.ellipse((self.SIZE / 4, self.SIZE / 4, self.SIZE / 4 * 3, self.SIZE / 4 * 3), (0, 0, 0, 0))
string = fromstring(image.tobytes(), image.size, image.mode)
image.close()
return string
class Life(GameChild): class Life(Meter):
SPACING = 30
MARGIN = 0
def __init__(self, parent): def __init__(self, parent):
GameChild.__init__(self, parent) Meter.__init__(self, parent)
self.heart = load(self.get_resource("Heart.png")).convert_alpha() dsr = self.get_display_surface().get_rect()
background = load(self.get_resource("HUD_health.png")).convert()
def reset(self): rect = background.get_rect()
self.count = 3 rect.bottomleft = 172, dsr.bottom - 4
self.setup(background, rect, 70, (255, 0, 0), 3)
def decrease(self): def decrease(self):
self.get_game().sfx["hurt"].play() self.get_game().sfx["hurt"].play()
if self.count > 0: self.change(-1)
self.count -= 1 if self.amount <= 0:
if self.count <= 0: self.amount = 0
self.count = 0 self.parent.boys.change(-1)
self.get_game().boss.finish_battle(False) self.get_game().boss.finish_battle(False)
def update(self):
ds = self.get_display_surface() class Boys(Meter):
dsr = ds.get_rect()
hr = self.heart.get_rect() def __init__(self, parent):
rect = Rect(0, 0, hr.w * self.count + self.SPACING * (self.count - 1), hr.h) Meter.__init__(self, parent)
rect.midbottom = dsr.centerx, dsr.h - self.MARGIN dsr = self.get_display_surface().get_rect()
for x in xrange(rect.left, rect.right, hr.w + self.SPACING): background = load(self.get_resource("HUD_lives.png")).convert()
ds.blit(self.heart, (x, rect.top)) rect = background.get_rect()
rect.bottomleft = 6, dsr.bottom - 4
self.setup(background, rect, 60, (0, 255, 0), 3)
class Boss(Animation): class Boss(Animation):
@ -1227,7 +1233,7 @@ class Boss(Animation):
self.spoopy.set_frameset("normal") self.spoopy.set_frameset("normal")
def start_level(self, index): def start_level(self, index):
self.level_index = 2 self.level_index = index
self.battle_finished = False self.battle_finished = False
self.player_defeated = False self.player_defeated = False
self.health.reset() self.health.reset()
@ -1669,34 +1675,20 @@ class Sword(Animation):
sprite.update(substitute=substitute) sprite.update(substitute=substitute)
class Health(GameChild): class Health(Meter):
TEXT = "BOSS" OFFSET = 4
BAR_POSITION = 23, 11
BACKGROUND_ALPHA = 125
OFFSET = 11
def __init__(self, parent): def __init__(self, parent):
GameChild.__init__(self, parent) Meter.__init__(self, parent)
self.background = Sprite(self)
self.background.load_from_path(self.get_resource("HUD_boss_health_background.png"), True)
dsr = self.get_display_surface().get_rect() dsr = self.get_display_surface().get_rect()
self.background.location.center = dsr.centerx, self.OFFSET background = load(self.get_resource("HUD_boss.png")).convert()
self.foreground = Sprite(self) rect = background.get_rect()
self.foreground.load_from_path(self.get_resource("HUD_boss_health_foreground.png"), True) rect.midtop = dsr.centerx, self.OFFSET
self.foreground.location.center = dsr.centerx, self.OFFSET self.setup(background, rect, 52, (255, 0, 255), 100)
self.label = Sprite(self)
font = Font(self.get_resource("rounded-mplus-1m-bold.ttf"), 24)
text = font.render(self.TEXT, True, Color("white"))
self.label.add_frame(text)
self.label.location.topleft = 2, -2
self.bar = load(self.get_resource("HUD_bar.png")).convert_alpha()
def reset(self):
self.amount = 100
def decrease(self, damage): def decrease(self, damage):
self.amount -= damage self.change(-damage)
self.parent.damage() self.parent.damage()
if self.amount <= 0: if self.amount <= 0:
self.amount = 0 self.amount = 0
@ -1706,22 +1698,6 @@ class Health(GameChild):
else: else:
self.parent.play(self.parent.cancel_flash, delay=1000, play_once=True) self.parent.play(self.parent.cancel_flash, delay=1000, play_once=True)
def update(self):
self.background.update()
if self.amount > 50:
shift = 0
elif self.amount > 25:
shift = -70
else:
shift = -120
ratio = self.amount / 100.0
ds = self.get_display_surface()
ds.set_clip((self.foreground.location.left, self.foreground.location.top,
int(self.foreground.location.w * ratio), self.foreground.location.h))
surface = get_hue_shifted_surface(self.foreground.get_current_frame(), shift)
ds.blit(surface, self.foreground.location.topleft)
ds.set_clip(None)
class Ending(Animation): class Ending(Animation):

BIN
resource/HUD_boss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

BIN
resource/HUD_circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

BIN
resource/HUD_health.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
resource/HUD_lives.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1013 B

BIN
resource/HUD_timer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -15,7 +15,3 @@
171204 171204
256769 256769
312561 312561
167744
91410
41874
32477