diff --git a/config b/config index bdb208d..16cc4d0 100644 --- a/config +++ b/config @@ -51,3 +51,12 @@ shift-2 = C 0.0 0.0, 210.0 4.2, 500.0 8.0 shift = C 0.0 0.0, 500.0 3.5, 1000.0 6.0 boost = L 0.0 0.0, 100.0 6.0 intensity = C 0.0 0.15, 10000 0.3, 25000 0.4 + +[land] +gradient = 80 +height = 180 +altitude-ratio = 0.005 +x-step = 50 +spacing-factor = 1.2 +velocity-ratio = 0.25 +fade-speed = 1.25 diff --git a/electric_sieve/ElectricSieve.py b/electric_sieve/ElectricSieve.py index 6444f79..5fc4a5b 100644 --- a/electric_sieve/ElectricSieve.py +++ b/electric_sieve/ElectricSieve.py @@ -18,6 +18,8 @@ from lib.pgfw.pgfw.Sprite import Sprite from lib.pgfw.pgfw.Vector import Vector from lib.pgfw.pgfw.extension import render_box +from electric_sieve.land.Land import Land + # Import GPIO library if available try: import RPi.GPIO as GPIO @@ -40,7 +42,16 @@ class ElectricSieve(Game): Game.__init__(self) # Add type declarations for custom config entries - self.get_configuration().type_declarations.add("bool", "display", "rotate") + self.get_configuration().type_declarations.add_chart({ + "display": + { + "bool": "rotate" + }, + "land": + { + "int": ["gradient", "height", "x-step"], + "float": ["altitude-ratio", "spacing-factor", "velocity-ratio", "fade-speed"] + }}) # Rotate the display if requested on the command line or in the configuration if self.check_command_line("-rotate"): @@ -53,6 +64,8 @@ class ElectricSieve(Game): # Initialize GPIO input and callbacks if GPIO library is loaded if "RPi.GPIO" in sys.modules: self.initialize_gpio() + + self.velocity = Vector(0, 0) # Create game objects self.title = Title(self) @@ -60,6 +73,7 @@ class ElectricSieve(Game): self.triangles = Triangles(self) self.acid = Acid(self) self.static = Static(self) + self.land = Land(self) # Create a purple background self.background = Surface(self.display.screen.get_size()) @@ -147,6 +161,7 @@ class ElectricSieve(Game): self.title.update() if self.triangles.active: self.display.screen.blit(self.background, (0, 0)) + self.land.update() self.static.update() self.triangles.update() self.sieve.update() @@ -578,7 +593,7 @@ class Triangles(GameChild, list): class Triangle(Sprite): def __init__(self, parent): - Sprite.__init__(self, parent) + Sprite.__init__(self, parent, 100) mark = randint(112, 328) sieve = self.parent.parent.sieve gaps = sieve.gaps @@ -588,22 +603,29 @@ class Triangle(Sprite): widths.append(gaps[(start + len(widths)) % len(gaps)]) surface = Surface((sum(widths), 20)) surface.set_colorkey((0, 0, 0)) - x = 0 height = surface.get_height() margin = 26 self.collision_rects = collision_rects = [] - for width in widths: - 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) - if not self.get_game().rotated: - collision_rects.append(Rect(points[0], (width - margin - 1, 1))) - else: - collision_rects.append(Rect(height - 2 - 1, self.get_display_surface().get_height() - x - width + margin // 2 + 1, 1, width - margin - 1)) - x += width - sieve.bar_w - self.add_frame(self.get_game().orient(surface)) + for ii, color in enumerate(((60, 255, 220), (90, 255, 190), (120, 255, 160), (150, 255, 130))): + x = 0 + surface = surface.copy() + for width in widths: + x += sieve.bar_w + points = ((x + margin // 2, height - 2), + (x + width - margin // 2 - 1, height - 2), + (x + width / 2.0, 1)) + polygon(surface, color, points) + if ii == 0: + if not self.get_game().rotated: + collision_rects.append(Rect(points[0], (width - margin - 1, 1))) + else: + collision_rects.append(Rect(height - 2 - 1, self.get_display_surface().get_height() - x - width + margin // 2 + 1, 1, width - margin - 1)) + points = ((x + margin // 2 + (width * .1), height - 2 - 2), + (x + width - margin // 2 - 1 - (width * .1), height - 2 - 2), + (x + width / 2.0, 1 + 5)) + polygon(surface, (0, 0, 0), points) + x += width - sieve.bar_w + self.add_frame(self.get_game().orient(surface)) if not self.get_game().rotated: self.location.centerx = self.get_display_surface().get_rect().centerx else: diff --git a/electric_sieve/land/Land.py b/electric_sieve/land/Land.py new file mode 100644 index 0000000..72af047 --- /dev/null +++ b/electric_sieve/land/Land.py @@ -0,0 +1,43 @@ +import pygame +from pygame import Rect +from pygame.locals import * + +from lib.pgfw.pgfw.GameChild import GameChild +from electric_sieve.land.Mask import Mask +from electric_sieve.land.Plate import Plate + +class Land(GameChild, Rect): + + def __init__(self, parent): + GameChild.__init__(self, parent) + self.load_configuration() + self.mask = Mask(self) + self.plate = Plate(self) + self.display_surface = self.get_display_surface() + self.intermediate = pygame.Surface(self.display_surface.get_size()) + self.intermediate.set_colorkey((0, 0, 0)) + self.init_rect() + self.reset() + + def load_configuration(self): + config = self.get_configuration("land") + self.height = config["height"] + self.altitude_ratio = config["altitude-ratio"] + + def init_rect(self): + Rect.__init__(self, (0, self.get_initial_top()), self.mask.get_size()) + + def get_initial_top(self): + return self.display_surface.get_height() - self.h + + def reset(self): + self.top = self.get_initial_top() + self.mask.reset() + self.plate.reset() + + def update(self): + self.mask.update() + self.plate.update() + self.intermediate.blit(self.plate, self) + self.intermediate.blit(self.mask, self, None, BLEND_RGB_MIN) + self.get_display_surface().blit(self.intermediate, (0, 0)) diff --git a/electric_sieve/land/Mask.py b/electric_sieve/land/Mask.py new file mode 100644 index 0000000..4c71341 --- /dev/null +++ b/electric_sieve/land/Mask.py @@ -0,0 +1,73 @@ +from math import tan, radians + +import pygame +from pygame import Surface +from pygame.draw import line + +from lib.pgfw.pgfw.GameChild import GameChild + +class Mask(GameChild, Surface): + + def __init__(self, parent): + GameChild.__init__(self, parent) + self.display_surface = self.get_display_surface() + self.load_configuration() + self.init_surface() + self.set_background() + self.reset() + + def load_configuration(self): + config = self.get_configuration("land") + self.height = config["height"] + self.spacing_factor = config["spacing-factor"] + self.gradient = config["gradient"] + self.x_step = config["x-step"] + self.velocity_ratio = config["velocity-ratio"] + + def init_surface(self): + Surface.__init__(self, (self.get_display_surface().get_width(), self.height)) + + def set_background(self): + background = Surface(self.get_size()) + background.fill((0, 0, 0)) + self.background = background + + def reset(self): + self.x_offset = 0 + + def update(self): + self.clear() + self.draw_y() + self.draw_x() + + def clear(self): + self.blit(self.background, (0, 0)) + + def draw_y(self): + yy = 0 + ii = 0 + rect = self.get_rect() + while yy < rect.bottom: + line(self, (255, 255, 255), (0, yy), (rect.right, yy)) + yy += int(self.spacing_factor ** ii) + ii += 1 + + def draw_x(self): + gradient = self.gradient + step = self.x_step + rect = self.get_rect() + edge = rect.right + xx = int(self.x_offset) + step + adjacent = rect.h + while xx < edge: + angle = (edge - float(xx)) / edge * 2 * gradient + (90 - gradient) + opposite = int(tan(radians(90 - angle)) * adjacent) + line(self, (255, 255, 255), (xx, 0), + (xx + opposite, adjacent)) + xx += step + self.decrement_x_offset() + + def decrement_x_offset(self): + self.x_offset -= self.parent.parent.velocity[0] * self.velocity_ratio + if self.x_offset <= -self.x_step: + self.x_offset += self.x_step diff --git a/electric_sieve/land/Plate.py b/electric_sieve/land/Plate.py new file mode 100644 index 0000000..7dbadaf --- /dev/null +++ b/electric_sieve/land/Plate.py @@ -0,0 +1,49 @@ +from pygame import Surface, Color + +from lib.pgfw.pgfw.GameChild import GameChild + +class Plate(GameChild, Surface): + + def __init__(self, parent): + GameChild.__init__(self, parent) + self.load_configuration() + self.init_surface() + self.set_background() + + def load_configuration(self): + config = self.get_configuration("land") + self.height = config["height"] + self.speed = config["fade-speed"] + + def init_surface(self): + Surface.__init__(self, (self.get_display_surface().get_width(), self.height)) + + def set_background(self): + width, height = self.get_size() + background = Surface((width, height)) + color = Color(0, 0, 0) + for y in range(height): + hue = abs(int(float(y) / (height) * 240) - 120) + color.hsva = hue, 100, 20, 100 + background.fill(color, (0, y, width, 1)) + self.background = background + + def reset(self): + self.offset = 0 + + def update(self): + self.update_offset() + self.draw() + + def update_offset(self): + offset = self.offset - self.speed + height = self.get_height() + if offset < -height: + offset += height + self.offset = offset + + def draw(self): + offset = int(self.offset) + background = self.background + self.blit(background, (0, offset)) + self.blit(background, (0, offset + self.get_height())) diff --git a/electric_sieve/land/__init__.py b/electric_sieve/land/__init__.py new file mode 100644 index 0000000..e69de29