compress
authorFrank DeMarco <frank.s.demarco@gmail.com>
Sun, 28 Aug 2016 19:48:24 +0000 (15:48 -0400)
committerFrank DeMarco <frank.s.demarco@gmail.com>
Sun, 28 Aug 2016 19:48:24 +0000 (15:48 -0400)
12 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
HEAVENSlime.py [new file with mode: 0644]
OPEN-GAME [new file with mode: 0755]
config [new file with mode: 0644]
lib [new submodule]
resource/Climb.ogg [new file with mode: 0644]
resource/Face.png [new file with mode: 0644]
resource/Ground.png [new file with mode: 0644]
resource/Platform.png [new file with mode: 0644]
resource/Title.ogg [new file with mode: 0644]
resource/Title.png [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..08d644d
--- /dev/null
@@ -0,0 +1,2 @@
+HEAVENSlime.pyc
+local/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..5500211
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "lib"]
+       path = lib
+       url = makar:/var/www/git/pgfw
diff --git a/HEAVENSlime.py b/HEAVENSlime.py
new file mode 100644 (file)
index 0000000..d9cf66d
--- /dev/null
@@ -0,0 +1,294 @@
+from pygame import Rect, Surface, Color, mixer
+from pygame.image import load
+from pygame.mixer import Sound
+from pygame.transform import scale
+
+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.Animation import Animation
+from lib.pgfw.pgfw.extension import get_hsla_color, get_value_in_range
+
+class SoundEffect(GameChild, Sound):
+
+    def __init__(self, parent, path, volume=1.0):
+        GameChild.__init__(self, parent)
+        Sound.__init__(self, path)
+        self.display_surface = self.get_display_surface()
+        self.set_volume(volume)
+
+    def play(self, loops=0, maxtime=0, fade_ms=0, position=None, x=None):
+        channel = Sound.play(self, loops, maxtime, fade_ms)
+        if x is not None:
+            position = float(x) / self.display_surface.get_width()
+       if position is not None and channel is not None:
+            channel.set_volume(*self.get_panning(position))
+        return channel
+
+    def get_panning(self, position):
+        return 1 - max(0, ((position - .5) * 2)), \
+               1 + min(0, ((position - .5) * 2))
+
+
+class HEAVENSlime(Game):
+
+    CROSSFADE_MS = 3000
+
+    def __init__(self):
+        Game.__init__(self)
+        self.title = Title(self)
+        self.arena = Arena(self)
+        self.title.activate()
+        self.get_input().register_any_press_ignore("left", "right", "pause")
+        self.subscribe(self.respond)
+
+    def respond(self, event):
+        if self.get_delegate().compare(event, "reset-game"):
+            if not self.title.active:
+                self.arena.deactivate()
+                self.title.activate()
+
+    def update(self):
+        self.title.update()
+        self.arena.update()
+
+
+class Title(GameChild):
+
+    CHARGE_INCREASE = 1
+    CHARGE_THRESHOLD = 30
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.music = Sound(self.get_resource("Title.ogg"))
+        self.music.set_volume(.45)
+        self.subscribe(self.respond)
+
+    def respond(self, event):
+        if self.active:
+            delegate = self.get_delegate()
+            if delegate.compare(event, "any"):
+                self.charging = True
+            elif delegate.compare(event, "any", cancel=True):
+                self.charging = False
+                self.spring()
+
+    def spring(self):
+        print self.charge
+        if self.charge > self.CHARGE_THRESHOLD:
+            self.deactivate()
+            self.parent.arena.activate()
+        self.charge = 0
+
+    def activate(self):
+        self.active = True
+        self.charging = False
+        self.charge = 0
+        self.music.play(-1, 0, HEAVENSlime.CROSSFADE_MS)
+
+    def deactivate(self):
+        self.active = False
+        self.music.fadeout(HEAVENSlime.CROSSFADE_MS)
+
+    def update(self):
+        if self.active:
+            background = load(self.get_resource("Title.png")).convert()
+            self.get_display_surface().blit(background, (0, 0))
+            if self.charging:
+                self.charge += self.CHARGE_INCREASE
+
+
+class Arena(Animation):
+
+    SKY_COLOR = (25, 168, 255)
+    GRADIENT_SPAN = 100
+    GRADIENT_INTERVAL = 400
+    GRADIENT_HUE_STEP = 1
+
+    def __init__(self, parent):
+        Animation.__init__(self, parent)
+        ground = self.ground = Sprite(self)
+        ground.load_from_path(self.get_resource("Ground.png"), True)
+        self.music = Sound(self.get_resource("Climb.ogg"))
+        self.meter = Meter(self)
+        self.slime = Slime(self)
+        self.register(self.set_gradient)
+        self.subscribe(self.respond)
+        self.deactivate()
+        self.play(self.set_gradient, interval=self.GRADIENT_INTERVAL)
+
+    def reset(self):
+        self.suppressing_input = False
+        self.ground.location.bottom = self.get_display_surface().get_rect().bottom
+        self.slime.reset()
+        self.meter.reset()
+
+    def respond(self, event):
+        if self.active and not self.suppressing_input:
+            delegate = self.get_delegate()
+            if delegate.compare(event, "pause"):
+                if self.paused:
+                    self.unpause()
+                else:
+                    self.pause()
+            elif not self.paused:
+                if delegate.compare(event, "any"):
+                    self.meter.hold()
+                elif delegate.compare(event, "any", cancel=True):
+                    self.meter.release()
+
+    def pause(self):
+        self.paused = True
+        mixer.pause()
+
+    def unpause(self):
+        self.paused = False
+        mixer.unpause()
+
+    def set_gradient(self):
+        if not self.paused:
+            self.background = Surface(self.get_screen().get_size())
+            rh = self.background.get_height() / self.GRADIENT_SPAN
+            y = self.background.get_height() - rh
+            for hue in xrange(self.sky_hue, self.sky_hue + self.GRADIENT_SPAN, 1):
+                color = Color(0, 0, 0)
+                color.hsla = hue % 360, 60, 60, 100
+                self.background.fill(get_hsla_color(hue, 60, 60),
+                                     (0, y, self.background.get_width(), y + rh))
+                y -= rh
+            self.sky_hue += self.GRADIENT_HUE_STEP
+            if self.sky_hue >= 360:
+                self.sky_hue -= 360
+
+    def activate(self):
+        self.active = True
+        self.paused = False
+        self.sky_hue = 0
+        self.music.play(-1, 0, HEAVENSlime.CROSSFADE_MS)
+        self.meter.reset()
+        self.reset()
+
+    def deactivate(self):
+        self.active = False
+        self.music.fadeout(HEAVENSlime.CROSSFADE_MS)
+
+    def update(self):
+        if self.active:
+            Animation.update(self)
+            ds = self.get_display_surface()
+            ds.blit(self.background, (0, 0))
+            self.ground.update()
+            self.meter.update()
+            self.slime.update()
+
+
+class Meter(Animation):
+
+    HUE_STEP = 60
+    CHARGE_INCREASE = .0125
+    WIDTH_RANGE = 4, 220
+    HEIGHT_RANGE = 1, 30
+    COLORS = ["#FF8080", "#FFC080", "#FFFF80", "#C0FF80", "#80FF80", "#80FFC0",
+              "#80FFFF", "#80C0FF", "#8080FF", "#C080FF", "#FF80FF"]
+
+    def __init__(self, parent):
+        Animation.__init__(self, parent)
+        self.color_index = 0
+
+    def reset(self):
+        self.charge = 0
+        self.charging = False
+
+    def hold(self):
+        self.charging = True
+
+    def release(self):
+        self.reset()
+
+    def update(self):
+        if self.charging:
+            self.charge += self.CHARGE_INCREASE
+            if self.charge > 1:
+                self.charge = 0
+            self.color_index += 1
+            if self.color_index == len(self.COLORS):
+                self.color_index = 0
+            width = get_value_in_range(self.WIDTH_RANGE[0], self.WIDTH_RANGE[1], self.charge)
+            height = get_value_in_range(self.HEIGHT_RANGE[0], self.HEIGHT_RANGE[1], self.charge)
+            rect = Rect(0, 0, width, height)
+            ds = self.get_display_surface()
+            rect.midbottom = ds.get_rect().midbottom
+            surface = Surface(rect.size)
+            surface.fill(Color(self.COLORS[self.color_index]))
+            ds.blit(surface, rect)
+
+
+class Slime(Sprite):
+
+    LAUNCH = 7.25
+    SEGMENT_WIDTH = 24
+    HEIGHT = 20
+    COMPRESS = 16
+    BULGE = 40
+    COLORS = Color(28, 187, 183), Color(235, 42, 128), Color(220, 240, 13)
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.face = load(self.get_resource("Face.png")).convert_alpha()
+
+    def reset(self):
+        self.segments = [self.COLORS[0]]
+
+    def place(self):
+        ds = self.get_display_surface()
+        self.location.bottom = ds.get_height() - self.parent.ground.location.h - 1
+        self.location.centerx = ds.get_rect().centerx
+
+    def set_frame(self):
+        self.clear_frames()
+        charge = self.parent.meter.charge
+        width_add = self.BULGE * charge
+        width = int((self.SEGMENT_WIDTH + width_add) * len(self.segments))
+        height_subtract = self.COMPRESS * charge
+        height = int(self.HEIGHT - height_subtract)
+        frame = Surface((width, height))
+        frame.fill((128, 128, 128))
+        frame.set_colorkey((128, 128, 128))
+        x = 1
+        segment_ii = 0
+        step = float(width - 2) / len(self.segments)
+        frame.set_clip((1, 1, width - 2, height - 2))
+        while x <= width - step:
+            frame.fill(self.segments[segment_ii], (int(x), 1, int(step) + 1, height - 2))
+            x += step
+            segment_ii += 1
+        frame.set_clip()
+        border = (0, 0, 0)
+        frame.fill(border, (2, 0, width - 4, 1))
+        frame.set_at((1, 1), border)
+        frame.set_at((width - 2, 1), border)
+        frame.fill(border, (0, 2, 1, height - 4))
+        frame.fill(border, (width - 1, 2, 1, height - 4))
+        frame.set_at((1, height - 2), border)
+        frame.set_at((width - 2, height - 2), border)
+        frame.fill(border, (2, height - 1, width - 4, 1))
+        face = self.face
+        if charge:
+            face = scale(face, (face.get_width() + int(width_add / 4),
+                                face.get_height() - int(height_subtract / 4)))
+        fr = face.get_rect()
+        sr = frame.get_rect()
+        fr.centerx = sr.centerx
+        fr.centery = sr.centery + sr.h / 8
+        frame.blit(face, fr)
+        self.add_frame(frame)
+        self.place()
+
+    def update(self):
+        self.set_frame()
+        Sprite.update(self)
+
+
+class Platform(Sprite):
+
+    pass
diff --git a/OPEN-GAME b/OPEN-GAME
new file mode 100755 (executable)
index 0000000..d447091
--- /dev/null
+++ b/OPEN-GAME
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+from os import environ, execvp, chdir, getcwd
+from os.path import exists, join, dirname
+from sys import version_info, argv, maxint
+
+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]))
+
+if is_python_3():
+    launch_alternative(["python2", "python2.7", "python2.6"])
+
+if maxint >> 33:
+    launch_alternative(["python-32", "python2-32", "python2.7-32", "python2.6-32"])
+
+if not can_import("pygame"):
+    launch_alternative(["python2.7", "python2.6"])
+
+if "--go-to-dir" in argv:
+    move_to_executable()
+
+from HEAVENSlime import HEAVENSlime
+
+HEAVENSlime().run()
diff --git a/config b/config
new file mode 100644 (file)
index 0000000..ffd1056
--- /dev/null
+++ b/config
@@ -0,0 +1,22 @@
+[display]
+caption = HEAVEN Slime
+show-framerate = False
+dimensions = 480, 800
+
+[mouse]
+visible = False
+
+[keys]
+pause = K_RETURN
+
+[joy]
+left = 4
+right = 5
+pause = 10
+
+[interpolate]
+shot-speed = C 0.0 2.0, 6.9 4.4, 11.0 6.5, 30.0 12.0
+shot-speed-1 = C 0.0 2.0, 10.0 7.5, 30.0 12.0
+shot-speed-4 = C 0.0 2.5, 10.0 4.0, 30.0 7.5
+shot-speed-3 = C 0.0 2.5, 10.0 5.0, 30.0 7.5
+shot-speed-2 = C 0.0 2.0, 10.0 6.0, 30.0 9.0
diff --git a/lib b/lib
new file mode 160000 (submodule)
index 0000000..004b577
--- /dev/null
+++ b/lib
@@ -0,0 +1 @@
+Subproject commit 004b577f9fd70f61c8dd4402055b290f72666a05
diff --git a/resource/Climb.ogg b/resource/Climb.ogg
new file mode 100644 (file)
index 0000000..77765df
Binary files /dev/null and b/resource/Climb.ogg differ
diff --git a/resource/Face.png b/resource/Face.png
new file mode 100644 (file)
index 0000000..91795a0
Binary files /dev/null and b/resource/Face.png differ
diff --git a/resource/Ground.png b/resource/Ground.png
new file mode 100644 (file)
index 0000000..2806392
Binary files /dev/null and b/resource/Ground.png differ
diff --git a/resource/Platform.png b/resource/Platform.png
new file mode 100644 (file)
index 0000000..ecd113a
Binary files /dev/null and b/resource/Platform.png differ
diff --git a/resource/Title.ogg b/resource/Title.ogg
new file mode 100644 (file)
index 0000000..208384f
Binary files /dev/null and b/resource/Title.ogg differ
diff --git a/resource/Title.png b/resource/Title.png
new file mode 100644 (file)
index 0000000..b7c8b06
Binary files /dev/null and b/resource/Title.png differ