ibitfit/electric_sieve/ElectricSieve.py

749 lines
27 KiB
Python
Raw Normal View History

2014-04-27 14:21:42 -04:00
# -*- coding: utf-8 -*-
2014-04-25 22:11:52 -04:00
from random import randint, randrange, choice
2014-04-27 18:12:18 -04:00
from time import time
2015-07-23 12:42:07 -04:00
from operator import itemgetter
2022-12-13 16:56:33 -05:00
import RPi.GPIO as GPIO
2014-04-25 18:12:47 -04:00
2014-04-26 06:06:54 -04:00
from pygame import Surface, PixelArray, Rect
2014-04-25 23:18:47 -04:00
from pygame.draw import aalines, polygon
2014-04-27 14:21:42 -04:00
from pygame.font import Font
2014-04-27 21:34:10 -04:00
from pygame.mixer import Sound
2014-04-25 23:18:47 -04:00
from pygame.locals import *
2014-04-25 13:22:01 -04:00
2015-07-21 17:44:07 -04:00
from lib.pgfw.pgfw.Game import Game
from lib.pgfw.pgfw.GameChild import GameChild
from lib.pgfw.pgfw.Sprite import Sprite
from lib.pgfw.pgfw.extension import render_box
2014-04-25 13:22:01 -04:00
2014-04-27 21:34:10 -04:00
class ElectricSieve(Game):
2014-04-25 13:22:01 -04:00
2022-12-13 16:56:33 -05:00
# The GPIO pins corresponding to the buttons and LED indicators
PIN_BUTTON_UP = 17
PIN_BUTTON_DOWN = 27
PIN_LED_UP = 22
PIN_LED_DOWN = 23
2014-04-25 13:22:01 -04:00
def __init__(self):
2022-12-13 16:56:33 -05:00
self.initialize_gpio()
2014-04-25 13:22:01 -04:00
Game.__init__(self)
self.background = Surface(self.display.screen.get_size())
self.background.fill((255, 80, 190))
2014-04-27 14:21:42 -04:00
self.title.activate()
2014-04-25 13:22:01 -04:00
2022-12-13 16:56:33 -05:00
def initialize_gpio(self):
"""
Set pin numbering mode to GPIO, initialize all buttons to input pullup.
"""
# Use GPIO numbering
GPIO.setmode(GPIO.BCM)
# Set all button pins to pullup
for pin in self.PIN_BUTTON_UP, self.PIN_BUTTON_DOWN:
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
2014-04-25 13:22:01 -04:00
def set_children(self):
Game.set_children(self)
2014-04-27 14:21:42 -04:00
self.title = Title(self)
2014-04-25 13:22:01 -04:00
self.sieve = Sieve(self)
2014-04-25 18:12:47 -04:00
self.triangles = Triangles(self)
2014-04-27 14:21:42 -04:00
self.acid = Acid(self)
2014-04-27 08:58:48 -04:00
self.static = Static(self)
2014-04-25 13:22:01 -04:00
def update(self):
2014-04-27 14:21:42 -04:00
self.title.update()
if self.triangles.active:
self.display.screen.blit(self.background, (0, 0))
2014-04-25 18:12:47 -04:00
self.triangles.update()
2014-04-25 13:22:01 -04:00
self.sieve.update()
2014-04-27 08:58:48 -04:00
self.static.update()
2014-04-25 13:22:01 -04:00
2014-04-27 14:21:42 -04:00
class Title(GameChild):
def __init__(self, parent):
GameChild.__init__(self, parent)
self.display_surface = self.get_display_surface()
self.delegate = self.parent.delegate
2014-04-27 16:27:58 -04:00
bg_color = (255, 222, 173)
2014-04-27 14:21:42 -04:00
self.background = surface = Surface(self.display_surface.get_size())
2014-04-27 16:27:58 -04:00
tile = Surface((2, 2))
tile.fill(bg_color)
tile.set_at((0, 1), (220, 119, 41))
tile.set_at((1, 0), (220, 119, 41))
2022-12-01 15:24:53 -05:00
for y in range(0, surface.get_height(), 2):
for x in range(0, surface.get_width(), 2):
2014-04-27 16:27:58 -04:00
surface.blit(tile, (x, y))
2015-07-21 17:44:07 -04:00
# font = Font(self.get_resource("display", "title-font-path"), 20)
# font.set_italic(True)
# font.set_bold(True)
# self.captions = captions = Sprite(self), Sprite(self)
# colors = (0, 68, 170), (255, 255, 255), (128, 128, 128), \
# (220, 119, 41), (255, 80, 80), (0, 90, 110)
# texts = ["", ""]
# for ii, text in \
# enumerate(self.get_configuration("display",
# "caption").upper().split()):
# texts[ii] += "•" * (5 if ii else 3)
# for ch in text:
# texts[ii] += ch + " "
# texts[ii] = texts[ii].strip() + "•" * (5 if ii else 3)
2022-12-01 15:24:53 -05:00
# for _ in range(25):
2015-07-21 17:44:07 -04:00
# color = choice(colors)
# captions[0].add_frame(font.render(texts[0], True, color, (220, 208, 255)))
# captions[1].add_frame(font.render(texts[1], True, color, (220, 208, 255)))
# cx = self.display_surface.get_rect().centerx
# captions[0].location.center = cx, 301
# captions[1].location.center = cx, 398
2014-04-27 16:27:58 -04:00
self.scoreboard = Scoreboard(self)
2014-04-27 21:34:10 -04:00
self.music = Sound(self.get_resource("audio", "title"))
self.advance = Sound(self.get_resource("audio", "title-advance"))
2014-04-27 14:21:42 -04:00
self.subscribe(self.respond)
def respond(self, event):
if self.active:
if self.delegate.compare(event, "advance"):
self.deactivate()
self.parent.triangles.activate()
self.parent.sieve.activate()
self.parent.static.activate()
2014-04-27 21:34:10 -04:00
self.advance.play()
2014-04-27 14:21:42 -04:00
def activate(self):
self.active = True
2014-04-27 21:34:10 -04:00
self.music.play(-1)
2014-04-27 14:21:42 -04:00
def deactivate(self):
self.active = False
2014-04-27 21:34:10 -04:00
self.music.fadeout(500)
2014-04-27 14:21:42 -04:00
def update(self):
if self.active:
self.display_surface.blit(self.background, (0, 0))
2015-07-21 17:44:07 -04:00
# for caption in self.captions:
# caption.update()
2014-04-27 16:27:58 -04:00
self.scoreboard.update()
2014-04-27 14:21:42 -04:00
2014-04-25 13:22:01 -04:00
class Strip(Sprite):
2014-04-25 14:37:23 -04:00
LEFT, RIGHT = range(2)
2014-04-25 13:22:01 -04:00
def __init__(self, parent):
Sprite.__init__(self, parent)
2022-12-13 16:56:33 -05:00
GPIO.add_event_detect(ElectricSieve.PIN_BUTTON_UP, GPIO.BOTH, self.respond)
GPIO.add_event_detect(ElectricSieve.PIN_BUTTON_DOWN, GPIO.BOTH, self.respond)
2014-04-27 14:21:42 -04:00
self.deactivate()
2014-04-25 13:22:01 -04:00
self.display_surface = self.get_display_surface()
2014-04-25 14:37:23 -04:00
self.delegate = self.get_game().delegate
2014-04-27 08:58:48 -04:00
self.hshifts = Shift(self, 1, "shift-2"), Shift(self, -1, "shift-2")
2014-04-25 13:22:01 -04:00
self.add_frames()
2014-04-25 14:37:23 -04:00
self.subscribe(self.respond)
2014-04-25 13:22:01 -04:00
2014-04-27 14:21:42 -04:00
def deactivate(self):
self.active = False
def reset(self):
for shift in self.hshifts:
shift.reset()
2014-04-25 13:22:01 -04:00
def add_frames(self):
pass
2014-04-25 14:37:23 -04:00
def respond(self, event):
2022-12-13 16:56:33 -05:00
if type(event) == int:
pressed = "pressed" if GPIO.input(event) == GPIO.LOW else "released"
print(f"pin {event} {pressed}")
2014-04-27 14:21:42 -04:00
if self.active:
2022-12-13 16:56:33 -05:00
move = False
if type(event) == int:
if event == ElectricSieve.PIN_BUTTON_UP:
direction = self.LEFT
move = True
elif event == ElectricSieve.PIN_BUTTON_DOWN:
direction = self.RIGHT
move = True
active = GPIO.input(event) == GPIO.LOW
else:
compare = self.delegate.compare
if compare(event, "left") or compare(event, "left", True):
direction = self.LEFT
move = True
elif compare(event, "right") or compare(event, "right", True):
direction = self.RIGHT
move = True
active = not event.cancel
if move:
self.hshifts[direction].active = active
2014-04-27 14:21:42 -04:00
def activate(self):
self.active = True
2014-04-25 14:37:23 -04:00
def update(self):
2014-04-27 14:21:42 -04:00
if self.active:
for shift in self.hshifts:
shift.update()
if shift.time:
self.move(shift.get_change())
Sprite.update(self)
2014-04-25 14:37:23 -04:00
2014-04-25 13:22:01 -04:00
2014-04-25 15:25:07 -04:00
class Shift(GameChild):
2014-04-26 01:06:45 -04:00
def __init__(self, parent, direction, nodeset):
2014-04-25 15:25:07 -04:00
GameChild.__init__(self, parent)
self.direction = direction
2014-04-27 14:21:42 -04:00
self.reset()
2014-04-25 15:25:07 -04:00
self.timer = self.get_game().time_filter
2014-04-26 01:06:45 -04:00
self.nodeset = self.get_game().interpolator.get_nodeset(nodeset)
2014-04-25 15:25:07 -04:00
2014-04-27 14:21:42 -04:00
def reset(self):
self.active = False
self.time = 0
2014-04-25 15:25:07 -04:00
def update(self):
least, greatest = self.nodeset[0].x, self.nodeset[-1].x
if self.active and self.time < greatest:
self.time = min(self.time + self.timer.get_last_frame_duration(),
greatest)
elif not self.active and self.time > least:
self.time = max(self.time - self.timer.get_last_frame_duration(),
least)
2014-04-26 01:06:45 -04:00
def get_change(self):
2014-04-25 15:25:07 -04:00
return self.nodeset.get_y(self.time) * self.direction
2015-07-21 17:44:07 -04:00
class Scoreboard(GameChild):
BACKGROUND = 255, 255, 255
FOREGROUND = 27, 27, 27
NEW = 27, 27, 27
SPACING = 70
MARGIN = 30
BLINK_INTERVAL = 400
2015-07-23 06:33:20 -04:00
PADDING = 6
BORDER = 1
2015-07-23 12:42:07 -04:00
SCORE_COUNT = 9
2014-04-27 16:27:58 -04:00
def __init__(self, parent):
2014-04-27 17:35:35 -04:00
GameChild.__init__(self, parent)
2015-07-21 17:44:07 -04:00
ds = self.display_surface = self.get_display_surface()
2014-04-27 18:12:18 -04:00
self.scores_path = self.get_resource("score", "path")
self.most_recent_score = None
2014-04-27 17:35:35 -04:00
self.load()
def load(self):
self.sprites = sprites = []
2015-07-21 17:44:07 -04:00
font_path = self.get_resource("display", "scoreboard-font-path")
2015-07-23 12:42:07 -04:00
sizes = [24] * self.SCORE_COUNT
blink = False
for ii, score in enumerate(self.get_scores()[:len(sizes)]):
2015-07-21 17:44:07 -04:00
font = Font(font_path, sizes[ii])
sprites.append((Sprite(self, self.BLINK_INTERVAL),
Sprite(self, self.BLINK_INTERVAL)))
score_text = str(score[1])
2015-07-23 12:42:07 -04:00
color = self.BACKGROUND if (self.most_recent_score and not blink and score[1:] == \
self.most_recent_score) else self.FOREGROUND
2015-07-21 17:44:07 -04:00
score_plate = font.render(score_text, False, color, self.BACKGROUND)
rect = score_plate.get_rect()
surface = Surface(rect.inflate((2, 2)).size)
surface.fill(self.FOREGROUND)
rect.center = surface.get_rect().center
surface.blit(score_plate, rect)
sprites[ii][1].add_frame(render_box(font, score_text, False, color,
2015-07-23 06:33:20 -04:00
self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))
2015-07-21 17:44:07 -04:00
sprites[ii][0].add_frame(render_box(font, score[2], False, color,
2015-07-23 06:33:20 -04:00
self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))
2015-07-23 12:42:07 -04:00
if self.most_recent_score and not blink and score[1:] == self.most_recent_score:
2015-07-21 17:44:07 -04:00
sprites[ii][1].add_frame(render_box(font, score_text, False, self.NEW,
2015-07-23 06:33:20 -04:00
self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))
2015-07-21 17:44:07 -04:00
sprites[ii][0].add_frame(render_box(font, score[2], False, self.NEW,
2015-07-23 06:33:20 -04:00
self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))
2015-07-23 12:42:07 -04:00
blink = True
2015-07-21 17:44:07 -04:00
sprites[ii][0].location.left = self.MARGIN
sprites[ii][1].location.right = self.get_display_surface().get_rect().right - self.MARGIN
y = self.get_display_surface().get_rect().centery + self.SPACING * (ii - len(sizes) / 2)
for sprite in sprites[ii]:
sprite.location.centery = y
2014-04-27 17:35:35 -04:00
2015-07-23 12:42:07 -04:00
def get_scores(self):
scores = []
2022-12-01 15:24:53 -05:00
for line in open(self.scores_path, "r"):
2015-07-23 12:42:07 -04:00
fields = line.split()
scores.append((float(fields[0]), int(fields[1]), fields[2]))
scores = sorted(scores, key=itemgetter(0))
return sorted(scores, key=itemgetter(1), reverse=True)
def write(self, initials):
2014-04-27 18:12:18 -04:00
score = int(round(self.get_game().triangles.score))
2015-07-23 12:42:07 -04:00
fields = str(time()), str(score), initials
2022-12-01 15:24:53 -05:00
open(self.scores_path, "a").write(fields[0] + " " + fields[1] + " " + fields[2] + "\n")
2015-07-23 12:42:07 -04:00
self.most_recent_score = score, initials
2014-04-27 18:12:18 -04:00
self.load()
2014-04-27 17:35:35 -04:00
def update(self):
2015-07-21 17:44:07 -04:00
for pair in self.sprites:
for sprite in pair:
sprite.update()
2014-04-27 16:27:58 -04:00
2014-04-25 13:22:01 -04:00
class Sieve(Strip):
2014-04-26 01:06:45 -04:00
UP, DOWN = range(2)
2014-04-25 13:22:01 -04:00
def __init__(self, parent):
Strip.__init__(self, parent)
2014-04-26 01:06:45 -04:00
self.delegate = self.get_game().delegate
2014-04-25 17:07:57 -04:00
self.electric = Electric(self)
2014-04-25 17:48:21 -04:00
self.add_location(offset=(self.location.w, 0))
2014-04-25 13:22:01 -04:00
def add_frames(self):
2014-04-25 16:28:51 -04:00
bar_locations = []
2014-04-26 06:06:54 -04:00
self.bar_rects = bar_rects = []
2014-04-25 16:28:51 -04:00
x = 0
2014-04-26 06:06:54 -04:00
sh = 30
2014-04-25 16:28:51 -04:00
nodeset = self.get_game().interpolator.get_nodeset("scale")
2014-04-25 22:11:52 -04:00
self.bar_w = bar_w = 3
2014-04-25 18:12:47 -04:00
self.gaps = gaps = []
2014-04-25 17:07:57 -04:00
while x < nodeset[-1].x:
2014-04-25 16:28:51 -04:00
bar_locations.append(x)
2014-04-26 06:06:54 -04:00
bar_rects.append(Rect(x, 0, bar_w, sh))
2014-04-25 22:11:52 -04:00
gaps.append(nodeset.get_y(x, natural=True))
x += gaps[-1]
2014-04-26 06:06:54 -04:00
surface = Surface((x, sh))
2014-04-25 13:22:01 -04:00
transparent_color = (255, 0, 255)
surface.fill(transparent_color)
surface.set_colorkey(transparent_color)
frames = surface, surface.copy()
2014-04-25 17:07:57 -04:00
colors = (0, 255, 0), (153, 0, 204)
for x in bar_locations:
2014-04-26 06:06:54 -04:00
bar_rects.append(Rect(x + surface.get_width(), 0, bar_w, sh))
2014-04-25 17:07:57 -04:00
for ii, frame in enumerate(frames):
2014-04-26 06:06:54 -04:00
frame.fill(colors[ii], (x, 0, bar_w, sh))
frame.fill(colors[ii - 1], (x + 1, 1, 1, sh - 2))
2014-04-25 17:07:57 -04:00
for frame in frames:
self.add_frame(frame)
2014-04-27 14:21:42 -04:00
def reset(self):
Strip.reset(self)
self.location.centerx = self.display_surface.get_rect().centerx
self.locations[1].centerx = self.location.centerx + self.location.w
2014-04-25 17:07:57 -04:00
def update(self):
2014-04-27 14:21:42 -04:00
if self.active:
if self.location.right < 0:
self.move(self.location.w)
if self.locations[1].left > self.display_surface.get_width():
self.move(-self.location.w)
for location in self.locations:
location.bottom = self.parent.acid.get_top()
self.electric.location.centery = self.location.centery + 13
self.electric.update()
for rect in self.bar_rects:
rect.centery = self.location.centery
Strip.update(self)
2014-04-25 17:07:57 -04:00
class Electric(Sprite):
def __init__(self, parent):
Sprite.__init__(self, parent)
self.display_surface = self.get_display_surface()
self.add_frames()
def add_frames(self):
surface = Surface((self.display_surface.get_width(),
self.parent.location.h - 10))
frames = surface, surface.copy()
colors = (255, 255, 0), (100, 89, 213)
2014-04-25 13:22:01 -04:00
pixel_arrays = PixelArray(frames[0]), PixelArray(frames[1])
2022-12-01 15:24:53 -05:00
for x in range(len(pixel_arrays[0])):
for y in range( len(pixel_arrays[0][0])):
2014-04-25 17:07:57 -04:00
pixel_arrays[0][x][y] = colors[(y + x) % 2]
pixel_arrays[1][x][y] = colors[(y + x + 1) % 2]
2014-04-25 13:22:01 -04:00
for pixels in pixel_arrays:
del pixels
for frame in frames:
self.add_frame(frame)
2014-04-25 17:48:21 -04:00
class Triangles(GameChild, list):
def __init__(self, parent):
GameChild.__init__(self, parent)
2014-04-27 21:34:10 -04:00
self.music = Sound(self.get_resource("audio", "triangles"))
2014-04-27 14:21:42 -04:00
self.deactivate()
2014-04-26 03:18:46 -04:00
self.display_surface = self.get_display_surface()
2014-04-26 12:51:02 -04:00
self.delegate = self.get_game().delegate
self.booster = Shift(self, 1, "boost")
2014-04-27 21:34:10 -04:00
self.hit = Sound(self.get_resource("audio", "hit"))
self.miss = Sound(self.get_resource("audio", "miss"))
2014-04-27 14:21:42 -04:00
self.reset()
2014-04-26 12:51:02 -04:00
self.subscribe(self.respond)
2014-04-26 03:18:46 -04:00
2014-04-27 14:21:42 -04:00
def deactivate(self):
self.active = False
2014-04-27 21:34:10 -04:00
self.music.fadeout(500)
2014-04-27 14:21:42 -04:00
def reset(self):
list.__init__(self, [])
self.streak = 0
self.score = 0
self.booster.reset()
2014-04-26 03:18:46 -04:00
def populate(self):
if not self:
self.append(Triangle(self))
self[-1].location.bottom = 0
self.set_next_gap()
while self[-1].location.top > -self.display_surface.get_height():
self.append(Triangle(self))
self[-1].location.bottom = self[-2].location.top - self.next_gap
self.set_next_gap()
2014-04-25 18:12:47 -04:00
def set_next_gap(self):
2014-04-27 08:58:48 -04:00
self.next_gap = randint(500, 800)
2014-04-25 18:12:47 -04:00
2014-04-26 12:51:02 -04:00
def respond(self, event):
2014-04-27 14:21:42 -04:00
if self.active:
compare = self.delegate.compare
if compare(event, "down") or compare(event, "down", True):
self.booster.active = not event.cancel
2014-04-26 12:51:02 -04:00
def get_boost(self):
return self.booster.get_change()
2014-04-27 14:21:42 -04:00
def activate(self):
self.active = True
2014-04-27 21:34:10 -04:00
self.music.play(-1, 0, 500)
2014-04-27 14:21:42 -04:00
2014-04-25 18:12:47 -04:00
def update(self):
2014-04-27 14:21:42 -04:00
if self.active:
self.populate()
self.booster.update()
if self[0].location.collidelist(self.parent.sieve.locations) != -1:
sieve = self.parent.sieve
if self[0].location.colliderect(sieve.electric.location):
self.parent.acid.increase()
self.streak += 1
self.score += self.streak ** .8 + \
self.parent.acid.get_volume() * 5 + \
self[0].count
self.remove(self[0])
2014-04-27 21:34:10 -04:00
self.hit.play()
2014-04-27 14:21:42 -04:00
else:
for br in sieve.bar_rects:
for tr in self[0].collision_rects:
if tr.move((self[0].location.left,
0)).colliderect(br.move((sieve.location.left,
0))):
self.remove(self[0])
self.parent.static.increase()
self.streak = 0
2014-04-27 21:34:10 -04:00
self.miss.play()
2014-04-27 14:21:42 -04:00
break
for triangle in self:
triangle.update()
2014-04-25 18:12:47 -04:00
class Triangle(Sprite):
def __init__(self, parent):
Sprite.__init__(self, parent)
2014-04-27 08:58:48 -04:00
mark = randint(112, 328)
2014-04-25 22:11:52 -04:00
sieve = self.parent.parent.sieve
gaps = sieve.gaps
start = randrange(0, len(gaps))
widths = [gaps[start]]
while sum(widths) < mark:
widths.append(gaps[(start + len(widths)) % len(gaps)])
surface = Surface((sum(widths), 20))
2014-04-25 23:18:47 -04:00
surface.set_colorkey((0, 0, 0))
2014-04-25 22:11:52 -04:00
x = 0
2014-04-25 23:18:47 -04:00
height = surface.get_height()
2014-04-26 07:26:09 -04:00
margin = 26
2014-04-26 06:06:54 -04:00
self.collision_rects = collision_rects = []
2014-04-25 22:11:52 -04:00
for width in widths:
2014-04-25 23:18:47 -04:00
x += sieve.bar_w
points = (x + margin / 2, height - 2), \
(x + width - margin / 2 - 1, height - 2), \
(x + width / 2.0, 1)
polygon(surface, (60, 255, 220), points)
2014-04-26 06:06:54 -04:00
collision_rects.append(Rect(points[0], (width - margin - 1, 1)))
2014-04-25 23:18:47 -04:00
x += width - sieve.bar_w
2014-04-25 18:12:47 -04:00
self.add_frame(surface)
2014-04-25 22:11:52 -04:00
self.location.centerx = self.get_display_surface().get_rect().centerx
2014-04-27 14:21:42 -04:00
self.count = len(widths)
2014-04-25 18:12:47 -04:00
def update(self):
2014-04-27 14:38:16 -04:00
self.move(dy=9.5 * self.get_game().acid.get_volume() + 3.8 + \
2014-04-26 12:51:02 -04:00
self.parent.get_boost())
2014-04-26 06:06:54 -04:00
for rect in self.collision_rects:
rect.bottom = self.location.bottom
2014-04-25 18:12:47 -04:00
Sprite.update(self)
2014-04-26 01:06:45 -04:00
class Acid(GameChild):
def __init__(self, parent):
GameChild.__init__(self, parent)
2014-04-26 12:33:42 -04:00
self.display_surface = self.get_display_surface()
self.level_r = 80, 320
self.nodeset = self.get_game().interpolator.get_nodeset("volume")
2014-04-27 14:21:42 -04:00
self.reset()
def reset(self):
self.substance = 0
2014-04-26 12:33:42 -04:00
def get_top(self):
return self.display_surface.get_height() - self.get_level()
2014-04-26 01:06:45 -04:00
def get_level(self):
2014-04-26 12:33:42 -04:00
return self.get_volume() * (self.level_r[1] - self.level_r[0]) + \
self.level_r[0]
def get_volume(self):
return self.nodeset.get_y(self.substance)
def increase(self):
self.substance += 1
2014-04-27 08:58:48 -04:00
class Static(Sprite):
def __init__(self, parent):
2014-04-27 14:21:42 -04:00
Sprite.__init__(self, parent, 120)
2014-04-27 21:34:10 -04:00
self.noise = Sound(self.get_resource("audio", "noise"))
self.end = Sound(self.get_resource("audio", "end"))
2014-04-27 14:21:42 -04:00
self.deactivate()
self.delegate = self.get_game().delegate
self.increaser = Shift(self, 1, "intensity")
self.total = Total(self)
2015-07-23 12:42:07 -04:00
self.initials = Initials(self)
2014-04-27 14:21:42 -04:00
self.reset()
2014-04-27 08:58:48 -04:00
self.add_frames()
2014-04-27 14:21:42 -04:00
self.subscribe(self.respond)
def deactivate(self):
self.active = False
2014-04-27 21:34:10 -04:00
self.end.fadeout(500)
2014-04-27 14:21:42 -04:00
def reset(self):
self.complete = False
2014-04-27 08:58:48 -04:00
self.intensity = 0
2014-04-27 21:34:10 -04:00
self.noise.set_volume(0)
2014-04-27 14:21:42 -04:00
self.increaser.reset()
2014-04-27 08:58:48 -04:00
def add_frames(self):
surface = Surface(self.get_display_surface().get_size())
frames = surface, surface.copy(), surface.copy(), surface.copy()
tiles = []
2022-12-01 15:24:53 -05:00
for _ in range(32):
2014-04-27 08:58:48 -04:00
tiles.append(Surface((16, 16)))
pixel_arrays = []
for tile in tiles:
pixel_arrays.append(PixelArray(tile))
colors = (0, 0, 0), (64, 64, 64), (128, 128, 128), (196, 196, 196), \
(255, 255, 255)
2022-12-01 15:24:53 -05:00
for x in range(len(pixel_arrays[0])):
for y in range(len(pixel_arrays[0][0])):
2014-04-27 08:58:48 -04:00
for pixels in pixel_arrays:
pixels[x][y] = choice(colors)
for pixels in pixel_arrays:
del pixels
del pixel_arrays
for frame in frames:
2022-12-01 15:24:53 -05:00
for y in range(0, frame.get_height(), tiles[0].get_height()):
for x in range(0, frame.get_width(), tiles[0].get_width()):
2014-04-27 08:58:48 -04:00
frame.blit(choice(tiles), (x, y))
self.add_frame(frame)
2014-04-27 14:21:42 -04:00
def respond(self, event):
2015-07-23 12:42:07 -04:00
if self.active and self.complete and not self.initials.active:
2014-04-27 14:21:42 -04:00
if self.delegate.compare(event, "advance"):
2015-07-23 12:42:07 -04:00
if self.get_game().triangles.score > \
self.get_game().title.scoreboard.get_scores()[Scoreboard.SCORE_COUNT - 1][1]:
self.total.deactivate()
self.initials.activate()
else:
self.finish(wipe=True)
def finish(self, text="---", wipe=False):
if wipe:
self.parent.title.scoreboard.most_recent_score = None
self.parent.title.scoreboard.write(text)
self.total.deactivate()
self.deactivate()
self.reset()
self.parent.acid.reset()
self.parent.triangles.reset()
self.parent.sieve.reset()
self.parent.title.activate()
2014-04-27 14:21:42 -04:00
2014-04-27 08:58:48 -04:00
def increase(self):
self.intensity += self.increaser.get_change()
if self.intensity > 1:
self.intensity = 1
self.increaser.time += 12000
if self.increaser.time >= self.increaser.nodeset[-1].x + 5000:
self.increaser.time = self.increaser.nodeset[-1].x + 5000
2014-04-27 14:21:42 -04:00
def activate(self):
self.active = True
2014-04-27 21:34:10 -04:00
self.noise.play(-1)
2014-04-27 14:21:42 -04:00
2014-04-27 08:58:48 -04:00
def update(self):
2014-04-27 14:21:42 -04:00
if self.active:
if not self.complete and self.intensity >= .65:
self.complete = True
self.parent.sieve.deactivate()
self.parent.triangles.deactivate()
self.set_alpha(255)
2014-04-27 21:34:10 -04:00
self.noise.fadeout(6000)
self.end.play(-1, 0, 4000)
2014-04-27 14:21:42 -04:00
self.total.load()
elif not self.complete:
self.set_alpha(int(self.intensity * 255))
if self.intensity > 0:
self.intensity *= .998
self.increaser.update()
2014-04-27 21:34:10 -04:00
self.noise.set_volume(self.intensity)
2014-04-27 14:21:42 -04:00
Sprite.update(self)
self.total.update()
2015-07-23 12:42:07 -04:00
self.initials.update()
class Initials(GameChild):
LETTER_SIZE = 24
FOREGROUND = 27, 27, 27
BACKGROUND = 255, 255, 255
PADDING = 10
ARROW_MARGIN = 40
ARROW_HEIGHT = 10
def __init__(self, parent):
GameChild.__init__(self, parent)
self.reset()
self.deactivate()
self.font = Font(self.get_resource("display", "initials-font"), self.LETTER_SIZE)
self.subscribe(self.respond)
def reset(self):
self.text = "---"
self.index = 0
def deactivate(self):
self.active = False
def respond(self, event):
if self.active:
compare = self.get_game().delegate.compare
if compare(event, "right") or compare(event, "advance"):
self.index += 1
if self.index == len(self.text):
self.index = 0
if compare(event, "advance"):
self.deactivate()
self.parent.finish(self.text)
elif compare(event, "left"):
self.index -= 1
if self.index == -1:
self.index = len(self.text) - 1
elif compare(event, "up") or compare(event, "down"):
if compare(event, "up"):
increment = 1
elif compare(event, "down"):
increment = -1
letter = self.text[self.index]
if letter == '-':
letter = 'A' if increment == 1 else 'Z'
else:
letter = chr(ord(letter) + increment)
if ord(letter) == 91 or ord(letter) == 64:
letter = '-'
replacement = ""
2022-12-01 15:24:53 -05:00
for ii in range(len(self.text)):
2015-07-23 12:42:07 -04:00
if ii == self.index:
replacement += letter
else:
replacement += self.text[ii]
self.text = replacement
def activate(self):
self.active = True
def update(self):
if self.active:
ds = self.get_display_surface()
for ii, letter in enumerate(self.text):
box = render_box(self.font, letter, False, self.FOREGROUND, self.BACKGROUND,
self.FOREGROUND, padding=self.PADDING)
rect = box.get_rect()
rect.centery = ds.get_rect().centery
rect.centerx = ii * ds.get_width() / 3 + ds.get_width() / 6
ds.blit(box, rect)
if ii == self.index:
margin = self.ARROW_MARGIN
polygon(ds, (0, 255, 0), ((rect.left, rect.top - margin),
(rect.right, rect.top - margin),
(rect.centerx,
rect.top - margin - self.ARROW_HEIGHT)))
polygon(ds, (0, 255, 0), ((rect.left, rect.bottom + margin),
(rect.right, rect.bottom + margin),
(rect.centerx,
rect.bottom + margin + self.ARROW_HEIGHT)))
2014-04-27 14:21:42 -04:00
class Total(Sprite):
def __init__(self, parent):
Sprite.__init__(self, parent, 68)
self.deactivate()
2015-07-23 06:33:20 -04:00
self.font = Font(self.get_resource("display", "score-font-path"), 72)
# self.font.set_italic(True)
2014-04-27 14:21:42 -04:00
def deactivate(self):
self.active = False
def load(self):
self.clear_frames()
score = ""
for ch in str(int(round(self.get_game().triangles.score))):
score += ch + " "
2015-07-23 06:33:20 -04:00
colors = (255, 255, 180), (180, 255, 255), (255, 180, 255), \
(255, 220, 160), (160, 255, 220), (220, 160, 255)
2014-04-27 14:21:42 -04:00
template = Surface((self.display_surface.get_width(), 100))
transparent_color = (255, 0, 255)
template.fill(transparent_color)
template.set_colorkey(transparent_color)
tr = template.get_rect()
template.fill((255, 0, 0), (0, 20, tr.w, 1))
template.fill((255, 128, 128), (0, 21, tr.w, 1))
2022-12-01 15:24:53 -05:00
for y in range(22, 78, 2):
2014-04-27 14:21:42 -04:00
template.fill((255, 255, 255), (0, y, tr.w, 1))
template.fill((255, 128, 128), (0, 78, tr.w, 1))
template.fill((255, 0, 0), (0, 79, tr.w, 1))
2022-12-01 15:24:53 -05:00
for _ in range(20):
2015-07-23 06:33:20 -04:00
# surface = template.copy()
surface = Surface(template.get_size(), SRCALPHA)
# polygon(surface, choice(colors), ((tr.centerx - 7, 19),
# (tr.centerx, 0),
# (tr.centerx + 7, 19)))
2014-04-27 14:21:42 -04:00
text = self.font.render(score, True, choice(colors))
rect = text.get_rect()
rect.center = tr.centerx, tr.centery + 2
surface.blit(text, rect)
2015-07-23 06:33:20 -04:00
# polygon(surface, choice(colors), ((tr.centerx - 7, 80),
# (tr.centerx, tr.h - 1),
# (tr.centerx + 7, 80)))
2014-04-27 14:21:42 -04:00
self.add_frame(surface)
self.location.center = self.display_surface.get_rect().center
self.active = True
def update(self):
if self.active:
Sprite.update(self)