magfest
commit
c9f71f9429
@ -0,0 +1,5 @@
|
||||
*.pyc
|
||||
local/
|
||||
MANIFEST
|
||||
dist/
|
||||
build/
|
@ -0,0 +1,3 @@
|
||||
[submodule "lib/pgfw"]
|
||||
path = lib/pgfw
|
||||
url = makar:/var/www/git/pgfw
|
@ -0,0 +1,463 @@
|
||||
from random import randint, choice
|
||||
from copy import copy
|
||||
|
||||
from pygame import Surface, Color
|
||||
from pygame.mixer import Sound
|
||||
from pygame.image import load
|
||||
from pygame.transform import rotate
|
||||
from pygame.time import get_ticks
|
||||
from pygame.font import Font
|
||||
from pygame.locals import *
|
||||
|
||||
from lib.pgfw.pgfw.Game import Game
|
||||
from lib.pgfw.pgfw.GameChild import GameChild
|
||||
from lib.pgfw.pgfw.Sprite import Sprite, RainbowSprite
|
||||
from lib.pgfw.pgfw.Animation import Animation
|
||||
from lib.pgfw.pgfw.extension import get_step_relative
|
||||
from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon
|
||||
|
||||
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.initial_volume = volume
|
||||
self.set_volume(volume)
|
||||
|
||||
def play(self, loops=0, maxtime=0, fade_ms=0, position=None, x=None):
|
||||
self.set_volume(self.initial_volume *
|
||||
self.get_configuration("audio", "sfx-volume"))
|
||||
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 NS(Game, Animation):
|
||||
|
||||
NW, NE, SE, SW = range(4)
|
||||
FRONT_WIDTH = 230
|
||||
BACK_WIDTH = 500
|
||||
LENGTH = 150
|
||||
FRONT = 300
|
||||
STEP = .4
|
||||
|
||||
def __init__(self):
|
||||
Game.__init__(self)
|
||||
Animation.__init__(self, self)
|
||||
self.subscribe(self.respond, KEYDOWN)
|
||||
self.subscribe(self.respond, KEYUP)
|
||||
self.subscribe(self.respond)
|
||||
ds = self.get_display_surface()
|
||||
self.background = Surface(ds.get_size())
|
||||
self.background.fill((0, 0, 0))
|
||||
self.lights = [
|
||||
Light(self, "cyan", self.NW),
|
||||
Light(self, "magenta", self.NE),
|
||||
Light(self, "yellow", self.SE),
|
||||
Light(self, "white", self.SW)
|
||||
]
|
||||
self.chemtrails = Chemtrails(self)
|
||||
self.boss = Boss(self)
|
||||
self.last_press = get_ticks()
|
||||
self.register(self.unsuppress_restart)
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.suppress_restart = False
|
||||
self.game_over = False
|
||||
self.boss.reset()
|
||||
self.chemtrails.reset()
|
||||
for light in self.lights:
|
||||
light.reset()
|
||||
|
||||
def respond(self, event):
|
||||
if event.type in (KEYDOWN, KEYUP):
|
||||
# if self.last_press <= get_ticks() - int(self.get_configuration("input", "buffer")):
|
||||
pressed = True if event.type == KEYDOWN else False
|
||||
if (event.key in (K_UP, K_o)):
|
||||
self.lights[0].pressed = pressed
|
||||
if self.game_over and not self.suppress_restart:
|
||||
self.reset()
|
||||
elif (event.key in (K_RIGHT, K_p)):
|
||||
self.lights[1].pressed = pressed
|
||||
elif (event.key in (K_DOWN, K_SEMICOLON)):
|
||||
self.lights[2].pressed = pressed
|
||||
elif (event.key in (K_LEFT, K_l)):
|
||||
self.lights[3].pressed = pressed
|
||||
self.last_press = get_ticks()
|
||||
else:
|
||||
if self.get_delegate().compare(event, "reset-game"):
|
||||
self.reset()
|
||||
|
||||
def finish_battle(self, win):
|
||||
self.game_over = True
|
||||
font = Font(self.get_resource("rounded-mplus-1m-bold.ttf"), 128)
|
||||
text = font.render("YOU WIN" if win else "GAME OVER", True, Color("white"))
|
||||
self.message = Sprite(self)
|
||||
self.message.add_frame(text)
|
||||
self.message.location.center = self.get_display_surface().get_rect().center
|
||||
self.boss.halt(self.boss.brandish)
|
||||
self.boss.sword.reset()
|
||||
self.boss.queue = []
|
||||
self.boss.brandish_complete = True
|
||||
if win:
|
||||
self.boss.set_frameset(0)
|
||||
self.suppress_restart = True
|
||||
self.play(self.unsuppress_restart, delay=4000, play_once=True)
|
||||
|
||||
def unsuppress_restart(self):
|
||||
self.suppress_restart = False
|
||||
font = Font(self.get_resource("rounded-mplus-1m-bold.ttf"), 48)
|
||||
text = font.render("(PRESS BLUE TO RESTART)", True, Color("white"))
|
||||
self.restart_message = Sprite(self)
|
||||
self.restart_message.add_frame(text)
|
||||
dsr = self.get_display_surface().get_rect()
|
||||
self.restart_message.location.center = dsr.centerx, dsr.centery + 80
|
||||
|
||||
def update(self):
|
||||
Animation.update(self)
|
||||
self.get_display_surface().blit(self.background, (0, 0))
|
||||
self.boss.update()
|
||||
for light in self.lights:
|
||||
light.update()
|
||||
self.chemtrails.update()
|
||||
if self.game_over:
|
||||
self.message.update()
|
||||
if not self.suppress_restart:
|
||||
self.restart_message.update()
|
||||
|
||||
|
||||
class Light(Animation):
|
||||
|
||||
def __init__(self, parent, color, position):
|
||||
Animation.__init__(self, parent)
|
||||
self.color = Color(color)
|
||||
self.position = position
|
||||
self.pressed = False
|
||||
ds = self.get_display_surface()
|
||||
frontleft = ds.get_width() / 2 - NS.FRONT_WIDTH / 2, NS.FRONT
|
||||
backleft = ds.get_width() / 2 - NS.BACK_WIDTH / 2, NS.FRONT + NS.LENGTH
|
||||
left_step = get_step_relative(frontleft, backleft, NS.STEP)
|
||||
midleft = frontleft[0] + left_step[0], frontleft[1] + left_step[1]
|
||||
frontmid = ds.get_width() / 2, NS.FRONT
|
||||
mid = ds.get_width() / 2, NS.FRONT + NS.LENGTH * NS.STEP
|
||||
backmid = ds.get_width() / 2, NS.FRONT + NS.LENGTH
|
||||
frontright = ds.get_width() / 2 + NS.FRONT_WIDTH / 2, NS.FRONT
|
||||
backright = ds.get_width() / 2 + NS.BACK_WIDTH / 2, NS.FRONT + NS.LENGTH
|
||||
right_step = get_step_relative(frontright, backright, NS.STEP)
|
||||
midright = frontright[0] + right_step[0], frontright[1] + right_step[1]
|
||||
if self.position == NS.NW:
|
||||
self.points = frontleft, frontmid, mid, midleft
|
||||
elif self.position == NS.NE:
|
||||
self.points = frontmid, frontright, midright, mid
|
||||
elif self.position == NS.SE:
|
||||
self.points = mid, midright, backright, backmid
|
||||
elif self.position == NS.SW:
|
||||
self.points = midleft, mid, backmid, backleft
|
||||
self.register(self.blink, interval=300)
|
||||
|
||||
def reset(self):
|
||||
self.hidden = False
|
||||
self.halt(self.blink)
|
||||
|
||||
def blink(self):
|
||||
self.hidden = not self.hidden
|
||||
|
||||
def update(self):
|
||||
Animation.update(self)
|
||||
boss = self.get_game().boss
|
||||
chemtrails = self.get_game().chemtrails
|
||||
if boss.queue and boss.brandish_complete and not self.is_playing(self.blink) \
|
||||
and self.in_orientation(boss.queue[chemtrails.queue_index]):
|
||||
self.play(self.blink)
|
||||
elif self.is_playing(self.blink) and (not boss.queue or
|
||||
not self.in_orientation(boss.queue[chemtrails.queue_index])):
|
||||
self.reset()
|
||||
if not self.hidden:
|
||||
aa_filled_polygon(self.get_display_surface(), self.points, self.color)
|
||||
|
||||
def in_orientation(self, orientation):
|
||||
if self.position == NS.NW:
|
||||
return orientation in (Sword.N, Sword.NW, Sword.W)
|
||||
elif self.position == NS.NE:
|
||||
return orientation in (Sword.N, Sword.NE, Sword.E)
|
||||
elif self.position == NS.SE:
|
||||
return orientation in (Sword.NW, Sword.E, Sword.S)
|
||||
elif self.position == NS.SW:
|
||||
return orientation in (Sword.S, Sword.NE, Sword.W)
|
||||
|
||||
|
||||
class Chemtrails(GameChild):
|
||||
|
||||
TIME_LIMIT = 8000
|
||||
TIME_ADDITION = 1000
|
||||
|
||||
def __init__(self, parent):
|
||||
GameChild.__init__(self, parent)
|
||||
self.image = load(self.get_resource("Chemtrails.png")).convert_alpha()
|
||||
self.life = Life(self)
|
||||
|
||||
def reset(self):
|
||||
self.life.reset()
|
||||
self.timer_remaining = self.TIME_LIMIT
|
||||
|
||||
def challenge(self):
|
||||
self.timer_remaining = self.TIME_LIMIT
|
||||
self.queue_index = 0
|
||||
|
||||
def update(self):
|
||||
self.orient()
|
||||
if self.get_game().boss.queue:
|
||||
self.timer_remaining -= self.get_game().time_filter.get_last_frame_duration()
|
||||
self.attack()
|
||||
if self.timer_remaining < 0:
|
||||
self.life.decrease()
|
||||
if not self.get_game().game_over:
|
||||
self.timer_remaining = self.TIME_LIMIT
|
||||
self.get_game().boss.combo()
|
||||
font = Font(self.get_resource("rounded-mplus-1m-bold.ttf"), 24)
|
||||
text = font.render("%.2f" % max(0, self.timer_remaining / 1000.0), True, Color("white"))
|
||||
rect = text.get_rect()
|
||||
ds = self.get_display_surface()
|
||||
rect.topright = ds.get_rect().topright
|
||||
ds.blit(text, rect)
|
||||
self.life.update()
|
||||
|
||||
def attack(self):
|
||||
boss = self.get_game().boss
|
||||
queue = boss.queue
|
||||
if self.orientation == queue[self.queue_index]:
|
||||
self.timer_remaining += self.TIME_ADDITION
|
||||
boss.health.decrease(5)
|
||||
self.queue_index += 1
|
||||
if self.queue_index == len(queue):
|
||||
self.timer_remaining = self.TIME_LIMIT
|
||||
self.get_game().boss.combo()
|
||||
for light in self.get_game().lights:
|
||||
light.reset()
|
||||
light.reset_timer()
|
||||
|
||||
def orient(self):
|
||||
ds = self.get_display_surface()
|
||||
lights = self.parent.lights
|
||||
pressed = [light.position for light in self.parent.lights if light.pressed]
|
||||
if NS.NW in pressed and NS.NE in pressed:
|
||||
rect = self.image.get_rect()
|
||||
rect.center = ds.get_width() / 2, NS.FRONT - 30
|
||||
ds.blit(self.image, rect.topleft)
|
||||
self.orientation = Sword.N
|
||||
elif NS.NE in pressed and NS.SE in pressed:
|
||||
image = rotate(self.image, 270)
|
||||
rect = image.get_rect()
|
||||
rect.center = ds.get_width() / 2 + NS.FRONT_WIDTH / 2, NS.FRONT + NS.LENGTH * NS.STEP + 10
|
||||
ds.blit(image, rect.topleft)
|
||||
self.orientation = Sword.E
|
||||
elif NS.SE in pressed and NS.SW in pressed:
|
||||
rect = self.image.get_rect()
|
||||
rect.center = ds.get_width() / 2, NS.FRONT + NS.LENGTH - NS.LENGTH * NS.STEP - 20
|
||||
ds.blit(self.image, rect.topleft)
|
||||
self.orientation = Sword.S
|
||||
elif NS.SW in pressed and NS.NW in pressed:
|
||||
image = rotate(self.image, 270)
|
||||
rect = image.get_rect()
|
||||
rect.center = ds.get_width() / 2 - NS.FRONT_WIDTH / 2 + 70, NS.FRONT + NS.LENGTH * NS.STEP + 10
|
||||
ds.blit(image, rect.topleft)
|
||||
self.orientation = Sword.W
|
||||
elif NS.NW in pressed and NS.SE in pressed:
|
||||
image = rotate(self.image, 315)
|
||||
rect = image.get_rect()
|
||||
rect.center = ds.get_width() / 2 + 45, NS.FRONT + NS.LENGTH * NS.STEP - 40
|
||||
ds.blit(image, rect.topleft)
|
||||
self.orientation = Sword.NW
|
||||
elif NS.NE in pressed and NS.SW in pressed:
|
||||
image = rotate(self.image, 45)
|
||||
rect = image.get_rect()
|
||||
rect.center = ds.get_width() / 2 - 30, NS.FRONT + NS.LENGTH * NS.STEP - 50
|
||||
ds.blit(image, rect.topleft)
|
||||
self.orientation = Sword.NE
|
||||
else:
|
||||
self.orientation = None
|
||||
|
||||
|
||||
class Life(GameChild):
|
||||
|
||||
SPACING = 30
|
||||
MARGIN = 0
|
||||
|
||||
def __init__(self, parent):
|
||||
GameChild.__init__(self, parent)
|
||||
self.heart = load(self.get_resource("Heart.png")).convert_alpha()
|
||||
|
||||
def reset(self):
|
||||
self.count = 3
|
||||
|
||||
def decrease(self):
|
||||
if self.count > 0:
|
||||
self.count -= 1
|
||||
if self.count <= 0:
|
||||
self.count = 0
|
||||
self.get_game().finish_battle(False)
|
||||
|
||||
def update(self):
|
||||
ds = self.get_display_surface()
|
||||
dsr = ds.get_rect()
|
||||
hr = self.heart.get_rect()
|
||||
rect = Rect(0, 0, hr.w * self.count + self.SPACING * (self.count - 1), hr.h)
|
||||
rect.midbottom = dsr.centerx, dsr.h - self.MARGIN
|
||||
for x in xrange(rect.left, rect.right, hr.w + self.SPACING):
|
||||
ds.blit(self.heart, (x, rect.top))
|
||||
|
||||
|
||||
class Boss(RainbowSprite):
|
||||
|
||||
def __init__(self, parent):
|
||||
RainbowSprite.__init__(self, parent, load("resource/Koolaid.png").convert_alpha(), 30)
|
||||
self.health = Health(self)
|
||||
self.sword = Sword(self)
|
||||
self.register(self.brandish, self.cancel_flash)
|
||||
self.add_frameset([0], name="normal")
|
||||
|
||||
def cancel_flash(self):
|
||||
self.set_frameset("normal")
|
||||
|
||||
def reset(self):
|
||||
self.unhide()
|
||||
self.cancel_flash()
|
||||
self.halt(self.cancel_flash)
|
||||
self.health.reset()
|
||||
self.halt(self.brandish)
|
||||
self.sword.reset()
|
||||
self.combo()
|
||||
self.queue = None
|
||||
self.brandish_complete = True
|
||||
|
||||
def combo(self):
|
||||
self.queue = None
|
||||
self.play(self.brandish, delay=2500, play_once=True)
|
||||
|
||||
def brandish(self):
|
||||
self.queue = []
|
||||
choices = range(6)
|
||||
if self.health.amount > 90:
|
||||
length = 1
|
||||
elif self.health.amount > 70:
|
||||
length = 2
|
||||
elif self.health.amount > 40:
|
||||
length = 3
|
||||
else:
|
||||
length = 4
|
||||
while len(self.queue) < length:
|
||||
while True:
|
||||
orientation = randint(0, 5)
|
||||
if not self.queue or orientation != self.queue[-1]:
|
||||
self.queue.append(orientation)
|
||||
break
|
||||
self.unbrandished = copy(self.queue)
|
||||
self.brandish_complete = False
|
||||
self.sword.play(self.sword.brandish, play_once=True)
|
||||
self.get_game().chemtrails.challenge()
|
||||
|
||||
def update(self):
|
||||
RainbowSprite.update(self)
|
||||
# self.get_display_surface().blit(self.image, (0, 0))
|
||||
self.sword.update()
|
||||
self.health.update()
|
||||
|
||||
|
||||
class Sword(Sprite):
|
||||
|
||||
N, E, S, W, NE, NW = range(6)
|
||||
|
||||
def __init__(self, parent):
|
||||
Sprite.__init__(self, parent)
|
||||
image = load(self.get_resource("Sword.png")).convert_alpha()
|
||||
self.add_frame(image)
|
||||
for angle in 270, 315, 45:
|
||||
self.add_frame(rotate(image, angle))
|
||||
self.add_frameset([0], name="vertical")
|
||||
self.add_frameset([1], name="horizontal")
|
||||
self.add_frameset([2], name="rdiagonal")
|
||||
self.add_frameset([3], name="ldiagonal")
|
||||
self.set_frameset("vertical")
|
||||
self.location.center = self.get_display_surface().get_rect().center
|
||||
self.register(self.brandish, self.lower)
|
||||
|
||||
def reset(self):
|
||||
self.halt(self.brandish)
|
||||
self.halt(self.lower)
|
||||
self.hide()
|
||||
|
||||
def brandish(self):
|
||||
self.unhide()
|
||||
position = self.parent.unbrandished.pop(0)
|
||||
dsr = self.get_display_surface().get_rect()
|
||||
if position in (self.W, self.E):
|
||||
self.set_frameset("vertical")
|
||||
self.location.centery = dsr.centery - 100
|
||||
if position == self.W:
|
||||
self.location.centerx = dsr.centerx - 100
|
||||
else:
|
||||
self.location.centerx = dsr.centerx + 100
|
||||
elif position in (self.N, self.S):
|
||||
self.set_frameset("horizontal")
|
||||
self.location.centerx = dsr.centerx
|
||||
if position == self.N:
|
||||
self.location.centery = dsr.centery - 200
|
||||
else:
|
||||
self.location.centery = dsr.centery
|
||||
else:
|
||||
if position == self.NW:
|
||||
self.set_frameset("ldiagonal")
|
||||
else:
|
||||
self.set_frameset("rdiagonal")
|
||||
self.location.center = dsr.centerx, dsr.centery - 100
|
||||
self.play(self.lower, delay=400, play_once=True)
|
||||
if len(self.parent.unbrandished) > 0:
|
||||
self.play(self.brandish, delay=600, play_once=True)
|
||||
|
||||
def lower(self):
|
||||
self.hide()
|
||||
if len(self.parent.unbrandished) == 0:
|
||||
self.parent.brandish_complete = True
|
||||
|
||||
def update(self):
|
||||
Sprite.update(self)
|
||||
|
||||
|
||||
class Health(GameChild):
|
||||
|
||||
WIDTH = 200
|
||||
HEIGHT = 32
|
||||
COLOR = "yellow"
|
||||
|
||||
def __init__(self, parent):
|
||||
GameChild.__init__(self, parent)
|
||||
|
||||
def reset(self):
|
||||
self.amount = 100
|
||||
|
||||
def decrease(self, damage):
|
||||
self.amount -= damage
|
||||
if self.amount <= 0:
|
||||
self.amount = 0
|
||||
self.get_game().finish_battle(True)
|
||||
else:
|
||||
self.parent.play(self.parent.cancel_flash, delay=1000, play_once=True)
|
||||
self.parent.set_frameset(0)
|
||||
|
||||
def update(self):
|
||||
surface = Surface((int(self.WIDTH * (self.amount / 100.0)), self.HEIGHT))
|
||||
surface.fill(Color(self.COLOR))
|
||||
surface.set_alpha(255)
|
||||
font = Font(self.get_resource("rounded-mplus-1m-bold.ttf"), 14)
|
||||
text = font.render("HEALTH", True, Color("black"))
|
||||
# surface.blit(text, (8, 0))
|
||||
self.get_display_surface().blit(surface, (0, 0))
|
@ -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 NS import NS
|
||||
|
||||
NS().run()
|
@ -0,0 +1,27 @@
|
||||
[setup]
|
||||
license = Public Domain
|
||||
title = Untitled
|
||||
url = http://A-O.in/
|
||||
version = 0.1
|
||||
init-script = OPEN-GAME
|
||||
additional-packages = lib
|
||||
data-exclude = local/, *.pyc
|
||||
|
||||
[display]
|
||||
caption = Untitled
|
||||
show-framerate = False
|
||||
dimensions = 640, 480
|
||||
fullscreen = no
|
||||
|
||||
[mouse]
|
||||
visible = False
|
||||
|
||||
[keys]
|
||||
quit = K_ESCAPE
|
||||
up = K_u
|
||||
|
||||
[audio]
|
||||
sfx-volume = .8
|
||||
|
||||
[input]
|
||||
buffer = 200
|
@ -0,0 +1 @@
|
||||
Subproject commit 446388ef9a6d52b8ebf111d277fc65ca5a6d9c31
|
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
@ -0,0 +1,13 @@
|
||||
from sys import platform
|
||||
|
||||
if __name__ == "__main__":
|
||||
if platform == "darwin":
|
||||
from lib.pgfw.pgfw.SetupOSX import SetupOSX
|
||||
SetupOSX("OPEN-GAME",
|
||||
["NS.py", "resource", "lib", "config"]).setup()
|
||||
elif platform == "win32":
|
||||
from lib.pgfw.pgfw.SetupWin import SetupWin
|
||||
SetupWin().setup()
|
||||
else:
|
||||
from lib.pgfw.pgfw.Setup import Setup
|
||||
Setup().setup()
|
Loading…
Reference in New Issue