lost original git repo master
authorFrank DeMarco <if.self.end@gmail.com>
Wed, 5 Feb 2020 19:37:12 +0000 (14:37 -0500)
committerFrank DeMarco <if.self.end@gmail.com>
Wed, 5 Feb 2020 19:37:12 +0000 (14:37 -0500)
346 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
README [new file with mode: 0644]
config [new file with mode: 0644]
doc/ending [new file with mode: 0644]
food-spring [new file with mode: 0755]
food_spring/FoodSpring.py [new file with mode: 0644]
food_spring/Siphon.py [new file with mode: 0644]
food_spring/Spanky.py [new file with mode: 0644]
food_spring/Timer.py [new file with mode: 0644]
food_spring/Types.py [new file with mode: 0644]
food_spring/__init__.py [new file with mode: 0644]
food_spring/gaia/Gaia.py [new file with mode: 0644]
food_spring/gaia/Swapper.py [new file with mode: 0644]
food_spring/gaia/__init__.py [new file with mode: 0644]
food_spring/gun/Gun.py [new file with mode: 0644]
food_spring/gun/GunLibrary.py [new file with mode: 0644]
food_spring/gun/__init__.py [new file with mode: 0644]
food_spring/home/Foods.py [new file with mode: 0644]
food_spring/home/Home.py [new file with mode: 0644]
food_spring/home/StaticEnvironment.py [new file with mode: 0644]
food_spring/home/View.py [new file with mode: 0644]
food_spring/home/__init__.py [new file with mode: 0644]
food_spring/home/collection/Collection.py [new file with mode: 0644]
food_spring/home/collection/__init__.py [new file with mode: 0644]
food_spring/introduction/Epithet.py [new file with mode: 0644]
food_spring/introduction/Introduction.py [new file with mode: 0644]
food_spring/introduction/__init__.py [new file with mode: 0644]
food_spring/level/ExitArrow.py [new file with mode: 0644]
food_spring/level/Food.py [new file with mode: 0644]
food_spring/level/Level.py [new file with mode: 0644]
food_spring/level/Levels.py [new file with mode: 0644]
food_spring/level/Window.py [new file with mode: 0644]
food_spring/level/__init__.py [new file with mode: 0644]
food_spring/level/door/Background.py [new file with mode: 0644]
food_spring/level/door/Door.py [new file with mode: 0644]
food_spring/level/door/Foreground.py [new file with mode: 0644]
food_spring/level/door/__init__.py [new file with mode: 0644]
food_spring/level/drop/Blinker.py [new file with mode: 0644]
food_spring/level/drop/Blob.py [new file with mode: 0644]
food_spring/level/drop/Drop.py [new file with mode: 0644]
food_spring/level/drop/Drops.py [new file with mode: 0644]
food_spring/level/drop/__init__.py [new file with mode: 0644]
food_spring/level/grapes/Grapes.py [new file with mode: 0644]
food_spring/level/grapes/__init__.py [new file with mode: 0644]
food_spring/level/land/Land.py [new file with mode: 0644]
food_spring/level/land/Mask.py [new file with mode: 0644]
food_spring/level/land/Plate.py [new file with mode: 0644]
food_spring/level/land/__init__.py [new file with mode: 0644]
food_spring/level/obstacle/Fireball.py [new file with mode: 0644]
food_spring/level/obstacle/Hurdle.py [new file with mode: 0644]
food_spring/level/obstacle/Missile.py [new file with mode: 0644]
food_spring/level/obstacle/Obstacles.py [new file with mode: 0644]
food_spring/level/obstacle/Spikes.py [new file with mode: 0644]
food_spring/level/obstacle/__init__.py [new file with mode: 0644]
food_spring/level/peach/Peach.py [new file with mode: 0644]
food_spring/level/peach/__init__.py [new file with mode: 0644]
food_spring/level/pineapple/Pineapple.py [new file with mode: 0644]
food_spring/level/pineapple/__init__.py [new file with mode: 0644]
food_spring/level/planet/Planet.py [new file with mode: 0644]
food_spring/level/planet/__init__.py [new file with mode: 0644]
food_spring/level/planet/moon/Moon.py [new file with mode: 0644]
food_spring/level/planet/moon/Moons.py [new file with mode: 0644]
food_spring/level/planet/moon/__init__.py [new file with mode: 0644]
food_spring/level/platform/Platform.py [new file with mode: 0644]
food_spring/level/platform/Platforms.py [new file with mode: 0644]
food_spring/level/platform/__init__.py [new file with mode: 0644]
food_spring/level/stars/Star.py [new file with mode: 0644]
food_spring/level/stars/Stars.py [new file with mode: 0644]
food_spring/level/stars/__init__.py [new file with mode: 0644]
food_spring/level/watermelon/Watermelon.py [new file with mode: 0644]
food_spring/level/watermelon/__init__.py [new file with mode: 0644]
food_spring/title/Title.py [new file with mode: 0644]
food_spring/title/__init__.py [new file with mode: 0644]
lib/__init__.py [new file with mode: 0644]
lib/pgfw [new submodule]
resource/Numans.ttf [new file with mode: 0644]
resource/aud/AHURA.ogg [new file with mode: 0644]
resource/aud/FLUFF/0.ogg [new file with mode: 0644]
resource/aud/FLUFF/1.ogg [new file with mode: 0644]
resource/aud/FLUFF/2.ogg [new file with mode: 0644]
resource/aud/FLUFF/3.ogg [new file with mode: 0644]
resource/aud/PAN-FLOUR.ogg [new file with mode: 0644]
resource/aud/SLIME-JIM.ogg [new file with mode: 0644]
resource/img/ALTERNATION/0/0.png [new file with mode: 0644]
resource/img/ALTERNATION/0/1.png [new file with mode: 0644]
resource/img/ALTERNATION/1/0.png [new file with mode: 0644]
resource/img/ALTERNATION/1/1.png [new file with mode: 0644]
resource/img/ALTERNATION/2/0.png [new file with mode: 0644]
resource/img/ALTERNATION/2/1.png [new file with mode: 0644]
resource/img/ALTERNATION/3/0.png [new file with mode: 0644]
resource/img/ALTERNATION/3/1.png [new file with mode: 0644]
resource/img/ALTERNATION/mouth/bg.png [new file with mode: 0644]
resource/img/ALTERNATION/mouth/lower-jaw.png [new file with mode: 0644]
resource/img/ALTERNATION/mouth/upper-jaw.png [new file with mode: 0644]
resource/img/BINOCULARS/environment.png [new file with mode: 0644]
resource/img/BINOCULARS/view/00.png [new file with mode: 0644]
resource/img/BINOCULARS/view/01.png [new file with mode: 0644]
resource/img/BINOCULARS/view/02.png [new file with mode: 0644]
resource/img/BINOCULARS/view/03.png [new file with mode: 0644]
resource/img/BINOCULARS/view/04.png [new file with mode: 0644]
resource/img/BINOCULARS/view/05.png [new file with mode: 0644]
resource/img/BINOCULARS/view/06.png [new file with mode: 0644]
resource/img/BINOCULARS/view/07.png [new file with mode: 0644]
resource/img/BINOCULARS/view/08.png [new file with mode: 0644]
resource/img/BINOCULARS/view/09.png [new file with mode: 0644]
resource/img/BINOCULARS/view/10.png [new file with mode: 0644]
resource/img/BINOCULARS/view/11.png [new file with mode: 0644]
resource/img/BINOCULARS/view/12.png [new file with mode: 0644]
resource/img/BINOCULARS/view/13.png [new file with mode: 0644]
resource/img/BINOCULARS/view/14.png [new file with mode: 0644]
resource/img/BINOCULARS/view/15.png [new file with mode: 0644]
resource/img/BINOCULARS/view/16.png [new file with mode: 0644]
resource/img/BINOCULARS/view/17.png [new file with mode: 0644]
resource/img/BINOCULARS/view/18.png [new file with mode: 0644]
resource/img/BINOCULARS/view/19.png [new file with mode: 0644]
resource/img/BINOCULARS/view/20.png [new file with mode: 0644]
resource/img/BINOCULARS/view/21.png [new file with mode: 0644]
resource/img/BINOCULARS/view/22.png [new file with mode: 0644]
resource/img/BINOCULARS/view/23.png [new file with mode: 0644]
resource/img/BINOCULARS/view/24.png [new file with mode: 0644]
resource/img/BINOCULARS/view/25.png [new file with mode: 0644]
resource/img/BINOCULARS/view/26.png [new file with mode: 0644]
resource/img/BINOCULARS/view/27.png [new file with mode: 0644]
resource/img/BINOCULARS/view/28.png [new file with mode: 0644]
resource/img/BINOCULARS/view/29.png [new file with mode: 0644]
resource/img/BINOCULARS/view/base.png [new file with mode: 0644]
resource/img/BINOCULARS/view/generate [new file with mode: 0755]
resource/img/CORDRAG/Landmouth.png [new file with mode: 0644]
resource/img/CORDRAG/gaia/0-line.png [new file with mode: 0644]
resource/img/CORDRAG/gaia/1-spread.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/01_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/02_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/03_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/04_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/05_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/06_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/07_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/08_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/09_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/10_.png [new file with mode: 0644]
resource/img/CORDRAG/spanky/11_.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/0/background.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/0/foreground.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/1/background.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/1/foreground.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/2/background.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/2/foreground.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/3/background.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/door/3/foreground.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/1.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/2.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/3.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/4.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/5.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/6.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/7.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/8.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/moon/animate [new file with mode: 0755]
resource/img/HUMAN-ORGANS/moon/out.gif [new file with mode: 0644]
resource/img/HUMAN-ORGANS/venus/0.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/venus/1.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/venus/2.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/venus/3.png [new file with mode: 0644]
resource/img/HUMAN-ORGANS/window.png [new file with mode: 0644]
resource/img/SHATTER/0/0/00.png [new file with mode: 0644]
resource/img/SHATTER/0/0/01.png [new file with mode: 0644]
resource/img/SHATTER/0/0/02.png [new file with mode: 0644]
resource/img/SHATTER/0/0/03.png [new file with mode: 0644]
resource/img/SHATTER/0/0/04.png [new file with mode: 0644]
resource/img/SHATTER/0/0/05.png [new file with mode: 0644]
resource/img/SHATTER/0/0/06.png [new file with mode: 0644]
resource/img/SHATTER/0/0/07.png [new file with mode: 0644]
resource/img/SHATTER/0/1/00.png [new file with mode: 0644]
resource/img/SHATTER/0/1/01.png [new file with mode: 0644]
resource/img/SHATTER/0/1/02.png [new file with mode: 0644]
resource/img/SHATTER/0/1/03.png [new file with mode: 0644]
resource/img/SHATTER/0/1/04.png [new file with mode: 0644]
resource/img/SHATTER/0/1/05.png [new file with mode: 0644]
resource/img/SHATTER/0/1/06.png [new file with mode: 0644]
resource/img/SHATTER/0/1/07.png [new file with mode: 0644]
resource/img/SHATTER/0/2/00.png [new file with mode: 0644]
resource/img/SHATTER/0/2/01.png [new file with mode: 0644]
resource/img/SHATTER/0/2/02.png [new file with mode: 0644]
resource/img/SHATTER/0/2/03.png [new file with mode: 0644]
resource/img/SHATTER/0/2/04.png [new file with mode: 0644]
resource/img/SHATTER/0/2/05.png [new file with mode: 0644]
resource/img/SHATTER/0/2/06.png [new file with mode: 0644]
resource/img/SHATTER/0/2/07.png [new file with mode: 0644]
resource/img/SHATTER/0/3/00.png [new file with mode: 0644]
resource/img/SHATTER/0/3/01.png [new file with mode: 0644]
resource/img/SHATTER/0/3/02.png [new file with mode: 0644]
resource/img/SHATTER/0/3/03.png [new file with mode: 0644]
resource/img/SHATTER/0/3/04.png [new file with mode: 0644]
resource/img/SHATTER/0/3/05.png [new file with mode: 0644]
resource/img/SHATTER/0/3/06.png [new file with mode: 0644]
resource/img/SHATTER/0/3/07.png [new file with mode: 0644]
resource/img/SHATTER/0/4/00.png [new file with mode: 0644]
resource/img/SHATTER/0/4/01.png [new file with mode: 0644]
resource/img/SHATTER/0/4/02.png [new file with mode: 0644]
resource/img/SHATTER/0/4/03.png [new file with mode: 0644]
resource/img/SHATTER/0/4/04.png [new file with mode: 0644]
resource/img/SHATTER/0/4/05.png [new file with mode: 0644]
resource/img/SHATTER/0/4/06.png [new file with mode: 0644]
resource/img/SHATTER/0/4/07.png [new file with mode: 0644]
resource/img/SHATTER/1/0/00.png [new file with mode: 0644]
resource/img/SHATTER/1/0/01.png [new file with mode: 0644]
resource/img/SHATTER/1/0/02.png [new file with mode: 0644]
resource/img/SHATTER/1/0/03.png [new file with mode: 0644]
resource/img/SHATTER/1/0/04.png [new file with mode: 0644]
resource/img/SHATTER/1/0/05.png [new file with mode: 0644]
resource/img/SHATTER/1/0/06.png [new file with mode: 0644]
resource/img/SHATTER/1/0/07.png [new file with mode: 0644]
resource/img/SHATTER/1/1/00.png [new file with mode: 0644]
resource/img/SHATTER/1/1/01.png [new file with mode: 0644]
resource/img/SHATTER/1/1/02.png [new file with mode: 0644]
resource/img/SHATTER/1/1/03.png [new file with mode: 0644]
resource/img/SHATTER/1/1/04.png [new file with mode: 0644]
resource/img/SHATTER/1/1/05.png [new file with mode: 0644]
resource/img/SHATTER/1/1/06.png [new file with mode: 0644]
resource/img/SHATTER/1/1/07.png [new file with mode: 0644]
resource/img/SHATTER/1/2/00.png [new file with mode: 0644]
resource/img/SHATTER/1/2/01.png [new file with mode: 0644]
resource/img/SHATTER/1/2/02.png [new file with mode: 0644]
resource/img/SHATTER/1/2/03.png [new file with mode: 0644]
resource/img/SHATTER/1/2/04.png [new file with mode: 0644]
resource/img/SHATTER/1/2/05.png [new file with mode: 0644]
resource/img/SHATTER/1/2/06.png [new file with mode: 0644]
resource/img/SHATTER/1/2/07.png [new file with mode: 0644]
resource/img/SHATTER/1/3/00.png [new file with mode: 0644]
resource/img/SHATTER/1/3/01.png [new file with mode: 0644]
resource/img/SHATTER/1/3/02.png [new file with mode: 0644]
resource/img/SHATTER/1/3/03.png [new file with mode: 0644]
resource/img/SHATTER/1/3/04.png [new file with mode: 0644]
resource/img/SHATTER/1/3/05.png [new file with mode: 0644]
resource/img/SHATTER/1/3/06.png [new file with mode: 0644]
resource/img/SHATTER/1/3/07.png [new file with mode: 0644]
resource/img/SHATTER/1/4/00.png [new file with mode: 0644]
resource/img/SHATTER/1/4/01.png [new file with mode: 0644]
resource/img/SHATTER/1/4/02.png [new file with mode: 0644]
resource/img/SHATTER/1/4/03.png [new file with mode: 0644]
resource/img/SHATTER/1/4/04.png [new file with mode: 0644]
resource/img/SHATTER/1/4/05.png [new file with mode: 0644]
resource/img/SHATTER/1/4/06.png [new file with mode: 0644]
resource/img/SHATTER/1/4/07.png [new file with mode: 0644]
resource/img/SHATTER/2/0/00.png [new file with mode: 0644]
resource/img/SHATTER/2/0/01.png [new file with mode: 0644]
resource/img/SHATTER/2/0/02.png [new file with mode: 0644]
resource/img/SHATTER/2/0/03.png [new file with mode: 0644]
resource/img/SHATTER/2/0/04.png [new file with mode: 0644]
resource/img/SHATTER/2/0/05.png [new file with mode: 0644]
resource/img/SHATTER/2/0/06.png [new file with mode: 0644]
resource/img/SHATTER/2/0/07.png [new file with mode: 0644]
resource/img/SHATTER/2/1/00.png [new file with mode: 0644]
resource/img/SHATTER/2/1/01.png [new file with mode: 0644]
resource/img/SHATTER/2/1/02.png [new file with mode: 0644]
resource/img/SHATTER/2/1/03.png [new file with mode: 0644]
resource/img/SHATTER/2/1/04.png [new file with mode: 0644]
resource/img/SHATTER/2/1/05.png [new file with mode: 0644]
resource/img/SHATTER/2/1/06.png [new file with mode: 0644]
resource/img/SHATTER/2/1/07.png [new file with mode: 0644]
resource/img/SHATTER/2/2/00.png [new file with mode: 0644]
resource/img/SHATTER/2/2/01.png [new file with mode: 0644]
resource/img/SHATTER/2/2/02.png [new file with mode: 0644]
resource/img/SHATTER/2/2/03.png [new file with mode: 0644]
resource/img/SHATTER/2/2/04.png [new file with mode: 0644]
resource/img/SHATTER/2/2/05.png [new file with mode: 0644]
resource/img/SHATTER/2/2/06.png [new file with mode: 0644]
resource/img/SHATTER/2/2/07.png [new file with mode: 0644]
resource/img/SHATTER/2/3/00.png [new file with mode: 0644]
resource/img/SHATTER/2/3/01.png [new file with mode: 0644]
resource/img/SHATTER/2/3/02.png [new file with mode: 0644]
resource/img/SHATTER/2/3/03.png [new file with mode: 0644]
resource/img/SHATTER/2/3/04.png [new file with mode: 0644]
resource/img/SHATTER/2/3/05.png [new file with mode: 0644]
resource/img/SHATTER/2/3/06.png [new file with mode: 0644]
resource/img/SHATTER/2/3/07.png [new file with mode: 0644]
resource/img/SHATTER/2/4/00.png [new file with mode: 0644]
resource/img/SHATTER/2/4/01.png [new file with mode: 0644]
resource/img/SHATTER/2/4/02.png [new file with mode: 0644]
resource/img/SHATTER/2/4/03.png [new file with mode: 0644]
resource/img/SHATTER/2/4/04.png [new file with mode: 0644]
resource/img/SHATTER/2/4/05.png [new file with mode: 0644]
resource/img/SHATTER/2/4/06.png [new file with mode: 0644]
resource/img/SHATTER/2/4/07.png [new file with mode: 0644]
resource/img/SHATTER/3/0/00.png [new file with mode: 0644]
resource/img/SHATTER/3/0/01.png [new file with mode: 0644]
resource/img/SHATTER/3/0/02.png [new file with mode: 0644]
resource/img/SHATTER/3/0/03.png [new file with mode: 0644]
resource/img/SHATTER/3/0/04.png [new file with mode: 0644]
resource/img/SHATTER/3/0/05.png [new file with mode: 0644]
resource/img/SHATTER/3/0/06.png [new file with mode: 0644]
resource/img/SHATTER/3/0/07.png [new file with mode: 0644]
resource/img/SHATTER/3/1/00.png [new file with mode: 0644]
resource/img/SHATTER/3/1/01.png [new file with mode: 0644]
resource/img/SHATTER/3/1/02.png [new file with mode: 0644]
resource/img/SHATTER/3/1/03.png [new file with mode: 0644]
resource/img/SHATTER/3/1/04.png [new file with mode: 0644]
resource/img/SHATTER/3/1/05.png [new file with mode: 0644]
resource/img/SHATTER/3/1/06.png [new file with mode: 0644]
resource/img/SHATTER/3/1/07.png [new file with mode: 0644]
resource/img/SHATTER/3/2/00.png [new file with mode: 0644]
resource/img/SHATTER/3/2/01.png [new file with mode: 0644]
resource/img/SHATTER/3/2/02.png [new file with mode: 0644]
resource/img/SHATTER/3/2/03.png [new file with mode: 0644]
resource/img/SHATTER/3/2/04.png [new file with mode: 0644]
resource/img/SHATTER/3/2/05.png [new file with mode: 0644]
resource/img/SHATTER/3/2/06.png [new file with mode: 0644]
resource/img/SHATTER/3/2/07.png [new file with mode: 0644]
resource/img/SHATTER/3/3/00.png [new file with mode: 0644]
resource/img/SHATTER/3/3/01.png [new file with mode: 0644]
resource/img/SHATTER/3/3/02.png [new file with mode: 0644]
resource/img/SHATTER/3/3/03.png [new file with mode: 0644]
resource/img/SHATTER/3/3/04.png [new file with mode: 0644]
resource/img/SHATTER/3/3/05.png [new file with mode: 0644]
resource/img/SHATTER/3/3/06.png [new file with mode: 0644]
resource/img/SHATTER/3/3/07.png [new file with mode: 0644]
resource/img/SHATTER/3/4/00.png [new file with mode: 0644]
resource/img/SHATTER/3/4/01.png [new file with mode: 0644]
resource/img/SHATTER/3/4/02.png [new file with mode: 0644]
resource/img/SHATTER/3/4/03.png [new file with mode: 0644]
resource/img/SHATTER/3/4/04.png [new file with mode: 0644]
resource/img/SHATTER/3/4/05.png [new file with mode: 0644]
resource/img/SHATTER/3/4/06.png [new file with mode: 0644]
resource/img/SHATTER/3/4/07.png [new file with mode: 0644]
resource/img/SHATTER/animate [new file with mode: 0755]
resource/img/SHATTER/blob/00.png [new file with mode: 0644]
resource/img/SHATTER/blob/01.png [new file with mode: 0644]
resource/img/SHATTER/blob/02.png [new file with mode: 0644]
resource/img/SHATTER/blob/03.png [new file with mode: 0644]
resource/img/SHATTER/blob/04.png [new file with mode: 0644]
resource/img/SHATTER/blob/05.png [new file with mode: 0644]
resource/img/SHATTER/blob/06.png [new file with mode: 0644]
resource/img/SHATTER/blob/07.png [new file with mode: 0644]
resource/img/SHATTER/blob/08.png [new file with mode: 0644]
resource/img/SHATTER/blob/09.png [new file with mode: 0644]
resource/img/SHATTER/blob/10.png [new file with mode: 0644]
resource/img/SHATTER/blob/11.png [new file with mode: 0644]
resource/img/SHATTER/blob/12.png [new file with mode: 0644]
resource/img/SHATTER/blob/13.png [new file with mode: 0644]
resource/img/SHATTER/blob/14.png [new file with mode: 0644]
resource/img/SHATTER/blob/15.png [new file with mode: 0644]
resource/img/SHATTER/blob/16.png [new file with mode: 0644]
resource/img/SHATTER/blob/animation.gif [new file with mode: 0644]
resource/img/SHATTER/blob/generate [new file with mode: 0755]
resource/img/SHATTER/generate [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..fbe6730
--- /dev/null
@@ -0,0 +1,6 @@
+pgfw-old/
+*.pyc
+__pycache__
+MANIFEST
+dist/
+local/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..b9cf2a1
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "lib/pgfw"]
+       path = lib/pgfw
+       url = http://git.shampoo.ooo/pgfw
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..b170297
--- /dev/null
+++ b/README
@@ -0,0 +1,6 @@
+Food Spring
+^^^^^^^^^^^
+
+To-do
+-----
+- Fruit falls into divot, ground springs to launch fruit
diff --git a/config b/config
new file mode 100644 (file)
index 0000000..f72be56
--- /dev/null
+++ b/config
@@ -0,0 +1,215 @@
+[display]
+font-path = Numans.ttf
+dimensions = 640, 480
+skip-frames = False
+
+[keys]
+quit = K_ESCAPE
+advance = K_RETURN
+
+[mouse]
+visible = False
+
+[gaia]
+offset = 30
+path = img/CORDRAG/gaia/
+
+[introduction]
+segments = 5
+transition = 5900
+audio = aud/AHURA.ogg
+
+[epithet]
+t-color = 200, 40, 220
+font-size = 28
+color = 255, 0, 0
+text = From dirt IT was made
+margin = 240
+outline-flash = 100
+i-color = 40, 190, 240
+width = 580
+outline-colors = white, gray, purple
+it-size = 52
+scramble = 0.01
+
+[spanky]
+jump-framerate = 700, 200, 160, 100
+jump-order = 5, 6, 7, 8
+walk-order = 4, 3
+wag-order = 2, 1
+path = img/CORDRAG/spanky/
+wag-framerate = 2000, 500
+walk-framerate = 600
+
+[title]
+morfeus-text = Existence of dreams
+gaia-text = Earth spirit
+background = img/CORDRAG/Landmouth.png
+morfeus-plate = Morfeus
+gaia-plate = Gaia
+audio = aud/SLIME-JIM.ogg
+
+[home]
+food-margin = 3
+tv-edge = 210
+food-inactive-x = 475
+food-inactive-y = 440
+food-active-y = 456
+static-environment-path = img/BINOCULARS/environment.png
+food-step = 4.0
+audio = aud/PAN-FLOUR.ogg
+
+[collection]
+coordinates = 230, 207
+size = 202, 233
+
+[view]
+alpha-step = 35
+coordinates = 27, 91
+path = img/BINOCULARS/view
+
+[level]
+gravity = 0.05
+entrance-speed = 2.0
+stall = 1100
+velocity = 5.0, 14.0
+fall-pause = 1300
+audio = aud/FLUFF/
+entrance-offset = 100
+background-color = 0, 0, 0
+
+[door]
+path = img/HUMAN-ORGANS/door/
+x = 320
+
+[exit-arrow]
+hue = 240, 310
+saturation = 85
+fade-in = 500
+arrow-count = 2
+interval = 0
+overlap = 0
+height = 11
+fade-out = 1000
+alpha = 150
+frame-count = 16
+offset = 5
+width = 11
+
+[land]
+gradient = 80
+height = 180
+altitude-ratio = 0.005
+x-step = 50
+spacing-factor = 1.2
+velocity-ratio = 0.25
+fade-speed = 0.25
+
+[planet]
+extension = png
+interval = 220
+shifts = 40
+offset = 150
+path = img/HUMAN-ORGANS/venus/
+
+[moon]
+count = 1, 1
+tint-level = 0.25
+interval = 4000, 6000
+path = img/HUMAN-ORGANS/moon/
+margin = 40
+
+[stars]
+count = 80, 90
+saturation = 0, 25
+size = 1, 2
+
+[gun]
+framerate = 120
+path = img/SHATTER
+
+[drop]
+blob-length = 3500
+spawn-decrease = 0.85
+first-spawn = 5000
+consecutive = 2
+speed = 1
+
+[blob]
+path = img/SHATTER/blob
+
+[food]
+lower-jaw-path = img/ALTERNATION/mouth/lower-jaw.png
+crouch = 3
+upper-jaw-path = img/ALTERNATION/mouth/upper-jaw.png
+angle-range = 0, 76
+mouth-size = 20, 18
+blink-rate = 160
+path = img/ALTERNATION
+mouth-bg-alpha = 255
+mouth-offset = 14, 14
+mouth-bg-shrink = -6, -4
+dx = 6.1
+offset = 440
+dx-boost = 0.25
+mouth-gap = 5
+drop-velocity = -5, 25
+freeze-length = 1350
+
+[platform]
+buffer = 640
+thickness = 6
+height = 82
+width = 420, 810
+first-gap = 160
+gap = 100, 280
+
+[obstacle]
+blink-rate = 40
+
+[missile]
+count = 1, 4
+angle = -10
+speed = 25.0
+delay = 1200
+chance = 0.002
+peak = 0.3
+margin = 10
+
+[hurdle]
+count = 1, 1
+pause = 5000
+speed = 17.0
+delay = 1500
+chance = 0.0015
+first-range = 200, 250
+margin = 16, 20
+
+[spikes]
+delay = 1500
+chance = 0.0022
+speed = 30.0
+
+[fireball]
+count = 1, 2
+delay = 1500
+chance = 0.00175
+peak = 40
+speed = 5.0
+
+[window]
+fade-step = 0.01
+remain-length = 20000
+alpha = 181
+path = img/HUMAN-ORGANS/window.png
+margin = 35
+
+[siphon]
+root-colors = 180, 180, 120, 134, 34, 134, 120, 120, 255, 34, 134, 34, 110, 110, 220, 180, 100, 50, 150, 150, 100, 34, 100, 204
+
+[interpolate]
+charge = C 0.0 0.0, 360.0 0.31, 3000.0 1.0
+template = L 0.0 0.0, 1000.0 1.0
+release = C 0.0 1.0, 520.0 -0.18, 900.0 0.25, 1200.0 -0.12, 1400.0 0.15, 1800.0 -0.085, 2000.0 0.065, 2100.0 -0.025, 2400.0 0.02, 2700.0 -0.01, 3000.0 0.0
+jump-width = L 0.0 0.0, 1.0 300.0
+jump-height = L 0.0 0.0, 1.0 500.0
diff --git a/doc/ending b/doc/ending
new file mode 100644 (file)
index 0000000..f3d2da5
--- /dev/null
@@ -0,0 +1,4 @@
+The monkey got as far as the Bering Strait before you obliterated it with an
+exaggerated arsenal of firepower.  Trees will continue growing, free from the
+burdensome expectations of agriculture.  Congratulations!  You stopped evolution
+before it happened!
diff --git a/food-spring b/food-spring
new file mode 100755 (executable)
index 0000000..120a41b
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+
+from os import environ, execvp, chdir, getcwd
+from os.path import exists, join, dirname
+from sys import version_info, argv
+
+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 not can_import("pygame"):
+    launch_alternative(["python2.7", "python2.6"])
+
+if "--go-to-dir" in argv:
+    move_to_executable()
+
+from food_spring.FoodSpring import FoodSpring
+
+FoodSpring().run()
diff --git a/food_spring/FoodSpring.py b/food_spring/FoodSpring.py
new file mode 100644 (file)
index 0000000..e00cbcb
--- /dev/null
@@ -0,0 +1,70 @@
+from pygame import Surface
+from pygame.font import Font
+from pygame.draw import line
+from pygame.locals import *
+
+from lib.pgfw.pgfw.Game import Game
+from food_spring.Types import Types
+from food_spring.gaia.Gaia import Gaia
+from food_spring.Spanky import Spanky
+from food_spring.introduction.Introduction import Introduction
+from food_spring.Timer import Timer
+from food_spring.title.Title import Title
+from food_spring.level.Levels import Levels
+from food_spring.home.Home import Home
+from food_spring.Siphon import Siphon
+from food_spring.gun.GunLibrary import GunLibrary
+
+class FoodSpring(Game):
+
+    def __init__(self):
+        Game.__init__(self, type_declarations=Types())
+        if self.check_command_line("-mute"):
+            self.audio.mute()
+        self.input.register_any_press_ignore(keys=[K_LALT, K_RALT, K_F4])
+        self.activate()
+        self.subscribe(self.respond)
+
+    def respond(self, event):
+        if self.delegate.compare(event, "reset-game"):
+            for child in (self.home, self.timer):
+                self.call("deactivate", child)
+                self.call("reset", child)
+            self.activate()
+
+    def call(self, method, obj):
+        if hasattr(obj, method):
+            attribute = getattr(obj, method)
+            if callable(attribute):
+                attribute()
+
+    def activate(self):
+        self.introduction.activate()
+        # self.home.activate()
+
+    def set_children(self):
+        Game.set_children(self)
+        self.gaia = Gaia(self)
+        self.spanky = Spanky(self)
+        self.introduction = Introduction(self)
+        self.title = Title(self)
+        self.timer = Timer(self)
+        self.gun_library = GunLibrary(self)
+        self.siphon = Siphon(self)
+        self.levels = Levels(self)
+        self.home = Home(self)
+
+    def update(self):
+        self.timer.update()
+        self.introduction.update()
+        self.title.update()
+        self.home.update()
+        self.levels.update()
+        self.draw_time()
+
+    def draw_time(self):
+        if self.check_command_line("-timer"):
+            surface = Font(None, 18).render(str(self.timer.get_remaining() / 1000),
+                                            False, (0, 0, 0),
+                                            (255, 255, 255))
+            self.get_display_surface().blit(surface, (0, 0))
diff --git a/food_spring/Siphon.py b/food_spring/Siphon.py
new file mode 100644 (file)
index 0000000..877e787
--- /dev/null
@@ -0,0 +1,419 @@
+from os.path import join
+from random import randint, randrange, choice
+from math import sin, cos, radians, ceil
+from collections import deque
+
+from pygame import Surface, Rect, PixelArray
+from pygame.image import load
+from pygame.mask import from_surface
+from pygame.draw import line, aaline
+from pygame.transform import rotate
+from pygame.locals import *
+
+from lib.pgfw.pgfw.Animation import Animation
+from lib.pgfw.pgfw.Sprite import Sprite
+from lib.pgfw.pgfw.GameChild import GameChild
+
+class Siphon(GameChild):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.time_filter = self.get_game().time_filter
+        self.color_index = 0
+        self.load_configuration()
+        self.set_roots()
+        self.cancel()
+        self.set_nodesets()
+        self.set_score()
+        self.set_badges()
+
+    def load_configuration(self):
+        self.badge_size = 60, 44
+        self.stem_width = 30
+        self.set_colors()
+
+    def set_colors(self):
+        components = self.get_configuration("siphon", "root-colors")
+        colors = self.colors = []
+        for ii in xrange(0, len(components), 6):
+            colors.append((components[ii:ii + 3], components[ii + 3:ii + 6]))
+
+    def set_roots(self):
+        roots = self.roots = Roots(self, Roots.HORIZONTAL)
+        roots.add_initial(self.stem_width)
+        roots.init_surfaces(Rect(0, 0, self.stem_width, self.badge_size[1]))
+
+    def cancel(self):
+        self.contracting = False
+        self.releasing = False
+        self.release_elapsed = 0
+        self.angle_deviation = 0
+
+    def set_nodesets(self):
+        interpolator = self.get_game().interpolator
+        self.release_nodeset = interpolator.get_nodeset("release")
+
+    def set_score(self):
+        self.score = [[0, 0, 0] for _ in xrange(5)]
+
+    def set_badges(self):
+        self.badges = [Badge(self.roots, ii, self.badge_size) for ii in \
+                       xrange(5)]
+        self.set_badge()
+
+    def set_badge(self):
+        points = self.get_points()
+        for ii, score in enumerate((2000, 5000, 10000, 16000)):
+            if points < score:
+                break
+        self.roots.set_badge(self.badges[ii])
+
+    def get_points(self):
+        points = 0
+        bases = 100, 200, 400, 800, 1600
+        for ii, level in enumerate(self.score):
+            base = bases[ii]
+            for jj in xrange(max(level)):
+                points += base * ((level[0] > jj) + (level[1] > jj) + \
+                                  (level[2] > jj))
+                base *= .9
+        return int(points)
+
+    def set_level(self, index=0):
+        self.cancel()
+        self.level = self.parent.levels[index]
+        self.planet_rect = self.level.planet.location
+        self.color_index = index
+        self.roots.place()
+        for badge in self.badges:
+            badge.place()
+        self.roots.gradient.set_tiles()
+        self.roots.gradient.set_frames()
+        self.draw_nodes()
+
+    def draw_nodes(self):
+        roots = self.roots
+        roots.clear_root_surface()
+        for node in roots.get_initial():
+            y = self.get_initial_y(node.id)
+            end = node.length, y
+            self.draw_line((0, y), end)
+            self.draw_children(node, end)
+
+    def get_initial_y(self, node_id):
+        modifier = -1 if node_id % 2 else 1
+        return self.roots.rect.h / 2 + modifier * 10 * ((node_id + 1) / 2)
+
+    def draw_line(self, start, end, alpha=180):
+        line(self.roots.root_surface, self.get_current_colors()[0], start, end,
+             3)
+        aaline(self.roots.root_surface, (255, 255, 255), start, end, 1)
+
+    def get_current_colors(self):
+        return self.colors[self.color_index]
+
+    def draw_children(self, node, start, depth=1):
+        for child in node.children:
+            end = self.get_offset_point(start, child.angle, child.length, True,
+                                        depth)
+            self.draw_line(start, end)
+            self.draw_children(child, end, depth + 1)
+
+    def get_offset_point(self, start, angle, length, deviate=False, depth=1):
+        if deviate:
+            angle -= self.angle_deviation * (angle - .8 ** depth * angle)
+        return int(round(start[0] + cos(radians(angle)) * length)), \
+               int(round(start[1] + sin(radians(angle)) * length))
+
+    def add(self, level):
+        offset = 70
+        length = [40, 52, 66, 84, 100][level]
+        for _ in xrange(25):
+            parent = self.get_random_parent()
+            for _ in xrange(3):
+                angle = randint(parent.angle - offset, parent.angle + offset)
+                if abs(angle) < 87 and (not parent.children or
+                                        abs(parent.children[0].angle - angle) >
+                                        45):
+                    end = self.get_offset_point(self.get_end(parent), angle,
+                                                length)
+                    if self.check_end(end):
+                        self.increase_score(level)
+                        roots = self.roots
+                        roots.add(length, angle, parent)
+                        self.resize_roots_rect(end)
+                        self.roots.init_surfaces(roots.rect)
+                        self.draw_nodes()
+                        return True
+
+    def get_random_parent(self):
+        node = self.roots[randrange(0, self.roots.initial_count)]
+        while node.children:
+            if len(node.children) == 1:
+                if randint(0, 1):
+                    break
+            node = choice(node.children)
+        return node
+
+    def get_end(self, node):
+        path = [node]
+        while node.parent is not None:
+            path.append(node.parent)
+            node = node.parent
+        x, y = node.length, self.get_initial_y(path.pop().id)
+        while path:
+            node = path.pop()
+            x, y = self.get_offset_point((x, y), node.angle, node.length)
+        return x, y
+
+    def check_end(self, end):
+        roots = self.roots.rect
+        planet = self.planet_rect
+        offset = end[0] + roots.left - planet.left, \
+                 end[1] + roots.top - planet.top
+        if planet.move(-planet.left, -planet.top).collidepoint(offset):
+            return self.level.planet.frames[0].get_at(offset)[3] == 255
+
+    def increase_score(self, level):
+        self.score[level][randint(0, 2)] += 1
+        self.set_badge()
+
+    def resize_roots_rect(self, end):
+        roots = self.roots.rect
+        if end[0] > roots.w:
+            roots.w = end[0]
+        if end[1] < 0:
+            roots.inflate_ip(0, -end[1] * 2)
+        elif end[1] > roots.h:
+            roots.inflate_ip(0, (end[1] - roots.h) * 2)
+
+    def contract(self):
+        self.contracting = True
+        self.releasing = False
+        self.charge_elapsed = 0
+        self.roots.gradient.reverse()
+
+    def release(self):
+        if self.contracting:
+            self.contracting = False
+            self.releasing = True
+            self.release_elapsed = 0
+            self.roots.gradient.reverse()
+
+    def update(self):
+        self.update_angle_deviation()
+        if self.contracting or self.releasing:
+            self.draw_nodes()
+        self.roots.update()
+
+    def update_angle_deviation(self):
+        if self.contracting:
+            self.angle_deviation = self.level.food.charge
+        elif self.releasing:
+            self.release_elapsed += self.time_filter.get_last_frame_duration()
+            if self.release_elapsed > self.release_nodeset.get_length():
+                self.releasing = False
+                self.angle_deviation = 0
+            else:
+                self.angle_deviation = self.release_nodeset.get_y(
+                    self.release_elapsed) * self.level.food.submitted_charge
+
+
+class Roots(GameChild, list):
+
+    HORIZONTAL, VERTICAL = range(2)
+
+    def __init__(self, parent, orientation):
+        GameChild.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.orientation = orientation
+        self.gradient = Gradient(self, 200)
+
+    def add(self, length, angle, parent=None):
+        self.append(Node(len(self), length, angle, parent))
+        if parent is not None:
+           parent.add_child(self[-1])
+
+    def add_initial(self, length):
+        count = self.initial_count = 5
+        for ii in xrange(count):
+            self.add(length, 0)
+
+    def get_initial(self):
+        return self[:self.initial_count]
+
+    def init_surfaces(self, rect):
+        surface = self.surface = Surface(rect.size)
+        surface.set_colorkey((0, 0, 0))
+        self.root_surface = Surface(rect.size)
+        self.rect = rect
+        self.gradient.set_frames()
+
+    def set_badge(self, badge):
+        self.badge = badge
+
+    def clear_root_surface(self):
+        self.root_surface.fill((0, 0, 0))
+
+    def place(self):
+        base = self.parent.level.planet.location
+        self.rect.midleft = base.left - self.parent.stem_width + 2, \
+                            base.centery
+
+    def update(self):
+        self.badge.update()
+        self.gradient.update()
+        self.surface.blit(self.root_surface, (0, 0), None, BLEND_MIN)
+        self.display_surface.blit(self.surface, self.rect)
+
+
+class Node:
+
+    def __init__(self, id, length, angle, parent=None):
+        self.id, self.length, self.angle, self.parent = id, length, angle, \
+                                                        parent
+        self.children = []
+
+    def add_child(self, child):
+        self.children.append(child)
+
+
+class Gradient(Sprite):
+
+    def __init__(self, parent, framerate):
+        Sprite.__init__(self, parent, framerate)
+        self.set_tiles()
+
+    def set_tiles(self):
+        tile_rect = Rect(0, 0, 16, 16)
+        colors = self.get_colors()
+        tiles = self.tiles = []
+        segment_count = len(colors)
+        segment_width = int(ceil(float(tile_rect.w) / segment_count))
+        for _ in xrange(segment_count):
+            frame = Surface(tile_rect.size)
+            x = 0
+            for color in colors:
+                frame.fill(color, (x, 0, segment_width, tile_rect.h))
+                x += segment_width
+            colors.rotate()
+            if self.parent.orientation == Roots.VERTICAL:
+                frame = rotate(frame, 90)
+            tiles.append(frame)
+
+    def get_colors(self):
+        count = 8
+        base_color = Color(*self.parent.parent.get_current_colors()[1])
+        bh, bs, bl, ba = base_color.hsla
+        bs_step = (100 - bs) / float(count - 1)
+        bl_step = (100 - bl) / float(count - 1)
+        colors = deque()
+        for _ in xrange(count):
+            color = Color(0, 0, 0)
+            color.hsla = map(int, (bh, min(100, bs), min(100, bl), ba))
+            colors.append(color)
+            bs += bs_step
+            bl += bl_step
+        return colors
+
+    def set_frames(self):
+        self.display_surface = self.parent.surface
+        index = 0 if not self.frames else \
+                self.get_current_frameset().get_current_id()
+        self.clear_frames()
+        rect = self.parent.rect
+        surface = Surface(rect.size)
+        if self.parent.orientation == Roots.VERTICAL:
+            surface = rotate(surface, 90)
+            rect = surface.get_rect()
+        for tile in self.tiles:
+            frame = surface.copy()
+            for x in xrange(0, rect.w, tile.get_width()):
+                for y in xrange(0, rect.h, tile.get_height()):
+                    frame.blit(tile, (x, y))
+            self.add_frame(frame)
+        for _ in xrange(index):
+            self.shift_frame()
+
+
+class Badge(Animation):
+
+    def __init__(self, parent, level, size):
+        Animation.__init__(self, parent)
+        self.level = level
+        self.rect = Rect((0, 0), size)
+        self.display_surface = self.get_display_surface()
+        self.background_color = Color(255, 222, 222)
+        self.set_background()
+        self.set_guns()
+        self.register(self.shift)
+        self.play(self.shift, 120)
+
+    def set_background(self):
+        width = 1
+        rect = self.rect
+        surface = Surface(rect.size)
+        colors = (0, 0, 0), (255, 255, 255)
+        for ii, x in enumerate(xrange(0, rect.w, width)):
+            surface.fill(colors[ii % 2], (x, 0, width, rect.h))
+        self.background = surface
+        self.surface = Surface(surface.get_size())
+
+    def set_guns(self):
+        width = 0
+        margin = 5
+        images = []
+        for guns in self.parent.parent.parent.gun_library:
+            image = guns[self.level].frames[0].copy()
+            mask = from_surface(image)
+            pixels = PixelArray(image)
+            for x in xrange(len(pixels)):
+                for y in xrange(len(pixels[0])):
+                    if mask.get_at((x, y)):
+                        pixels[x][y] = (0, 0, 0)
+                    else:
+                        pixels[x][y] = (255, 255, 255)
+            del pixels
+            width += image.get_width() + margin
+            images.append(image)
+        self.img = images[0]
+        surface = Surface((width, self.rect.h))
+        surface.fill((255, 255, 255))
+        x = 0
+        for image in images:
+            rect = image.get_rect()
+            rect.midleft = x, self.rect.h / 2
+            if self.level == 0:
+                rect.centery += 3
+            surface.blit(image, rect)
+            x += image.get_width() + margin
+        self.gun_surface = surface
+        self.gun_rect = surface.get_rect()
+        self.gun_rect.right = self.rect.w
+
+    def shift(self):
+        rect = self.gun_rect
+        rect.move_ip(2, 0)
+        if rect.left >= rect.w:
+            rect.left -= rect.w
+
+    def place(self):
+        if self.parent.orientation == Roots.HORIZONTAL:
+            self.rect.midright = self.parent.rect.midleft
+        else:
+            self.rect.midtop = self.parent.rect.midbottom
+
+    def update(self):
+        Animation.update(self)
+        gr = self.gun_rect
+        self.surface.fill(self.background_color)
+        self.background.set_colorkey((255, 255, 255))
+        self.surface.blit(self.background, (0, 0))
+        self.surface.blit(self.gun_surface, gr, None, BLEND_MIN)
+        self.surface.blit(self.gun_surface, gr.move(-gr.w, 0), None, BLEND_MIN)
+        self.display_surface.blit(self.surface, self.rect)
+        h, s, v, a = self.background_color.hsva
+        h += 2
+        if h > 360:
+            h -= 360
+        self.background_color.hsva = h, s, v, a
diff --git a/food_spring/Spanky.py b/food_spring/Spanky.py
new file mode 100644 (file)
index 0000000..f6daff5
--- /dev/null
@@ -0,0 +1,31 @@
+from os.path import join
+from glob import glob
+
+from pygame import Surface
+from pygame.image import load
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Spanky(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.load_from_path(self.get_resource(self.root), True, False)
+        self.set_framesets()
+        self.set_frameset("jump")
+
+    def load_configuration(self):
+        config = self.get_configuration("spanky")
+        self.root = config["path"]
+        self.jump_order = config["jump-order"]
+        self.jump_framerate = config["jump-framerate"]
+        self.wag_order = config["wag-order"]
+        self.wag_framerate = config["wag-framerate"]
+        self.walk_order = config["walk-order"]
+        self.walk_framerate = config["walk-framerate"]
+
+    def set_framesets(self):
+        for verb in ("jump", "wag", "walk"):
+            self.add_frameset(getattr(self, verb + "_order"),
+                              getattr(self, verb + "_framerate"), verb)
diff --git a/food_spring/Timer.py b/food_spring/Timer.py
new file mode 100644 (file)
index 0000000..5b50ad3
--- /dev/null
@@ -0,0 +1,35 @@
+from pygame.time import get_ticks
+
+from lib.pgfw.pgfw.GameChild import GameChild
+
+class Timer(GameChild):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.reset()
+        self.limit = 300000
+
+    def reset(self):
+        self.elapsed = 0
+        self.stop()
+
+    def start(self):
+        self.running = True
+        self.last_ticks = get_ticks()
+
+    def stop(self):
+        self.running = False
+
+    def get_remaining(self):
+        return self.limit - self.elapsed
+
+    def get_ratio_remaining(self):
+        return float(self.get_remaining()) / self.limit
+
+    def update(self):
+        if self.running:
+            ticks = get_ticks()
+            self.elapsed += ticks - self.last_ticks
+            self.last_ticks = ticks
+            if self.elapsed >= self.limit:
+                self.reset()
diff --git a/food_spring/Types.py b/food_spring/Types.py
new file mode 100644 (file)
index 0000000..c6c1551
--- /dev/null
@@ -0,0 +1,137 @@
+from lib.pgfw.pgfw.Configuration import TypeDeclarations
+
+class Types(TypeDeclarations):
+
+    additional_defaults = {
+
+        "gaia": {"path": "path",
+
+                 "int": "offset"},
+
+        "introduction": {"int": ["segments", "transition"]},
+
+        "epithet": {"int": ["width", "margin", "font-size", "it-size",
+                            "outline-flash"],
+
+                    "float": "scramble",
+
+                    "int-list": ["color", "i-color", "t-color"]},
+
+        "spanky": {"path": "path",
+
+                   "int-list": ["jump-order", "jump-framerate", "wag-order",
+                                "wag-framerate", "walk-order",
+                                "walk-framerate"]},
+
+        "title": {"path": "background"},
+
+        "home": {"path": ["static-environment-path", "audio"],
+
+                 "int": ["food-inactive-x", "food-inactive-y", "food-active-y",
+                         "food-margin", "tv-edge"],
+
+                 "float": "food-step"},
+
+        "collection": {"int-list": ["coordinates", "size"]},
+
+        "view": {"int": ["hue-shift", "alpha-step"],
+
+                 "path": "path",
+
+                 "int-list": "coordinates"},
+
+        "level": {"int": ["stall", "fall-pause", "entrance-offset"],
+
+                  "path": "audio",
+
+                  "int-list": "background-color",
+
+                  "float": ["gravity", "entrance-speed"],
+
+                  "float-list": "velocity"},
+
+        "door": {"int": "x",
+
+                 "path": "path"},
+
+        "exit-arrow": {"int": ["width", "height", "overlap", "arrow-count",
+                               "frame-count", "interval", "saturation",
+                               "offset", "fade-in", "fade-out", "alpha"],
+
+                       "int-list": "hue"},
+
+        "land": {"int": ["horizon", "gradient", "x-step", "height"],
+
+                 "float": ["spacing-factor", "velocity-ratio",
+                           "altitude-ratio", "fade-speed"]},
+
+        "planet": {"path": "path",
+
+                   "int": ["interval", "shifts", "offset"]},
+
+        "moon": {"path": "path",
+
+                 "int": "margin",
+
+                 "float": "tint-level",
+
+                 "int-list": ["count", "interval"]},
+
+        "stars": {"int-list": ["count", "size", "saturation"]},
+
+        "gun": {"path": "path",
+
+                "int": "framerate"},
+
+        "drop": {"float": "spawn-decrease",
+
+                 "int": ["consecutive", "speed", "first-spawn", "blob-length"]},
+
+        "food": {"path": ["path", "mouth-bg-path", "upper-jaw-path",
+                          "lower-jaw-path"],
+
+                 "int": ["offset", "crouch", "mouth-bg-alpha", "mouth-gap",
+                         "blink-rate", "freeze-length"],
+
+                 "int-list": ["angle-range", "mouth-offset", "mouth-size",
+                              "mouth-bg-shrink", "drop-velocity"],
+
+                 "float": ["dx", "dx-boost"]},
+
+        "platform": {"int": ["height", "first-gap", "buffer", "thickness"],
+
+                     "int-list": ["gap", "width"]},
+
+        "obstacle": {"int": "blink-rate"},
+
+        "missile": {"int": ["margin", "delay", "angle"],
+
+                    "int-list": "count",
+
+                    "float": ["chance", "peak", "speed"]},
+
+        "hurdle": {"int-list": ["count", "first-range", "margin"],
+
+                   "int": ["delay", "pause"],
+
+                   "float": ["chance", "speed"]},
+
+        "spikes": {"int": "delay",
+
+                   "float": ["speed", "chance"]},
+
+        "fireball": {"int": ["delay", "peak"],
+
+                     "int-list": "count",
+
+                     "float": ["chance", "speed"]},
+
+        "window": {"path": "path",
+
+                   "int": ["alpha", "remain-length", "margin"],
+
+                   "float": "fade-step"},
+
+        "siphon": {"int-list": "root-colors"},
+        
+        }
diff --git a/food_spring/__init__.py b/food_spring/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/gaia/Gaia.py b/food_spring/gaia/Gaia.py
new file mode 100644 (file)
index 0000000..f1e1b81
--- /dev/null
@@ -0,0 +1,23 @@
+from os.path import join
+from glob import glob
+
+from pygame import Surface
+from pygame.image import load
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.gaia.Swapper import Swapper
+
+class Gaia(GameChild):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.offset = self.get_configuration("gaia", "offset")
+        self.set_images()
+        self.swapper = Swapper(self)
+
+    def set_images(self):
+        images = []
+        for path in sorted(glob(join(self.get_resource("gaia", "path"),
+                                     "*.png"))):
+            images.append(load(path).convert_alpha())
+        self.images = images
diff --git a/food_spring/gaia/Swapper.py b/food_spring/gaia/Swapper.py
new file mode 100644 (file)
index 0000000..4290cdb
--- /dev/null
@@ -0,0 +1,93 @@
+from random import shuffle, choice
+
+from pygame import Surface
+from pygame.time import get_ticks
+from pygame.locals import *
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Swapper(GameChild, Surface):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.load_configuration()
+        self.init_surface()
+        self.set_segments()
+
+    def load_configuration(self):
+        config = self.get_configuration("introduction")
+        self.segment_count = config["segments"]
+        self.transition_time = config["transition"]
+
+    def init_surface(self):
+        parent = self.parent
+        offset = parent.offset
+        line, spread  = parent.images
+        Surface.__init__(self, (line.get_width(), line.get_height() + offset),
+                         SRCALPHA)
+        self.blit(line, (0, 0))
+        self.blit(spread, (0, offset))
+        rect = self.get_rect()
+        rect.left = self.get_display_surface().get_width() / 2 - \
+                    self.get_width() / 2
+        self.rect = rect
+
+    def set_segments(self):
+        width, height = self.get_size()
+        count = self.segment_count
+        segment_width = width / count
+        remainder = width % count
+        x = 0
+        segments = []
+        for _ in xrange(count):
+            adjusted_width = segment_width + (remainder > 0)
+            segments.append(Segment(self, x, 0, adjusted_width, height))
+            x += adjusted_width
+            remainder -= 1
+        self.segments = segments
+
+    def swap(self, p, q):
+        if isinstance(p, int):
+            p, q = self.segments[p], self.segments[q]
+        if not (p.moving() or q.moving()):
+            p.set_destination(q.location.right)
+            q.set_destination(p.location.right)
+
+    def update(self):
+        for segment in self.segments:
+            segment.update()
+        self.swap(choice(self.segments), choice(self.segments))
+
+
+class Segment(Sprite):
+
+    def __init__(self, parent, *args):
+        Sprite.__init__(self, parent)
+        self.add_frame(self.parent.subsurface(args).copy())
+        self.location.topleft = args[0] + self.parent.rect.left, args[1]
+        self.destination = self.location.right
+
+    def moving(self):
+        return self.destination != self.location.right
+
+    def set_destination(self, right):
+        self.destination = right
+        self.distance = abs(self.location.right - right)
+        self.last_ticks = get_ticks()
+
+    def update(self):
+        right = self.location.right
+        destination = self.destination
+        ticks = get_ticks()
+        if self.moving():
+            elapsed = float(ticks - self.last_ticks)
+            step = int(self.distance * elapsed / self.parent.transition_time) \
+                   or 1
+            if destination < right:
+                step = -step
+            self.move(step)
+            if abs(step) >= abs(self.location.right - destination):
+                self.location.right = destination
+        self.last_ticks = ticks
+        Sprite.update(self)
diff --git a/food_spring/gaia/__init__.py b/food_spring/gaia/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/gun/Gun.py b/food_spring/gun/Gun.py
new file mode 100644 (file)
index 0000000..39392fa
--- /dev/null
@@ -0,0 +1,33 @@
+from random import choice
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Gun(Sprite):
+
+    def __init__(self, parent, path):
+        Sprite.__init__(self, parent)
+        self.load_from_path(path, True)
+        self.set_framerate(self.get_configuration("gun", "framerate"))
+        self.reset()
+
+    def reset(self):
+        self.hide()
+        self.unfollow()
+
+    def hide(self):
+        self.visible = False
+
+    def unfollow(self):
+        self.following = False
+
+    def show(self):
+        self.visible = True
+
+    def follow(self, food):
+        self.food = food
+        self.following = True
+
+    def update(self):
+        if self.visible:
+            if self.following:
+                self.location.centerx = self.food.location.centerx
+            Sprite.update(self)
diff --git a/food_spring/gun/GunLibrary.py b/food_spring/gun/GunLibrary.py
new file mode 100644 (file)
index 0000000..1811f45
--- /dev/null
@@ -0,0 +1,46 @@
+from os import listdir
+from os.path import join
+
+from pygame import Surface
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.gun.Gun import Gun
+
+class GunLibrary(GameChild, list):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.load_configuration()
+        self.set_guns()
+
+    def load_configuration(self):
+        config = self.get_configuration("gun")
+        self.root = config["path"]
+
+    def set_guns(self):
+        for ii in xrange(4):
+            self.append(Guns(self, self.get_resource(join(self.root, str(ii)))))
+
+
+class Guns(GameChild, list):
+
+    def __init__(self, parent, root):
+        GameChild.__init__(self, parent)
+        for path in sorted(listdir(root)):
+            self.append(Gun(self, join(root, path)))
+        self.reset()
+
+    def reset(self):
+        for gun in self:
+            gun.reset()
+            gun.unfollow()
+
+    def hide(self, exclude=None):
+        for gun in self:
+            gun.hide()
+        if exclude is not None:
+            self[exclude].show()
+
+    def update(self):
+        for gun in self:
+            gun.update()
diff --git a/food_spring/gun/__init__.py b/food_spring/gun/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/home/Foods.py b/food_spring/home/Foods.py
new file mode 100644 (file)
index 0000000..de2897e
--- /dev/null
@@ -0,0 +1,135 @@
+from pygame import Rect
+
+from lib.pgfw.pgfw.GameChild import GameChild
+
+class Foods(GameChild, list):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.active_index = 0
+        self.display_surface = self.get_display_surface()
+        self.compare = self.get_delegate().compare
+        self.bounds = self.get_display_surface().get_rect()
+        self.load_configuration()
+        self.set_foods()
+        self.set_tv_rect()
+        self.reset()
+        self.subscribe(self.respond)
+
+    def load_configuration(self):
+        config = self.get_configuration("home")
+        self.inactive_x = config["food-inactive-x"]
+        self.inactive_y = config["food-inactive-y"]
+        self.active_y = config["food-active-y"]
+        self.margin = config["food-margin"]
+        self.step = config["food-step"]
+        self.tv_edge = config["tv-edge"]
+
+    def set_foods(self):
+        levels = self.get_game().levels
+        for ii in range(len(levels)):
+            self.append(levels[ii].food)
+
+    def set_tv_rect(self):
+        self.tv_rect = Rect(0, 0, self.tv_edge,
+                            self.display_surface.get_height())
+
+    def swap_in(self, index):
+        self.store(self.get_active())
+        self.active_index = index
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_active().location.bottomleft = self.get_x(self.active_index), \
+                                                self.active_y
+
+    def get_x(self, index):
+        x = self.inactive_x
+        for ii in range(index):
+            x += self[ii].location.w + self.margin
+        return x
+
+    def respond(self, event):
+        if self.parent.active:
+            if self.compare(event, "left"):
+                self.moving[0] = True
+            elif self.compare(event, "left", True):
+                self.moving[0] = False
+            elif self.compare(event, "right"):
+                self.moving[1] = True
+            elif self.compare(event, "right", True):
+                self.moving[1] = False
+            elif self.compare(event, "any"):
+                self.do()
+
+    def do(self):
+        rect = self.get_active().location
+        if not self.collide_other():
+            if rect.colliderect(self.tv_rect):
+                self.stop_moving()
+                self.store_location()
+                self.parent.deactivate()
+                self.get_game().levels.activate(self.active_index)
+            elif rect.colliderect(self.parent.collection):
+                pass
+
+    def stop_moving(self):
+        self.moving = [False, False]
+
+    def collide_other(self):
+        active = self.get_active()
+        rect = active.location
+        clip = None
+        closest = None
+        for food in self:
+            if active != food and rect.colliderect(food):
+                if not clip or rect.clip(food).w > clip.w:
+                    clip = rect.clip(food)
+                    closest = food
+        if closest:
+            self.swap_in(self.index(closest))
+            return True
+
+    def store_location(self):
+        self.stored_location = self.get_active().location.topleft
+
+    def reset(self):
+        for food in self:
+            self.store(food)
+        self.swap_in(0)
+        self.stop_moving()
+        self.store_location()
+
+    def activate(self):
+        for food in self:
+            if self.index(food) != self.active_index:
+                self.store(food)
+        self.get_active().location.topleft = self.stored_location
+
+    def store(self, food):
+        index = self.index(food)
+        self[index].location.bottomleft = self.get_x(index), self.inactive_y
+
+    def update(self):
+        active = self.get_active()
+        if True in self.moving:
+            if self.moving[0]:
+                active.move(-self.step)
+            if self.moving[1]:
+                active.move(self.step)
+            self.wrap()
+        for food in self:
+            if self.index(food) != self.active_index:
+                food.update()
+        active.update()
+
+    def get_active(self):
+        return self[self.active_index]
+
+    def wrap(self):
+        rect = self.get_active().location
+        bounds = self.bounds
+        if rect.left > bounds.right:
+            rect.right = bounds.left
+        elif rect.right < bounds.left:
+            rect.left = bounds.right
diff --git a/food_spring/home/Home.py b/food_spring/home/Home.py
new file mode 100644 (file)
index 0000000..3069c4e
--- /dev/null
@@ -0,0 +1,62 @@
+from pygame import mixer
+from pygame.image import load
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.home.View import View
+from food_spring.home.StaticEnvironment import StaticEnvironment
+from food_spring.home.Foods import Foods
+from food_spring.home.collection.Collection import Collection
+
+class Home(GameChild):
+
+    any_press_ignored = ["left", "right"]
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.input = self.get_input()
+        self.compare = self.get_delegate().compare
+        self.audio = self.get_audio()
+        self.audio_path = self.get_resource("home", "audio")
+        self.static_environment = StaticEnvironment(self)
+        self.view = View(self)
+        self.foods = Foods(self)
+        self.collection = Collection(self)
+        self.reset()
+        self.deactivate()
+
+    def deactivate(self):
+        self.active = False
+        self.input.unregister_any_press_ignore(*self.any_press_ignored)
+        # self.audio.stop_current_channel()
+        mixer.music.stop()
+        mixer.quit()
+        mixer.init(self.stored_frequency)
+
+    def reset(self):
+        self.foods.reset()
+        self.store_frequency()
+
+    def store_frequency(self):
+        self.stored_frequency = mixer.get_init()[0]
+
+    def activate(self):
+        self.active = True
+        self.input.register_any_press_ignore(*self.any_press_ignored)
+        self.foods.activate()
+        self.start_audio()
+
+    def start_audio(self):
+        self.store_frequency()
+        mixer.quit()
+        mixer.init(int(self.parent.timer.get_ratio_remaining() * \
+                       self.stored_frequency))
+        # self.audio.play_bgm(self.audio_path)
+        mixer.music.load(self.audio_path)
+        mixer.music.play(-1)
+
+    def update(self):
+        if self.active:
+            self.view.update()
+            self.static_environment.update()
+            self.foods.update()
diff --git a/food_spring/home/StaticEnvironment.py b/food_spring/home/StaticEnvironment.py
new file mode 100644 (file)
index 0000000..4444918
--- /dev/null
@@ -0,0 +1,9 @@
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class StaticEnvironment(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_from_path(self.get_resource("home",
+                                              "static-environment-path"),
+                            True)
diff --git a/food_spring/home/View.py b/food_spring/home/View.py
new file mode 100644 (file)
index 0000000..439bf7d
--- /dev/null
@@ -0,0 +1,67 @@
+from glob import glob
+from os.path import join
+
+from pygame import Color, PixelArray
+from pygame.image import load
+
+from lib.pgfw.pgfw.GameChild import GameChild
+
+class View(GameChild):
+
+    MAX_ALPHA = 255
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.index = 0
+        self.alpha = self.MAX_ALPHA
+        self.frame_index = 1
+        self.display_surface = self.get_display_surface()
+        self.load_configuration()
+        self.set_frames()
+
+    def load_configuration(self):
+        config = self.get_configuration("view")
+        self.coordinates = config["coordinates"]
+        self.root = config["path"]
+        self.alpha_step = config["alpha-step"]
+
+    def set_frames(self):
+        frames = []
+        for path in sorted(glob(join(self.get_resource(self.root), "[0-9]*"))):
+            frames.append(load(path).convert())
+        self.frames = frames
+
+    def update(self):
+        self.decrement_alpha()
+        self.draw()
+
+    def decrement_alpha(self):
+        alpha = self.alpha - self.alpha_step
+        if alpha <= 0:
+            alpha = self.MAX_ALPHA
+            self.get_previous_frame().set_alpha(alpha)
+            self.increment_frame_index()
+        self.get_previous_frame().set_alpha(alpha)
+        self.alpha = alpha
+
+    def get_current_frame(self):
+        return self.frames[self.frame_index]
+
+    def increment_frame_index(self):
+        index = self.frame_index + 1
+        if index >= len(self.frames):
+            index = 0
+        self.frame_index = index
+
+    def draw(self):
+        display_surface = self.display_surface
+        coordinates = self.coordinates
+        display_surface.blit(self.get_current_frame(), coordinates)
+        display_surface.blit(self.get_previous_frame(), coordinates)
+
+    def get_previous_frame(self):
+        frames = self.frames
+        index = self.frame_index - 1
+        if index < 0:
+            index = len(frames) - 1
+        return frames[index]
diff --git a/food_spring/home/__init__.py b/food_spring/home/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/home/collection/Collection.py b/food_spring/home/collection/Collection.py
new file mode 100644 (file)
index 0000000..2243a24
--- /dev/null
@@ -0,0 +1,18 @@
+from pygame import Rect
+
+from lib.pgfw.pgfw.GameChild import GameChild
+
+class Collection(GameChild, Rect):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.load_configuration()
+        self.init_rect()
+
+    def load_configuration(self):
+        config = self.get_configuration("collection")
+        self.coordinates = config["coordinates"]
+        self.size = config["size"]
+
+    def init_rect(self):
+        Rect.__init__(self, self.coordinates, self.size)
diff --git a/food_spring/home/collection/__init__.py b/food_spring/home/collection/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/introduction/Epithet.py b/food_spring/introduction/Epithet.py
new file mode 100644 (file)
index 0000000..83f5a6c
--- /dev/null
@@ -0,0 +1,101 @@
+from random import randint
+
+from pygame import Rect, Surface, Color
+from pygame.font import Font
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Epithet(GameChild, Rect):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.load_configuration()
+        self.init_rect()
+        self.set_glyphs()
+
+    def load_configuration(self):
+        config = self.get_configuration("epithet")
+        self.font_path = self.get_resource("display", "font-path")
+        self.width = config["width"]
+        self.margin = config["margin"]
+        self.text = config["text"]
+        self.color = config["color"]
+        self.i_color = config["i-color"]
+        self.t_color = config["t-color"]
+        self.font_size = config["font-size"]
+        self.it_size = config["it-size"]
+
+    def init_rect(self):
+        Rect.__init__(self, 0, 0, self.width, 0)
+        self.midtop = self.get_display_surface().get_rect().centerx, self.margin
+
+    def set_glyphs(self):
+        glyphs = []
+        for ii, character in enumerate(self.text):
+            if character != " ":
+                color = None
+                if character in "IT":
+                    size = self.it_size
+                    italic = True
+                    bold = True
+                    if character == "I":
+                        color = self.i_color
+                    elif character == "T":
+                        color = self.t_color
+                else:
+                    size = self.font_size
+                    italic = False
+                    bold = False
+                glyphs.append(Glyph(self, character, color, size, bold, italic,
+                                    ii))
+        self.glyphs = glyphs
+
+    def update(self):
+        for glyph in self.glyphs:
+            glyph.update()
+
+    def clear(self):
+        parent = self.parent
+        for glyph in self.glyphs:
+            for location in glyph.locations:
+                parent.display_surface.blit(parent.background, location,
+                                            location)
+
+
+class Glyph(Sprite):
+
+    def __init__(self, parent, character, color, size, bold, italic, ii):
+        Sprite.__init__(self, parent, randint(40, 120))
+        self.set_frames(character, size, color, bold, italic)
+        self.place(ii)
+        self.add_location(offset=(-5, 8))
+
+    def set_frames(self, character, size, color, bold, italic):
+        color = Color(0, 0, 0)
+        background_color = Color(0, 0, 0)
+        count = 30
+        font = Font(self.parent.font_path, size)
+        font.set_italic(italic)
+        font.set_bold(bold)
+        for ii in xrange(count):
+            hue = randint(0, 255)
+            color.hsla = hue, 100, 50, randint(30, 100)
+            background_hue = hue + 128
+            if background_hue > 255:
+                background_hue -= 255
+            background_color.hsla = background_hue, 100, 50, randint(30, 100)
+            frame = font.render(character, True, color, background_color)
+            if not ii % (count / 6):
+                surface = Surface(frame.get_size())
+                surface.set_colorkey((0, 0, 0))
+                midpoint = frame.get_width() / 2
+                surface.blit(frame, (midpoint, 0))
+                surface.blit(frame, (-midpoint, 0))
+                frame = surface
+            self.add_frame(frame)
+
+    def place(self, ii):
+        parent = self.parent
+        offset = int(parent.w * float(ii) / (len(parent.text) - 1))
+        self.location.center = parent.left + offset, parent.top
diff --git a/food_spring/introduction/Introduction.py b/food_spring/introduction/Introduction.py
new file mode 100644 (file)
index 0000000..791bde9
--- /dev/null
@@ -0,0 +1,60 @@
+from pygame import Surface, mixer
+
+from lib.pgfw.pgfw.Animation import Animation
+from food_spring.introduction.Epithet import Epithet
+
+class Introduction(Animation):
+
+    def __init__(self, parent):
+        Animation.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.audio = self.get_audio()
+        self.delegate = self.get_delegate()
+        self.audio_path = self.get_resource("introduction", "audio")
+        self.set_background()
+        self.epithet = Epithet(self)
+        self.spanky = parent.spanky
+        self.reset()
+        self.deactivate()
+        self.subscribe(self.respond)
+
+    def set_background(self):
+        surface = Surface(self.display_surface.get_size())
+        surface.fill((0, 0, 0))
+        self.background = surface
+
+    def respond(self, event):
+        if self.active:
+            if self.delegate.compare(event, "any"):
+                self.deactivate()
+                self.parent.title.queue_activation()
+
+    def reset(self):
+        self.display_surface.blit(self.background, (0, 0))
+
+    def deactivate(self):
+        self.active = False
+        # self.audio.stop_current_channel()
+        mixer.music.stop()
+
+    def activate(self):
+        self.active = True
+        # self.audio.play_bgm(self.audio_path)
+        mixer.music.load(self.audio_path)
+        mixer.music.play(-1)
+        self.spanky.location.midbottom = \
+                                       self.display_surface.get_rect().midbottom
+
+    def update(self):
+        if self.active:
+            self.get_display_surface().fill((0, 0, 0))
+            self.clear()
+            Animation.update(self)
+            self.parent.gaia.swapper.update()
+            self.epithet.update()
+            self.spanky.update()
+
+    def clear(self):
+        for rect in (self.parent.gaia.swapper.rect, self.spanky.location):
+            self.display_surface.blit(self.background, rect, rect)
+        self.epithet.clear()
diff --git a/food_spring/introduction/__init__.py b/food_spring/introduction/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/ExitArrow.py b/food_spring/level/ExitArrow.py
new file mode 100644 (file)
index 0000000..1e2b90e
--- /dev/null
@@ -0,0 +1,99 @@
+from math import ceil
+from collections import deque
+
+from pygame import Surface
+from pygame.draw import polygon
+from pygame.locals import *
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class ExitArrow(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.set_mask()
+        self.set_hues()
+        self.set_frames()
+        self.reset()
+        self.set_framerate(self.interval)
+        self.set_alpha(self.alpha)
+
+    def load_configuration(self):
+        config = self.get_configuration("exit-arrow")
+        self.width = config["width"]
+        self.height = config["height"]
+        self.overlap = config["overlap"]
+        self.arrow_count = config["arrow-count"]
+        self.hue = config["hue"]
+        self.frame_count = config["frame-count"]
+        self.interval = config["interval"]
+        self.saturation = config["saturation"]
+        self.offset = config["offset"]
+        self.fade_in_length = config["fade-in"]
+        self.fade_out_length = config["fade-out"]
+        self.alpha = config["alpha"]
+
+    def set_mask(self):
+        surface = Surface(self.get_size())
+        surface.set_colorkey((0, 0, 0))
+        rect = surface.get_rect()
+        width = self.width
+        x = 0
+        for ii in xrange(self.arrow_count):
+            points = (x, rect.centery), (x + width, 0), (x + width, rect.bottom)
+            polygon(surface, (255, 255, 255), points)
+            x += width - self.overlap
+        self.mask = surface
+
+    def get_size(self):
+        count = self.arrow_count
+        return self.width * count - self.overlap * (count - 1), self.height
+
+    def set_hues(self):
+        start, end = self.hue
+        step = float(end - start) / (self.frame_count - 1)
+        hues = deque([start])
+        while start < end:
+            start += step
+            hues.append(start)
+        hues.append(end)
+        self.hues = hues
+
+    def set_frames(self):
+        for _ in xrange(self.frame_count):
+            self.append_frame()
+
+    def append_frame(self):
+        width, height = self.get_size()
+        gradient = Surface((width, height))
+        gradient.set_colorkey((0, 0, 0))
+        hues = self.hues
+        step = float(width) / self.arrow_count / len(hues)
+        x = 0
+        color = Color(0, 0, 0)
+        while x < width:
+            for hue in hues:
+                color.hsla = hue, self.saturation, 50, 100
+                gradient.fill(color, (int(x), 0, ceil(step), height))
+                x += step
+        hues.rotate(-1)
+        mask = self.mask.convert()
+        gradient.blit(mask, (0, 0), None, BLEND_RGBA_MIN)
+        self.add_frame(gradient)
+
+    def reset(self):
+        location = self.location
+        base = self.parent.door.background.location
+        location.left = base.centerx + self.offset
+        location.centery = base.centery
+        self.fade(0, out=True)
+
+    def fade(self, length=None, out=None):
+        if length is None:
+            length = self.fade_out_length if out else self.fade_in_length
+        Sprite.fade(self, length, out)
+
+    def update(self):
+        self.move(-self.parent.velocity[0])
+        Sprite.update(self)
diff --git a/food_spring/level/Food.py b/food_spring/level/Food.py
new file mode 100644 (file)
index 0000000..8108aa5
--- /dev/null
@@ -0,0 +1,422 @@
+from os.path import join
+from math import tan, radians
+
+from pygame import Rect, Surface, Color
+from pygame.image import load
+from pygame.draw import polygon, ellipse, circle
+from pygame.mask import from_surface, Mask
+from pygame.locals import *
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Food(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.compare = self.get_delegate().compare
+        self.time_filter = self.get_game().time_filter
+        self.mouth = Mouth(self)
+        self.scope = Scope(self)
+        self.load_configuration()
+        self.load_nodesets()
+        self.set_frames()
+        self.set_frameset("cursed")
+        self.subscribe(self.respond)
+        self.register(self.unfreeze)
+        self.set_mask()
+        self.reset()
+        self.set_base()
+
+    def load_configuration(self):
+        config = self.get_configuration("food")
+        self.root = config["path"]
+        self.offset = config["offset"]
+        self.dx = config["dx"]
+        self.angle_range = config["angle-range"]
+        self.crouch_offset = config["crouch"]
+        self.drop_velocity = config["drop-velocity"]
+        self.dx_boost = config["dx-boost"]
+        self.blink_rate = config["blink-rate"]
+        self.freeze_length = config["freeze-length"]
+
+    def load_nodesets(self):
+        interpolator = self.get_game().interpolator
+        self.charge_nodeset = interpolator.get_nodeset("charge")
+        self.jump_width_nodeset = interpolator.get_nodeset("jump-width");
+        self.jump_height_nodeset = interpolator.get_nodeset("jump-height");
+
+    def set_frames(self):
+        root = self.get_resource(join(self.root, str(self.parent.index)))
+        self.load_from_path(root, True, omit=True)
+        self.add_frameset(0, name="cursed")
+        self.add_frameset(1, name="uncursed")
+        self.add_frameset([0, 1], name="transforming")
+        self.set_crouched()
+        self.set_frozen()
+
+    def set_crouched(self):
+        cursed = self.frames[0]
+        cursed_rect = cursed.get_rect()
+        offset = self.crouch_offset
+        surface = Surface((cursed_rect.w, cursed_rect.h - offset), SRCALPHA)
+        destination = Rect(0, 0, cursed_rect.w, cursed_rect.h / 2 + 1)
+        area = destination.move(0, 0)
+        destination.bottom = surface.get_rect().bottom
+        area.bottom = cursed_rect.bottom
+        surface.blit(cursed, destination, area)
+        destination.top = 0
+        surface.blit(cursed, destination, destination)
+        self.add_frame(surface, omit=True)
+        self.add_frameset(2, name="crouched")
+
+    def set_frozen(self):
+        surface = Surface(self.location.size)
+        surface.set_colorkey((0, 0, 0))
+        self.add_frame(surface, omit=True)
+        self.add_frameset([0, 3], self.blink_rate, "frozen")
+
+    def respond(self, event):
+        parent = self.parent
+        if parent.active:
+            if self.compare(event, "any") and not self.charging() and \
+                   not self.frozen:
+                self.activate_charge(event.id)
+            elif self.compare(event, "any", cancel=True):
+                if event.id == self.charge_key:
+                    if not self.jumping and parent.is_going():
+                        parent.exit_available = False
+                        parent.exit_arrow.fade(out=True)
+                        self.jump()
+                    self.cancel_charge()
+
+    def activate_charge(self, key):
+        self.charge_key = key
+        self.set_frameset("crouched")
+        self.move(0, self.crouch_offset)
+        self.parent.siphon.contract()
+
+    def jump(self):
+        self.jumping = True
+        self.submitted_charge = self.charge
+        rect = self.jump_rect = Rect((0, 0), self.get_jump_size())
+        rect.bottomleft = self.location.center
+
+    def get_jump_size(self):
+        charge = self.submitted_charge
+        return int(round(self.jump_width_nodeset.get_y(charge))), \
+               int(round(self.jump_height_nodeset.get_y(charge)))
+
+    def cancel_charge(self):
+        self.set_frameset("cursed")
+        self.move(0, -self.crouch_offset)
+        self.charge_key = None
+        self.charge_length = 0
+        self.charge = 0
+        self.parent.siphon.release()
+
+    def set_mask(self):
+        self.mask = from_surface(self.get_current_frame())
+
+    def reset(self):
+        self.ground = self.parent.platforms[0].rect.top
+        self.falling = False
+        self.dropping = False
+        self.submitted_charge = 0
+        self.cancel_jump()
+        self.cancel_charge()
+        self.place_at_start()
+        self.unfreeze()
+        self.scope.reset()
+
+    def place_at_start(self):
+        self.rect.bottomleft = self.offset, self.ground
+
+    def cancel_jump(self, offset=None):
+        self.location.bottom = self.ground
+        if offset:
+            self.location.right -= offset
+        self.jumping = False
+        self.gravity_effect = 0
+        self.previous_location = None
+        self.last_jump_x = 0
+
+    def set_base(self):
+        rect = self.rect
+        yy = rect.h - 2
+        start = None
+        for xx in xrange(rect.w):
+            visible = self.mask.get_at((xx, yy))
+            if start is None:
+                if visible:
+                    start = xx
+            else:
+                if not visible:
+                    break
+        width = xx - start
+        self.base = Rect(start, yy, width, 3)
+
+    def freeze(self):
+        if not self.frozen:
+            self.frozen = True
+            if self.charging():
+                self.cancel_charge()
+            self.set_frameset("frozen")
+            self.play(self.unfreeze, delay=self.freeze_length, play_once=True)
+
+    def unfreeze(self):
+        self.frozen = False
+        self.set_frameset("cursed")
+
+    def update(self):
+        if self.parent.active:
+            if self.jumping:
+                self.propell()
+                if not self.falling and self.rect.bottom >= self.ground and \
+                       self.last_jump_x > 0:
+                    collide = self.collide_with_platform()
+                    if collide:
+                        self.cancel_jump(collide)
+                    else:
+                        self.falling = True
+                elif self.rect.top > self.display_surface.get_height():
+                    self.parent.queue_reset()
+            elif self.parent.is_going():
+                self.move(-self.parent.velocity[0])
+            if self.falling:
+                index = self.location.collidelist(self.parent.platforms)
+                if index > -1:
+                    platform = self.parent.platforms[index].location
+                    intersection = self.location.clip(platform)
+                    if platform.left > self.location.left:
+                        self.location.right = platform.left
+                    else:
+                        self.location.left = platform.right
+                    self.dropping = True
+            self.update_charge()
+        self.scope.place()
+        Sprite.update(self)
+        if self.charging():
+            self.mouth.update()
+        self.scope.update()
+
+    def propell(self):
+        self.previous_location = Rect(self.location)
+        if not self.dropping:
+            rect = self.jump_rect
+            w, h = rect.size = self.get_jump_size()
+            x = self.dx + (self.parent.velocity[0] - 1) * self.dx_boost + \
+                self.last_jump_x
+            if w == 0:
+                w = .00000000001
+            y = (-2 * h / (.5 * w ** 2)) * x ** 2 + (4 * h / w) * x
+            self.location.center = rect.move(int(round(x)),
+                                             int(round(-y))).bottomleft
+            self.last_jump_x = x
+        else:
+            self.move(*self.drop_velocity)
+
+    def collide_with_platform(self):
+        base = self.base
+        previous = base.move(*self.previous_location.topleft)
+        current = base.move(*self.location.topleft)
+        box = Rect(previous.topleft, (current.right - previous.left,
+                                      current.bottom - previous.top))
+        platform_index = box.collidelist(self.parent.platforms)
+        if platform_index > -1:
+            stripe = Surface(box.size)
+            stripe.set_colorkey((0, 0, 0))
+            polygon(stripe, (255, 255, 255),
+                    ((0, 0), (base.w, 0), box.size, (box.w - base.w, box.h)))
+            stripe_mask = from_surface(stripe)
+            platform = self.parent.platforms[platform_index]
+            platform_mask = from_surface(Surface((platform.location.w, 3)))
+            offset = platform.location.left - box.left, \
+                     platform.location.top - 1 - box.top
+            overlap = stripe_mask.overlap(platform_mask, offset)
+            if overlap:
+                for x in xrange(stripe_mask.get_size()[0]):
+                    if stripe_mask.get_at((x, overlap[1] + 1)):
+                        break
+                return box.w - base.w - x
+
+    def update_charge(self):
+        if self.charging():
+            self.charge_length += self.time_filter.get_last_frame_duration()
+            self.charge = self.charge_nodeset.get_y(self.charge_length)
+
+    def charging(self):
+        return self.charge_key is not None
+
+
+class Mouth(Surface, GameChild):
+
+    transparent_color = (255, 0, 255)
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.set_images()
+        self.init_surface()
+        self.set_background()
+        self.load_configuration()
+
+    def set_images(self):
+        get = self.get_resource
+        self.lower_jaw = load(get("food", "lower-jaw-path")).convert_alpha()
+        self.lower_jaw_rect = self.lower_jaw.get_rect()
+        self.upper_jaw = load(get("food", "upper-jaw-path")).convert_alpha()
+        self.upper_jaw_rect = self.upper_jaw.get_rect()
+
+    def init_surface(self):
+        Surface.__init__(self, self.get_configuration("food", "mouth-size"),
+                         SRCALPHA)
+
+    def set_background(self):
+        surface = Surface(self.get_size())
+        key = self.transparent_color
+        surface.fill(key)
+        surface.set_colorkey(key)
+        surface.set_alpha(self.get_configuration("food", "mouth-bg-alpha"))
+        self.background = surface
+
+    def load_configuration(self):
+        config = self.get_configuration("food")
+        self.offset = config["mouth-offset"]
+        self.background_shrink = config["mouth-bg-shrink"]
+        self.gap = config["mouth-gap"]
+
+    def update(self):
+        self.display_surface = self.parent.display_surface
+        self.init_surface()
+        self.clear_background()
+        self.rect = self.get_position(self.parent.location)
+        self.draw_jaws()
+        mask = self.draw_mask()
+        self.draw_background(mask, self.rect)
+        self.display_surface.blit(self, self.rect)
+        if self.parent.scope.active:
+            scope_rect = self.get_position(self.parent.scope.extra_location)
+            self.draw_background(mask, scope_rect)
+            self.display_surface.blit(self, scope_rect)
+
+    def clear_background(self):
+        self.background.fill(self.transparent_color)
+
+    def get_position(self, base):
+        offset = self.offset
+        rect = self.get_rect()
+        rect.center = base.left + offset[0], base.bottom - offset[1]
+        return rect
+
+    def draw_jaws(self):
+        rect = self.rect
+        center = rect.h / 2
+        offset = max(self.gap, int(round(self.parent.charge * center)))
+        lower_rect = self.lower_jaw_rect
+        lower_rect.bottom = center + offset
+        self.blit(self.lower_jaw, lower_rect)
+        upper_rect = self.upper_jaw_rect
+        upper_rect.top = center - offset
+        self.blit(self.upper_jaw, upper_rect)
+
+    def draw_mask(self):
+        surface = Surface(self.get_size(), SRCALPHA)
+        width = self.rect.w
+        height = int(round(self.rect.h * self.parent.charge))
+        rect = Rect(0, 0, width, height)
+        rect.centery = self.rect.h / 2
+        ellipse(surface, (255, 255, 255), rect)
+        self.blit(surface, (0, 0), None, BLEND_RGBA_MIN)
+        return rect
+
+    def draw_background(self, ellipse_rect, rect):
+        shrink = self.background_shrink
+        if ellipse_rect.h >= -shrink[0]:
+            ellipse(self.background, (0, 0, 0), ellipse_rect.inflate(*shrink))
+            self.display_surface.blit(self.background, rect)
+
+
+class LowerJaw(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_from_path(self.get_resource("food", "lower-jaw-path"), True)
+
+
+class UpperJaw(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_from_path(self.get_resource("food", "upper-jaw-path"), True)
+
+
+class Scope(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.active = False
+        self.limit = 400
+        self.reset()
+
+    def offset_points(self, points):
+        offset = []
+        for point in points:
+            offset.append((point[0], point[1] + 2))
+        return offset
+
+    def reset(self):
+        if self.active:
+            self.parent.remove_locations(self.extra_location)
+            self.active = False
+
+    def place(self):
+        if self.parent.parent.is_going():
+            if not self.active and self.parent.location.right <= 0:
+                self.active = True
+                self.extra_location = self.parent.add_location()
+            if self.active:
+                if self.parent.location.right > 0:
+                    self.reset()
+                else:
+                    if self.parent.location.right <= -self.limit:
+                        self.parent.parent.queue_reset()
+                    self.set_frame()
+                    location = self.location
+                    location.centery = self.parent.location.centery
+                    self.extra_location.reset_motion_overflow()
+                    self.extra_location.midright = location.right - 15, \
+                                                   location.centery
+
+    def set_frame(self):
+        surface = Surface((76, 60))
+        rect = surface.get_rect()
+        key = (255, 0, 255)
+        surface.fill(key)
+        surface.set_colorkey(key)
+        background = (128, 128, 128)
+        distance = self.parent.location.right
+        if distance < -self.limit:
+            distance = -self.limit
+        foreground = Color(0, 0, 0)
+        limit = self.limit
+        foreground.hsla = int(120 * (limit + distance) / limit), 95, 55, 100
+        points = (0, rect.h / 2 - 1), (8, rect.h / 2 - 11), (8, rect.h / 2 + 9)
+        polygon(surface, background, self.offset_points(points))
+        polygon(surface, foreground, points)
+        square = Rect(8, rect.h / 2 - 6, 10, 10)
+        surface.fill(background, square.move(0, 2))
+        surface.fill(foreground, square)
+        center = 46, rect.h / 2 - 1
+        radius = 29
+        circle(surface, background, (center[0], center[1] + 2), radius, 10)
+        area = circle(surface, foreground, center, radius, 10)
+        ellipse(surface, foreground, area.inflate(-1, 0), 9)
+        ellipse(surface, foreground, area.inflate(0, -1), 9)
+        ellipse(surface, foreground, area.inflate(-2, -1), 8)
+        ellipse(surface, foreground, area.inflate(-1, -2), 8)
+        self.clear_frames()
+        self.add_frame(surface)
+
+    def update(self):
+        if self.parent.parent.is_going() and self.active:
+            Sprite.update(self)
diff --git a/food_spring/level/Level.py b/food_spring/level/Level.py
new file mode 100644 (file)
index 0000000..b3bca49
--- /dev/null
@@ -0,0 +1,231 @@
+from os.path import join
+
+from pygame import Surface, mixer
+from pygame.font import Font
+from pygame.locals import *
+
+from lib.pgfw.pgfw.Animation import Animation
+from food_spring.level.land.Land import Land
+from food_spring.level.platform.Platforms import Platforms
+from food_spring.level.Food import Food
+from food_spring.level.planet.Planet import Planet
+from food_spring.level.stars.Stars import Stars
+from food_spring.level.drop.Drops import Drops
+from food_spring.level.door.Door import Door
+from food_spring.level.ExitArrow import ExitArrow
+from food_spring.level.obstacle.Obstacles import Obstacles
+from food_spring.level.Window import Window
+
+class Level(Animation):
+
+    any_press_ignored = "left"
+    transparent_color = 255, 0, 255
+
+    def __init__(self, parent, index, horizontal_drop=False):
+        Animation.__init__(self, parent)
+        self.index = index
+        self.display_surface = self.get_display_surface()
+        self.input = self.get_input()
+        self.compare = self.get_delegate().compare
+        self.audio = self.get_audio()
+        self.timer = self.get_game().timer
+        self.siphon = self.get_game().siphon
+        self.velocity = [0, 0]
+        self.time = 0.0
+        self.altitude = 0
+        self.load_configuration()
+        self.assign_defaults()
+        self.set_background()
+        self.land = Land(self)
+        self.planet = Planet(self)
+        self.stars = Stars(self)
+        self.guns = self.parent.parent.gun_library[index]
+        self.drops = Drops(self)
+        self.platforms = Platforms(self)
+        self.food = Food(self)
+        self.door = Door(self)
+        self.exit_arrow = ExitArrow(self)
+        self.obstacles = Obstacles(self)
+        self.window = Window(self)
+        self.saved_food_surface = self.food.display_surface
+        self.subscribe(self.respond)
+        self.register(self.go, self.stall, self.enter, self.transition_to_go,
+                      self.exit, self.fade_in_arrow)
+        self.deactivate()
+
+    def load_configuration(self):
+        config = self.get_configuration("level")
+        self.background_color = config["background-color"]
+        self.gravity = config["gravity"]
+        self.velocity_range = config["velocity"]
+        self.stall_length = config["stall"]
+        self.fall_pause = config["fall-pause"]
+        self.entrance_offset = config["entrance-offset"]
+        self.entrance_speed = config["entrance-speed"]
+        self.audio_root = config["audio"]
+
+    def assign_defaults(self):
+        self.distance = 0.0
+        self.velocity[0] = 0.0
+        self.time = 0.0
+        self.reset_queued = False
+
+    def set_background(self):
+        surface = Surface(self.display_surface.get_size())
+        surface.fill(self.background_color)
+        self.background = surface
+
+    def deactivate(self):
+        self.active = False
+        self.halt()
+        self.input.unregister_any_press_ignore(self.any_press_ignored)
+        self.restore_food_surface()
+        # self.audio.stop_current_channel()
+        mixer.music.stop()
+
+    def restore_food_surface(self):
+        self.food.display_surface = self.saved_food_surface
+
+    def respond(self, event):
+        if self.compare(event, "reset-game"):
+            self.deactivate()
+        elif self.active and self.compare(event, "left") and \
+                 self.exit_available and self.is_playing(check_all=True):
+            self.halt()
+            self.timer.stop()
+            self.velocity[0] = 0.0
+            food = self.food.location
+            difference = self.platforms[0].location.right - food.right
+            rect = self.get_entrance_mask()[1]
+            food.bottomright = rect.w - difference, rect.h
+            self.play(self.exit)
+
+    def reset(self):
+        self.assign_defaults()
+        self.land.reset()
+        self.drops.reset()
+        self.platforms.reset()
+        self.food.reset()
+        self.door.reset()
+        self.exit_arrow.reset()
+        self.obstacles.reset()
+        self.window.reset()
+
+    def activate(self):
+        self.active = True
+        self.exit_available = False
+        self.siphon.set_level(self.index)
+        self.reset()
+        self.input.register_any_press_ignore(self.any_press_ignored)
+        mask, rect = self.get_entrance_mask()
+        self.food.location.bottomleft = -self.entrance_offset, rect.h
+        self.saved_food_surface = self.food.display_surface
+        # self.audio.play_bgm(self.get_resource(join(self.audio_root,
+        #                                            str(self.index) + ".ogg")))
+        mixer.music.load(
+            self.get_resource(join(self.audio_root, str(self.index) + ".ogg")))
+        mixer.music.play(-1)
+        self.play(self.enter)
+
+    def get_entrance_mask(self):
+        base = self.door.foreground.location
+        width = self.platforms[0].location.right - base.right
+        mask = Surface((width, base.h), SRCALPHA)
+        rect = mask.get_rect()
+        rect.topleft = base.topright
+        return mask, rect
+
+    def enter(self):
+        self.food.move(self.entrance_speed)
+        mask, rect = self.get_entrance_mask()
+        self.food.display_surface = mask
+        self.clear_and_update_children()
+        self.display_surface.blit(mask, rect)
+        if self.food.location.left >= self.food.offset - rect.left:
+            self.restore_food_surface()
+            self.food.place_at_start()
+            self.halt()
+            self.play(self.stall)
+            self.play(self.transition_to_go, delay=self.stall_length)
+
+    def go(self):
+        self.distance += self.velocity[0]
+        self.clear_and_update_children()
+        self.accelerate()
+        self.time += 1
+        if self.reset_queued:
+            self.reset()
+            self.halt()
+            self.timer.stop()
+            self.exit_available = True
+            self.play(self.stall, delay=self.fall_pause)
+            self.play(self.fade_in_arrow, delay=self.fall_pause)
+            self.play(self.transition_to_go,
+                      delay=self.stall_length + self.fall_pause)
+
+    def stall(self):
+        self.clear_and_update_children()
+
+    def transition_to_go(self):
+        self.halt()
+        self.velocity[0] = self.velocity_range[0]
+        self.timer.start()
+        self.play(self.go)
+
+    def fade_in_arrow(self):
+        self.exit_arrow.fade(out=False)
+
+    def exit(self):
+        self.food.move(-self.entrance_speed)
+        mask, rect = self.get_entrance_mask()
+        self.food.display_surface = mask
+        self.clear_and_update_children()
+        self.display_surface.blit(mask, rect)
+        if self.food.location.left <= -self.entrance_offset:
+            self.restore_food_surface()
+            self.halt()
+            self.deactivate()
+            self.get_game().home.activate()
+
+    def queue_reset(self):
+        self.reset_queued = True
+
+    def is_going(self):
+        return self.is_playing(self.go)
+
+    def update(self):
+        if self.active:
+            Animation.update(self)
+
+    def clear_and_update_children(self):
+        self.clear()
+        self.stars.update()
+        self.planet.update()
+        self.siphon.update()
+        self.land.update()
+        self.door.background.update()
+        self.exit_arrow.update()
+        self.guns.update()
+        if not self.food.scope.active:
+            self.food.update()
+        self.door.foreground.update()
+        self.drops.update()
+        self.platforms.update()
+        if self.food.scope.active:
+            self.food.update()
+        self.obstacles.update()
+        self.window.update()
+
+    def clear(self):
+        self.display_surface.blit(self.background, (0, 0))
+
+    def accelerate(self):
+        time = self.time
+        minimum, maximum = self.velocity_range
+        self.velocity[0] =  minimum + time * maximum / (2000 + time)
+        # self.print_velocity()
+
+    def print_velocity(self):
+        surface = Font(None, 24).render("%.2f" % self.velocity[0], False,
+                                        (255, 255, 255))
+        self.get_display_surface().blit(surface, (0, 0))
diff --git a/food_spring/level/Levels.py b/food_spring/level/Levels.py
new file mode 100644 (file)
index 0000000..ba660be
--- /dev/null
@@ -0,0 +1,21 @@
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.watermelon.Watermelon import Watermelon
+from food_spring.level.peach.Peach import Peach
+from food_spring.level.pineapple.Pineapple import Pineapple
+from food_spring.level.grapes.Grapes import Grapes
+
+class Levels(GameChild, list):
+
+    WATERMELON, PEACH, GRAPES, PINEAPPLE = range(4)
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        list.__init__(self, (Watermelon(self), Peach(self), Grapes(self),
+                             Pineapple(self)))
+
+    def activate(self, index):
+        self[index].activate()
+
+    def update(self):
+        for level in self:
+            level.update()
diff --git a/food_spring/level/Window.py b/food_spring/level/Window.py
new file mode 100644 (file)
index 0000000..6671723
--- /dev/null
@@ -0,0 +1,70 @@
+from random import randrange, choice
+
+from pygame import Surface, PixelArray, Color
+from pygame.image import load, save
+from pygame.locals import *
+
+from lib.pgfw.pgfw.Animation import Animation
+
+class Window(Animation):
+
+    def __init__(self, parent):
+        Animation.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.load_configuration()
+        self.set_images()
+        self.set_x_range()
+        self.alpha_ratio = randrange(100) * .01
+        self.alpha_direction = choice((1, -1))
+
+    def load_configuration(self):
+        config = self.get_configuration("window")
+        self.alpha = config["alpha"]
+        self.remain_length = config["remain-length"]
+        self.fade_step = config["fade-step"]
+        self.margin = config["margin"]
+
+    def set_images(self):
+        image = load(self.get_resource("window", "path")).convert()
+        inverted = Surface(image.get_size())
+        inverted.fill((255, 255, 255))
+        inverted.blit(image, (0, 0), None, BLEND_SUB)
+        pixels = PixelArray(inverted)
+        for x in xrange(len(pixels) - 1):
+            for y in xrange(len(pixels[x]) - 1):
+                color = Color(*image.unmap_rgb(pixels[x][y]))
+                hue, saturation, value, alpha = color.hsva
+                color.hsva = hue, saturation, 100 - value, alpha
+                pixels[x][y] = color
+        del pixels
+        self.images = image, inverted
+        self.rect = image.get_rect()
+        self.rect.right = self.display_surface.get_rect().right - self.margin
+
+    def set_x_range(self):
+        margin = self.margin
+        self.x_range = margin, \
+                       self.display_surface.get_width() - margin - self.rect.w
+
+    def reset(self):
+        pass
+
+    def update(self):
+        Animation.update(self)
+        self.update_alpha()
+        intermediate = Surface(self.rect.size)
+        intermediate.blit(self.images[0], (0, 0))
+        intermediate.blit(self.images[1], (0, 0))
+        self.display_surface.blit(intermediate, self.rect, None, BLEND_MAX)
+
+    def update_alpha(self):
+        self.alpha_ratio += self.fade_step * self.alpha_direction
+        if self.alpha_ratio < 0:
+            self.alpha_ratio = 0
+            self.alpha_direction = 1
+        elif self.alpha_ratio > 1:
+            self.alpha_ratio = 1
+            self.alpha_direction = -1
+        alpha = self.alpha
+        self.images[0].set_alpha(int(alpha * self.alpha_ratio))
+        self.images[1].set_alpha(int(alpha * (1 - self.alpha_ratio)))
diff --git a/food_spring/level/__init__.py b/food_spring/level/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/door/Background.py b/food_spring/level/door/Background.py
new file mode 100644 (file)
index 0000000..4ca89e7
--- /dev/null
@@ -0,0 +1,20 @@
+from os.path import join
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Background(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_from_path(join(self.get_resource("door", "path"),
+                                 str(self.parent.parent.index),
+                                 "background.png"), True, True)
+        self.location.bottom = self.parent.parent.platforms[0].location.top
+        self.reset()
+
+    def reset(self):
+        self.location.left = self.parent.foreground.location.right
+
+    def update(self):
+        self.move(-self.parent.parent.velocity[0])
+        Sprite.update(self)
diff --git a/food_spring/level/door/Door.py b/food_spring/level/door/Door.py
new file mode 100644 (file)
index 0000000..c5c8bec
--- /dev/null
@@ -0,0 +1,14 @@
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.door.Foreground import Foreground
+from food_spring.level.door.Background import Background
+
+class Door(GameChild):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.foreground = Foreground(self)
+        self.background = Background(self)
+
+    def reset(self):
+        self.foreground.reset()
+        self.background.reset()
diff --git a/food_spring/level/door/Foreground.py b/food_spring/level/door/Foreground.py
new file mode 100644 (file)
index 0000000..858d5c3
--- /dev/null
@@ -0,0 +1,27 @@
+from os.path import join
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Foreground(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        index = str(self.parent.parent.index)
+        self.load_from_path(self.get_resource(join(self.root, index,
+                                                   "foreground.png")), True,
+                            True)
+        self.location.bottom = self.parent.parent.platforms[0].location.top
+        self.reset()
+
+    def reset(self):
+        self.location.left = self.x
+
+    def load_configuration(self):
+        config = self.get_configuration("door")
+        self.x = config["x"]
+        self.root = config["path"]
+
+    def update(self):
+        self.move(-self.parent.parent.velocity[0])
+        Sprite.update(self)
diff --git a/food_spring/level/door/__init__.py b/food_spring/level/door/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/drop/Blinker.py b/food_spring/level/drop/Blinker.py
new file mode 100644 (file)
index 0000000..e751be2
--- /dev/null
@@ -0,0 +1,10 @@
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Blinker(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.set_frames()
+
+    def set_frames(self):
+        pass
diff --git a/food_spring/level/drop/Blob.py b/food_spring/level/drop/Blob.py
new file mode 100644 (file)
index 0000000..184e826
--- /dev/null
@@ -0,0 +1,23 @@
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Blob(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_from_path(self.get_resource("blob", "path"), True, True,
+                            query="*.png")
+        self.hide()
+
+    def hide(self):
+        self.visible = False
+
+    def show(self):
+        self.visible = True
+
+    def update(self):
+        if self.visible:
+            if not self.parent.horizontal:
+                self.location.centerx = self.parent.parent.food.location.centerx
+            else:
+                self.location.centery = self.parent.parent.food.location.centery
+            Sprite.update(self)
diff --git a/food_spring/level/drop/Drop.py b/food_spring/level/drop/Drop.py
new file mode 100644 (file)
index 0000000..e6eeef0
--- /dev/null
@@ -0,0 +1,6 @@
+from lib.pgfw.pgfw.Animation import Animation
+
+class Drop(Animation):
+
+    def __init__(self, parent):
+        Animation.__init__(self, parent)
diff --git a/food_spring/level/drop/Drops.py b/food_spring/level/drop/Drops.py
new file mode 100644 (file)
index 0000000..d9a6b6e
--- /dev/null
@@ -0,0 +1,66 @@
+from lib.pgfw.pgfw.Animation import Animation
+from food_spring.level.drop.Blob import Blob
+
+class Drops(Animation):
+
+    def __init__(self, parent, horizontal=False):
+        Animation.__init__(self, parent)
+        self.horizontal = horizontal
+        self.display_surface = self.get_display_surface()
+        self.load_configuration()
+        self.guns = self.parent.guns
+        self.blob = Blob(self)
+        self.reset()
+        self.register(self.spawn, self.send_gun)
+
+    def load_configuration(self):
+        config = self.get_configuration("drop")
+        self.first_spawn = config["first-spawn"]
+        self.spawn_decrease = config["spawn-decrease"]
+        self.speed = config["speed"]
+        self.blob_length = config["blob-length"]
+        self.consecutive = config["consecutive"]
+
+    def reset(self):
+        self.started = False
+        self.spawn_delay = self.first_spawn
+        self.count = 0
+        self.return_to_origin()
+        self.guns.reset()
+        self.blob.hide()
+        self.halt()
+
+    def return_to_origin(self):
+        self.y = 0
+
+    def update(self):
+        if self.parent.is_going():
+            if not self.started:
+                self.play(self.spawn, delay=self.spawn_delay, play_once=True)
+                self.started = True
+            Animation.update(self)
+            self.blob.update()
+
+    def spawn(self):
+        self.blob.show()
+        self.play(self.send_gun, delay=self.blob_length)
+
+    def send_gun(self):
+        guns = self.guns
+        visible_gun_index = min(len(guns) - 1, self.count / self.consecutive)
+        if guns[visible_gun_index].location.colliderect(self.parent.food):
+            self.count += 1
+            self.return_to_origin()
+            guns[visible_gun_index].location.bottom = self.y
+            guns.hide()
+            self.spawn_delay *= self.spawn_decrease
+            self.play(self.spawn, delay=self.spawn_delay, play_once=True)
+            self.halt(self.send_gun)
+            self.parent.siphon.add(visible_gun_index)
+        else:
+            self.blob.hide()
+            guns.hide(visible_gun_index)
+            gun = guns[visible_gun_index]
+            gun.location.bottom = self.y
+            gun.follow(self.parent.food)
+            self.y += self.speed
diff --git a/food_spring/level/drop/__init__.py b/food_spring/level/drop/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/grapes/Grapes.py b/food_spring/level/grapes/Grapes.py
new file mode 100644 (file)
index 0000000..cf04130
--- /dev/null
@@ -0,0 +1,6 @@
+from food_spring.level.Level import Level
+
+class Grapes(Level):
+
+    def __init__(self, parent):
+        Level.__init__(self, parent, parent.GRAPES)
diff --git a/food_spring/level/grapes/__init__.py b/food_spring/level/grapes/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/land/Land.py b/food_spring/level/land/Land.py
new file mode 100644 (file)
index 0000000..32e07b1
--- /dev/null
@@ -0,0 +1,39 @@
+from pygame import Rect
+from pygame.locals import *
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.land.Mask import Mask
+from food_spring.level.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.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.display_surface.blit(self.plate, self)
+        self.display_surface.blit(self.mask, self, None, BLEND_RGB_MIN)
diff --git a/food_spring/level/land/Mask.py b/food_spring/level/land/Mask.py
new file mode 100644 (file)
index 0000000..197348a
--- /dev/null
@@ -0,0 +1,73 @@
+from math import tan, radians
+
+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/food_spring/level/land/Plate.py b/food_spring/level/land/Plate.py
new file mode 100644 (file)
index 0000000..82a1eb6
--- /dev/null
@@ -0,0 +1,50 @@
+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 xrange(height):
+            hue = int(float(y) / (height) * 360)
+            color.hsva = hue, 100, 100, 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/food_spring/level/land/__init__.py b/food_spring/level/land/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/obstacle/Fireball.py b/food_spring/level/obstacle/Fireball.py
new file mode 100644 (file)
index 0000000..ff96734
--- /dev/null
@@ -0,0 +1,62 @@
+from random import randrange
+
+from pygame import Surface
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Fireball(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.set_frames()
+        self.register(self.spew)
+        self.reset()
+
+    def load_configuration(self):
+        config = self.get_configuration("fireball")
+        self.delay = config["delay"]
+        self.speed = config["speed"]
+        self.peak = config["peak"]
+
+    def set_frames(self):
+        surface = Surface((24, 8))
+        surface.fill((0, 255, 255))
+        self.add_frame(surface, omit=True)
+        self.add_frameset(0, name="spewing")
+        blank = Surface(self.location.size)
+        blank.set_colorkey((0, 0, 0))
+        self.add_frame(blank, omit=True)
+        self.add_frameset([0, 1], self.parent.blink_rate, "queued")
+
+    def reset(self):
+        self.halt(self.spew)
+        self.set_frameset("queued")
+        self.active = False
+        self.queue_reset = False
+        limit = self.display_surface.get_rect()
+        self.location.midleft = randrange(0, limit.w - self.location.w), limit.h
+        self.direction = -1
+
+    def queue_spew(self):
+        self.active = True
+        self.play(self.spew, delay=self.delay)
+
+    def spew(self):
+        self.set_frameset("spewing")
+        self.move(0, self.direction * self.speed)
+        limit = self.parent.parent.platforms[0].location.top - self.peak
+        if self.direction == -1 and self.location.centery <= limit:
+            self.location.centery = limit
+            self.direction = 1
+        elif self.direction == 1 and \
+             self.location.top >= self.display_surface.get_height():
+            self.queue_reset = True
+        if self.location.colliderect(self.parent.parent.food):
+            self.parent.parent.food.freeze()
+
+    def update(self):
+        if self.active:
+            Sprite.update(self)
+        if self.queue_reset:
+            self.reset()
diff --git a/food_spring/level/obstacle/Hurdle.py b/food_spring/level/obstacle/Hurdle.py
new file mode 100644 (file)
index 0000000..29ba413
--- /dev/null
@@ -0,0 +1,64 @@
+from pygame import Surface
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Hurdle(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.set_frames()
+        self.register(self.enter, self.exit)
+        self.reset()
+
+    def load_configuration(self):
+        config = self.get_configuration("hurdle")
+        self.delay = config["delay"]
+        self.speed = config["speed"]
+        self.pause = config["pause"]
+
+    def set_frames(self):
+        surface = Surface((32, 8))
+        surface.fill((255, 255, 0))
+        self.add_frame(surface, omit=True)
+        self.add_frameset(0, name="entered")
+        blank = Surface(self.location.size)
+        blank.set_colorkey((0, 0, 0))
+        self.add_frame(blank, omit=True)
+        self.add_frameset([0, 1], self.parent.blink_rate, "queued")
+
+    def reset(self):
+        self.halt(self.enter)
+        self.halt(self.exit)
+        self.active = False
+        self.queue_reset = False
+        self.location.centerx = self.display_surface.get_rect().left
+        self.set_frameset("queued")
+
+    def queue_entrance(self, dy):
+        self.location.centery = self.parent.parent.platforms[0].location.top - \
+                                dy
+        self.active = True
+        self.play(self.enter, delay=self.delay)
+
+    def enter(self):
+        self.set_frameset("entered")
+        self.move(self.speed, 0)
+        if self.location.centerx >= self.display_surface.get_rect().centerx:
+            self.halt(self.enter)
+            self.play(self.exit, delay=self.pause)
+
+    def exit(self):
+        self.move(self.speed, 0)
+        if self.location.right >= self.display_surface.get_rect().right:
+            self.queue_reset = True
+
+    def update(self):
+        if self.active:
+            if self.is_playing(self.enter, include_delay=True) or \
+               self.is_playing(self.exit):
+                if self.location.colliderect(self.parent.parent.food):
+                    self.parent.parent.food.freeze()
+            Sprite.update(self)
+        if self.queue_reset:
+            self.reset()
diff --git a/food_spring/level/obstacle/Missile.py b/food_spring/level/obstacle/Missile.py
new file mode 100644 (file)
index 0000000..d46a60d
--- /dev/null
@@ -0,0 +1,70 @@
+from math import atan, degrees, radians, sqrt, sin, cos
+from random import randint, randrange
+
+from pygame import Surface
+from pygame.transform import rotate
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Missile(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.load_configuration()
+        self.set_step()
+        self.set_frames()
+        self.register(self.fly)
+        self.reset()
+
+    def load_configuration(self):
+        config = self.get_configuration("missile")
+        self.margin = config["margin"]
+        self.speed = config["speed"]
+        self.peak = config["peak"]
+        self.delay = config["delay"]
+        self.angle = config["angle"]
+
+    def set_step(self):
+        angle = radians(self.angle)
+        self.step = sin(angle) * self.speed, cos(angle) * self.speed
+
+    def set_frames(self):
+        surface = Surface((8, 32))
+        surface.fill((255, 0, 0))
+        surface.set_colorkey((255, 0, 255))
+        self.add_frame(rotate(surface, self.angle), omit=True)
+        self.add_frameset(0, name="flying")
+        blank = Surface(self.location.size)
+        blank.set_colorkey((0, 0, 0))
+        self.add_frame(blank, omit=True)
+        self.add_frameset([0, 1], self.parent.blink_rate, "queued")
+
+    def reset(self):
+        self.halt(self.fly)
+        self.active = False
+        self.queue_reset = False
+        self.location.center = randrange(40, 640), 0
+        self.set_frameset("queued")
+
+    def is_flying(self):
+        return self.is_playing(self.fly)
+
+    def queue_fly(self):
+        self.active = True
+        self.play(self.fly, delay=self.delay)
+
+    def fly(self):
+        self.set_frameset("flying")
+        self.move(*self.step)
+        location = self.location
+        if location.colliderect(self.parent.parent.food):
+            self.parent.parent.food.freeze()
+        if location.top > self.display_surface.get_height():
+            self.queue_reset = True
+
+    def update(self):
+        if self.active:
+            Sprite.update(self)
+        if self.queue_reset:
+            self.reset()
diff --git a/food_spring/level/obstacle/Obstacles.py b/food_spring/level/obstacle/Obstacles.py
new file mode 100644 (file)
index 0000000..a775f50
--- /dev/null
@@ -0,0 +1,83 @@
+from random import randint, random
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.obstacle.Missile import Missile
+from food_spring.level.obstacle.Hurdle import Hurdle
+from food_spring.level.obstacle.Spikes import Spikes
+from food_spring.level.obstacle.Fireball import Fireball
+
+class Obstacles(GameChild, dict):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.load_configuration()
+        self.init_dict()
+
+    def load_configuration(self):
+        config = self.get_configuration
+        self.missile_chance = config("missile", "chance")
+        self.missile_count = config("missile", "count")
+        self.blink_rate = config("obstacle", "blink-rate")
+        self.hurdle_count = config("hurdle", "count")
+        self.hurdle_chance = config("hurdle", "chance")
+        self.hurdle_first = config("hurdle", "first-range")
+        self.hurdle_margin = config("hurdle", "margin")
+        self.spikes_chance = config("spikes", "chance")
+        self.fireball_chance = config("fireball", "chance")
+        self.fireball_count = config("fireball", "count")
+
+    def init_dict(self):
+        missiles = [Missile(self) for _ in xrange(self.missile_count[1])]
+        hurdles = [Hurdle(self) for _ in xrange(self.hurdle_count[1])]
+        fireballs = [Fireball(self) for _ in xrange(self.fireball_count[1])]
+        dict.__init__(self, {"missile": missiles, "spikes": [Spikes(self)],
+                             "hurdle": hurdles, "fireball": fireballs})
+
+    def reset(self):
+        for obstacle in self.get_obstacles():
+            obstacle.reset()
+
+    def get_obstacles(self, exclude=[]):
+        if isinstance(exclude, str):
+            exclude = [exclude]
+        for kind in set(("hurdle", "fireball", "spikes",
+                         "missile")).difference(exclude):
+            for obstacle in self[kind]:
+                yield obstacle
+
+    def update(self):
+        if self.parent.is_going():
+            self.spawn_missiles()
+            self.spawn_hurdles()
+            self.spawn_spikes()
+            self.spawn_fireballs()
+        for obstacle in self.get_obstacles():
+            obstacle.update()
+
+    def spawn_missiles(self):
+        if all(not missile.is_flying() for missile in self["missile"]):
+            if random() < self.missile_chance:
+                for ii in xrange(randint(*self.missile_count)):
+                    self["missile"][ii].queue_fly()
+
+    def spawn_hurdles(self):
+        if all(not hurdle.is_playing(hurdle.enter) and \
+               not hurdle.is_playing(hurdle.exit) for \
+               hurdle in self["hurdle"]):
+            if random() < self.hurdle_chance:
+                dy = randint(*self.hurdle_first)
+                for ii in xrange(randint(*self.hurdle_count)):
+                    self["hurdle"][ii].queue_entrance(dy)
+                    dy += randint(*self.hurdle_margin)
+
+    def spawn_spikes(self):
+        if not self["spikes"][0].is_playing(self["spikes"][0].slide):
+            if random() < self.spikes_chance:
+                self["spikes"][0].queue_slide()
+
+    def spawn_fireballs(self):
+        if all(not fireball.is_playing(fireball.spew) for fireball in \
+               self["fireball"]):
+            if random() < self.fireball_chance:
+                for ii in xrange(randint(*self.fireball_count)):
+                    self["fireball"][ii].queue_spew()
diff --git a/food_spring/level/obstacle/Spikes.py b/food_spring/level/obstacle/Spikes.py
new file mode 100644 (file)
index 0000000..43c3bf4
--- /dev/null
@@ -0,0 +1,53 @@
+from pygame import Surface
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Spikes(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.set_frames()
+        self.register(self.slide)
+        self.reset()
+
+    def load_configuration(self):
+        config = self.get_configuration("spikes")
+        self.delay = config["delay"]
+        self.speed = config["speed"]
+
+    def set_frames(self):
+        surface = Surface((32, 8))
+        surface.fill((0, 255, 0))
+        self.add_frame(surface, omit=True)
+        self.add_frameset(0, name="sliding")
+        blank = Surface(self.location.size)
+        blank.set_colorkey((0, 0, 0))
+        self.add_frame(blank, omit=True)
+        self.add_frameset([0, 1], self.parent.blink_rate, "queued")
+
+    def reset(self):
+        self.set_frameset("queued")
+        self.halt(self.slide)
+        self.active = False
+        self.queue_reset = False
+        self.location.center = self.display_surface.get_rect().right, \
+                               self.parent.parent.platforms[0].location.top
+
+    def queue_slide(self):
+        self.active = True
+        self.play(self.slide, delay=self.delay)
+
+    def slide(self):
+        self.set_frameset("sliding")
+        self.move(-self.speed)
+        if self.location.right <= self.display_surface.get_rect().left:
+            self.queue_reset = True
+        if self.location.colliderect(self.parent.parent.food):
+            self.parent.parent.food.freeze()
+
+    def update(self):
+        if self.active:
+            Sprite.update(self)
+        if self.queue_reset:
+            self.reset()
diff --git a/food_spring/level/obstacle/__init__.py b/food_spring/level/obstacle/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/peach/Peach.py b/food_spring/level/peach/Peach.py
new file mode 100644 (file)
index 0000000..9646abf
--- /dev/null
@@ -0,0 +1,6 @@
+from food_spring.level.Level import Level
+
+class Peach(Level):
+
+    def __init__(self, parent):
+        Level.__init__(self, parent, parent.PEACH)
diff --git a/food_spring/level/peach/__init__.py b/food_spring/level/peach/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/pineapple/Pineapple.py b/food_spring/level/pineapple/Pineapple.py
new file mode 100644 (file)
index 0000000..4dc9525
--- /dev/null
@@ -0,0 +1,6 @@
+from food_spring.level.Level import Level
+
+class Pineapple(Level):
+
+    def __init__(self, parent):
+        Level.__init__(self, parent, parent.PINEAPPLE)
diff --git a/food_spring/level/pineapple/__init__.py b/food_spring/level/pineapple/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/planet/Planet.py b/food_spring/level/planet/Planet.py
new file mode 100644 (file)
index 0000000..58637e8
--- /dev/null
@@ -0,0 +1,58 @@
+from random import randrange, randint
+from os.path import join
+
+from pygame import PixelArray
+
+from lib.pgfw.pgfw.Sprite import Sprite
+from food_spring.level.planet.moon.Moons import Moons
+
+class Planet(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.load_image()
+        self.place()
+        self.register(self.scramble, interval=self.interval)
+        self.play(self.scramble)
+        self.moons = Moons(self)
+
+    def load_configuration(self):
+        config = self.get_configuration("planet")
+        self.root = config["path"]
+        self.interval = config["interval"]
+        self.shifts = config["shifts"]
+        self.offset = config["offset"]
+        self.extension = config["extension"]
+
+    def load_image(self):
+        path = self.get_resource(join(self.root, "%i.%s" % (self.parent.index,
+                                                            self.extension)))
+        self.load_from_path(path, True)
+
+    def place(self):
+        self.rect.center = self.display_surface.get_width() / 2, \
+                           self.parent.land.top - self.offset
+
+    def scramble(self):
+        surface = self.get_current_frame()
+        pixels = PixelArray(surface)
+        width, height = self.location.size
+        x = randrange(0, width)
+        y = randrange(0, height)
+        components = surface.unmap_rgb(pixels[x][y])
+        if components[3] == 255:
+            for _ in xrange(self.shifts):
+                dx, dy = randint(-1, 1), randint(-1, 1)
+                nx, ny = x + dx, y + dy
+                if nx < 0 or ny < 0 or nx >= width or ny >= height:
+                    break
+                if surface.unmap_rgb(pixels[nx][ny])[3] == 255:
+                    pixels[nx][ny] = components
+                    x = nx
+                    y = ny
+        del pixels
+
+    def update(self):
+        Sprite.update(self)
+        self.moons.update()
diff --git a/food_spring/level/planet/__init__.py b/food_spring/level/planet/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/planet/moon/Moon.py b/food_spring/level/planet/moon/Moon.py
new file mode 100644 (file)
index 0000000..896fe2a
--- /dev/null
@@ -0,0 +1,64 @@
+from random import randint, randrange
+from glob import glob
+from os.path import join
+
+from pygame import Color, PixelArray
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Moon(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent)
+        self.load_configuration()
+        self.set_frames()
+        self.tint()
+        self.place()
+        self.set_framerate(randint(*self.interval))
+        self.frame_index = randrange(0, len(self.frames))
+
+    def load_configuration(self):
+        config = self.get_configuration("moon")
+        self.tint_level = config["tint-level"]
+        self.interval = config["interval"]
+        self.margin = config["margin"]
+        self.path = self.get_resource(config["path"])
+
+    def set_frames(self):
+        for path in glob(join(self.path, "*.png")):
+            self.load_from_path(path, True, True)
+
+    def tint(self):
+        color = Color(0, 0, 0)
+        color.hsla = randint(0, 360), 100, 50
+        level = self.tint_level
+        transparent_color = self.get_current_frame().get_colorkey()
+        for frame in self.frames:
+            pixels = PixelArray(frame)
+            for x in xrange(len(pixels)):
+                for y in xrange(len(pixels[x])):
+                    if pixels[x][y] != transparent_color:
+                        r, g, b, a = frame.unmap_rgb(pixels[x][y])
+                        r = self.tint_component(r, color.r)
+                        g = self.tint_component(g, color.g)
+                        b = self.tint_component(b, color.b)
+                        pixels[x][y] = r, g, b, a
+
+    def tint_component(self, component, tint):
+        return self.tint_level * (tint - component) + component
+
+    def place(self):
+        margin = self.margin
+        box = self.parent.parent.location.inflate([margin] * 2)
+        moons = [moon.location.inflate([margin] * 2) for moon in self.parent]
+        self.set_center()
+        location = self.location
+        while location.colliderect(box) or location.collidelist(moons) != -1:
+            self.set_center()
+
+    def set_center(self):
+        display = self.display_surface.get_rect()
+        margin = self.margin
+        x = randrange(margin, display.w - margin)
+        y = randrange(margin, self.parent.parent.parent.land.top - margin)
+        self.location.center = x, y
diff --git a/food_spring/level/planet/moon/Moons.py b/food_spring/level/planet/moon/Moons.py
new file mode 100644 (file)
index 0000000..d2b124a
--- /dev/null
@@ -0,0 +1,15 @@
+from random import randint
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.planet.moon.Moon import Moon
+
+class Moons(GameChild, list):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        for _ in xrange(randint(*self.get_configuration("moon", "count"))):
+            self.append(Moon(self))
+
+    def update(self):
+        for moon in self:
+            moon.update()
diff --git a/food_spring/level/planet/moon/__init__.py b/food_spring/level/planet/moon/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/platform/Platform.py b/food_spring/level/platform/Platform.py
new file mode 100644 (file)
index 0000000..aed68d7
--- /dev/null
@@ -0,0 +1,38 @@
+from random import randint
+
+from pygame import Surface
+from pygame.draw import line
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Platform(Sprite):
+
+    def __init__(self, parent, width, x):
+        Sprite.__init__(self, parent)
+        self.width = width
+        self.load_configuration()
+        self.rect.topleft = x, self.display_surface.get_height() - self.height
+        self.add_frame()
+
+    def load_configuration(self):
+        config = self.get_configuration("platform")
+        self.height = config["height"]
+        self.thickness = config["thickness"]
+
+    def add_frame(self):
+        surface = Surface((self.width, self.thickness))
+        surface.fill(self.parent.parent.background_color)
+        self.draw_borders(surface)
+        Sprite.add_frame(self, surface)
+
+    def draw_borders(self, surface):
+        width, height = surface.get_size()
+        color = (255, 255, 255)
+        line(surface, color, (0, 0), (width - 1, 0))
+        line(surface, color, (0, 0), (0, height - 1))
+        line(surface, color, (width - 1, 0), (width - 1, height))
+        line(surface, color, (0, height - 1), (width - 1, height - 1))
+
+    def update(self):
+        self.move(-self.parent.parent.velocity[0])
+        Sprite.update(self)
diff --git a/food_spring/level/platform/Platforms.py b/food_spring/level/platform/Platforms.py
new file mode 100644 (file)
index 0000000..964a4c4
--- /dev/null
@@ -0,0 +1,56 @@
+from random import randint
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.platform.Platform import Platform
+
+class Platforms(GameChild, list):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.edge = self.display_surface.get_width()
+        self.load_configuration()
+        self.reset()
+
+    def load_configuration(self):
+        config = self.get_configuration("platform")
+        self.gap_range = config["gap"]
+        self.width_range = config["width"]
+        self.first_gap = config["first-gap"]
+        self.buffer = config["buffer"]
+
+    def reset(self):
+        list.__init__(self, [])
+        self.add_first()
+        self.populate()
+
+    def add_first(self):
+        gap = self.first_gap
+        self.append(Platform(self, self.edge, -gap))
+        self.add_platform(gap)
+
+    def populate(self):
+        while self.get_end() < self.edge:
+            self.add_platform()
+
+    def get_end(self):
+        if not self:
+            return 0
+        return self[-1].rect.right
+
+    def add_platform(self, gap=None):
+        if gap is None:
+            gap = randint(*self.gap_range)
+        x = self.get_end() + gap
+        self.append(Platform(self, randint(*self.width_range), x))
+
+    def update(self):
+        self.retire_platforms()
+        self.populate()
+        for platform in self:
+            platform.update()
+
+    def retire_platforms(self):
+        for platform in self:
+            if platform.rect.right < -self.buffer:
+                self.remove(platform)
diff --git a/food_spring/level/platform/__init__.py b/food_spring/level/platform/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/stars/Star.py b/food_spring/level/stars/Star.py
new file mode 100644 (file)
index 0000000..d7f80a0
--- /dev/null
@@ -0,0 +1,32 @@
+from random import randint, randrange
+
+from pygame import Surface, Color
+
+from lib.pgfw.pgfw.Sprite import Sprite
+
+class Star(Sprite):
+
+    def __init__(self, parent):
+        Sprite.__init__(self, parent, randint(100, 1000))
+        self.load_configuration()
+        self.add_frames()
+        self.place()
+
+    def load_configuration(self):
+        config = self.get_configuration("stars")
+        self.size = config["size"]
+        self.saturation = config["saturation"]
+
+    def add_frames(self):
+        size = randint(*self.size)
+        color = Color(0, 0, 0)
+        hue = randint(0, 360)
+        for _ in xrange(10):
+            color.hsla = hue, randint(*self.saturation), randint(0, 100), 100
+            surface = Surface((size, size))
+            surface.fill(color)
+            self.add_frame(surface)
+
+    def place(self):
+        width, height = self.display_surface.get_size()
+        self.location.center = randrange(0, width), randrange(0, height)
diff --git a/food_spring/level/stars/Stars.py b/food_spring/level/stars/Stars.py
new file mode 100644 (file)
index 0000000..500e22d
--- /dev/null
@@ -0,0 +1,23 @@
+from random import randint
+
+from lib.pgfw.pgfw.GameChild import GameChild
+from food_spring.level.stars.Star import Star
+
+class Stars(GameChild, list):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.load_configuration()
+        self.populate()
+
+    def load_configuration(self):
+        config = self.get_configuration("stars")
+        self.count = config["count"]
+
+    def populate(self):
+        for _ in xrange(randint(*self.count)):
+            self.append(Star(self))
+
+    def update(self):
+        for star in self:
+            star.update()
diff --git a/food_spring/level/stars/__init__.py b/food_spring/level/stars/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/level/watermelon/Watermelon.py b/food_spring/level/watermelon/Watermelon.py
new file mode 100644 (file)
index 0000000..e98a85e
--- /dev/null
@@ -0,0 +1,6 @@
+from food_spring.level.Level import Level
+
+class Watermelon(Level):
+
+    def __init__(self, parent):
+        Level.__init__(self, parent, parent.WATERMELON)
diff --git a/food_spring/level/watermelon/__init__.py b/food_spring/level/watermelon/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/food_spring/title/Title.py b/food_spring/title/Title.py
new file mode 100644 (file)
index 0000000..eb92dab
--- /dev/null
@@ -0,0 +1,55 @@
+from pygame import mixer
+from pygame.image import load
+
+from lib.pgfw.pgfw.GameChild import GameChild
+
+class Title(GameChild):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.delegate = self.get_delegate()
+        self.audio = self.get_audio()
+        self.load_configuration()
+        self.set_background()
+        self.subscribe(self.respond)
+        self.reset()
+
+    def load_configuration(self):
+        config = self.get_configuration("title")
+        self.background_path = self.get_resource("title", "background")
+        self.audio_path = self.get_resource("title", "audio")
+
+    def set_background(self):
+        self.background = load(self.background_path).convert()
+
+    def respond(self, event):
+        if self.active:
+            if self.delegate.compare(event, "any"):
+                self.deactivate()
+                self.parent.home.activate()
+        if self.activate_queued:
+            self.activate()
+            self.activate_queued = False
+
+    def reset(self):
+        self.activate_queued = False
+        self.deactivate()
+
+    def deactivate(self):
+        self.active = False
+        # self.audio.stop_current_channel()
+        mixer.music.stop()
+
+    def activate(self):
+        self.active = True
+        # self.audio.play_bgm(self.audio_path)
+        mixer.music.load(self.audio_path)
+        mixer.music.play(-1)
+
+    def queue_activation(self):
+        self.activate_queued = True
+
+    def update(self):
+        if self.active:
+            self.display_surface.blit(self.background, (0, 0))
diff --git a/food_spring/title/__init__.py b/food_spring/title/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/__init__.py b/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/pgfw b/lib/pgfw
new file mode 160000 (submodule)
index 0000000..7a4f318
--- /dev/null
+++ b/lib/pgfw
@@ -0,0 +1 @@
+Subproject commit 7a4f318ac2fca2f9c5d533a50b85e094de29b3ad
diff --git a/resource/Numans.ttf b/resource/Numans.ttf
new file mode 100644 (file)
index 0000000..4fee5ee
Binary files /dev/null and b/resource/Numans.ttf differ
diff --git a/resource/aud/AHURA.ogg b/resource/aud/AHURA.ogg
new file mode 100644 (file)
index 0000000..1242141
Binary files /dev/null and b/resource/aud/AHURA.ogg differ
diff --git a/resource/aud/FLUFF/0.ogg b/resource/aud/FLUFF/0.ogg
new file mode 100644 (file)
index 0000000..913c7cc
Binary files /dev/null and b/resource/aud/FLUFF/0.ogg differ
diff --git a/resource/aud/FLUFF/1.ogg b/resource/aud/FLUFF/1.ogg
new file mode 100644 (file)
index 0000000..a26d0ff
Binary files /dev/null and b/resource/aud/FLUFF/1.ogg differ
diff --git a/resource/aud/FLUFF/2.ogg b/resource/aud/FLUFF/2.ogg
new file mode 100644 (file)
index 0000000..0ec1da4
Binary files /dev/null and b/resource/aud/FLUFF/2.ogg differ
diff --git a/resource/aud/FLUFF/3.ogg b/resource/aud/FLUFF/3.ogg
new file mode 100644 (file)
index 0000000..7cbd6fa
Binary files /dev/null and b/resource/aud/FLUFF/3.ogg differ
diff --git a/resource/aud/PAN-FLOUR.ogg b/resource/aud/PAN-FLOUR.ogg
new file mode 100644 (file)
index 0000000..de20ee3
Binary files /dev/null and b/resource/aud/PAN-FLOUR.ogg differ
diff --git a/resource/aud/SLIME-JIM.ogg b/resource/aud/SLIME-JIM.ogg
new file mode 100644 (file)
index 0000000..2f9b8a8
Binary files /dev/null and b/resource/aud/SLIME-JIM.ogg differ
diff --git a/resource/img/ALTERNATION/0/0.png b/resource/img/ALTERNATION/0/0.png
new file mode 100644 (file)
index 0000000..b6694e5
Binary files /dev/null and b/resource/img/ALTERNATION/0/0.png differ
diff --git a/resource/img/ALTERNATION/0/1.png b/resource/img/ALTERNATION/0/1.png
new file mode 100644 (file)
index 0000000..be06c0a
Binary files /dev/null and b/resource/img/ALTERNATION/0/1.png differ
diff --git a/resource/img/ALTERNATION/1/0.png b/resource/img/ALTERNATION/1/0.png
new file mode 100644 (file)
index 0000000..e8b1cd1
Binary files /dev/null and b/resource/img/ALTERNATION/1/0.png differ
diff --git a/resource/img/ALTERNATION/1/1.png b/resource/img/ALTERNATION/1/1.png
new file mode 100644 (file)
index 0000000..96bc442
Binary files /dev/null and b/resource/img/ALTERNATION/1/1.png differ
diff --git a/resource/img/ALTERNATION/2/0.png b/resource/img/ALTERNATION/2/0.png
new file mode 100644 (file)
index 0000000..89e866b
Binary files /dev/null and b/resource/img/ALTERNATION/2/0.png differ
diff --git a/resource/img/ALTERNATION/2/1.png b/resource/img/ALTERNATION/2/1.png
new file mode 100644 (file)
index 0000000..6b3fa0f
Binary files /dev/null and b/resource/img/ALTERNATION/2/1.png differ
diff --git a/resource/img/ALTERNATION/3/0.png b/resource/img/ALTERNATION/3/0.png
new file mode 100644 (file)
index 0000000..c000a20
Binary files /dev/null and b/resource/img/ALTERNATION/3/0.png differ
diff --git a/resource/img/ALTERNATION/3/1.png b/resource/img/ALTERNATION/3/1.png
new file mode 100644 (file)
index 0000000..a1e6950
Binary files /dev/null and b/resource/img/ALTERNATION/3/1.png differ
diff --git a/resource/img/ALTERNATION/mouth/bg.png b/resource/img/ALTERNATION/mouth/bg.png
new file mode 100644 (file)
index 0000000..99f4981
Binary files /dev/null and b/resource/img/ALTERNATION/mouth/bg.png differ
diff --git a/resource/img/ALTERNATION/mouth/lower-jaw.png b/resource/img/ALTERNATION/mouth/lower-jaw.png
new file mode 100644 (file)
index 0000000..cc2bfc8
Binary files /dev/null and b/resource/img/ALTERNATION/mouth/lower-jaw.png differ
diff --git a/resource/img/ALTERNATION/mouth/upper-jaw.png b/resource/img/ALTERNATION/mouth/upper-jaw.png
new file mode 100644 (file)
index 0000000..0ec387b
Binary files /dev/null and b/resource/img/ALTERNATION/mouth/upper-jaw.png differ
diff --git a/resource/img/BINOCULARS/environment.png b/resource/img/BINOCULARS/environment.png
new file mode 100644 (file)
index 0000000..301f57c
Binary files /dev/null and b/resource/img/BINOCULARS/environment.png differ
diff --git a/resource/img/BINOCULARS/view/00.png b/resource/img/BINOCULARS/view/00.png
new file mode 100644 (file)
index 0000000..44d6113
Binary files /dev/null and b/resource/img/BINOCULARS/view/00.png differ
diff --git a/resource/img/BINOCULARS/view/01.png b/resource/img/BINOCULARS/view/01.png
new file mode 100644 (file)
index 0000000..e2e7412
Binary files /dev/null and b/resource/img/BINOCULARS/view/01.png differ
diff --git a/resource/img/BINOCULARS/view/02.png b/resource/img/BINOCULARS/view/02.png
new file mode 100644 (file)
index 0000000..6fbd1ab
Binary files /dev/null and b/resource/img/BINOCULARS/view/02.png differ
diff --git a/resource/img/BINOCULARS/view/03.png b/resource/img/BINOCULARS/view/03.png
new file mode 100644 (file)
index 0000000..2b5e3c0
Binary files /dev/null and b/resource/img/BINOCULARS/view/03.png differ
diff --git a/resource/img/BINOCULARS/view/04.png b/resource/img/BINOCULARS/view/04.png
new file mode 100644 (file)
index 0000000..9febb23
Binary files /dev/null and b/resource/img/BINOCULARS/view/04.png differ
diff --git a/resource/img/BINOCULARS/view/05.png b/resource/img/BINOCULARS/view/05.png
new file mode 100644 (file)
index 0000000..336ca08
Binary files /dev/null and b/resource/img/BINOCULARS/view/05.png differ
diff --git a/resource/img/BINOCULARS/view/06.png b/resource/img/BINOCULARS/view/06.png
new file mode 100644 (file)
index 0000000..08865b2
Binary files /dev/null and b/resource/img/BINOCULARS/view/06.png differ
diff --git a/resource/img/BINOCULARS/view/07.png b/resource/img/BINOCULARS/view/07.png
new file mode 100644 (file)
index 0000000..bf4981b
Binary files /dev/null and b/resource/img/BINOCULARS/view/07.png differ
diff --git a/resource/img/BINOCULARS/view/08.png b/resource/img/BINOCULARS/view/08.png
new file mode 100644 (file)
index 0000000..3218e8b
Binary files /dev/null and b/resource/img/BINOCULARS/view/08.png differ
diff --git a/resource/img/BINOCULARS/view/09.png b/resource/img/BINOCULARS/view/09.png
new file mode 100644 (file)
index 0000000..57b6a58
Binary files /dev/null and b/resource/img/BINOCULARS/view/09.png differ
diff --git a/resource/img/BINOCULARS/view/10.png b/resource/img/BINOCULARS/view/10.png
new file mode 100644 (file)
index 0000000..48136c3
Binary files /dev/null and b/resource/img/BINOCULARS/view/10.png differ
diff --git a/resource/img/BINOCULARS/view/11.png b/resource/img/BINOCULARS/view/11.png
new file mode 100644 (file)
index 0000000..7144713
Binary files /dev/null and b/resource/img/BINOCULARS/view/11.png differ
diff --git a/resource/img/BINOCULARS/view/12.png b/resource/img/BINOCULARS/view/12.png
new file mode 100644 (file)
index 0000000..04a2841
Binary files /dev/null and b/resource/img/BINOCULARS/view/12.png differ
diff --git a/resource/img/BINOCULARS/view/13.png b/resource/img/BINOCULARS/view/13.png
new file mode 100644 (file)
index 0000000..a8e0c54
Binary files /dev/null and b/resource/img/BINOCULARS/view/13.png differ
diff --git a/resource/img/BINOCULARS/view/14.png b/resource/img/BINOCULARS/view/14.png
new file mode 100644 (file)
index 0000000..b32f60c
Binary files /dev/null and b/resource/img/BINOCULARS/view/14.png differ
diff --git a/resource/img/BINOCULARS/view/15.png b/resource/img/BINOCULARS/view/15.png
new file mode 100644 (file)
index 0000000..0cb4a1a
Binary files /dev/null and b/resource/img/BINOCULARS/view/15.png differ
diff --git a/resource/img/BINOCULARS/view/16.png b/resource/img/BINOCULARS/view/16.png
new file mode 100644 (file)
index 0000000..1e96af1
Binary files /dev/null and b/resource/img/BINOCULARS/view/16.png differ
diff --git a/resource/img/BINOCULARS/view/17.png b/resource/img/BINOCULARS/view/17.png
new file mode 100644 (file)
index 0000000..07c0fe9
Binary files /dev/null and b/resource/img/BINOCULARS/view/17.png differ
diff --git a/resource/img/BINOCULARS/view/18.png b/resource/img/BINOCULARS/view/18.png
new file mode 100644 (file)
index 0000000..5fa9dae
Binary files /dev/null and b/resource/img/BINOCULARS/view/18.png differ
diff --git a/resource/img/BINOCULARS/view/19.png b/resource/img/BINOCULARS/view/19.png
new file mode 100644 (file)
index 0000000..6ed2609
Binary files /dev/null and b/resource/img/BINOCULARS/view/19.png differ
diff --git a/resource/img/BINOCULARS/view/20.png b/resource/img/BINOCULARS/view/20.png
new file mode 100644 (file)
index 0000000..264c76c
Binary files /dev/null and b/resource/img/BINOCULARS/view/20.png differ
diff --git a/resource/img/BINOCULARS/view/21.png b/resource/img/BINOCULARS/view/21.png
new file mode 100644 (file)
index 0000000..394bb2f
Binary files /dev/null and b/resource/img/BINOCULARS/view/21.png differ
diff --git a/resource/img/BINOCULARS/view/22.png b/resource/img/BINOCULARS/view/22.png
new file mode 100644 (file)
index 0000000..e099c5c
Binary files /dev/null and b/resource/img/BINOCULARS/view/22.png differ
diff --git a/resource/img/BINOCULARS/view/23.png b/resource/img/BINOCULARS/view/23.png
new file mode 100644 (file)
index 0000000..98237e4
Binary files /dev/null and b/resource/img/BINOCULARS/view/23.png differ
diff --git a/resource/img/BINOCULARS/view/24.png b/resource/img/BINOCULARS/view/24.png
new file mode 100644 (file)
index 0000000..e36f6f4
Binary files /dev/null and b/resource/img/BINOCULARS/view/24.png differ
diff --git a/resource/img/BINOCULARS/view/25.png b/resource/img/BINOCULARS/view/25.png
new file mode 100644 (file)
index 0000000..f0fe4bd
Binary files /dev/null and b/resource/img/BINOCULARS/view/25.png differ
diff --git a/resource/img/BINOCULARS/view/26.png b/resource/img/BINOCULARS/view/26.png
new file mode 100644 (file)
index 0000000..b37bbb5
Binary files /dev/null and b/resource/img/BINOCULARS/view/26.png differ
diff --git a/resource/img/BINOCULARS/view/27.png b/resource/img/BINOCULARS/view/27.png
new file mode 100644 (file)
index 0000000..2f73afd
Binary files /dev/null and b/resource/img/BINOCULARS/view/27.png differ
diff --git a/resource/img/BINOCULARS/view/28.png b/resource/img/BINOCULARS/view/28.png
new file mode 100644 (file)
index 0000000..b118bd4
Binary files /dev/null and b/resource/img/BINOCULARS/view/28.png differ
diff --git a/resource/img/BINOCULARS/view/29.png b/resource/img/BINOCULARS/view/29.png
new file mode 100644 (file)
index 0000000..34a02cc
Binary files /dev/null and b/resource/img/BINOCULARS/view/29.png differ
diff --git a/resource/img/BINOCULARS/view/base.png b/resource/img/BINOCULARS/view/base.png
new file mode 100644 (file)
index 0000000..3d9d0ba
Binary files /dev/null and b/resource/img/BINOCULARS/view/base.png differ
diff --git a/resource/img/BINOCULARS/view/generate b/resource/img/BINOCULARS/view/generate
new file mode 100755 (executable)
index 0000000..d3e34d9
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use feature "say";
+
+use Image::Magick;
+
+my $base_path = "base.png";
+my $count = 30;
+
+generate();
+
+sub generate
+{
+    my $base = Image::Magick->new();
+    $base->Read($base_path);
+    my ($frame, $modulation);
+    for (0..$count - 1)
+    {
+        $frame = $base->Clone();
+        $modulation = 200 / $count * $_ + 100;
+        $frame->Modulate(hue=>$modulation);
+        $frame->Write(sprintf "%02d.png", $_);
+    }
+}
diff --git a/resource/img/CORDRAG/Landmouth.png b/resource/img/CORDRAG/Landmouth.png
new file mode 100644 (file)
index 0000000..2b05442
Binary files /dev/null and b/resource/img/CORDRAG/Landmouth.png differ
diff --git a/resource/img/CORDRAG/gaia/0-line.png b/resource/img/CORDRAG/gaia/0-line.png
new file mode 100644 (file)
index 0000000..74c3801
Binary files /dev/null and b/resource/img/CORDRAG/gaia/0-line.png differ
diff --git a/resource/img/CORDRAG/gaia/1-spread.png b/resource/img/CORDRAG/gaia/1-spread.png
new file mode 100644 (file)
index 0000000..caae84e
Binary files /dev/null and b/resource/img/CORDRAG/gaia/1-spread.png differ
diff --git a/resource/img/CORDRAG/spanky/01_.png b/resource/img/CORDRAG/spanky/01_.png
new file mode 100644 (file)
index 0000000..0339a78
Binary files /dev/null and b/resource/img/CORDRAG/spanky/01_.png differ
diff --git a/resource/img/CORDRAG/spanky/02_.png b/resource/img/CORDRAG/spanky/02_.png
new file mode 100644 (file)
index 0000000..53a5525
Binary files /dev/null and b/resource/img/CORDRAG/spanky/02_.png differ
diff --git a/resource/img/CORDRAG/spanky/03_.png b/resource/img/CORDRAG/spanky/03_.png
new file mode 100644 (file)
index 0000000..fc8ca37
Binary files /dev/null and b/resource/img/CORDRAG/spanky/03_.png differ
diff --git a/resource/img/CORDRAG/spanky/04_.png b/resource/img/CORDRAG/spanky/04_.png
new file mode 100644 (file)
index 0000000..87ff47e
Binary files /dev/null and b/resource/img/CORDRAG/spanky/04_.png differ
diff --git a/resource/img/CORDRAG/spanky/05_.png b/resource/img/CORDRAG/spanky/05_.png
new file mode 100644 (file)
index 0000000..0737920
Binary files /dev/null and b/resource/img/CORDRAG/spanky/05_.png differ
diff --git a/resource/img/CORDRAG/spanky/06_.png b/resource/img/CORDRAG/spanky/06_.png
new file mode 100644 (file)
index 0000000..e48f91d
Binary files /dev/null and b/resource/img/CORDRAG/spanky/06_.png differ
diff --git a/resource/img/CORDRAG/spanky/07_.png b/resource/img/CORDRAG/spanky/07_.png
new file mode 100644 (file)
index 0000000..29717b5
Binary files /dev/null and b/resource/img/CORDRAG/spanky/07_.png differ
diff --git a/resource/img/CORDRAG/spanky/08_.png b/resource/img/CORDRAG/spanky/08_.png
new file mode 100644 (file)
index 0000000..3306918
Binary files /dev/null and b/resource/img/CORDRAG/spanky/08_.png differ
diff --git a/resource/img/CORDRAG/spanky/09_.png b/resource/img/CORDRAG/spanky/09_.png
new file mode 100644 (file)
index 0000000..f0990bf
Binary files /dev/null and b/resource/img/CORDRAG/spanky/09_.png differ
diff --git a/resource/img/CORDRAG/spanky/10_.png b/resource/img/CORDRAG/spanky/10_.png
new file mode 100644 (file)
index 0000000..32a7479
Binary files /dev/null and b/resource/img/CORDRAG/spanky/10_.png differ
diff --git a/resource/img/CORDRAG/spanky/11_.png b/resource/img/CORDRAG/spanky/11_.png
new file mode 100644 (file)
index 0000000..9fb5f28
Binary files /dev/null and b/resource/img/CORDRAG/spanky/11_.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/0/background.png b/resource/img/HUMAN-ORGANS/door/0/background.png
new file mode 100644 (file)
index 0000000..c9d5b98
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/0/background.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/0/foreground.png b/resource/img/HUMAN-ORGANS/door/0/foreground.png
new file mode 100644 (file)
index 0000000..1d83bbd
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/0/foreground.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/1/background.png b/resource/img/HUMAN-ORGANS/door/1/background.png
new file mode 100644 (file)
index 0000000..b94fd4e
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/1/background.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/1/foreground.png b/resource/img/HUMAN-ORGANS/door/1/foreground.png
new file mode 100644 (file)
index 0000000..f030cd0
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/1/foreground.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/2/background.png b/resource/img/HUMAN-ORGANS/door/2/background.png
new file mode 100644 (file)
index 0000000..14c58ae
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/2/background.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/2/foreground.png b/resource/img/HUMAN-ORGANS/door/2/foreground.png
new file mode 100644 (file)
index 0000000..3879b08
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/2/foreground.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/3/background.png b/resource/img/HUMAN-ORGANS/door/3/background.png
new file mode 100644 (file)
index 0000000..55031d4
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/3/background.png differ
diff --git a/resource/img/HUMAN-ORGANS/door/3/foreground.png b/resource/img/HUMAN-ORGANS/door/3/foreground.png
new file mode 100644 (file)
index 0000000..bf9327c
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/door/3/foreground.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/1.png b/resource/img/HUMAN-ORGANS/moon/1.png
new file mode 100644 (file)
index 0000000..f6c307a
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/1.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/2.png b/resource/img/HUMAN-ORGANS/moon/2.png
new file mode 100644 (file)
index 0000000..e17e865
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/2.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/3.png b/resource/img/HUMAN-ORGANS/moon/3.png
new file mode 100644 (file)
index 0000000..7f82ebf
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/3.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/4.png b/resource/img/HUMAN-ORGANS/moon/4.png
new file mode 100644 (file)
index 0000000..bed6f40
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/4.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/5.png b/resource/img/HUMAN-ORGANS/moon/5.png
new file mode 100644 (file)
index 0000000..d510ef0
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/5.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/6.png b/resource/img/HUMAN-ORGANS/moon/6.png
new file mode 100644 (file)
index 0000000..0a40002
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/6.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/7.png b/resource/img/HUMAN-ORGANS/moon/7.png
new file mode 100644 (file)
index 0000000..3d1a01c
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/7.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/8.png b/resource/img/HUMAN-ORGANS/moon/8.png
new file mode 100644 (file)
index 0000000..c0d8a52
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/8.png differ
diff --git a/resource/img/HUMAN-ORGANS/moon/animate b/resource/img/HUMAN-ORGANS/moon/animate
new file mode 100755 (executable)
index 0000000..27e79ce
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+convert *.png -delay 421 -fill "hsb(130,255,255)" -tint 80 out.gif
diff --git a/resource/img/HUMAN-ORGANS/moon/out.gif b/resource/img/HUMAN-ORGANS/moon/out.gif
new file mode 100644 (file)
index 0000000..c5bd02a
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/moon/out.gif differ
diff --git a/resource/img/HUMAN-ORGANS/venus/0.png b/resource/img/HUMAN-ORGANS/venus/0.png
new file mode 100644 (file)
index 0000000..91a4a7f
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/venus/0.png differ
diff --git a/resource/img/HUMAN-ORGANS/venus/1.png b/resource/img/HUMAN-ORGANS/venus/1.png
new file mode 100644 (file)
index 0000000..062ffee
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/venus/1.png differ
diff --git a/resource/img/HUMAN-ORGANS/venus/2.png b/resource/img/HUMAN-ORGANS/venus/2.png
new file mode 100644 (file)
index 0000000..71ebeaa
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/venus/2.png differ
diff --git a/resource/img/HUMAN-ORGANS/venus/3.png b/resource/img/HUMAN-ORGANS/venus/3.png
new file mode 100644 (file)
index 0000000..2cf0cef
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/venus/3.png differ
diff --git a/resource/img/HUMAN-ORGANS/window.png b/resource/img/HUMAN-ORGANS/window.png
new file mode 100644 (file)
index 0000000..e363c37
Binary files /dev/null and b/resource/img/HUMAN-ORGANS/window.png differ
diff --git a/resource/img/SHATTER/0/0/00.png b/resource/img/SHATTER/0/0/00.png
new file mode 100644 (file)
index 0000000..2bbf4c0
Binary files /dev/null and b/resource/img/SHATTER/0/0/00.png differ
diff --git a/resource/img/SHATTER/0/0/01.png b/resource/img/SHATTER/0/0/01.png
new file mode 100644 (file)
index 0000000..ae58d57
Binary files /dev/null and b/resource/img/SHATTER/0/0/01.png differ
diff --git a/resource/img/SHATTER/0/0/02.png b/resource/img/SHATTER/0/0/02.png
new file mode 100644 (file)
index 0000000..787869e
Binary files /dev/null and b/resource/img/SHATTER/0/0/02.png differ
diff --git a/resource/img/SHATTER/0/0/03.png b/resource/img/SHATTER/0/0/03.png
new file mode 100644 (file)
index 0000000..aa04b0f
Binary files /dev/null and b/resource/img/SHATTER/0/0/03.png differ
diff --git a/resource/img/SHATTER/0/0/04.png b/resource/img/SHATTER/0/0/04.png
new file mode 100644 (file)
index 0000000..9b690ec
Binary files /dev/null and b/resource/img/SHATTER/0/0/04.png differ
diff --git a/resource/img/SHATTER/0/0/05.png b/resource/img/SHATTER/0/0/05.png
new file mode 100644 (file)
index 0000000..4042e77
Binary files /dev/null and b/resource/img/SHATTER/0/0/05.png differ
diff --git a/resource/img/SHATTER/0/0/06.png b/resource/img/SHATTER/0/0/06.png
new file mode 100644 (file)
index 0000000..dec629d
Binary files /dev/null and b/resource/img/SHATTER/0/0/06.png differ
diff --git a/resource/img/SHATTER/0/0/07.png b/resource/img/SHATTER/0/0/07.png
new file mode 100644 (file)
index 0000000..5c87042
Binary files /dev/null and b/resource/img/SHATTER/0/0/07.png differ
diff --git a/resource/img/SHATTER/0/1/00.png b/resource/img/SHATTER/0/1/00.png
new file mode 100644 (file)
index 0000000..b819f53
Binary files /dev/null and b/resource/img/SHATTER/0/1/00.png differ
diff --git a/resource/img/SHATTER/0/1/01.png b/resource/img/SHATTER/0/1/01.png
new file mode 100644 (file)
index 0000000..b74ff9d
Binary files /dev/null and b/resource/img/SHATTER/0/1/01.png differ
diff --git a/resource/img/SHATTER/0/1/02.png b/resource/img/SHATTER/0/1/02.png
new file mode 100644 (file)
index 0000000..331d703
Binary files /dev/null and b/resource/img/SHATTER/0/1/02.png differ
diff --git a/resource/img/SHATTER/0/1/03.png b/resource/img/SHATTER/0/1/03.png
new file mode 100644 (file)
index 0000000..19fb21a
Binary files /dev/null and b/resource/img/SHATTER/0/1/03.png differ
diff --git a/resource/img/SHATTER/0/1/04.png b/resource/img/SHATTER/0/1/04.png
new file mode 100644 (file)
index 0000000..703fcf9
Binary files /dev/null and b/resource/img/SHATTER/0/1/04.png differ
diff --git a/resource/img/SHATTER/0/1/05.png b/resource/img/SHATTER/0/1/05.png
new file mode 100644 (file)
index 0000000..490833b
Binary files /dev/null and b/resource/img/SHATTER/0/1/05.png differ
diff --git a/resource/img/SHATTER/0/1/06.png b/resource/img/SHATTER/0/1/06.png
new file mode 100644 (file)
index 0000000..ec09422
Binary files /dev/null and b/resource/img/SHATTER/0/1/06.png differ
diff --git a/resource/img/SHATTER/0/1/07.png b/resource/img/SHATTER/0/1/07.png
new file mode 100644 (file)
index 0000000..909fdbf
Binary files /dev/null and b/resource/img/SHATTER/0/1/07.png differ
diff --git a/resource/img/SHATTER/0/2/00.png b/resource/img/SHATTER/0/2/00.png
new file mode 100644 (file)
index 0000000..1b1719c
Binary files /dev/null and b/resource/img/SHATTER/0/2/00.png differ
diff --git a/resource/img/SHATTER/0/2/01.png b/resource/img/SHATTER/0/2/01.png
new file mode 100644 (file)
index 0000000..327bef3
Binary files /dev/null and b/resource/img/SHATTER/0/2/01.png differ
diff --git a/resource/img/SHATTER/0/2/02.png b/resource/img/SHATTER/0/2/02.png
new file mode 100644 (file)
index 0000000..07f569a
Binary files /dev/null and b/resource/img/SHATTER/0/2/02.png differ
diff --git a/resource/img/SHATTER/0/2/03.png b/resource/img/SHATTER/0/2/03.png
new file mode 100644 (file)
index 0000000..1bb2a2d
Binary files /dev/null and b/resource/img/SHATTER/0/2/03.png differ
diff --git a/resource/img/SHATTER/0/2/04.png b/resource/img/SHATTER/0/2/04.png
new file mode 100644 (file)
index 0000000..e398451
Binary files /dev/null and b/resource/img/SHATTER/0/2/04.png differ
diff --git a/resource/img/SHATTER/0/2/05.png b/resource/img/SHATTER/0/2/05.png
new file mode 100644 (file)
index 0000000..030ca61
Binary files /dev/null and b/resource/img/SHATTER/0/2/05.png differ
diff --git a/resource/img/SHATTER/0/2/06.png b/resource/img/SHATTER/0/2/06.png
new file mode 100644 (file)
index 0000000..cf3a97a
Binary files /dev/null and b/resource/img/SHATTER/0/2/06.png differ
diff --git a/resource/img/SHATTER/0/2/07.png b/resource/img/SHATTER/0/2/07.png
new file mode 100644 (file)
index 0000000..da9d3cb
Binary files /dev/null and b/resource/img/SHATTER/0/2/07.png differ
diff --git a/resource/img/SHATTER/0/3/00.png b/resource/img/SHATTER/0/3/00.png
new file mode 100644 (file)
index 0000000..1b27ff7
Binary files /dev/null and b/resource/img/SHATTER/0/3/00.png differ
diff --git a/resource/img/SHATTER/0/3/01.png b/resource/img/SHATTER/0/3/01.png
new file mode 100644 (file)
index 0000000..2d7c174
Binary files /dev/null and b/resource/img/SHATTER/0/3/01.png differ
diff --git a/resource/img/SHATTER/0/3/02.png b/resource/img/SHATTER/0/3/02.png
new file mode 100644 (file)
index 0000000..50d76e6
Binary files /dev/null and b/resource/img/SHATTER/0/3/02.png differ
diff --git a/resource/img/SHATTER/0/3/03.png b/resource/img/SHATTER/0/3/03.png
new file mode 100644 (file)
index 0000000..d716063
Binary files /dev/null and b/resource/img/SHATTER/0/3/03.png differ
diff --git a/resource/img/SHATTER/0/3/04.png b/resource/img/SHATTER/0/3/04.png
new file mode 100644 (file)
index 0000000..ad7659a
Binary files /dev/null and b/resource/img/SHATTER/0/3/04.png differ
diff --git a/resource/img/SHATTER/0/3/05.png b/resource/img/SHATTER/0/3/05.png
new file mode 100644 (file)
index 0000000..0ad8082
Binary files /dev/null and b/resource/img/SHATTER/0/3/05.png differ
diff --git a/resource/img/SHATTER/0/3/06.png b/resource/img/SHATTER/0/3/06.png
new file mode 100644 (file)
index 0000000..a53b607
Binary files /dev/null and b/resource/img/SHATTER/0/3/06.png differ
diff --git a/resource/img/SHATTER/0/3/07.png b/resource/img/SHATTER/0/3/07.png
new file mode 100644 (file)
index 0000000..0f8edd1
Binary files /dev/null and b/resource/img/SHATTER/0/3/07.png differ
diff --git a/resource/img/SHATTER/0/4/00.png b/resource/img/SHATTER/0/4/00.png
new file mode 100644 (file)
index 0000000..db62cf9
Binary files /dev/null and b/resource/img/SHATTER/0/4/00.png differ
diff --git a/resource/img/SHATTER/0/4/01.png b/resource/img/SHATTER/0/4/01.png
new file mode 100644 (file)
index 0000000..1a20ad6
Binary files /dev/null and b/resource/img/SHATTER/0/4/01.png differ
diff --git a/resource/img/SHATTER/0/4/02.png b/resource/img/SHATTER/0/4/02.png
new file mode 100644 (file)
index 0000000..3f2c9e5
Binary files /dev/null and b/resource/img/SHATTER/0/4/02.png differ
diff --git a/resource/img/SHATTER/0/4/03.png b/resource/img/SHATTER/0/4/03.png
new file mode 100644 (file)
index 0000000..75a346c
Binary files /dev/null and b/resource/img/SHATTER/0/4/03.png differ
diff --git a/resource/img/SHATTER/0/4/04.png b/resource/img/SHATTER/0/4/04.png
new file mode 100644 (file)
index 0000000..66be5ea
Binary files /dev/null and b/resource/img/SHATTER/0/4/04.png differ
diff --git a/resource/img/SHATTER/0/4/05.png b/resource/img/SHATTER/0/4/05.png
new file mode 100644 (file)
index 0000000..2d66105
Binary files /dev/null and b/resource/img/SHATTER/0/4/05.png differ
diff --git a/resource/img/SHATTER/0/4/06.png b/resource/img/SHATTER/0/4/06.png
new file mode 100644 (file)
index 0000000..3f02141
Binary files /dev/null and b/resource/img/SHATTER/0/4/06.png differ
diff --git a/resource/img/SHATTER/0/4/07.png b/resource/img/SHATTER/0/4/07.png
new file mode 100644 (file)
index 0000000..cdf512f
Binary files /dev/null and b/resource/img/SHATTER/0/4/07.png differ
diff --git a/resource/img/SHATTER/1/0/00.png b/resource/img/SHATTER/1/0/00.png
new file mode 100644 (file)
index 0000000..44572ee
Binary files /dev/null and b/resource/img/SHATTER/1/0/00.png differ
diff --git a/resource/img/SHATTER/1/0/01.png b/resource/img/SHATTER/1/0/01.png
new file mode 100644 (file)
index 0000000..d7d2e5f
Binary files /dev/null and b/resource/img/SHATTER/1/0/01.png differ
diff --git a/resource/img/SHATTER/1/0/02.png b/resource/img/SHATTER/1/0/02.png
new file mode 100644 (file)
index 0000000..526e57e
Binary files /dev/null and b/resource/img/SHATTER/1/0/02.png differ
diff --git a/resource/img/SHATTER/1/0/03.png b/resource/img/SHATTER/1/0/03.png
new file mode 100644 (file)
index 0000000..274fc0f
Binary files /dev/null and b/resource/img/SHATTER/1/0/03.png differ
diff --git a/resource/img/SHATTER/1/0/04.png b/resource/img/SHATTER/1/0/04.png
new file mode 100644 (file)
index 0000000..773b611
Binary files /dev/null and b/resource/img/SHATTER/1/0/04.png differ
diff --git a/resource/img/SHATTER/1/0/05.png b/resource/img/SHATTER/1/0/05.png
new file mode 100644 (file)
index 0000000..bed53d6
Binary files /dev/null and b/resource/img/SHATTER/1/0/05.png differ
diff --git a/resource/img/SHATTER/1/0/06.png b/resource/img/SHATTER/1/0/06.png
new file mode 100644 (file)
index 0000000..3f0fb51
Binary files /dev/null and b/resource/img/SHATTER/1/0/06.png differ
diff --git a/resource/img/SHATTER/1/0/07.png b/resource/img/SHATTER/1/0/07.png
new file mode 100644 (file)
index 0000000..5b95f31
Binary files /dev/null and b/resource/img/SHATTER/1/0/07.png differ
diff --git a/resource/img/SHATTER/1/1/00.png b/resource/img/SHATTER/1/1/00.png
new file mode 100644 (file)
index 0000000..ad494c0
Binary files /dev/null and b/resource/img/SHATTER/1/1/00.png differ
diff --git a/resource/img/SHATTER/1/1/01.png b/resource/img/SHATTER/1/1/01.png
new file mode 100644 (file)
index 0000000..c973d8a
Binary files /dev/null and b/resource/img/SHATTER/1/1/01.png differ
diff --git a/resource/img/SHATTER/1/1/02.png b/resource/img/SHATTER/1/1/02.png
new file mode 100644 (file)
index 0000000..22e977b
Binary files /dev/null and b/resource/img/SHATTER/1/1/02.png differ
diff --git a/resource/img/SHATTER/1/1/03.png b/resource/img/SHATTER/1/1/03.png
new file mode 100644 (file)
index 0000000..8ac0160
Binary files /dev/null and b/resource/img/SHATTER/1/1/03.png differ
diff --git a/resource/img/SHATTER/1/1/04.png b/resource/img/SHATTER/1/1/04.png
new file mode 100644 (file)
index 0000000..bd1047e
Binary files /dev/null and b/resource/img/SHATTER/1/1/04.png differ
diff --git a/resource/img/SHATTER/1/1/05.png b/resource/img/SHATTER/1/1/05.png
new file mode 100644 (file)
index 0000000..36eec09
Binary files /dev/null and b/resource/img/SHATTER/1/1/05.png differ
diff --git a/resource/img/SHATTER/1/1/06.png b/resource/img/SHATTER/1/1/06.png
new file mode 100644 (file)
index 0000000..248a613
Binary files /dev/null and b/resource/img/SHATTER/1/1/06.png differ
diff --git a/resource/img/SHATTER/1/1/07.png b/resource/img/SHATTER/1/1/07.png
new file mode 100644 (file)
index 0000000..fc5df44
Binary files /dev/null and b/resource/img/SHATTER/1/1/07.png differ
diff --git a/resource/img/SHATTER/1/2/00.png b/resource/img/SHATTER/1/2/00.png
new file mode 100644 (file)
index 0000000..2fce360
Binary files /dev/null and b/resource/img/SHATTER/1/2/00.png differ
diff --git a/resource/img/SHATTER/1/2/01.png b/resource/img/SHATTER/1/2/01.png
new file mode 100644 (file)
index 0000000..d662e0c
Binary files /dev/null and b/resource/img/SHATTER/1/2/01.png differ
diff --git a/resource/img/SHATTER/1/2/02.png b/resource/img/SHATTER/1/2/02.png
new file mode 100644 (file)
index 0000000..8627b40
Binary files /dev/null and b/resource/img/SHATTER/1/2/02.png differ
diff --git a/resource/img/SHATTER/1/2/03.png b/resource/img/SHATTER/1/2/03.png
new file mode 100644 (file)
index 0000000..527fbf0
Binary files /dev/null and b/resource/img/SHATTER/1/2/03.png differ
diff --git a/resource/img/SHATTER/1/2/04.png b/resource/img/SHATTER/1/2/04.png
new file mode 100644 (file)
index 0000000..00e23b5
Binary files /dev/null and b/resource/img/SHATTER/1/2/04.png differ
diff --git a/resource/img/SHATTER/1/2/05.png b/resource/img/SHATTER/1/2/05.png
new file mode 100644 (file)
index 0000000..1dd8eb2
Binary files /dev/null and b/resource/img/SHATTER/1/2/05.png differ
diff --git a/resource/img/SHATTER/1/2/06.png b/resource/img/SHATTER/1/2/06.png
new file mode 100644 (file)
index 0000000..acf29bc
Binary files /dev/null and b/resource/img/SHATTER/1/2/06.png differ
diff --git a/resource/img/SHATTER/1/2/07.png b/resource/img/SHATTER/1/2/07.png
new file mode 100644 (file)
index 0000000..493ec45
Binary files /dev/null and b/resource/img/SHATTER/1/2/07.png differ
diff --git a/resource/img/SHATTER/1/3/00.png b/resource/img/SHATTER/1/3/00.png
new file mode 100644 (file)
index 0000000..9a25021
Binary files /dev/null and b/resource/img/SHATTER/1/3/00.png differ
diff --git a/resource/img/SHATTER/1/3/01.png b/resource/img/SHATTER/1/3/01.png
new file mode 100644 (file)
index 0000000..8dcd13b
Binary files /dev/null and b/resource/img/SHATTER/1/3/01.png differ
diff --git a/resource/img/SHATTER/1/3/02.png b/resource/img/SHATTER/1/3/02.png
new file mode 100644 (file)
index 0000000..8218e12
Binary files /dev/null and b/resource/img/SHATTER/1/3/02.png differ
diff --git a/resource/img/SHATTER/1/3/03.png b/resource/img/SHATTER/1/3/03.png
new file mode 100644 (file)
index 0000000..fb027aa
Binary files /dev/null and b/resource/img/SHATTER/1/3/03.png differ
diff --git a/resource/img/SHATTER/1/3/04.png b/resource/img/SHATTER/1/3/04.png
new file mode 100644 (file)
index 0000000..b02cfc8
Binary files /dev/null and b/resource/img/SHATTER/1/3/04.png differ
diff --git a/resource/img/SHATTER/1/3/05.png b/resource/img/SHATTER/1/3/05.png
new file mode 100644 (file)
index 0000000..aace722
Binary files /dev/null and b/resource/img/SHATTER/1/3/05.png differ
diff --git a/resource/img/SHATTER/1/3/06.png b/resource/img/SHATTER/1/3/06.png
new file mode 100644 (file)
index 0000000..3e5cf67
Binary files /dev/null and b/resource/img/SHATTER/1/3/06.png differ
diff --git a/resource/img/SHATTER/1/3/07.png b/resource/img/SHATTER/1/3/07.png
new file mode 100644 (file)
index 0000000..f2a52d7
Binary files /dev/null and b/resource/img/SHATTER/1/3/07.png differ
diff --git a/resource/img/SHATTER/1/4/00.png b/resource/img/SHATTER/1/4/00.png
new file mode 100644 (file)
index 0000000..7c8efc5
Binary files /dev/null and b/resource/img/SHATTER/1/4/00.png differ
diff --git a/resource/img/SHATTER/1/4/01.png b/resource/img/SHATTER/1/4/01.png
new file mode 100644 (file)
index 0000000..f193d29
Binary files /dev/null and b/resource/img/SHATTER/1/4/01.png differ
diff --git a/resource/img/SHATTER/1/4/02.png b/resource/img/SHATTER/1/4/02.png
new file mode 100644 (file)
index 0000000..73c0d9b
Binary files /dev/null and b/resource/img/SHATTER/1/4/02.png differ
diff --git a/resource/img/SHATTER/1/4/03.png b/resource/img/SHATTER/1/4/03.png
new file mode 100644 (file)
index 0000000..6414250
Binary files /dev/null and b/resource/img/SHATTER/1/4/03.png differ
diff --git a/resource/img/SHATTER/1/4/04.png b/resource/img/SHATTER/1/4/04.png
new file mode 100644 (file)
index 0000000..840f8fd
Binary files /dev/null and b/resource/img/SHATTER/1/4/04.png differ
diff --git a/resource/img/SHATTER/1/4/05.png b/resource/img/SHATTER/1/4/05.png
new file mode 100644 (file)
index 0000000..c17b309
Binary files /dev/null and b/resource/img/SHATTER/1/4/05.png differ
diff --git a/resource/img/SHATTER/1/4/06.png b/resource/img/SHATTER/1/4/06.png
new file mode 100644 (file)
index 0000000..bd63494
Binary files /dev/null and b/resource/img/SHATTER/1/4/06.png differ
diff --git a/resource/img/SHATTER/1/4/07.png b/resource/img/SHATTER/1/4/07.png
new file mode 100644 (file)
index 0000000..4af35ff
Binary files /dev/null and b/resource/img/SHATTER/1/4/07.png differ
diff --git a/resource/img/SHATTER/2/0/00.png b/resource/img/SHATTER/2/0/00.png
new file mode 100644 (file)
index 0000000..f97af8a
Binary files /dev/null and b/resource/img/SHATTER/2/0/00.png differ
diff --git a/resource/img/SHATTER/2/0/01.png b/resource/img/SHATTER/2/0/01.png
new file mode 100644 (file)
index 0000000..9713761
Binary files /dev/null and b/resource/img/SHATTER/2/0/01.png differ
diff --git a/resource/img/SHATTER/2/0/02.png b/resource/img/SHATTER/2/0/02.png
new file mode 100644 (file)
index 0000000..06fc7f4
Binary files /dev/null and b/resource/img/SHATTER/2/0/02.png differ
diff --git a/resource/img/SHATTER/2/0/03.png b/resource/img/SHATTER/2/0/03.png
new file mode 100644 (file)
index 0000000..1292e7f
Binary files /dev/null and b/resource/img/SHATTER/2/0/03.png differ
diff --git a/resource/img/SHATTER/2/0/04.png b/resource/img/SHATTER/2/0/04.png
new file mode 100644 (file)
index 0000000..ee13b39
Binary files /dev/null and b/resource/img/SHATTER/2/0/04.png differ
diff --git a/resource/img/SHATTER/2/0/05.png b/resource/img/SHATTER/2/0/05.png
new file mode 100644 (file)
index 0000000..9861040
Binary files /dev/null and b/resource/img/SHATTER/2/0/05.png differ
diff --git a/resource/img/SHATTER/2/0/06.png b/resource/img/SHATTER/2/0/06.png
new file mode 100644 (file)
index 0000000..417763f
Binary files /dev/null and b/resource/img/SHATTER/2/0/06.png differ
diff --git a/resource/img/SHATTER/2/0/07.png b/resource/img/SHATTER/2/0/07.png
new file mode 100644 (file)
index 0000000..abe01a6
Binary files /dev/null and b/resource/img/SHATTER/2/0/07.png differ
diff --git a/resource/img/SHATTER/2/1/00.png b/resource/img/SHATTER/2/1/00.png
new file mode 100644 (file)
index 0000000..fc7b4f4
Binary files /dev/null and b/resource/img/SHATTER/2/1/00.png differ
diff --git a/resource/img/SHATTER/2/1/01.png b/resource/img/SHATTER/2/1/01.png
new file mode 100644 (file)
index 0000000..a512008
Binary files /dev/null and b/resource/img/SHATTER/2/1/01.png differ
diff --git a/resource/img/SHATTER/2/1/02.png b/resource/img/SHATTER/2/1/02.png
new file mode 100644 (file)
index 0000000..9205c21
Binary files /dev/null and b/resource/img/SHATTER/2/1/02.png differ
diff --git a/resource/img/SHATTER/2/1/03.png b/resource/img/SHATTER/2/1/03.png
new file mode 100644 (file)
index 0000000..8f954c5
Binary files /dev/null and b/resource/img/SHATTER/2/1/03.png differ
diff --git a/resource/img/SHATTER/2/1/04.png b/resource/img/SHATTER/2/1/04.png
new file mode 100644 (file)
index 0000000..2cae653
Binary files /dev/null and b/resource/img/SHATTER/2/1/04.png differ
diff --git a/resource/img/SHATTER/2/1/05.png b/resource/img/SHATTER/2/1/05.png
new file mode 100644 (file)
index 0000000..5087f2a
Binary files /dev/null and b/resource/img/SHATTER/2/1/05.png differ
diff --git a/resource/img/SHATTER/2/1/06.png b/resource/img/SHATTER/2/1/06.png
new file mode 100644 (file)
index 0000000..2fa58d3
Binary files /dev/null and b/resource/img/SHATTER/2/1/06.png differ
diff --git a/resource/img/SHATTER/2/1/07.png b/resource/img/SHATTER/2/1/07.png
new file mode 100644 (file)
index 0000000..cde0249
Binary files /dev/null and b/resource/img/SHATTER/2/1/07.png differ
diff --git a/resource/img/SHATTER/2/2/00.png b/resource/img/SHATTER/2/2/00.png
new file mode 100644 (file)
index 0000000..8c4828c
Binary files /dev/null and b/resource/img/SHATTER/2/2/00.png differ
diff --git a/resource/img/SHATTER/2/2/01.png b/resource/img/SHATTER/2/2/01.png
new file mode 100644 (file)
index 0000000..62c0c02
Binary files /dev/null and b/resource/img/SHATTER/2/2/01.png differ
diff --git a/resource/img/SHATTER/2/2/02.png b/resource/img/SHATTER/2/2/02.png
new file mode 100644 (file)
index 0000000..60d365b
Binary files /dev/null and b/resource/img/SHATTER/2/2/02.png differ
diff --git a/resource/img/SHATTER/2/2/03.png b/resource/img/SHATTER/2/2/03.png
new file mode 100644 (file)
index 0000000..9991e8a
Binary files /dev/null and b/resource/img/SHATTER/2/2/03.png differ
diff --git a/resource/img/SHATTER/2/2/04.png b/resource/img/SHATTER/2/2/04.png
new file mode 100644 (file)
index 0000000..b7663c1
Binary files /dev/null and b/resource/img/SHATTER/2/2/04.png differ
diff --git a/resource/img/SHATTER/2/2/05.png b/resource/img/SHATTER/2/2/05.png
new file mode 100644 (file)
index 0000000..c843107
Binary files /dev/null and b/resource/img/SHATTER/2/2/05.png differ
diff --git a/resource/img/SHATTER/2/2/06.png b/resource/img/SHATTER/2/2/06.png
new file mode 100644 (file)
index 0000000..b547f37
Binary files /dev/null and b/resource/img/SHATTER/2/2/06.png differ
diff --git a/resource/img/SHATTER/2/2/07.png b/resource/img/SHATTER/2/2/07.png
new file mode 100644 (file)
index 0000000..ff82fe6
Binary files /dev/null and b/resource/img/SHATTER/2/2/07.png differ
diff --git a/resource/img/SHATTER/2/3/00.png b/resource/img/SHATTER/2/3/00.png
new file mode 100644 (file)
index 0000000..1ad4704
Binary files /dev/null and b/resource/img/SHATTER/2/3/00.png differ
diff --git a/resource/img/SHATTER/2/3/01.png b/resource/img/SHATTER/2/3/01.png
new file mode 100644 (file)
index 0000000..d125a0b
Binary files /dev/null and b/resource/img/SHATTER/2/3/01.png differ
diff --git a/resource/img/SHATTER/2/3/02.png b/resource/img/SHATTER/2/3/02.png
new file mode 100644 (file)
index 0000000..515b680
Binary files /dev/null and b/resource/img/SHATTER/2/3/02.png differ
diff --git a/resource/img/SHATTER/2/3/03.png b/resource/img/SHATTER/2/3/03.png
new file mode 100644 (file)
index 0000000..6720f0a
Binary files /dev/null and b/resource/img/SHATTER/2/3/03.png differ
diff --git a/resource/img/SHATTER/2/3/04.png b/resource/img/SHATTER/2/3/04.png
new file mode 100644 (file)
index 0000000..7419d23
Binary files /dev/null and b/resource/img/SHATTER/2/3/04.png differ
diff --git a/resource/img/SHATTER/2/3/05.png b/resource/img/SHATTER/2/3/05.png
new file mode 100644 (file)
index 0000000..4e2081a
Binary files /dev/null and b/resource/img/SHATTER/2/3/05.png differ
diff --git a/resource/img/SHATTER/2/3/06.png b/resource/img/SHATTER/2/3/06.png
new file mode 100644 (file)
index 0000000..00ac2d3
Binary files /dev/null and b/resource/img/SHATTER/2/3/06.png differ
diff --git a/resource/img/SHATTER/2/3/07.png b/resource/img/SHATTER/2/3/07.png
new file mode 100644 (file)
index 0000000..a66b44e
Binary files /dev/null and b/resource/img/SHATTER/2/3/07.png differ
diff --git a/resource/img/SHATTER/2/4/00.png b/resource/img/SHATTER/2/4/00.png
new file mode 100644 (file)
index 0000000..9636907
Binary files /dev/null and b/resource/img/SHATTER/2/4/00.png differ
diff --git a/resource/img/SHATTER/2/4/01.png b/resource/img/SHATTER/2/4/01.png
new file mode 100644 (file)
index 0000000..6602257
Binary files /dev/null and b/resource/img/SHATTER/2/4/01.png differ
diff --git a/resource/img/SHATTER/2/4/02.png b/resource/img/SHATTER/2/4/02.png
new file mode 100644 (file)
index 0000000..2da06a0
Binary files /dev/null and b/resource/img/SHATTER/2/4/02.png differ
diff --git a/resource/img/SHATTER/2/4/03.png b/resource/img/SHATTER/2/4/03.png
new file mode 100644 (file)
index 0000000..bee3d8b
Binary files /dev/null and b/resource/img/SHATTER/2/4/03.png differ
diff --git a/resource/img/SHATTER/2/4/04.png b/resource/img/SHATTER/2/4/04.png
new file mode 100644 (file)
index 0000000..3326910
Binary files /dev/null and b/resource/img/SHATTER/2/4/04.png differ
diff --git a/resource/img/SHATTER/2/4/05.png b/resource/img/SHATTER/2/4/05.png
new file mode 100644 (file)
index 0000000..d100687
Binary files /dev/null and b/resource/img/SHATTER/2/4/05.png differ
diff --git a/resource/img/SHATTER/2/4/06.png b/resource/img/SHATTER/2/4/06.png
new file mode 100644 (file)
index 0000000..199dc05
Binary files /dev/null and b/resource/img/SHATTER/2/4/06.png differ
diff --git a/resource/img/SHATTER/2/4/07.png b/resource/img/SHATTER/2/4/07.png
new file mode 100644 (file)
index 0000000..30239b3
Binary files /dev/null and b/resource/img/SHATTER/2/4/07.png differ
diff --git a/resource/img/SHATTER/3/0/00.png b/resource/img/SHATTER/3/0/00.png
new file mode 100644 (file)
index 0000000..94bcada
Binary files /dev/null and b/resource/img/SHATTER/3/0/00.png differ
diff --git a/resource/img/SHATTER/3/0/01.png b/resource/img/SHATTER/3/0/01.png
new file mode 100644 (file)
index 0000000..f485b47
Binary files /dev/null and b/resource/img/SHATTER/3/0/01.png differ
diff --git a/resource/img/SHATTER/3/0/02.png b/resource/img/SHATTER/3/0/02.png
new file mode 100644 (file)
index 0000000..695b865
Binary files /dev/null and b/resource/img/SHATTER/3/0/02.png differ
diff --git a/resource/img/SHATTER/3/0/03.png b/resource/img/SHATTER/3/0/03.png
new file mode 100644 (file)
index 0000000..2c16fe1
Binary files /dev/null and b/resource/img/SHATTER/3/0/03.png differ
diff --git a/resource/img/SHATTER/3/0/04.png b/resource/img/SHATTER/3/0/04.png
new file mode 100644 (file)
index 0000000..14baec0
Binary files /dev/null and b/resource/img/SHATTER/3/0/04.png differ
diff --git a/resource/img/SHATTER/3/0/05.png b/resource/img/SHATTER/3/0/05.png
new file mode 100644 (file)
index 0000000..6bc95ec
Binary files /dev/null and b/resource/img/SHATTER/3/0/05.png differ
diff --git a/resource/img/SHATTER/3/0/06.png b/resource/img/SHATTER/3/0/06.png
new file mode 100644 (file)
index 0000000..e0d18b7
Binary files /dev/null and b/resource/img/SHATTER/3/0/06.png differ
diff --git a/resource/img/SHATTER/3/0/07.png b/resource/img/SHATTER/3/0/07.png
new file mode 100644 (file)
index 0000000..9ec0a82
Binary files /dev/null and b/resource/img/SHATTER/3/0/07.png differ
diff --git a/resource/img/SHATTER/3/1/00.png b/resource/img/SHATTER/3/1/00.png
new file mode 100644 (file)
index 0000000..91731db
Binary files /dev/null and b/resource/img/SHATTER/3/1/00.png differ
diff --git a/resource/img/SHATTER/3/1/01.png b/resource/img/SHATTER/3/1/01.png
new file mode 100644 (file)
index 0000000..8ccbfb7
Binary files /dev/null and b/resource/img/SHATTER/3/1/01.png differ
diff --git a/resource/img/SHATTER/3/1/02.png b/resource/img/SHATTER/3/1/02.png
new file mode 100644 (file)
index 0000000..2f88210
Binary files /dev/null and b/resource/img/SHATTER/3/1/02.png differ
diff --git a/resource/img/SHATTER/3/1/03.png b/resource/img/SHATTER/3/1/03.png
new file mode 100644 (file)
index 0000000..92d8d93
Binary files /dev/null and b/resource/img/SHATTER/3/1/03.png differ
diff --git a/resource/img/SHATTER/3/1/04.png b/resource/img/SHATTER/3/1/04.png
new file mode 100644 (file)
index 0000000..e3542fd
Binary files /dev/null and b/resource/img/SHATTER/3/1/04.png differ
diff --git a/resource/img/SHATTER/3/1/05.png b/resource/img/SHATTER/3/1/05.png
new file mode 100644 (file)
index 0000000..e289715
Binary files /dev/null and b/resource/img/SHATTER/3/1/05.png differ
diff --git a/resource/img/SHATTER/3/1/06.png b/resource/img/SHATTER/3/1/06.png
new file mode 100644 (file)
index 0000000..f58e520
Binary files /dev/null and b/resource/img/SHATTER/3/1/06.png differ
diff --git a/resource/img/SHATTER/3/1/07.png b/resource/img/SHATTER/3/1/07.png
new file mode 100644 (file)
index 0000000..264e562
Binary files /dev/null and b/resource/img/SHATTER/3/1/07.png differ
diff --git a/resource/img/SHATTER/3/2/00.png b/resource/img/SHATTER/3/2/00.png
new file mode 100644 (file)
index 0000000..3f872af
Binary files /dev/null and b/resource/img/SHATTER/3/2/00.png differ
diff --git a/resource/img/SHATTER/3/2/01.png b/resource/img/SHATTER/3/2/01.png
new file mode 100644 (file)
index 0000000..757ac68
Binary files /dev/null and b/resource/img/SHATTER/3/2/01.png differ
diff --git a/resource/img/SHATTER/3/2/02.png b/resource/img/SHATTER/3/2/02.png
new file mode 100644 (file)
index 0000000..22ff65b
Binary files /dev/null and b/resource/img/SHATTER/3/2/02.png differ
diff --git a/resource/img/SHATTER/3/2/03.png b/resource/img/SHATTER/3/2/03.png
new file mode 100644 (file)
index 0000000..40b66a8
Binary files /dev/null and b/resource/img/SHATTER/3/2/03.png differ
diff --git a/resource/img/SHATTER/3/2/04.png b/resource/img/SHATTER/3/2/04.png
new file mode 100644 (file)
index 0000000..c369536
Binary files /dev/null and b/resource/img/SHATTER/3/2/04.png differ
diff --git a/resource/img/SHATTER/3/2/05.png b/resource/img/SHATTER/3/2/05.png
new file mode 100644 (file)
index 0000000..4c8a75d
Binary files /dev/null and b/resource/img/SHATTER/3/2/05.png differ
diff --git a/resource/img/SHATTER/3/2/06.png b/resource/img/SHATTER/3/2/06.png
new file mode 100644 (file)
index 0000000..840463e
Binary files /dev/null and b/resource/img/SHATTER/3/2/06.png differ
diff --git a/resource/img/SHATTER/3/2/07.png b/resource/img/SHATTER/3/2/07.png
new file mode 100644 (file)
index 0000000..cb4077b
Binary files /dev/null and b/resource/img/SHATTER/3/2/07.png differ
diff --git a/resource/img/SHATTER/3/3/00.png b/resource/img/SHATTER/3/3/00.png
new file mode 100644 (file)
index 0000000..32a0bfd
Binary files /dev/null and b/resource/img/SHATTER/3/3/00.png differ
diff --git a/resource/img/SHATTER/3/3/01.png b/resource/img/SHATTER/3/3/01.png
new file mode 100644 (file)
index 0000000..4bd1447
Binary files /dev/null and b/resource/img/SHATTER/3/3/01.png differ
diff --git a/resource/img/SHATTER/3/3/02.png b/resource/img/SHATTER/3/3/02.png
new file mode 100644 (file)
index 0000000..2a84311
Binary files /dev/null and b/resource/img/SHATTER/3/3/02.png differ
diff --git a/resource/img/SHATTER/3/3/03.png b/resource/img/SHATTER/3/3/03.png
new file mode 100644 (file)
index 0000000..efa92c5
Binary files /dev/null and b/resource/img/SHATTER/3/3/03.png differ
diff --git a/resource/img/SHATTER/3/3/04.png b/resource/img/SHATTER/3/3/04.png
new file mode 100644 (file)
index 0000000..56896ad
Binary files /dev/null and b/resource/img/SHATTER/3/3/04.png differ
diff --git a/resource/img/SHATTER/3/3/05.png b/resource/img/SHATTER/3/3/05.png
new file mode 100644 (file)
index 0000000..999654f
Binary files /dev/null and b/resource/img/SHATTER/3/3/05.png differ
diff --git a/resource/img/SHATTER/3/3/06.png b/resource/img/SHATTER/3/3/06.png
new file mode 100644 (file)
index 0000000..a8e6ccb
Binary files /dev/null and b/resource/img/SHATTER/3/3/06.png differ
diff --git a/resource/img/SHATTER/3/3/07.png b/resource/img/SHATTER/3/3/07.png
new file mode 100644 (file)
index 0000000..0685483
Binary files /dev/null and b/resource/img/SHATTER/3/3/07.png differ
diff --git a/resource/img/SHATTER/3/4/00.png b/resource/img/SHATTER/3/4/00.png
new file mode 100644 (file)
index 0000000..116542d
Binary files /dev/null and b/resource/img/SHATTER/3/4/00.png differ
diff --git a/resource/img/SHATTER/3/4/01.png b/resource/img/SHATTER/3/4/01.png
new file mode 100644 (file)
index 0000000..828cff0
Binary files /dev/null and b/resource/img/SHATTER/3/4/01.png differ
diff --git a/resource/img/SHATTER/3/4/02.png b/resource/img/SHATTER/3/4/02.png
new file mode 100644 (file)
index 0000000..5cbedce
Binary files /dev/null and b/resource/img/SHATTER/3/4/02.png differ
diff --git a/resource/img/SHATTER/3/4/03.png b/resource/img/SHATTER/3/4/03.png
new file mode 100644 (file)
index 0000000..d2cb119
Binary files /dev/null and b/resource/img/SHATTER/3/4/03.png differ
diff --git a/resource/img/SHATTER/3/4/04.png b/resource/img/SHATTER/3/4/04.png
new file mode 100644 (file)
index 0000000..dff42a1
Binary files /dev/null and b/resource/img/SHATTER/3/4/04.png differ
diff --git a/resource/img/SHATTER/3/4/05.png b/resource/img/SHATTER/3/4/05.png
new file mode 100644 (file)
index 0000000..753bd55
Binary files /dev/null and b/resource/img/SHATTER/3/4/05.png differ
diff --git a/resource/img/SHATTER/3/4/06.png b/resource/img/SHATTER/3/4/06.png
new file mode 100644 (file)
index 0000000..10cb3a3
Binary files /dev/null and b/resource/img/SHATTER/3/4/06.png differ
diff --git a/resource/img/SHATTER/3/4/07.png b/resource/img/SHATTER/3/4/07.png
new file mode 100644 (file)
index 0000000..0009805
Binary files /dev/null and b/resource/img/SHATTER/3/4/07.png differ
diff --git a/resource/img/SHATTER/animate b/resource/img/SHATTER/animate
new file mode 100755 (executable)
index 0000000..0185f05
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/python
+
+from sys import argv
+from os import listdir
+from os.path import join
+from subprocess import call
+
+from pygame import Color, Rect
+from pygame.display import set_mode
+from pygame.locals import *
+from pgfw.Game import Game
+from pgfw.Sprite import Sprite
+
+FRAMERATE = 120
+COLORS = ("black", "red", "skyblue", "gray", "white")
+DEFAULT_ROOT = "0/0"
+GUN_COUNT = 5
+LEVEL_COUNT = 4
+
+class Animator(Game):
+
+    def __init__(self):
+        Game.__init__(self)
+        self.root = [0, 0]
+        self.refresh()
+        self.subscribe(self.respond, KEYDOWN)
+
+    def refresh(self):
+        self.set_gun()
+        self.distribute_guns()
+        self.set_screen_dimensions()
+
+    def set_gun(self):
+        framerate = FRAMERATE if len(argv) < 3 else argv[2]
+        gun = Sprite(self, framerate)
+        root = self.get_root_string()
+        for path in sorted(listdir(root)):
+            gun.load_from_path(join(root, path), True)
+        self.gun = gun
+
+    def get_root_string(self):
+        return join(*(str(dir) for dir in self.root))
+
+    def distribute_guns(self):
+        self.gun.add_location(offset=(self.gun.location.w, 0), count=GUN_COUNT)
+
+    def set_screen_dimensions(self):
+        width, height = self.gun.rect.size
+        set_mode((width * len(COLORS), height))
+
+    def respond(self, event):
+        if event.key == K_k:
+            self.change_root(1)
+        elif event.key == K_j:
+            self.change_root(-1)
+        elif event.key == K_l:
+            self.change_root(GUN_COUNT)
+        elif event.key == K_h:
+            self.change_root(-GUN_COUNT)
+        elif event.key == K_r:
+            self.reanimate()
+
+    def change_root(self, increment):
+        level, ii = self.root
+        sign = increment / abs(increment)
+        for _ in xrange(abs(increment)):
+            ii += sign
+            if ii >= GUN_COUNT:
+                ii = 0
+                level += sign
+            elif ii < 0:
+                ii = GUN_COUNT - 1
+                level -= sign
+            if level >= LEVEL_COUNT:
+                level = 0
+            elif level < 0:
+                level = LEVEL_COUNT - 1
+        self.root = [level, ii]
+        self.refresh()
+
+    def reanimate(self):
+        call(["perl", "generate", self.get_root_string()])
+        self.refresh()
+
+    def update(self):
+        self.clear()
+        self.gun.update()
+
+    def clear(self):
+        colors = COLORS
+        gun = self.gun
+        screen = self.get_screen()
+        for ii in xrange(len(colors)):
+            screen.fill(Color(colors[ii]), (ii * gun.rect.w, 0, gun.rect.w,
+                                            screen.get_width()))
+
+
+if __name__ == "__main__":
+    Animator().run()
diff --git a/resource/img/SHATTER/blob/00.png b/resource/img/SHATTER/blob/00.png
new file mode 100644 (file)
index 0000000..4856b38
Binary files /dev/null and b/resource/img/SHATTER/blob/00.png differ
diff --git a/resource/img/SHATTER/blob/01.png b/resource/img/SHATTER/blob/01.png
new file mode 100644 (file)
index 0000000..457effd
Binary files /dev/null and b/resource/img/SHATTER/blob/01.png differ
diff --git a/resource/img/SHATTER/blob/02.png b/resource/img/SHATTER/blob/02.png
new file mode 100644 (file)
index 0000000..9ce4984
Binary files /dev/null and b/resource/img/SHATTER/blob/02.png differ
diff --git a/resource/img/SHATTER/blob/03.png b/resource/img/SHATTER/blob/03.png
new file mode 100644 (file)
index 0000000..4925b59
Binary files /dev/null and b/resource/img/SHATTER/blob/03.png differ
diff --git a/resource/img/SHATTER/blob/04.png b/resource/img/SHATTER/blob/04.png
new file mode 100644 (file)
index 0000000..815d4c5
Binary files /dev/null and b/resource/img/SHATTER/blob/04.png differ
diff --git a/resource/img/SHATTER/blob/05.png b/resource/img/SHATTER/blob/05.png
new file mode 100644 (file)
index 0000000..7bba358
Binary files /dev/null and b/resource/img/SHATTER/blob/05.png differ
diff --git a/resource/img/SHATTER/blob/06.png b/resource/img/SHATTER/blob/06.png
new file mode 100644 (file)
index 0000000..28dfb72
Binary files /dev/null and b/resource/img/SHATTER/blob/06.png differ
diff --git a/resource/img/SHATTER/blob/07.png b/resource/img/SHATTER/blob/07.png
new file mode 100644 (file)
index 0000000..97bbd1d
Binary files /dev/null and b/resource/img/SHATTER/blob/07.png differ
diff --git a/resource/img/SHATTER/blob/08.png b/resource/img/SHATTER/blob/08.png
new file mode 100644 (file)
index 0000000..97bbd1d
Binary files /dev/null and b/resource/img/SHATTER/blob/08.png differ
diff --git a/resource/img/SHATTER/blob/09.png b/resource/img/SHATTER/blob/09.png
new file mode 100644 (file)
index 0000000..28dfb72
Binary files /dev/null and b/resource/img/SHATTER/blob/09.png differ
diff --git a/resource/img/SHATTER/blob/10.png b/resource/img/SHATTER/blob/10.png
new file mode 100644 (file)
index 0000000..7bba358
Binary files /dev/null and b/resource/img/SHATTER/blob/10.png differ
diff --git a/resource/img/SHATTER/blob/11.png b/resource/img/SHATTER/blob/11.png
new file mode 100644 (file)
index 0000000..815d4c5
Binary files /dev/null and b/resource/img/SHATTER/blob/11.png differ
diff --git a/resource/img/SHATTER/blob/12.png b/resource/img/SHATTER/blob/12.png
new file mode 100644 (file)
index 0000000..4925b59
Binary files /dev/null and b/resource/img/SHATTER/blob/12.png differ
diff --git a/resource/img/SHATTER/blob/13.png b/resource/img/SHATTER/blob/13.png
new file mode 100644 (file)
index 0000000..9ce4984
Binary files /dev/null and b/resource/img/SHATTER/blob/13.png differ
diff --git a/resource/img/SHATTER/blob/14.png b/resource/img/SHATTER/blob/14.png
new file mode 100644 (file)
index 0000000..457effd
Binary files /dev/null and b/resource/img/SHATTER/blob/14.png differ
diff --git a/resource/img/SHATTER/blob/15.png b/resource/img/SHATTER/blob/15.png
new file mode 100644 (file)
index 0000000..4856b38
Binary files /dev/null and b/resource/img/SHATTER/blob/15.png differ
diff --git a/resource/img/SHATTER/blob/16.png b/resource/img/SHATTER/blob/16.png
new file mode 100644 (file)
index 0000000..4856b38
Binary files /dev/null and b/resource/img/SHATTER/blob/16.png differ
diff --git a/resource/img/SHATTER/blob/animation.gif b/resource/img/SHATTER/blob/animation.gif
new file mode 100644 (file)
index 0000000..8766d37
Binary files /dev/null and b/resource/img/SHATTER/blob/animation.gif differ
diff --git a/resource/img/SHATTER/blob/generate b/resource/img/SHATTER/blob/generate
new file mode 100755 (executable)
index 0000000..a0ecd88
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use feature "say";
+
+use Image::Magick;
+use File::Spec;
+
+my $framerate = 10;
+my $gem_path = "gem/";
+my $gem_margin = 8;
+my @hues = (0, 33.33, 66.66);
+my $height = 40;
+my $drop_width = 4;
+my $drop_frame_count = 8;
+my $fall_height = 9;
+my $fall_frame_count = 0;
+my $fall_min_alpha = 1;
+my $hue_adjustment = 100;
+my $compose = "Plus";
+
+generate();
+
+sub generate
+{
+    my $gem_frames = load_gems();
+    my $gem_width = $gem_frames->[0]->Get("width");
+    my $gem_height = $gem_frames->[0]->Get("height");
+    my (@drop_frames, @fall_frames);
+    for (@hues)
+    {
+        push @drop_frames, get_drop_frames($gem_width, $gem_height, $_);
+        push @fall_frames, get_fall_frames($gem_width, $gem_height, $_);
+    }
+    my $frames = get_frames($gem_frames, \@drop_frames, \@fall_frames,
+                            $gem_width);
+    write_frames($frames);
+}
+
+sub load_gems
+{
+    my (@frames, $frame);
+    for (glob File::Spec->catfile($gem_path, "*.png"))
+    {
+        $frame = Image::Magick->new();
+        $frame->Read($_);
+        push @frames, $frame;
+    }
+    \@frames;
+}
+
+sub get_drop_frames
+{
+    my ($gem_width, $height, $hue) = @_;
+    my $width = $drop_width * $gem_width;
+    my (@frames, $frame, $ratio, $rect_width, $rect_height, $points, $margin);
+    for (0..$drop_frame_count - 1)
+    {
+        $frame = Image::Magick->new(size=>"${width}x$height");
+        $frame->Read("xc:none");
+        $ratio = $_ / ($drop_frame_count - 1);
+        $rect_width = $gem_width + ($width - $gem_width) * (1 - $ratio);
+        $rect_height = $height * $ratio;
+        $margin = ($width - $rect_width) / 2;
+        $points =  "$margin,0 " . ($width - $margin - 1) . ",$rect_height";
+        $frame->Draw(primitive=>"rectangle", fill=>"hsl($hue%, 100%, 50%)",
+                     points=>$points);
+        push @frames, $frame;
+    }
+    \@frames;
+}
+
+sub get_fall_frames
+{
+    my ($width, $gem_height, $hue) = @_;
+    my $step = ($fall_height - $gem_height) / ($fall_frame_count - 1);
+    my (@frames, $frame, $points, $y, $alpha);
+    for (1..$fall_frame_count - 1)
+    {
+        $frame = Image::Magick->new(size=>"${width}x$fall_height");
+        $frame->Read("xc:none");
+        $y = $step * $_;
+        $points = "0,$y $width," . ($y + $gem_height);
+        $alpha = (1 - $fall_min_alpha) * (1 - $_ / ($fall_frame_count - 1)) +
+            $fall_min_alpha;
+        $frame->Draw(primitive=>"rectangle", points=>$points,
+                     fill=>"hsla($hue%, 100%, 50%, $alpha)");
+        push @frames, $frame;
+    }
+    \@frames;
+}
+
+sub get_frames
+{
+    my ($gem_frames, $drop_frames, $fall_frames, $gem_width) = @_;
+    my $drop_width = $drop_frames->[0]->[0]->Get("width");
+    my $width = $gem_width * 3 + $gem_margin * 2 + $drop_width - $gem_width;
+    my $size = "${width}x$fall_height";
+    my $frame_ii = 1;
+    my (@frames, $frame);
+    for (0..@{$drop_frames->[0]} - 1)
+    {
+        $frame = Image::Magick->new(size=>$size);
+        $frame->Read("xc:none");
+        $frame->Composite(image=>$drop_frames->[0]->[$_], compose=>$compose);
+        $frame->Composite(image=>$drop_frames->[2]->[$_], compose=>$compose,
+                          gravity=>"NorthEast");
+        $frame->Composite(image=>$drop_frames->[1]->[$_], compose=>$compose,
+                          gravity=>"North");
+        push @frames, $frame;
+    }
+    my @indents;
+    for (0..@{$fall_frames} - 1)
+    {
+        push @indents, ($drop_width - $gem_width) / 2 + ($gem_width +
+                                                         $gem_margin) * $_;
+    }
+    my $count;
+    for (my $ii = 0; $ii < @{$fall_frames->[0]}; $ii++)
+    {
+        $frame = Image::Magick->new(size=>$size);
+        $frame->Read("xc:none");
+        for (0..@{$fall_frames} - 1)
+        {
+            $frame->Composite(image=>$fall_frames->[$_]->[$ii],
+                              x=>$indents[$_], compose=>$compose);
+        }
+        push @frames, $frame;
+    }
+    for (my $ii = @{$fall_frames->[0]} - 1; $ii >= 0; $ii--)
+    {
+        $frame = Image::Magick->new(size=>$size);
+        $frame->Read("xc:none");
+        for (0..@{$fall_frames} - 1)
+        {
+            $frame->Composite(image=>$fall_frames->[$_]->[$ii],
+                              x=>$indents[$_], compose=>$compose);
+        }
+        push @frames, $frame;
+    }
+    for (my $ii = @{$drop_frames->[0]} - 1; $ii >= 0; $ii--)
+    {
+        my $count = $ii > 0 ? 1 : 2;
+        for (1..$count)
+        {
+            $frame = Image::Magick->new(size=>$size);
+            $frame->Read("xc:none");
+            $frame->Composite(image=>$drop_frames->[0]->[$ii],
+                              compose=>$compose);
+            $frame->Composite(image=>$drop_frames->[2]->[$ii],
+                              compose=>$compose,
+                              gravity=>"NorthEast");
+            $frame->Composite(image=>$drop_frames->[1]->[$ii],
+                              compose=>$compose,
+                              gravity=>"North");
+            push @frames, $frame;
+        }
+    }
+    \@frames;
+}
+
+sub write_frames
+{
+    my $frames = shift;
+    my $frame;
+    for (0..@{$frames} - 1)
+    {
+        $frame = $frames->[$_];
+        $frame->Modulate(hue=>$hue_adjustment);
+        $frame->Write(sprintf "%02d.png", $_);
+    }
+}
diff --git a/resource/img/SHATTER/generate b/resource/img/SHATTER/generate
new file mode 100755 (executable)
index 0000000..9bbde43
--- /dev/null
@@ -0,0 +1,280 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use feature "say";
+
+use Image::Magick;
+use POSIX;
+use Math::Trig;
+use File::Spec;
+use Data::Dumper;
+
+my @guns = ([",", "z", "#", "A", "!"],
+            ["+", "t", "]", "F", "Y"],
+            [";", "5", "}", "U", "Z"],
+            [":", ">", "~", "H", "S"]);
+my $character = "H";
+my $font = "Outgunned-Regular";
+my $font_size = 38;
+my $font_color = "white";
+my $font_stroke = "black";
+my $font_stroke_width = 0;
+my $frame_count = 8;
+my $gradient_range = 100;
+my $gradient_resolution = 24;
+my $delay = 10;
+my $wave_count = 8;
+my @wave_period_range = (8, 48);
+my $wave_min_amplitude = 32;
+my $wave_hue_step = .1;
+my $gradient_saturation = 65;
+my $wave_fill_brightness = 80;
+my $wave_stroke_brightness = 17;
+my $wave_stroke_width = 8;
+my $dot_count = 4;
+my $dot_x = .9;
+my $dot_margin = 0;
+my $dot_single_speed = 2;
+my $dot_double_speed = 2;
+my $dot_saturation = 30;
+my $dot_brightness = 100;
+
+generate();
+
+sub generate
+{
+    my $root;
+    if (@ARGV > 0)
+    {
+        $root = $ARGV[0];
+        my ($level, $ii) = $root =~ /([0-9]+)\/([0-9])+/;
+        write_gun($root, $guns[$level][$ii]);
+    }
+    else
+    {
+        for (my $level = 0; $level < @guns; $level++)
+        {
+            mkdir $level;
+            for (my $ii = 0; $ii < @{$guns[$level]}; $ii++)
+            {
+                $root = File::Spec->catfile($level, $ii);
+                mkdir $root;
+                write_gun($root, $guns[$level][$ii]);
+            }
+        }
+    }
+}
+
+sub write_gun
+{
+    my ($root, $character) = @_;
+    my ($width, $height) = get_size($character);
+    my $size = "${width}x$height";
+    my $mask = get_mask($character, $size);
+    my $animation = Image::Magick->new(size=>$size);
+    my $gradient = get_gradient($width, $height);
+    my @periods = get_periods();
+    my @directions = get_directions();
+    my @waves = get_waves($width, $height, \@periods);
+    my @dots = get_dots($width, $height);
+    my $frame;
+    for (0..$frame_count - 1)
+    {
+        $animation->Read("xc:$font_color");
+        $frame = $animation->[$_];
+        $frame->Set(delay=>$delay);
+        $frame->Composite(image=>$gradient);
+        draw_waves($frame, \@waves, $_, \@periods, \@directions);
+        draw_dots($frame, \@dots, $_, $size);
+        $frame->Composite(image=>$mask, compose=>"CopyOpacity");
+        $frame->Write(File::Spec->catfile($root, sprintf("%02i.png", $_)));
+    }
+    say "Wrote $root";
+}
+
+sub get_size
+{
+    my $image = Image::Magick->new();
+    $image->Read("xc:none");
+    my @metrics = $image->QueryFontMetrics(text=>shift, font=>$font,
+                                           pointsize=>$font_size,
+                                           stroke=>$font_stroke,
+                                           strokewidth=>$font_stroke_width);
+    map { ceil($_) } ($metrics[4], $metrics[5]);
+}
+
+sub get_mask
+{
+    my ($character, $size) = @_;
+    my $mask = Image::Magick->new(size=>$size);
+    $mask->Read("xc:black");
+    $mask->Annotate(text=>$character, font=>$font, pointsize=>$font_size,
+                    fill=>$font_color, antialias=>1, x=>0, 'y'=>0,
+                    gravity=>"NorthWest");
+    $mask->Set(alpha=>"Off");
+    $mask;
+}
+
+sub get_gradient
+{
+    my ($width, $height) = @_;
+    my $gradient = Image::Magick->new(size=>"${width}x$height");
+    $gradient->Read("xc:none");
+    my @radiuses = get_radiuses($width, $height);
+    my $cx = 0;
+    my $cy = $height / 2;
+    my $hue = get_random_int(0, 100);
+    my ($edge, $points, $offset_hue);
+    for (0..$gradient_resolution - 1)
+    {
+        $edge = $radiuses[$_] + $cx;
+        $points = "$cx,$cy $edge,$cy";
+        $offset_hue = $hue - ($gradient_range / $gradient_resolution) *
+            ($gradient_resolution - $_ - 1);
+        $gradient->Draw(primitive=>"circle", antialias=>1,
+                        points=>$points,
+                        fill=>"hsb($offset_hue%, $gradient_saturation%, 100%)");
+    }
+    $gradient;
+}
+
+sub get_radiuses
+{
+    push my @radiuses, sqrt($_[0] ** 2 + ($_[1] / 2) ** 2);
+    my $step = $radiuses[0] / $gradient_resolution;
+    while (@radiuses < $gradient_resolution)
+    {
+        push @radiuses, $radiuses[-1] - $step;
+    }
+    @radiuses;
+}
+
+sub get_random_int
+{
+    $_[0] + int rand(1 + $_[1] - $_[0]);
+}
+
+sub get_periods
+{
+    my @periods;
+    for (1..$wave_count)
+    {
+        push @periods, get_random_int(@wave_period_range);
+    }
+    @periods;
+}
+
+sub get_directions
+{
+    my @directions;
+    for (1..$wave_count)
+    {
+        push @directions, get_random_int(0, 1) ? 1 : -1;
+    }
+    @directions;
+}
+
+sub get_waves
+{
+    my ($frame_width, $height, $periods) = @_;
+    my $width = $frame_width + $wave_period_range[1] * 2;
+    my (@waves, $amplitude, $wave, $x, $hue, $points, $period,
+        $margin, $y, $py);
+    for (0..$wave_count - 1)
+    {
+        $amplitude = get_random_int($wave_min_amplitude, $height / 2);
+        $margin = ($height - $amplitude * 2) / 2;
+        $wave = Image::Magick->new(size=>"${width}x$height");
+        $wave->Read("xc:none");
+        $period = $periods->[$_];
+        $hue = get_random_int(0, 100);
+        $py = $margin;
+        for ($x = 2; $x < $width; $x += 2)
+        {
+            $y = sin($x / ($period / pi / 2)) * $amplitude + $margin +
+                $amplitude;
+            $points = ($x - 2) . ",$py $x,$y";
+            $py = $y;
+            $wave->Draw(primitive=>"line", points=>"$points",
+                        antialias=>0,
+                        fill=>"hsb($hue%, 100%, $wave_fill_brightness%)",
+                        stroke=>"hsb($hue%, 100%, $wave_stroke_brightness%)",
+                        strokewidth=>$wave_stroke_width);
+            $hue += $wave_hue_step;
+        }
+        push @waves, $wave;
+    }
+    @waves;
+}
+
+sub get_dots
+{
+    my ($width, $height) = @_;
+    my @dots;
+    my $single = Image::Magick->new(size=>"${width}x" .
+                                    ($height * $dot_single_speed));
+    $single->Read("xc:none");
+    my $double = Image::Magick->new(size=>"${width}x" .
+                                    ($height * $dot_double_speed));
+    $double->Read("xc:none");
+    my $saturation = $dot_saturation;
+    my $brightness = $dot_brightness;
+    my @colors = ("hsb(0%, $saturation%, $brightness%)",
+                  "hsb(33.3%, $saturation%, $brightness%)",
+                  "hsb(66.6%, $saturation%, $brightness%)");
+    my $radius = my $y = $single->Get("height") / @colors / 2 / $dot_count;
+    my $x = $dot_x * $width;
+    my ($points, $offset_x, $color, $ii);
+    for ($ii = 0; $y <= $single->Get("height"); $ii++)
+    {
+        $points = "$x,$y $x," . ($y - $radius);
+        $single->Draw(primitive=>"circle", antialias=>0,
+                      fill=>$colors[$ii % @colors], points=>$points);
+        $y += $radius * 2 + $dot_margin;
+    }
+    $radius = $y = $double->Get("height") / @colors / 2 / $dot_count;
+    for ($ii = 1; $y <= $double->Get("height"); $ii++)
+    {
+        $color = $colors[$ii % @colors];
+        for (-$radius, $radius)
+        {
+            $offset_x = $x + $_;
+            $points = "$offset_x,$y $offset_x," . ($y - $radius);
+            $double->Draw(primitive=>"circle", antialias=>0, fill=>$color,
+                          points=>$points);
+        }
+        $y += $radius * 2 + $dot_margin;
+    }
+    push @dots, $single;
+    push @dots, $double;
+    @dots;
+}
+
+sub draw_waves
+{
+    my ($frame, $waves, $index, $periods, $directions) = @_;
+    my $offset_ratio = $index / $frame_count;
+    my ($offset, $x);
+    for (0..$#{$waves})
+    {
+        $offset = $periods->[$_] * $offset_ratio * $directions->[$_];
+        $x = $offset - $wave_period_range[1];
+        $frame->Composite(image=>$waves->[$_], x=>$x, compose=>"ColorDodge");
+    }
+}
+
+sub draw_dots
+{
+    my ($frame, $dots, $index, $size) = @_;
+    my $single = $dots->[0];
+    my $ratio = 1 - $index / $frame_count;
+    my $single_offset = -$single->Get("height") / 2 * $ratio;
+    my $double = $dots->[1];
+    my $double_offset = -$double->Get("height") / 2 * $ratio;
+    my $merge = Image::Magick->new(size=>$size);
+    $merge->Read("xc:none");
+    $merge->Composite(image=>$dots->[1], 'y'=>$double_offset);
+    $merge->Composite(image=>$dots->[0], 'y'=>$single_offset, compose=>"Add");
+    $frame->Composite(image=>$merge, compose=>"Modulate");
+}