PyIgnition

https://github.com/animatinator/PyIgnition update for Python 3
Clone: git clone https://git.frombelow.net/PyIgnition.git
Log | Files | Refs | README

commit ac44a2ef4f5aad516fbddd2e205f8a2abafb1c95
Author: David Barker <barkerd@google.com>
Date:   Mon, 16 Nov 2015 18:14:36 +0000

Commit existing code

Diffstat:
A.bzr/README | 3+++
A.bzr/branch-format | 1+
A.bzr/branch/branch.conf | 3+++
A.bzr/branch/format | 1+
A.bzr/branch/last-revision | 1+
A.bzr/branch/tags | 0
A.bzr/checkout/conflicts | 1+
A.bzr/checkout/dirstate | 0
A.bzr/checkout/format | 1+
A.bzr/checkout/merge-hashes | 1+
A.bzr/checkout/views | 0
A.bzr/repository/format | 1+
A.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.cix | 0
A.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.iix | 0
A.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.rix | 0
A.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.six | 5+++++
A.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.tix | 0
A.bzr/repository/indices/3842963d0d72724190e27bd55f601203.cix | 0
A.bzr/repository/indices/3842963d0d72724190e27bd55f601203.iix | 0
A.bzr/repository/indices/3842963d0d72724190e27bd55f601203.rix | 0
A.bzr/repository/indices/3842963d0d72724190e27bd55f601203.six | 5+++++
A.bzr/repository/indices/3842963d0d72724190e27bd55f601203.tix | 0
A.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.cix | 0
A.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.iix | 0
A.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.rix | 0
A.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.six | 5+++++
A.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.tix | 0
A.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.cix | 7+++++++
A.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.iix | 0
A.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.rix | 0
A.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.six | 5+++++
A.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.tix | 0
A.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.cix | 0
A.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.iix | 0
A.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.rix | 0
A.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.six | 5+++++
A.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.tix | 9+++++++++
A.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.cix | 7+++++++
A.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.iix | 0
A.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.rix | 0
A.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.six | 5+++++
A.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.tix | 0
A.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.cix | 0
A.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.iix | 0
A.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.rix | 0
A.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.six | 5+++++
A.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.tix | 0
A.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.cix | 0
A.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.iix | 0
A.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.rix | 0
A.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.six | 5+++++
A.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.tix | 0
A.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.cix | 7+++++++
A.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.iix | 0
A.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.rix | 0
A.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.six | 5+++++
A.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.tix | 0
A.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.cix | 12++++++++++++
A.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.iix | 0
A.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.rix | 0
A.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.six | 5+++++
A.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.tix | 0
A.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.cix | 7+++++++
A.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.iix | 0
A.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.rix | 0
A.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.six | 5+++++
A.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.tix | 10++++++++++
A.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.cix | 0
A.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.iix | 0
A.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.rix | 0
A.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.six | 5+++++
A.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.tix | 0
A.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.cix | 0
A.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.iix | 0
A.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.rix | 0
A.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.six | 5+++++
A.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.tix | 0
A.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.cix | 7+++++++
A.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.iix | 8++++++++
A.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.pack | 0
A.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.rix | 0
A.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.six | 5+++++
A.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.tix | 0
A.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.cix | 0
A.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.iix | 0
A.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.pack | 0
A.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.rix | 0
A.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.six | 5+++++
A.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.tix | 8++++++++
A.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.cix | 0
A.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.iix | 0
A.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.pack | 0
A.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.rix | 0
A.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.six | 5+++++
A.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.tix | 0
A.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.cix | 0
A.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.iix | 0
A.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.pack | 0
A.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.rix | 0
A.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.six | 5+++++
A.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.tix | 0
A.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.cix | 0
A.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.iix | 0
A.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.pack | 0
A.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.rix | 0
A.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.six | 5+++++
A.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.tix | 0
A.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.cix | 7+++++++
A.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.iix | 0
A.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.pack | 0
A.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.rix | 0
A.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.six | 5+++++
A.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.tix | 0
A.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.cix | 0
A.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.iix | 0
A.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.pack | 0
A.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.rix | 0
A.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.six | 5+++++
A.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.tix | 0
A.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.cix | 8++++++++
A.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.iix | 0
A.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.pack | 0
A.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.rix | 0
A.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.six | 5+++++
A.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.tix | 0
A.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.cix | 0
A.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.iix | 0
A.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.pack | 0
A.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.rix | 0
A.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.six | 5+++++
A.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.tix | 10++++++++++
A.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.cix | 0
A.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.iix | 0
A.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.pack | 0
A.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.rix | 0
A.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.six | 5+++++
A.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.tix | 0
A.bzr/repository/pack-names | 0
A.bzr/repository/packs/037263fdedbf45fffcfe6dd8efa76bb8.pack | 0
A.bzr/repository/packs/3842963d0d72724190e27bd55f601203.pack | 0
A.bzr/repository/packs/42cee61c0355fb0cd28fcdbbf8262763.pack | 0
A.bzr/repository/packs/5c4f812fbeabcbfec04fdd059fd19cba.pack | 0
A.bzr/repository/packs/897caeb05199b27ece69492c28df63ba.pack | 0
A.bzr/repository/packs/95c256dac521a93af7ac90004cfd6295.pack | 0
A.bzr/repository/packs/9e8be04edf7a3de81e96c0f134ac5856.pack | 0
A.bzr/repository/packs/cf8cbec562d46ff49fa70afdf3e718a7.pack | 0
A.bzr/repository/packs/d09d56bcfed72df64e6a6b90a82df7ec.pack | 0
A.bzr/repository/packs/d285aa05c541e9984c92ac902761275c.pack | 0
A.bzr/repository/packs/e69f55fe122639a8c252f18d55f11dea.pack | 0
A.bzr/repository/packs/f51030c58a83f4360b8a9b6fe797c2fe.pack | 0
A.bzr/repository/packs/f7a959a68aee021a47f587adb4343790.pack | 0
A.bzr/repository/shared-storage | 0
ABubbles!.py | 32++++++++++++++++++++++++++++++++
ACatherine wheel.py | 40++++++++++++++++++++++++++++++++++++++++
AControlled Eruption.py | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADocumentation/.bzr/README | 3+++
ADocumentation/.bzr/branch-format | 1+
ADocumentation/.bzr/branch/branch.conf | 2++
ADocumentation/.bzr/branch/format | 1+
ADocumentation/.bzr/branch/last-revision | 1+
ADocumentation/.bzr/branch/tags | 0
ADocumentation/.bzr/checkout/conflicts | 1+
ADocumentation/.bzr/checkout/dirstate | 0
ADocumentation/.bzr/checkout/format | 1+
ADocumentation/.bzr/checkout/views | 0
ADocumentation/Instruction manual - template.odt | 0
ADocumentation/Instruction manual 1.0.pdf | 0
ADocumentation/Instruction manual WIP.pdf | 0
ADocumentation/Instruction manual.odt | 0
ADocumentation/Instruction manual.pdf | 0
ADocumentation/Instructions cover (Beta 2).png | 0
ADocumentation/Instructions cover OLD.png | 0
ADocumentation/Instructions cover OLD.xcf | 0
ADocumentation/Instructions cover.png | 0
ADocumentation/Instructions cover.xcf | 0
AFile format faffery.xml | 50++++++++++++++++++++++++++++++++++++++++++++++++++
AFire.ppe | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AGravity test.py | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyframe selector widget testery.py | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALine counter.py | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AName ideas.txt | 17+++++++++++++++++
AObsidian frame pointer.svg | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AObsidian keyframe pointer.svg | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AOld branding/Branding image 1 (small).png | 0
AOld branding/Branding image 1.png | 0
AOld branding/Branding image 1.xcf | 0
APPE (Pygame Particle Effect) file format.xml | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
APyIgnition ravery.zip | 0
APyIgnition test - fire.py | 45+++++++++++++++++++++++++++++++++++++++++++++
APyIgnition test.ppe | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
APyIgnition.py | 739+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
APyIgnition.pyc | 0
AReleases/Particle engine.7z | 0
AReleases/PyIgnition alpha 1.7z | 0
AReleases/PyIgnition alpha 2-and-a-bit.zip | 0
AReleases/PyIgnition alpha 2.zip | 0
AReleases/PyIgnition alpha 3.zip | 0
AReleases/PyIgnition beta 1.zip | 0
AReleases/PyIgnition beta 2.zip | 0
AReleases/PyIgnition version 1.zip | 0
AScreenshots and branding/Alpha 1 promo.jpg | 0
AScreenshots and branding/Alpha 1 promo.xcf | 0
AScreenshots and branding/Alpha 3 promo.jpg | 0
AScreenshots and branding/Alpha 3 promo.xcf | 0
AScreenshots and branding/Another vortex demo.jpg | 0
AScreenshots and branding/Beta 2 promo A.png | 0
AScreenshots and branding/Beta 2 promo A.xcf | 0
AScreenshots and branding/Branding image 1.xcf | 0
AScreenshots and branding/Bubbles demo.png | 0
AScreenshots and branding/Catherine wheel.png | 0
AScreenshots and branding/Controlled Eruption.jpg | 0
AScreenshots and branding/Controlled Eruption.png | 0
AScreenshots and branding/Features list.txt | 20++++++++++++++++++++
AScreenshots and branding/Fiiiire!.png | 0
AScreenshots and branding/First tangible demo.png | 0
AScreenshots and branding/Flames with Physics.png | 0
AScreenshots and branding/Logo 1.png | 0
AScreenshots and branding/Logo 1.xcf | 0
AScreenshots and branding/Logo 2.png | 0
AScreenshots and branding/Logo 2.xcf | 0
AScreenshots and branding/Logo 3.png | 0
AScreenshots and branding/Logo 3.xcf | 0
AScreenshots and branding/Magical keyframed colours.png | 0
AScreenshots and branding/More physicsy fire.jpg | 0
AScreenshots and branding/Promo large.jpg | 0
AScreenshots and branding/Promo large.xcf | 0
AScreenshots and branding/PyIgnition cushion distance before-after/After.jpg | 0
AScreenshots and branding/PyIgnition cushion distance before-after/Before-after.png | 0
AScreenshots and branding/PyIgnition cushion distance before-after/Before-after.xcf | 0
AScreenshots and branding/PyIgnition cushion distance before-after/Before.jpg | 0
AScreenshots and branding/The mad effects of gravity.png | 0
AScreenshots and branding/Vortex gravity!.jpg | 0
AScreenshots and branding/Water.png | 0
AScreenshots and branding/Wind.png | 0
ASpark.png | 0
ATest load.py | 29+++++++++++++++++++++++++++++
ATest.xml | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AVortex gravity test.py | 35+++++++++++++++++++++++++++++++++++
AWater.ppe | 216+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AWater.py | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
AWind.py | 33+++++++++++++++++++++++++++++++++
Aconstants.py | 29+++++++++++++++++++++++++++++
Aconstants.pyc | 0
Acourbd.ttf | 0
Aeuphemia.ttf | 0
Aframepointer.png | 0
Agravity.py | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agravity.pyc | 0
Ainterpolate.py | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainterpolate.pyc | 0
Akeyframepointer.png | 0
Akeyframes test.py | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Akeyframes.py | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Akeyframes.pyc | 0
Aobstacles.py | 405+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aobstacles.pyc | 0
Aparticles.py | 202+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aparticles.pyc | 0
Apygamedisplay.pyc | 0
Atimelinectrl.pyc | 0
Atrunk/.bzr/README | 3+++
Atrunk/.bzr/branch-format | 1+
Atrunk/.bzr/branch/branch.conf | 0
Atrunk/.bzr/branch/format | 1+
Atrunk/.bzr/branch/last-revision | 1+
Atrunk/.bzr/branch/tags | 0
Atrunk/.bzr/checkout/conflicts | 1+
Atrunk/.bzr/checkout/dirstate | 0
Atrunk/.bzr/checkout/format | 1+
Atrunk/.bzr/checkout/views | 0
Awx test 2.py | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awx test.py | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Axml.py | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Axml.pyc | 0
274 files changed, 4011 insertions(+), 0 deletions(-)

diff --git a/.bzr/README b/.bzr/README @@ -0,0 +1,3 @@ +This is a Bazaar control directory. +Do not change any files in this directory. +See http://bazaar-vcs.org/ for more information about Bazaar. diff --git a/.bzr/branch-format b/.bzr/branch-format @@ -0,0 +1 @@ +Bazaar-NG meta directory, format 1 diff --git a/.bzr/branch/branch.conf b/.bzr/branch/branch.conf @@ -0,0 +1,3 @@ +push_location = bzr+ssh://bazaar.launchpad.net/~animatinator/flint/trunk/ +parent_location = bzr+ssh://bazaar.launchpad.net/~animatinator/flint/trunk/ +[commit_data] diff --git a/.bzr/branch/format b/.bzr/branch/format @@ -0,0 +1 @@ +Bazaar Branch Format 7 (needs bzr 1.6) diff --git a/.bzr/branch/last-revision b/.bzr/branch/last-revision @@ -0,0 +1 @@ +49 animatinator@gmail.com-20100828173501-5fcod1b3dx31fbl8 diff --git a/.bzr/branch/tags b/.bzr/branch/tags diff --git a/.bzr/checkout/conflicts b/.bzr/checkout/conflicts @@ -0,0 +1 @@ +BZR conflict list format 1 diff --git a/.bzr/checkout/dirstate b/.bzr/checkout/dirstate Binary files differ. diff --git a/.bzr/checkout/format b/.bzr/checkout/format @@ -0,0 +1 @@ +Bazaar Working Tree Format 6 (bzr 1.14) diff --git a/.bzr/checkout/merge-hashes b/.bzr/checkout/merge-hashes @@ -0,0 +1 @@ +BZR merge-modified list format 1 diff --git a/.bzr/checkout/views b/.bzr/checkout/views diff --git a/.bzr/repository/format b/.bzr/repository/format @@ -0,0 +1 @@ +Bazaar repository format 2a (needs bzr 1.16 or later) diff --git a/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.cix b/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.cix Binary files differ. diff --git a/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.iix b/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.iix Binary files differ. diff --git a/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.rix b/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.rix Binary files differ. diff --git a/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.six b/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.tix b/.bzr/repository/indices/037263fdedbf45fffcfe6dd8efa76bb8.tix Binary files differ. diff --git a/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.cix b/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.cix Binary files differ. diff --git a/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.iix b/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.iix Binary files differ. diff --git a/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.rix b/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.rix Binary files differ. diff --git a/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.six b/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.tix b/.bzr/repository/indices/3842963d0d72724190e27bd55f601203.tix Binary files differ. diff --git a/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.cix b/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.cix Binary files differ. diff --git a/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.iix b/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.iix Binary files differ. diff --git a/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.rix b/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.rix Binary files differ. diff --git a/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.six b/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.tix b/.bzr/repository/indices/42cee61c0355fb0cd28fcdbbf8262763.tix Binary files differ. diff --git a/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.cix b/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.cix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=1 +row_lengths=1 +xœ Ç1€ PfNÁ°”Öšx˜Ò|âà`¢‹·×·½ç½°Ÿð™ï×MbºJSÖøc\ÙF8Pn+Á0%ZJÔ•Šr/µuË5î¿+ \ No newline at end of file diff --git a/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.iix b/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.iix Binary files differ. diff --git a/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.rix b/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.rix Binary files differ. diff --git a/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.six b/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.tix b/.bzr/repository/indices/5c4f812fbeabcbfec04fdd059fd19cba.tix Binary files differ. diff --git a/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.cix b/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.cix Binary files differ. diff --git a/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.iix b/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.iix Binary files differ. diff --git a/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.rix b/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.rix Binary files differ. diff --git a/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.six b/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.tix b/.bzr/repository/indices/897caeb05199b27ece69492c28df63ba.tix @@ -0,0 +1,8 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=2 +len=2 +row_lengths=1 +xœµÏ;nÃ0PÕ>….@c¹¤¸daÀWÙPTÀDü@¢-+§W\:Ý43ƒ×öNsàéóÚ–‹o±äÄùÂó±ŒAD‰¨'<]¿dHN› ˾ +ÕqŽ‰[ÌÜÊrþLç£/éQ´R¢’N[Q·o¾má£þ¸AÑ +ݽi#æ0Au¹jãíIwV‘í Õ@ØÃ=8zA®ãÓ€¸5qq |‚-Á.äûÈïy{MÖØÿ©•¹sQYB<ü73–´+ \ No newline at end of file diff --git a/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.cix b/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.cix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=2 +row_lengths=1 +xœ%ÌÁ Â0 О;EF°bÇAb˜ÄµÅC¥ra{¼Þë}Æý3÷ë1ùÆÚAs­ŒÌl’=Ѫ‚—÷Pï>M°hÛ@ÐfR £P1Ô€Àõ.¬FWjž’γ:þ d`ý<ÐöÙõ$w+ \ No newline at end of file diff --git a/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.iix b/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.iix Binary files differ. diff --git a/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.rix b/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.rix Binary files differ. diff --git a/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.six b/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.tix b/.bzr/repository/indices/95c256dac521a93af7ac90004cfd6295.tix Binary files differ. diff --git a/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.cix b/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.cix Binary files differ. diff --git a/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.iix b/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.iix Binary files differ. diff --git a/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.rix b/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.rix Binary files differ. diff --git a/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.six b/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.tix b/.bzr/repository/indices/9e8be04edf7a3de81e96c0f134ac5856.tix Binary files differ. diff --git a/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.cix b/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.cix Binary files differ. diff --git a/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.iix b/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.iix Binary files differ. diff --git a/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.rix b/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.rix Binary files differ. diff --git a/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.six b/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.tix b/.bzr/repository/indices/cf8cbec562d46ff49fa70afdf3e718a7.tix Binary files differ. diff --git a/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.cix b/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.cix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=1 +row_lengths=1 +xœÁÁ € PÎLÁZ~1q˜Ò@8x0Ñ‹ÛûÞûÝ󼦭ølË ÃTÀl˳Íæ2H›Ãàƒt¡… ¹ÕÖD©éñÈ + \ No newline at end of file diff --git a/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.iix b/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.iix Binary files differ. diff --git a/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.rix b/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.rix Binary files differ. diff --git a/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.six b/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.tix b/.bzr/repository/indices/d09d56bcfed72df64e6a6b90a82df7ec.tix Binary files differ. diff --git a/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.cix b/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.cix @@ -0,0 +1,11 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=12 +row_lengths=1 +xœU’;Ž1 D'ÞSôø§hÀ‡‘( +80`'¾½9ÛÌD +¤z*Vñï¿ßõóWÍóñçsâ ã•z $üÌ‚(ZiL¶jÇÊi¤Ë +Ñ‹ˆãº$Ô¾®†¨à2&jùšn {¹@¦Ø~C´úR¤¸T:­r!ëØÖ6Žƒ×*µÂ1O_¼"x_ƒnã^;Ùq™”+^ûøŽHwY£ö¤zsÁl—(èó$`©˜x™ƒ €†’$îê‰(û5>ŠC.6ºà +„[­:E&êSK$Yîœ +S9Ç&Šüf ÿþŠóF¦Å>ªÑ¾1au#(É{áÜg®EýÉyEÀ…Æò­:Ó[iGgÍ cæ¹»ÜåÏ™ºŒF&¾êŸê¯,oDØ8wËaQD±Žeg€÷\YÃk ·— :«qßúÃrÉæò´]¤ÍÌÀ³ÁŸ%7Å_-<÷àRQ¿ƒ7ÛŒ!†V#pd!õÔ¤=ß–¡÷à«ÎqV§´2NVw±Ç2AqfÍÙë`tzysÑ.5ÿe¦Æ•+ \ No newline at end of file diff --git a/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.iix b/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.iix Binary files differ. diff --git a/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.rix b/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.rix Binary files differ. diff --git a/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.six b/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.tix b/.bzr/repository/indices/d285aa05c541e9984c92ac902761275c.tix Binary files differ. diff --git a/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.cix b/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.cix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=1 +row_lengths=1 +xœÁÁ € PÎLÁðm ˜8 -4<˜èÅí}ïýîu\kx|ÎQvØ’¹˜6íÄIÃј ŧ©gSE'³j‘–ª åHŽ?4ÉÍ+ \ No newline at end of file diff --git a/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.iix b/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.iix Binary files differ. diff --git a/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.rix b/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.rix Binary files differ. diff --git a/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.six b/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.tix b/.bzr/repository/indices/e69f55fe122639a8c252f18d55f11dea.tix @@ -0,0 +1,9 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=2 +len=3 +row_lengths=1 +xœ­‘Anƒ0DYs +.àèÛßØ‹J½Š Äq¶“N_W]´«.¢lf3==MÞÓð6ö\w1¬Ù†¼žÒÎ8 @[² +Z¶¥Lø¸“;Àj†• ~²Ù›ãòî&ëÇS§Ÿ¡FB!„Ô,Ç®ÍC^z7Ƶz!¥åJJÎÔ´Drér3¼ÿ¨”BjˆDVºNvɾ‡_hÁqŽ¦l×+Ð6¹3úåŠ÷õ`Ϻ½ +'Òl3’æû:º…Ãu¾’¥h¸Ôßv¨N»wÁgòA"DÅnp™í؃ßÛI~Šç¿{)æ?ÞÈ¢Uì¸ë/V)Ïs+ \ No newline at end of file diff --git a/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.cix b/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.cix Binary files differ. diff --git a/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.iix b/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.iix Binary files differ. diff --git a/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.rix b/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.rix Binary files differ. diff --git a/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.six b/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.tix b/.bzr/repository/indices/f51030c58a83f4360b8a9b6fe797c2fe.tix Binary files differ. diff --git a/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.cix b/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.cix Binary files differ. diff --git a/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.iix b/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.iix Binary files differ. diff --git a/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.rix b/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.rix Binary files differ. diff --git a/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.six b/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.tix b/.bzr/repository/indices/f7a959a68aee021a47f587adb4343790.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.cix b/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.cix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=2 +row_lengths=1 +xœ%̱ 1 Pê›"#Ø9ÇùFbÇg‹‚ ¶ç¼÷þ<óöH¯íuw¾š¢’1<iu3‘8ÀXZ é2"1˜z¹0ƒ­íDXÿ¼–H­°Š”‘k2ˆÓ`t·˜Úë\äÇÙö¦]OÞ‰Çö0 #`+ \ No newline at end of file diff --git a/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.iix b/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.iix @@ -0,0 +1,7 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=1 +len=1 +row_lengths=1 +xœ…ËM Ю{ +.€ù` ÀÂÄ«L¬cø1†ÔØÓ׸y»7¾¯|-™ï37©<¤ñèïÛVYÊeíU[ üŒÕí~Y$¹Ò×4ýk€t .‡GAµÏ}CŠ“±Æ$e½WP7ŸËã(<+ \ No newline at end of file diff --git a/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.pack b/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.rix b/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.six b/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.tix b/.bzr/repository/obsolete_packs/0dfafd3ab74947c640507e99578669ee.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.cix b/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.iix b/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.pack b/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.rix b/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.six b/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.tix b/.bzr/repository/obsolete_packs/13d90736ea56ba05c2b982df1734f323.tix @@ -0,0 +1,7 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=2 +len=2 +row_lengths=1 +xœ­ÏK‚0…aƬ‚ Ôôöu™˜¸•[‚H¥´ eõ21N'gvòåÏ%õÇ©§sÝÅpÏòý +8Ç}QŽlIYÃó"‡˜†SË ¢0zÊc o§ÁÓ8ºèßGJµÙm^¼qÛzNëµn­þ­¡[æ‡-.…Š%~™Æ2Wn”Q oCínvSÿA hZ3¯ÜÃâìÊýžöoå{šD!÷20­ÁúS‹²+ \ No newline at end of file diff --git a/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.cix b/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.iix b/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.pack b/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.rix b/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.six b/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.tix b/.bzr/repository/obsolete_packs/18c8c00231d937612e58794548b4282f.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.cix b/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.iix b/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.pack b/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.rix b/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.six b/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.tix b/.bzr/repository/obsolete_packs/20090a6d210167bb07c9b5ff82649905.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.cix b/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.iix b/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.pack b/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.rix b/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.six b/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.tix b/.bzr/repository/obsolete_packs/28084ffd8e1981446f25087627e8f29d.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.cix b/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.cix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=1 +row_lengths=1 +xœÁÁ € PÎLÁ-H?˜8 ¥%<˜èÅí}ïýn?.+>ç཰©ÍV©™K¼(“-XïØ´¹ì!H%AK”2q?0åª+ \ No newline at end of file diff --git a/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.iix b/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.pack b/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.rix b/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.six b/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.tix b/.bzr/repository/obsolete_packs/547a7eb0dc00e0416cf4d48627566cda.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.cix b/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.iix b/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.pack b/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.rix b/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.six b/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.tix b/.bzr/repository/obsolete_packs/5ae54c73bf793a1c627b0826a2ee78ac.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.cix b/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.cix @@ -0,0 +1,7 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=1 +row_lengths=1 +xœ ɱ €@ЫoŠPà4qÔO,,L´q{}í{Þ Ë‰ÈzÁ³@ð­<hß-édé +8©{䟕Â2ª73mÔ„XëM‡Ø+ \ No newline at end of file diff --git a/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.iix b/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.pack b/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.rix b/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.six b/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.tix b/.bzr/repository/obsolete_packs/fa57d22467a3bb91f2fe125ff6c5cc4b.tix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.cix b/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.iix b/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.pack b/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.rix b/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.six b/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.tix b/.bzr/repository/obsolete_packs/fb1b0fcc722d626507ec8256501bcce0.tix @@ -0,0 +1,9 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=2 +len=3 +row_lengths=1 +xœ­‘KŽƒ0DYs +.àÈÝþÁ"Ò\Å$Àc°§G³™ÙFl[*½W]iŸ»ëÔé¾ mLú6uñ2ï)P*Aà q|ÜZõð­Uc‹|$PhoœNÆëÖ¯Ái3]nÁýŠœj8'—€q[_­«;kâT +…šÕ™²‰Ã°§Ò4| +·¦àX1ÎyE+ÈW(g½&óŸšãoÅh©x¸¡³ZØâA€~Zîd ¥,ë“V‰>õ¡V>tqï…¤ÐT˜5r¿¦,çÝ Þ$üp“-$y¾ü÷¢§;5»ÊfŸow6óì@ÜhÙ3úɯvØùâ ÆkY¡`ì=Ãò)¯Î·+ \ No newline at end of file diff --git a/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.cix b/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.cix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.iix b/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.iix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.pack b/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.pack Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.rix b/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.rix Binary files differ. diff --git a/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.six b/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.tix b/.bzr/repository/obsolete_packs/fbc203ae04fcda2acb2ad332afadc98a.tix Binary files differ. diff --git a/.bzr/repository/pack-names b/.bzr/repository/pack-names Binary files differ. diff --git a/.bzr/repository/packs/037263fdedbf45fffcfe6dd8efa76bb8.pack b/.bzr/repository/packs/037263fdedbf45fffcfe6dd8efa76bb8.pack Binary files differ. diff --git a/.bzr/repository/packs/3842963d0d72724190e27bd55f601203.pack b/.bzr/repository/packs/3842963d0d72724190e27bd55f601203.pack Binary files differ. diff --git a/.bzr/repository/packs/42cee61c0355fb0cd28fcdbbf8262763.pack b/.bzr/repository/packs/42cee61c0355fb0cd28fcdbbf8262763.pack Binary files differ. diff --git a/.bzr/repository/packs/5c4f812fbeabcbfec04fdd059fd19cba.pack b/.bzr/repository/packs/5c4f812fbeabcbfec04fdd059fd19cba.pack Binary files differ. diff --git a/.bzr/repository/packs/897caeb05199b27ece69492c28df63ba.pack b/.bzr/repository/packs/897caeb05199b27ece69492c28df63ba.pack Binary files differ. diff --git a/.bzr/repository/packs/95c256dac521a93af7ac90004cfd6295.pack b/.bzr/repository/packs/95c256dac521a93af7ac90004cfd6295.pack Binary files differ. diff --git a/.bzr/repository/packs/9e8be04edf7a3de81e96c0f134ac5856.pack b/.bzr/repository/packs/9e8be04edf7a3de81e96c0f134ac5856.pack Binary files differ. diff --git a/.bzr/repository/packs/cf8cbec562d46ff49fa70afdf3e718a7.pack b/.bzr/repository/packs/cf8cbec562d46ff49fa70afdf3e718a7.pack Binary files differ. diff --git a/.bzr/repository/packs/d09d56bcfed72df64e6a6b90a82df7ec.pack b/.bzr/repository/packs/d09d56bcfed72df64e6a6b90a82df7ec.pack Binary files differ. diff --git a/.bzr/repository/packs/d285aa05c541e9984c92ac902761275c.pack b/.bzr/repository/packs/d285aa05c541e9984c92ac902761275c.pack Binary files differ. diff --git a/.bzr/repository/packs/e69f55fe122639a8c252f18d55f11dea.pack b/.bzr/repository/packs/e69f55fe122639a8c252f18d55f11dea.pack Binary files differ. diff --git a/.bzr/repository/packs/f51030c58a83f4360b8a9b6fe797c2fe.pack b/.bzr/repository/packs/f51030c58a83f4360b8a9b6fe797c2fe.pack Binary files differ. diff --git a/.bzr/repository/packs/f7a959a68aee021a47f587adb4343790.pack b/.bzr/repository/packs/f7a959a68aee021a47f587adb4343790.pack Binary files differ. diff --git a/.bzr/repository/shared-storage b/.bzr/repository/shared-storage diff --git a/Bubbles!.py b/Bubbles!.py @@ -0,0 +1,32 @@ +# Bubbles! + +import PyIgnition, pygame, sys, math + + +screen = pygame.display.set_mode((800, 600)) +pygame.display.set_caption("PyIgnition demo: bubbles") +clock = pygame.time.Clock() + +effect = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +source = effect.CreateSource(initspeed = 1.0, initdirection = 0.0, initspeedrandrange = 0.5, initdirectionrandrange = math.pi, particlelife = 1000, colour = (200, 255, 200), drawtype = PyIgnition.DRAWTYPE_BUBBLE, radius = 4.0) +source.CreateParticleKeyframe(500, colour = (250, 100, 250)) +source.CreateParticleKeyframe(75, colour = (190, 190, 200)) +source.CreateParticleKeyframe(100, colour = (50, 250, 252)) +source.CreateParticleKeyframe(125, colour = (250, 250, 255)) +effect.CreateDirectedGravity(strength = 0.04, direction = [0, -1]) + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + elif event.type == pygame.MOUSEBUTTONDOWN: + source.CreateKeyframe(source.curframe + 1, pos = pygame.mouse.get_pos(), particlesperframe = 1) + source.CreateKeyframe(source.curframe + 2, pos = pygame.mouse.get_pos(), particlesperframe = 0) + + screen.fill((100, 150, 255)) + effect.Update() + effect.Redraw() + pygame.display.update() + clock.tick(30) diff --git a/Catherine wheel.py b/Catherine wheel.py @@ -0,0 +1,40 @@ +# Catherine wheel + +import PyIgnition, pygame, sys + + +screen = pygame.display.set_mode((600, 600)) +pygame.display.set_caption("PyIgnition demo: catherine wheel") +clock = pygame.time.Clock() + +wheel = PyIgnition.ParticleEffect(screen, (0, 0), (600, 600)) +flame = wheel.CreateSource((300, 300), initspeed = 20.0, initdirection = 0.0, initspeedrandrange = 0.0, initdirectionrandrange = 0.5, particlesperframe = 3, particlelife = 50, drawtype = PyIgnition.DRAWTYPE_SCALELINE, colour = (255, 200, 200), length = 20.0) +sparks = wheel.CreateSource((300, 300), initspeed = 1.0, initdirection = 0.0, initspeedrandrange = 0.9, initdirectionrandrange = 3.141592653, particlesperframe = 1, particlelife = 300, genspacing = 3, drawtype = PyIgnition.DRAWTYPE_IMAGE, imagepath = "spark.png") +wheel.CreateDirectedGravity(strength = 0.05, direction = [0, 1]) + +velocity = 0.1 +maxvelocity = 0.5 +acceleration = 0.001 + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_s: + wheel.SaveToFile("Test.xml") + + flame.SetInitDirection(flame.initdirection + velocity) + if flame.curframe % 30 == 0: + flame.ConsolidateKeyframes() + + if velocity <= maxvelocity: + velocity += acceleration + + screen.fill((10, 0, 50)) + wheel.Update() + wheel.Redraw() + pygame.display.update() + clock.tick(30) diff --git a/Controlled Eruption.py b/Controlled Eruption.py @@ -0,0 +1,163 @@ +# Controlled Eruption - PyIgnition beta 1 demo +# Copyright David Barker 2010 +# +# Be forewarned - this is quite possibly the messiest code you will see all year. +# Let this mess be a lesson to those who try tostart coding without deciding +# what they're going to code beforehand... + +import PyIgnition, pygame, sys, math, random + + +pygame.font.init() +screen = pygame.display.set_mode((800, 600)) +pygame.display.set_caption("PyIgnition 'Controlled Eruption' demo") +clock = pygame.time.Clock() + +curframe = 0 +started = False + +# 'Press space to start' text +starttextfont = pygame.font.Font("courbd.ttf", 50) +starttext = starttextfont.render("Press space to start", True, (255, 255, 255), (0, 0, 0)) +starttextpos = ((400 - (starttext.get_width() / 2)), (300 - (starttext.get_height() / 2))) + +# Background +background = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +backgroundsource = background.CreateSource((10, 10), initspeed = 5.0, initdirection = 2.35619449, initspeedrandrange = 2.0, initdirectionrandrange = 1.0, particlesperframe = 5, particlelife = 125, drawtype = PyIgnition.DRAWTYPE_SCALELINE, colour = (255, 255, 255), length = 10.0) +backgroundsource.CreateParticleKeyframe(50, colour = (0, 255, 0), length = 10.0) +backgroundsource.CreateParticleKeyframe(75, colour = (255, 255, 0), length = 10.0) +backgroundsource.CreateParticleKeyframe(100, colour = (0, 255, 255), length = 10.0) +backgroundsource.CreateParticleKeyframe(125, colour = (0, 0, 0), length = 10.0) +backgroundsource2 = background.CreateSource((790, 10), initspeed = 5.0, initdirection = -2.35619449, initspeedrandrange = 2.0, initdirectionrandrange = 1.0, particlesperframe = 0, particlelife = 125, drawtype = PyIgnition.DRAWTYPE_SCALELINE, colour = (255, 255, 255), length = 10.0) +backgroundsource2.CreateParticleKeyframe(50, colour = (0, 255, 0), length = 10.0) +backgroundsource2.CreateParticleKeyframe(75, colour = (255, 255, 0), length = 10.0) +backgroundsource2.CreateParticleKeyframe(100, colour = (0, 255, 255), length = 10.0) +backgroundsource2.CreateParticleKeyframe(125, colour = (0, 0, 0), length = 10.0) + +# Periodic firework +fireworkcounter = 0.0 +fireworkdist = 200.0 +firework = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +firework.CreateDirectedGravity(strength = 0.2, direction = [0, 1]) +fireworksource = firework.CreateSource((10, 10), initspeed = 8.0, initdirection = 0.0, initspeedrandrange = 2.0, initdirectionrandrange = math.pi, particlesperframe = 0, particlelife = 150, drawtype = PyIgnition.DRAWTYPE_IMAGE, imagepath = "Spark.png") +fireworkblast = background.CreateCircle(pos = (1000, 1000), colour = (0, 0, 0), bounce = 1.5, radius = 100.0) + +# Ground-level bubbles +bubbles = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +bubblesource = bubbles.CreateSource(initspeed = 1.0, initdirection = 0.0, initspeedrandrange = 0.5, initdirectionrandrange = math.pi, particlesperframe = 0, particlelife = 200, colour = (200, 255, 200), drawtype = PyIgnition.DRAWTYPE_BUBBLE, radius = 5.0, genspacing = 5) +bubblesource.CreateParticleKeyframe(500, colour = (250, 100, 250)) +bubblesource.CreateParticleKeyframe(75, colour = (190, 190, 200)) +bubblesource.CreateParticleKeyframe(100, colour = (50, 250, 252)) +bubblesource.CreateParticleKeyframe(125, colour = (250, 250, 255)) +bubbles.CreateDirectedGravity(strength = 0.04, direction = [0, -1]) + +# Fire, just for laughs +fire = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +gravity = fire.CreateDirectedGravity(strength = 0.07, direction = [0, -1]) +wind = fire.CreateDirectedGravity(strength = 0.05, direction = [1, 0]) +source = fire.CreateSource((150, 500), initspeed = 2.0, initdirection = 0.0, initspeedrandrange = 1.0, initdirectionrandrange = 0.5, particlesperframe = 10, particlelife = 100, drawtype = PyIgnition.DRAWTYPE_CIRCLE, colour = (255, 200, 100), radius = 3.0) +source.CreateParticleKeyframe(10, colour = (200, 50, 20), radius = 4.0) +source.CreateParticleKeyframe(30, colour = (150, 0, 0), radius = 6.0) +source.CreateParticleKeyframe(60, colour = (50, 20, 20), radius = 20.0) +source.CreateParticleKeyframe(80, colour = (0, 0, 0), radius = 50.0) + +# Text +font = pygame.font.Font("euphemia.ttf", 70) +font2 = pygame.font.Font("euphemia.ttf", 40) +text = font.render("PyIgnition", True, (255, 255, 255), (0, 0, 0)) +text2 = font2.render("ExeSoft", True, (200, 200, 200), (0, 0, 0)) +textalpha = font.render("PyIgnition", True, (255, 255, 255)) +text2alpha = font2.render("ExeSoft", True, (200, 200, 200)) +temptext = text.copy() +temptext2 = text2.copy() +temptext.set_alpha(0) +temptext2.set_alpha(0) +textpos = ((400 - (text.get_width() / 2)), 250) +textpos2 = (textpos[0] + 110, textpos[1] - 30) +font3 = pygame.font.Font("courbd.ttf", 20) +text3 = font3.render("Version 1.0", True, (200, 200, 255), (0, 0, 0)) +textpos3 = ((800 - text3.get_width()) - 5, (600 - text3.get_height())) + + +def Update(): + global curframe, fireworkcounter, temptext, temptext2 + + background.Update() + + if curframe == 100: + backgroundsource2.SetParticlesPerFrame(5) + + fireworksource.SetPos((400 + fireworkdist * math.cos(fireworkcounter), 300 + fireworkdist * math.sin(fireworkcounter))) + if (curframe > 200) and (curframe % 50 == 0): + fireworksource.CreateKeyframe(fireworksource.curframe, particlesperframe = 10) + fireworksource.CreateKeyframe(fireworksource.curframe + 4, particlesperframe = 0) + firework.Update() + fireworkblast.SetPos(fireworksource.pos) + fireworksource.ConsolidateKeyframes() + #fireworkblast.ConsolidateKeyframes() + else: + if curframe % 30 == 0: + fireworkblast.ConsolidateKeyframes() + firework.Update() + fireworkblast.SetPos((1000, 1000)) + fireworkcounter = fireworkcounter + 0.1 + + random.seed() + if curframe == 400: + bubblesource.SetParticlesPerFrame(1) + bubbles.Update() + bubblesource.SetPos((random.randint(0, 800), 600)) + if curframe % 30 == 0: + bubblesource.ConsolidateKeyframes() + + if curframe > 500: + fire.Update() + source.SetPos(pygame.mouse.get_pos()) + if curframe % 30 == 0: + source.ConsolidateKeyframes() + + if curframe > 400: + if curframe > 500: + temptext = textalpha.copy() + temptext2 = text2alpha.copy() + else: + factor = (float(curframe) - 400.0) / 100.0 + if factor > 1.0: + factor = 1.0 + alpha = int(factor * 255.0) + temptext = text.copy() + temptext.set_alpha(alpha) + temptext2 = text2.copy() + temptext2.set_alpha(alpha) + + curframe = curframe + 1 + +def Redraw(): + if curframe > 500: + screen.blit(text3, textpos3) + fire.Redraw() + screen.blit(temptext, textpos) + screen.blit(temptext2, textpos2) + background.Redraw() + firework.Redraw() + bubbles.Redraw() + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + started = True + + screen.fill((0, 0, 0)) + + if started: + Update() + Redraw() + else: + screen.blit(starttext, starttextpos) + + pygame.display.update() + clock.tick(30) diff --git a/Documentation/.bzr/README b/Documentation/.bzr/README @@ -0,0 +1,3 @@ +This is a Bazaar control directory. +Do not change any files in this directory. +See http://bazaar-vcs.org/ for more information about Bazaar. diff --git a/Documentation/.bzr/branch-format b/Documentation/.bzr/branch-format @@ -0,0 +1 @@ +Bazaar-NG meta directory, format 1 diff --git a/Documentation/.bzr/branch/branch.conf b/Documentation/.bzr/branch/branch.conf @@ -0,0 +1,2 @@ +push_location = bzr+ssh://bazaar.launchpad.net/~animatinator/pyignition/documentation/ +[commit_data] diff --git a/Documentation/.bzr/branch/format b/Documentation/.bzr/branch/format @@ -0,0 +1 @@ +Bazaar Branch Format 7 (needs bzr 1.6) diff --git a/Documentation/.bzr/branch/last-revision b/Documentation/.bzr/branch/last-revision @@ -0,0 +1 @@ +9 animatinator@gmail.com-20100811231948-pwkaxwebpz9537s0 diff --git a/Documentation/.bzr/branch/tags b/Documentation/.bzr/branch/tags diff --git a/Documentation/.bzr/checkout/conflicts b/Documentation/.bzr/checkout/conflicts @@ -0,0 +1 @@ +BZR conflict list format 1 diff --git a/Documentation/.bzr/checkout/dirstate b/Documentation/.bzr/checkout/dirstate Binary files differ. diff --git a/Documentation/.bzr/checkout/format b/Documentation/.bzr/checkout/format @@ -0,0 +1 @@ +Bazaar Working Tree Format 6 (bzr 1.14) diff --git a/Documentation/.bzr/checkout/views b/Documentation/.bzr/checkout/views diff --git a/Documentation/Instruction manual - template.odt b/Documentation/Instruction manual - template.odt Binary files differ. diff --git a/Documentation/Instruction manual 1.0.pdf b/Documentation/Instruction manual 1.0.pdf Binary files differ. diff --git a/Documentation/Instruction manual WIP.pdf b/Documentation/Instruction manual WIP.pdf Binary files differ. diff --git a/Documentation/Instruction manual.odt b/Documentation/Instruction manual.odt Binary files differ. diff --git a/Documentation/Instruction manual.pdf b/Documentation/Instruction manual.pdf Binary files differ. diff --git a/Documentation/Instructions cover (Beta 2).png b/Documentation/Instructions cover (Beta 2).png Binary files differ. diff --git a/Documentation/Instructions cover OLD.png b/Documentation/Instructions cover OLD.png Binary files differ. diff --git a/Documentation/Instructions cover OLD.xcf b/Documentation/Instructions cover OLD.xcf Binary files differ. diff --git a/Documentation/Instructions cover.png b/Documentation/Instructions cover.png Binary files differ. diff --git a/Documentation/Instructions cover.xcf b/Documentation/Instructions cover.xcf Binary files differ. diff --git a/File format faffery.xml b/File format faffery.xml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> + + <head> + <title>Particle Test</title> + <author>Doove & Joomz</author> + <info>A little particle test down in the park!</info> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + + <filename> + + <ParticleSource> + + <properties> + <drawtype>0</drawtype> + <particleimage>"test.jpg"</particleimage> + </properties> + + <keyframes> + + <keyframe id=0> + <initspeed>20</initspeed> + <initdirection>3.141</initdirection> + <particlesperframe>3</particlesperframe> + </keyframe> + + <keyframe id=200> + <initspeed>2</initspeed> + <initdirection>0</initdirection> + <particlesperframe>50</particlesperframe> + </keyframe> + + </keyframes> + + </ParticleSource> + + <DirectedGravity> + <keyframes> + <keyframe id=0> + <pos>[200, 200]</keyframe> + <direction>[3, 1]</direction> + <strength>20</strength> + </keyframe> + </keyframes> + </DirectedGravity> + + </filename> + +</xml>+ \ No newline at end of file diff --git a/Fire.ppe b/Fire.ppe @@ -0,0 +1,94 @@ +<?xml version = "1.0"?> +<?pyignition version = "1.000000"?> + +<effect> + <source> + <pos>(300, 500)</pos> + <initspeed>2.000000</initspeed> + <initdirection>0.000000</initdirection> + <initspeedrandrange>1.000000</initspeedrandrange> + <initdirectionrandrange>0.500000</initdirectionrandrange> + <particlesperframe>10</particlesperframe> + <particlelife>100</particlelife> + <genspacing>0</genspacing> + <drawtype>circle</drawtype> + <colour>(255, 200, 100)</colour> + <radius>3.000000</radius> + <length>0.000000</length> + <imagepath>None</imagepath> + <keyframes> + </keyframes> + <particlekeyframes> + <keyframe frame = "10"> + <colour_r>200</colour_r> + <length>None</length> + <interpolationtype>linear</interpolationtype> + <radius>4.0</radius> + <colour_b>20</colour_b> + <colour_g>50</colour_g> + </keyframe> + <keyframe frame = "30"> + <colour_r>150</colour_r> + <length>None</length> + <interpolationtype>linear</interpolationtype> + <radius>6.0</radius> + <colour_b>0</colour_b> + <colour_g>0</colour_g> + </keyframe> + <keyframe frame = "60"> + <colour_r>50</colour_r> + <length>None</length> + <interpolationtype>linear</interpolationtype> + <radius>20.0</radius> + <colour_b>20</colour_b> + <colour_g>20</colour_g> + </keyframe> + <keyframe frame = "80"> + <colour_r>0</colour_r> + <length>None</length> + <interpolationtype>linear</interpolationtype> + <radius>50.0</radius> + <colour_b>0</colour_b> + <colour_g>0</colour_g> + </keyframe> + </particlekeyframes> + </source> + + <directedgravity> + <strength>0.070000</strength> + <strengthrandrange>0.000000</strengthrandrange> + <direction>(0.000000, -1.000000)</direction> + <keyframes> + </keyframes> + </directedgravity> + + <directedgravity> + <strength>0.050000</strength> + <strengthrandrange>0.000000</strengthrandrange> + <direction>(1.000000, 0.000000)</direction> + <keyframes> + </keyframes> + </directedgravity> + + <rectangle> + <pos>(400, 100)</pos> + <colour>(200, 100, 100)</colour> + <bounce>0.200000</bounce> + <width>100</width> + <height>20</height> + <keyframes> + <keyframe frame = "500"> + <width>200</width> + <pos_x>400</pos_x> + <pos_y>250</pos_y> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>linear</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + <height>30</height> + </keyframe> + </keyframes> + </rectangle> + +</effect>+ \ No newline at end of file diff --git a/Gravity test.py b/Gravity test.py @@ -0,0 +1,59 @@ +# Gravity test + +import pygame, sys, gravity, math, numpy + + +screen = pygame.display.set_mode((600, 480)) +pygame.display.set_caption("ExeSoft particle engine gravity test") +clock = pygame.time.Clock() + + +# Magnitude of a vector +def mag(v): + return math.sqrt(v[0]**2 + v[1]**2) + +# Draw the supplied gravitational point sources' fields to the supplied surface +def DrawField(sources, surf): + surf.fill((0, 0, 0)) + maxforce = sources[0].GetMaxForce() # Not accurate (should take the largest max force) but bollocks to it + pixels = pygame.surfarray.pixels3d(surf) + + for x in range(0, 600): + for y in range(0, 480): + forcemag = 0 + for source in sources: + forcemag += mag(source.GetForce((x, y))) + + # Map force to colour (chopped at 255) + col = (forcemag * 255.0) / 10.0 + if col > 255.0: + col = 255.0 + + pixels[x][y] = [col, col, col] + + return surf + + +surf = pygame.Surface((600, 480)) +grav = gravity.PointGravity(9.8, (300, 240)) +grav2 = gravity.PointGravity(9.8, (400, 300)) +surf = DrawField([grav, grav2], surf) + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.MOUSEMOTION: + pygame.mouse.get_pos() + + screen.blit(surf, (0, 0)) + + a = pygame.mouse.get_pos() + f = grav.GetForce(a) + g = grav2.GetForce(a) + b = [a[0] + f[0] + g[0], a[1] + f[1] + g[1]] + pygame.draw.aaline(screen, (0, 255, 0), a, b) + + pygame.display.update() + clock.tick(30) diff --git a/Keyframe selector widget testery.py b/Keyframe selector widget testery.py @@ -0,0 +1,153 @@ +import wx + + +class Timeline(wx.Panel): + def __init__(self, parent, id, max_ = 300): + wx.Panel.__init__(self, parent, id, style = wx.NO_BORDER) + self.SetSize((0, 80)) + self.max = max_ + self.curframe = 0 + self.sidepadding = 5 + self.drawpos = (0, 0) + self.size = (0, 0) + self.mousetolerance = 5 + self.dragging = False + self.pointerimg = wx.Image("framepointer.png", wx.BITMAP_TYPE_PNG) + self.pointerbmp = wx.BitmapFromImage(self.pointerimg) + self.keypointerimg = wx.Image("keyframepointer.png", wx.BITMAP_TYPE_PNG) + self.keypointerbmp = wx.BitmapFromImage(self.keypointerimg) + self.keyedframes = [0, 10, 25, 27, 49, 68, 98, 106, 132] + + self.font = wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, False) + + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_LEFT_DOWN, self.OnClick) + self.Bind(wx.EVT_LEFT_UP, self.OnRelease) + self.Bind(wx.EVT_MOTION, self.OnMouseMotion) + + def Update(self, event): + self.curframe += 1 + + def SetMax(self, val): + self.max = val + + def SetCurframe(self, val): + self.curframe = val + + def OnClick(self, event): + p = event.GetPosition() + + foundFrameTarget = False + for frame in self.keyedframes: + drawpos = (self.drawpos[0] + int((float(frame) / float(self.max)) * float(self.size[0])), self.drawpos[1] - (self.keypointerbmp.GetHeight())) + if p[1] > (drawpos[1]) and \ + p[1] < (drawpos[1]+ self.keypointerimg.GetHeight()) and \ + p[0] > (drawpos[0]) and \ + p[0] < (drawpos[0] + self.keypointerbmp.GetWidth()): + self.curframe = frame + foundFrameTarget = True + + if foundFrameTarget: + self.SendSliderEvent() + + if p[1] > (self.drawpos[1] - self.mousetolerance) and \ + p[1] < (self.drawpos[1] + self.size[1] + self.pointerbmp.GetHeight()) and \ + p[0] > (self.drawpos[0] - self.mousetolerance) and \ + p[0] < (self.drawpos[0] + self.size[0] + self.mousetolerance): + self.dragging = True + self.CaptureMouse() + self.OnMouseMotion(event) + + def OnRelease(self, event): + if self.HasCapture(): + self.ReleaseMouse() + self.dragging = False + + def OnMouseMotion(self, event): + if self.dragging: + posx = event.GetPosition()[0] - self.drawpos[0] + if posx >= self.size[0]: + self.curframe = self.max + elif posx <= 0: + self.curframe = 0 + else: + self.curframe = int(float(posx) / float(self.size[0]) * self.max) + self.SendSliderEvent() + + def SendSliderEvent(self): + event = wx.CommandEvent(wx.EVT_SLIDER.typeId, self.GetId()) + event.SetInt(self.curframe) + self.GetEventHandler().ProcessEvent(event) + + def OnPaint(self, event): + self.DoPaint() + + def DoPaint(self): + windc = wx.ClientDC(self) + dc = wx.BufferedDC(windc) + w, h = self.GetSize() + + # Background fill + #dc.Clear() + dc.SetBrush(windc.GetBackground()) + dc.DrawRectangle(0, 0, w, h) + + # Slider bar pos/size calculations + self.drawpos = (self.sidepadding, self.keypointerbmp.GetHeight() + self.sidepadding) + self.size = (w - (self.sidepadding * 2), 4) + + # Slider bar + dc.SetPen(wx.Pen('#000000')) + dc.SetBrush(wx.Brush('#FFFFFF')) + dc.DrawRectangle(self.drawpos[0], self.drawpos[1], self.size[0], self.size[1]) + + # Curframe pointer + pointerpos = ((self.drawpos[0] + int((float(self.size[0]) * (float(self.curframe) / float(self.max))))) - (self.pointerbmp.GetWidth() / 2), self.drawpos[1]) + #dc.DrawRectangle(pointerpos[0], pointerpos[1], self.pointerbmp.GetWidth(), self.pointerbmp.GetHeight()) + dc.DrawBitmap(self.pointerbmp, pointerpos[0], pointerpos[1]) + + # Keyed frame pointers + for frame in self.keyedframes: + drawpos = (self.drawpos[0] + int((float(frame) / float(self.max)) * float(self.size[0])), self.drawpos[1] - (self.keypointerbmp.GetHeight())) + dc.DrawBitmap(self.keypointerbmp, drawpos[0], drawpos[1]) + + # Current frame text + #dc.SetFont(self.font) + string = "Current frame: %i" % self.curframe + stringwidth, stringheight = dc.GetTextExtent(string) + dc.DrawText(string, w - (self.sidepadding + stringwidth), h - (self.sidepadding + stringheight)) + + +class Frame(wx.Frame): + def __init__(self, parent): + wx.Frame.__init__(self, parent, -1) + + self.panel = wx.Panel(self, -1) + self.timeline = Timeline(self.panel, -1) + + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.sizer.Add(self.timeline, 0, flag = wx.EXPAND) + + self.panel.SetSizer(self.sizer) + self.Layout() + self.timeline.SetMax(150) + + self.Bind(wx.EVT_CLOSE, self.Exit) + self.Bind(wx.EVT_SLIDER, self.Slider) + + def Exit(self, event): + self.timeline.Destroy() + self.Destroy() + + def Slider(self, event): + pass#print "Frame = %i" % event.GetInt()) + + +if __name__ == "__main__": + app = wx.PySimpleApp() + frame = Frame(None) + frame.SetTitle("ExeSoft Obsidian - timeline widget test") + frame.Show() + app.SetTopWindow(frame) + app.MainLoop() diff --git a/Line counter.py b/Line counter.py @@ -0,0 +1,72 @@ +import os + +lines = 0 +linesextended = 0 +comments = 0 +whitespace = 0 +files = os.listdir(os.getcwd()) +allowedextensions = ["py"] +excluded = ["Bubbles!.py", "Catherine wheel.py", "Controlled Eruption.py", "Gravity test.py", + "Keyframe selector widget testery.py", "keyframes test.py", "particleeditor.py", + "pygamedisplay.py", "PyIgnition test - fire.py", "Test load.py", "timelinectrl.py", + "Vortex gravity test.py", "Water.py", "Wind.py", "wx test.py", "wx test 2.py", + "xml OLD.py", "XML reader test.py"] + +print " --ExeSoft line counter--" +print +print "Counting lines in all files with the following extensions:" + +for extension in allowedextensions: + print "\t*.%s" % extension + +print +print "Excluding the following files:" + +for excludedfile in excluded: + print "\t%s" % excludedfile +print +print "Counting..." + +for item in files: + extension = item.split(".")[len(item.split(".")) - 1] + if (extension in allowedextensions) and (item not in excluded) and (item != "Line counter.py"): + opened = open(item) + print "\tCounting in \'%s\'..." % item + + totalcount = 0 + totalextended = 0 + for line in opened.readlines(): + temp = line.replace("\t", "") + temp = temp.replace(" ", "") + temp = temp.replace("\n", "") + if (temp != "") and (temp[0] != "#"): + totalcount += 1 + totalextended += 1 + else: + if temp == "": + whitespace += 1 + elif temp[0] == "#": + comments += 1 + totalextended += 1 + + lines += totalcount + linesextended += totalextended + opened.close() + +print +print "Done!" +raw_input() +print +print +print "Line counts:\n\t-Excluding comments and whitespace: %i\n\t-Everything: %i" % (lines, linesextended) +raw_input() +print +print "Extras:\n\t-Number of comments: %i\n\t-Number of blank lines: %i" % (comments, whitespace) +raw_input() +print +codepercent = (float(lines) / float(linesextended)) * 100.0 +commentpercent = (float(comments) / float(linesextended)) * 100.0 +whitespacepercent = (float(whitespace) / float(linesextended)) * 100.0 +print "Code breakdown:" +print "\t-Functional code: %f%%\n\t-Comments: %f%%\n\t-Whitespace: %f%%" % (codepercent, commentpercent, whitespacepercent) +raw_input() diff --git a/Name ideas.txt b/Name ideas.txt @@ -0,0 +1,16 @@ +Ignition ~(Appren.) +Supernova ~ +x-ulum, x-ium? +Combustion ~(Autodesk) +Pyrotex ~(Firework company) - abbreviation of [py]rotechnics (py from python!) +Pyroxic ~(Someone's username) +Pyroxulum +Pyrocitor +Pyrocitum +Pyrocity (this and the above three are stressed as _'_-) +Flint +Obsidian +[PyIgnition] / PyIgnite + + -Final decision - PyIgnite + -Obsidian shall be used as the name for the particle effects creator application+ \ No newline at end of file diff --git a/Obsidian frame pointer.svg b/Obsidian frame pointer.svg @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="10" + height="18" + id="svg3016" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="Obsidian frame pointer.svg"> + <defs + id="defs3018"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective3024" /> + <inkscape:perspective + id="perspective3004" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3672" + id="linearGradient3678" + x1="7.8258276" + y1="427.44122" + x2="12.120488" + y2="438.79822" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(171.02297,426.79392)" /> + <linearGradient + id="linearGradient3672"> + <stop + style="stop-color:#a6a6a6;stop-opacity:1;" + offset="0" + id="stop3674" /> + <stop + style="stop-color:#434343;stop-opacity:1;" + offset="1" + id="stop3676" /> + </linearGradient> + <linearGradient + y2="438.79822" + x2="12.120488" + y1="427.44122" + x1="7.8258276" + gradientTransform="matrix(1.0937718,0,0,1.0474002,-5.8430958,589.86425)" + gradientUnits="userSpaceOnUse" + id="linearGradient3014" + xlink:href="#linearGradient3672" + inkscape:collect="always" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="11.097718" + inkscape:cy="9.1673026" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1366" + inkscape:window-height="706" + inkscape:window-x="-8" + inkscape:window-y="-8" + inkscape:window-maximized="1" /> + <metadata + id="metadata3021"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1034.3622)"> + <path + style="fill:url(#linearGradient3014);fill-opacity:1;stroke:none" + d="m 0.00253516,1039.5654 4.99773834,-5.2017 5.0233345,5.2017 0,12.7951 -10.02107284,0 0,-12.7951 z" + id="rect3669" + sodipodi:nodetypes="cccccc" + inkscape:label="curframepointer" + inkscape:export-filename="C:\Users\David\Documents\Code\Python\Particle effects\PyIgnition\framepointer.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <desc + id="desc3690">Current frame pointer</desc> + </path> + </g> +</svg> diff --git a/Obsidian keyframe pointer.svg b/Obsidian keyframe pointer.svg @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="20" + height="25" + id="svg3935" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="Obsidian keyframe pointer.svg"> + <defs + id="defs3937"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective3943" /> + <inkscape:perspective + id="perspective4465" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="4" + inkscape:cx="-16.949778" + inkscape:cy="25.210882" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1366" + inkscape:window-height="706" + inkscape:window-x="-8" + inkscape:window-y="-8" + inkscape:window-maximized="1" /> + <metadata + id="metadata3940"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1027.3622)"> + <path + style="fill:#eaeaea;fill-opacity:1;stroke:#000000;stroke-width:1.45622718;stroke-linejoin:miter;stroke-opacity:1" + d="m 0.73212235,1028.0885 18.53771165,0 0,16.0041 -12.0495135,0 -6.48819815,6.7516 0,-6.7516 0,-16.0041 z" + id="rect3692" + sodipodi:nodetypes="ccccccc" + inkscape:export-filename="C:\Users\David\Documents\Code\Python\Particle effects\PyIgnition\keyframepointer.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> +</svg> diff --git a/Old branding/Branding image 1 (small).png b/Old branding/Branding image 1 (small).png Binary files differ. diff --git a/Old branding/Branding image 1.png b/Old branding/Branding image 1.png Binary files differ. diff --git a/Old branding/Branding image 1.xcf b/Old branding/Branding image 1.xcf Binary files differ. diff --git a/PPE (Pygame Particle Effect) file format.xml b/PPE (Pygame Particle Effect) file format.xml @@ -0,0 +1,101 @@ +<?xml version = "1.0"?> +<?pyignition version = "1.0"?> + +<effect> +<!-- This represents a ParticleEffect class --> + <source> + <!-- This is a ParticleSource - all variables are stored here --> + <pos>(300, 300)</pos> + <initspeed>10</initspeed> + <initdirection>3.141592653</initdirection> + <initspeedrandrange>10</initspeedrandrange> + <initdirectionrandrange>0.0</initdirectionrandrange> + <particlesperframe>5</particlesperframe> + <particlelife>1000</particlelife> + <genspacing>0</genspacing> + <drawtype>point</drawtype> + <!-- drawtype can be any of: + -point + -circle + -line + -scaleline + -bubble + -image + These are replaced with the appropriate constants when loaded --> + <colour>(100, 200, 100)</colour> + <radius>3.0</radius> + <length>3.0</length> + <imagepath>Raves.jpg</imagepath> + <keyframes> + <!-- Note that the keyframe for frame zero is automatically created on ParticleSource + initialisation, and so does not need to be defined here --> + <keyframe frame = "30"> + <pos>None</pos> + <!-- Although keyframes shown in this example file omit several variables, in the + actual implementation it is more likely that all variables will be present and will + use 'None' for undefined ones as demonstrated here --> + <initspeed>None</initspeed> + <initdirection>None</initdirection> + <initspeedrandrange>None</initspeedrandrange> + <initdirectionrandrange>3.0</initdirectionrandrange> + <particlesperframe>1</particlesperframe> + <particlelife>10</particlelife> + <genspacing>100</genspacing> + <interpolationtype>linear</interpolationtype> + <!-- Can be either linear or cosine --> + </keyframe> + <keyframe frame= "35"> + <colour>(0, 0, 0)</colour> + <interpolationtype>cosine</interpolationtype> + </keyframe> + </keyframes> + <particlekeyframes> + <!-- (Exclusive to ParticleSource objects) --> + <!-- As before, note that no keyframe is defined for frame 0 as this is automatically + created anyway --> + <keyframe frame = "40"> + <length>1000.0</length> + </keyframe> + </particlekeyframes> + </source> + + <source> + <!-- This is another ParticleSource --> + <pos>(100, 250)</pos> + <initspeed>40</initspeed> + <initdirection>3.141592653</initdirection> + <initspeedrandrange>1000</initspeedrandrange> + <initdirectionrandrange>10.0</initdirectionrandrange> + <particlesperframe>5000</particlesperframe> + <particlelife>1</particlelife> + <genspacing>50</genspacing> + <drawtype>bubble</drawtype> + <colour>(250, 100, 109)</colour> + <radius>30.0</radius> + <length>0.09</length> + <imagepath>None</imagepath> + <keyframes> + <keyframe frame = "30"> + <initspeed>None</initspeed> + <initdirection>None</initdirection> + <initspeedrandrange>None</initspeedrandrange> + <initdirectionrandrange>3.0</initdirectionrandrange> + <particlesperframe>1</particlesperframe> + <particlelife>10</particlelife> + <genspacing>100</genspacing> + <interpolationtype>linear</interpolationtype> + </keyframe> + <keyframe frame= "35"> + <colour>(0, 0, 0)</colour> + <interpolationtype>cosine</interpolationtype> + </keyframe> + </keyframes> + <particlekeyframes> + <keyframe frame = "40"> + <length>1000.0</length> + </keyframe> + </particlekeyframes> + </source> + + <!-- All other object types follow the same pattern as the ParticleSource objects shown above --> +</effect>+ \ No newline at end of file diff --git a/PyIgnition ravery.zip b/PyIgnition ravery.zip Binary files differ. diff --git a/PyIgnition test - fire.py b/PyIgnition test - fire.py @@ -0,0 +1,45 @@ +# PyIgnition test + +import PyIgnition, pygame, sys + + +screen = pygame.display.set_mode((800, 600)) +pygame.display.set_caption("PyIgnition demo: fire") +clock = pygame.time.Clock() + +fire = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +gravity = fire.CreateDirectedGravity(strength = 0.07, direction = [0, -1]) +wind = fire.CreateDirectedGravity(strength = 0.05, direction = [1, 0]) +source = fire.CreateSource((300, 500), initspeed = 2.0, initdirection = 0.0, initspeedrandrange = 1.0, initdirectionrandrange = 0.5, particlesperframe = 10, particlelife = 100, drawtype = PyIgnition.DRAWTYPE_CIRCLE, colour = (255, 200, 100), radius = 3.0) +source.CreateParticleKeyframe(10, colour = (200, 50, 20), radius = 4.0) +source.CreateParticleKeyframe(30, colour = (150, 0, 0), radius = 6.0) +source.CreateParticleKeyframe(60, colour = (50, 20, 20), radius = 20.0) +source.CreateParticleKeyframe(80, colour = (0, 0, 0), radius = 50.0) +rect = fire.CreateRectangle((400, 100), (200, 100, 100), bounce = 0.2, width = 100, height = 20) +rect.CreateKeyframe(frame = 500, pos = (400, 250), width = 200, height = 30) +#fire.CreateCircle((350, 200), (200, 100, 100), bounce = 0.2, radius = 25) +#fire.CreateCircle((450, 200), (200, 100, 100), bounce = 0.2, radius = 25) + +# Test shizz for generic keyframe creation function +#source.CreateParticleKeyframe(2, colour = (0, 0, 255)) +#source.CreateParticleKeyframe(5, colour = (0, 0, 0)) +#source.CreateParticleKeyframe(0, colour = (255, 255, 255)) +#source.CreateParticleKeyframe(0, colour = (0, 255, 0)) +#source.CreateParticleKeyframe(80, colour = (255, 255, 255), radius = 1.0) + +fire.SaveToFile("Fire.ppe") + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + screen.fill((0, 0, 0)) + source.SetPos(pygame.mouse.get_pos()) + if source.curframe % 30 == 0: + source.ConsolidateKeyframes() + fire.Update() + fire.Redraw() + pygame.display.update() + clock.tick(30) diff --git a/PyIgnition test.ppe b/PyIgnition test.ppe @@ -0,0 +1,129 @@ +<?xml version = "1.0"?> +<?pyignition version = "1.000000"?> + +<effect> + <source> + <pos>(10, 10)</pos> + <initspeed>5.000000</initspeed> + <initdirection>2.356194</initdirection> + <initspeedrandrange>2.000000</initspeedrandrange> + <initdirectionrandrange>1.000000</initdirectionrandrange> + <particlesperframe>5</particlesperframe> + <particlelife>125</particlelife> + <genspacing>0</genspacing> + <drawtype>scaleline</drawtype> + <colour>(255, 255, 255)</colour> + <radius>0.000000</radius> + <length>10.000000</length> + <imagepath>None</imagepath> + <keyframes> + </keyframes> + <particlekeyframes> + <keyframe frame = "50"> + <colour_r>0</colour_r> + <length>10.0</length> + <interpolationtype>linear</interpolationtype> + <radius>None</radius> + <colour_b>0</colour_b> + <colour_g>255</colour_g> + </keyframe> + <keyframe frame = "75"> + <colour_r>255</colour_r> + <length>10.0</length> + <interpolationtype>linear</interpolationtype> + <radius>None</radius> + <colour_b>0</colour_b> + <colour_g>255</colour_g> + </keyframe> + <keyframe frame = "100"> + <colour_r>0</colour_r> + <length>10.0</length> + <interpolationtype>linear</interpolationtype> + <radius>None</radius> + <colour_b>255</colour_b> + <colour_g>255</colour_g> + </keyframe> + <keyframe frame = "125"> + <colour_r>0</colour_r> + <length>10.0</length> + <interpolationtype>linear</interpolationtype> + <radius>None</radius> + <colour_b>0</colour_b> + <colour_g>0</colour_g> + </keyframe> + </particlekeyframes> + </source> + + <pointgravity> + <strength>1.000000</strength> + <strengthrandrange>0.000000</strengthrandrange> + <pos>(500, 380)</pos> + <keyframes> + <keyframe frame = "300"> + <interpolationtype>linear</interpolationtype> + <pos_x>0</pos_x> + <strength>10.0</strength> + <strengthrandrange>None</strengthrandrange> + <pos_y>0</pos_y> + </keyframe> + <keyframe frame = "450"> + <interpolationtype>linear</interpolationtype> + <pos_x>40</pos_x> + <strength>10.0</strength> + <strengthrandrange>None</strengthrandrange> + <pos_y>40</pos_y> + </keyframe> + <keyframe frame = "550"> + <interpolationtype>linear</interpolationtype> + <pos_x>600</pos_x> + <strength>-2.0</strength> + <strengthrandrange>None</strengthrandrange> + <pos_y>480</pos_y> + </keyframe> + <keyframe frame = "600"> + <interpolationtype>linear</interpolationtype> + <pos_x>600</pos_x> + <strength>-20.0</strength> + <strengthrandrange>None</strengthrandrange> + <pos_y>0</pos_y> + </keyframe> + <keyframe frame = "650"> + <interpolationtype>linear</interpolationtype> + <pos_x>500</pos_x> + <strength>1.0</strength> + <strengthrandrange>None</strengthrandrange> + <pos_y>380</pos_y> + </keyframe> + </keyframes> + </pointgravity> + + <directedgravity> + <strength>0.040000</strength> + <strengthrandrange>0.000000</strengthrandrange> + <direction>(1.000000, 0.000000)</direction> + <keyframes> + <keyframe frame = "300"> + <direction_y>1</direction_y> + <direction_x>-0.5</direction_x> + <interpolationtype>linear</interpolationtype> + <strength>1.0</strength> + <strengthrandrange>None</strengthrandrange> + </keyframe> + <keyframe frame = "600"> + <direction_y>-0.1</direction_y> + <direction_x>1.0</direction_x> + <interpolationtype>linear</interpolationtype> + <strength>1.0</strength> + <strengthrandrange>None</strengthrandrange> + </keyframe> + <keyframe frame = "650"> + <direction_y>0</direction_y> + <direction_x>1</direction_x> + <interpolationtype>linear</interpolationtype> + <strength>0.04</strength> + <strengthrandrange>None</strengthrandrange> + </keyframe> + </keyframes> + </directedgravity> + +</effect>+ \ No newline at end of file diff --git a/PyIgnition.py b/PyIgnition.py @@ -0,0 +1,739 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Particle effect manager + + +import particles, gravity, obstacles, constants, sys, pygame, xml +from constants import * + + +class ParticleEffect: + def __init__(self, display, pos = (0, 0), size = (0, 0)): + self.display = display + self.pos = pos + self.size = size + + self.left = pos[0] + self.top = pos[1] + self.right = pos[0] + size[0] + self.bottom = pos[1] + size[1] + + self.particles = [] + self.sources = [] + self.gravities = [] + self.obstacles = [] + + def Update(self): + for source in self.sources: + source.Update() + + for gravity in self.gravities: + gravity.Update() + + for obstacle in self.obstacles: + obstacle.Update() + + for particle in self.particles: + radius = 0.0 # Used for making sure radii don't overlap objects... + + if particle.drawtype == DRAWTYPE_CIRCLE or particle.drawtype == DRAWTYPE_BUBBLE: + radius = particle.radius * (1.0 - RADIUS_PERMITTIVITY) # ...But only set if the particle is actually circular + + # First calculate the forces acting on the particle + totalforce = [0.0, 0.0] + + for gravity in self.gravities: + force = gravity.GetForceOnParticle(particle) + totalforce[0] += force[0] + totalforce[1] += force[1] + + for obstacle in self.obstacles: + force = obstacle.GetForce(particle.pos, particle.velocity, radius) + totalforce[0] += force[0] + totalforce[1] += force[1] + + # Apply the forces to the velocity and update the particle + particle.velocity = [particle.velocity[0] + totalforce[0], particle.velocity[1] + totalforce[1]] + + particle.Update() + + # Resolve collisions + for obstacle in self.obstacles: + if (not obstacle.OutOfRange(particle.pos)) and (obstacle.InsideObject(particle.pos, radius)): + particle.pos = obstacle.GetResolved(particle.pos, radius) + + # Delete dead particles + for particle in self.particles: + if not particle.alive: + self.particles.remove(particle) + + def Redraw(self): + for particle in self.particles: + particle.Draw(self.display) + + for obstacle in self.obstacles: + obstacle.Draw(self.display) + + def CreateSource(self, pos = (0, 0), initspeed = 0.0, initdirection = 0.0, initspeedrandrange = 0.0, initdirectionrandrange = 0.0, particlesperframe = 0, particlelife = -1, genspacing = 0, drawtype = 0, colour = (0, 0, 0), radius = 0.0, length = 0.0, imagepath = None): + newsource = particles.ParticleSource(self, pos, initspeed, initdirection, initspeedrandrange, initdirectionrandrange, particlesperframe, particlelife, genspacing, drawtype, colour, radius, length, imagepath) + self.sources.append(newsource) + return newsource # Effectively a reference + + def CreatePointGravity(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)): + newgrav = gravity.PointGravity(strength, strengthrandrange, pos) + self.gravities.append(newgrav) + return newgrav + + def CreateDirectedGravity(self, strength = 0.0, strengthrandrange = 0.0, direction = [0, 1]): + newgrav = gravity.DirectedGravity(strength, strengthrandrange, direction) + self.gravities.append(newgrav) + return newgrav + + def CreateVortexGravity(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)): + newgrav = gravity.VortexGravity(strength, strengthrandrange, pos) + self.gravities.append(newgrav) + return newgrav + + def CreateCircle(self, pos = (0, 0), colour = (0, 0, 0), bounce = 1.0, radius = 0.0): + newcircle = obstacles.Circle(self, pos, colour, bounce, radius) + self.obstacles.append(newcircle) + return newcircle + + def CreateRectangle(self, pos = (0, 0), colour = (0, 0, 0), bounce = 1.0, width = 0.0, height = 0.0): + newrect = obstacles.Rectangle(self, pos, colour, bounce, width, height) + self.obstacles.append(newrect) + return newrect + + def CreateBoundaryLine(self, pos = (0, 0), colour = (0, 0, 0), bounce = 1.0, normal = [0, 1]): + newline = obstacles.BoundaryLine(self, pos, colour, bounce, normal) + self.obstacles.append(newline) + return newline + + def AddParticle(self, particle): + self.particles.append(particle) + + def GetDrawtypeAsString(self, drawtype): + if drawtype == DRAWTYPE_POINT: + return "point" + elif drawtype == DRAWTYPE_CIRCLE: + return "circle" + elif drawtype == DRAWTYPE_LINE: + return "line" + elif drawtype == DRAWTYPE_SCALELINE: + return "scaleline" + elif drawtype == DRAWTYPE_BUBBLE: + return "bubble" + elif drawtype == DRAWTYPE_IMAGE: + return "image" + else: + return "ERROR: Invalid drawtype" + + def GetStringAsDrawtype(self, string): + if string == "point": + return DRAWTYPE_POINT + elif string == "circle": + return DRAWTYPE_CIRCLE + elif string == "line": + return DRAWTYPE_LINE + elif string == "scaleline": + return DRAWTYPE_SCALELINE + elif string == "bubble": + return DRAWTYPE_BUBBLE + elif string == "image": + return DRAWTYPE_IMAGE + else: + return DRAWTYPE_POINT + + def GetInterpolationtypeAsString(self, interpolationtype): + if interpolationtype == INTERPOLATIONTYPE_LINEAR: + return "linear" + elif interpolationtype == INTERPOLATIONTYPE_COSINE: + return "cosine" + + def GetStringAsInterpolationtype(self, string): + if string == "linear": + return INTERPOLATIONTYPE_LINEAR + elif string == "cosine": + return INTERPOLATIONTYPE_COSINE + else: + return INTERPOLATIONTYPE_LINEAR + + def TranslatePos(self, pos): + return (pos[0] - self.pos[0], pos[1] - self.pos[1]) + + def ConvertXMLTuple(self, string): + # 'string' must be of the form "(value, value, value, [...])" + bracketless = string.replace("(", "").replace(")", "") + strings = bracketless.split(", ") + finaltuple = [] + for string in strings: + temp = string.split(".") + if len(temp) > 1: + finaltuple.append(float(string)) + else: + finaltuple.append(int(string)) + + return tuple(finaltuple) + + def SaveToFile(self, outfilename): + outfile = open(outfilename, 'w') + + outfile.write("<?xml version = \"1.0\"?>\n<?pyignition version = \"%f\"?>\n\n" % PYIGNITION_VERSION) + outfile.write("<effect>\n") + + # Write out sources + for source in self.sources: + outfile.write("\t<source>\n") + + # Write out source variables + outfile.write("\t\t<pos>(%i, %i)</pos>\n" % source.pos) + outfile.write("\t\t<initspeed>%f</initspeed>\n" % source.initspeed) + outfile.write("\t\t<initdirection>%f</initdirection>\n" % source.initdirection) + outfile.write("\t\t<initspeedrandrange>%f</initspeedrandrange>\n" % source.initspeedrandrange) + outfile.write("\t\t<initdirectionrandrange>%f</initdirectionrandrange>\n" % source.initdirectionrandrange) + outfile.write("\t\t<particlesperframe>%i</particlesperframe>\n" % source.particlesperframe) + outfile.write("\t\t<particlelife>%i</particlelife>\n" % source.particlelife) + outfile.write("\t\t<genspacing>%i</genspacing>\n" % source.genspacing) + outfile.write("\t\t<drawtype>%s</drawtype>\n" % self.GetDrawtypeAsString(source.drawtype)) + outfile.write("\t\t<colour>(%i, %i, %i)</colour>\n" % source.colour) + outfile.write("\t\t<radius>%f</radius>\n" % source.radius) + outfile.write("\t\t<length>%f</length>\n" % source.length) + outfile.write("\t\t<imagepath>%s</imagepath>\n" % source.imagepath) + + # Write out source keyframes + outfile.write("\t\t<keyframes>\n") + + for keyframe in source.keyframes: + if keyframe.frame == 0: # Don't bother writing out the first keyframe + continue + + outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame) + + # Write out keyframed variables + for variable in keyframe.variables.keys(): + if variable == "interpolationtype": + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable)) + else: + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable)) + + outfile.write("\t\t\t</keyframe>\n") + + outfile.write("\t\t</keyframes>\n") + + # Write out source particle keyframes + outfile.write("\t\t<particlekeyframes>\n") + + for keyframe in source.particlekeyframes: + if keyframe.frame == 0: # Don't bother writing out the first keyframe + continue + + outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame) + + # Write out keyframed variables + for variable in keyframe.variables.keys(): + if variable == "interpolationtype": + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable)) + else: + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable)) + + outfile.write("\t\t\t</keyframe>\n") + + outfile.write("\t\t</particlekeyframes>\n") + + outfile.write("\t</source>\n\n") + + # Write out gravities + for gravity in self.gravities: + # Identify type + gtype = gravity.type + + outfile.write("\t<%sgravity>\n" % gtype) + + # Write out gravity variables + outfile.write("\t\t<strength>%f</strength>\n" % gravity.initstrength) + outfile.write("\t\t<strengthrandrange>%f</strengthrandrange>\n" % gravity.strengthrandrange) + if gtype == "directed": + outfile.write("\t\t<direction>(%f, %f)</direction>\n" % tuple(gravity.direction)) + elif gtype == "point" or gtype == "vortex": + outfile.write("\t\t<pos>(%i, %i)</pos>\n" % gravity.pos) + + # Write out gravity keyframes + outfile.write("\t\t<keyframes>\n") + + for keyframe in gravity.keyframes: + if keyframe.frame == 0: # Don't bother writing out the first keyframe + continue + + outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame) + + # Write out keyframed variables + for variable in keyframe.variables.keys(): + if variable == "interpolationtype": + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable)) + else: + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable)) + + outfile.write("\t\t\t</keyframe>\n") + + outfile.write("\t\t</keyframes>\n") + + outfile.write("\t</%sgravity>\n\n" % gtype) + + # Write out obstacles + for obstacle in self.obstacles: + # Identify type + otype = obstacle.type + + outfile.write("\t<%s>\n" % otype) + + # Write out obstacle variables + outfile.write("\t\t<pos>(%i, %i)</pos>\n" % obstacle.pos) + outfile.write("\t\t<colour>(%i, %i, %i)</colour>\n" % obstacle.colour) + outfile.write("\t\t<bounce>%f</bounce>\n" % obstacle.bounce) + if otype == "circle": + outfile.write("\t\t<radius>%f</radius>\n" % obstacle.radius) + elif otype == "rectangle": + outfile.write("\t\t<width>%i</width>\n" % obstacle.width) + outfile.write("\t\t<height>%i</height>\n" % obstacle.height) + elif otype == "boundaryline": + outfile.write("\t\t<normal>(%f, %f)</normal>\n" % tuple(obstacle.normal)) + + # Write out obstacle keyframes + outfile.write("\t\t<keyframes>\n") + + for keyframe in obstacle.keyframes: + if keyframe.frame == 0: # Don't bother writing out the first keyframe + continue + + outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame) + + # Write out keyframed variables + for variable in keyframe.variables.keys(): + if variable == "interpolationtype": + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable)) + else: + outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable)) + + outfile.write("\t\t\t</keyframe>\n") + + outfile.write("\t\t</keyframes>\n") + + outfile.write("\t</%s>\n\n" % otype) + + outfile.write("</effect>") + outfile.close() + + def LoadFromFile(self, infilename): + infile = open(infilename, "r") + + data = xml.XMLParser(infile.read()).Parse() + infile.close() + + for child in data.children: + if child.tag == "source": # Source object + pos = (0, 0) + initspeed = 0.0 + initdirection = 0.0 + initspeedrandrange = 0.0 + initdirectionrandrange = 0.0 + particlesperframe = 0 + particlelife = 0 + genspacing = 0 + drawtype = DRAWTYPE_POINT + colour = (0, 0, 0) + radius = 0.0 + length = 0.0 + imagepath = None + + keyframes = None + particlekeyframes = None + + for parameter in child.children: + if parameter.tag == "pos": + pos = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "initspeed": + initspeed = float(parameter.inside) + elif parameter.tag == "initdirection": + initdirection = float(parameter.inside) + elif parameter.tag == "initspeedrandrange": + initspeedrandrange = float(parameter.inside) + elif parameter.tag == "initdirectionrandrange": + initdirectionrandrange = float(parameter.inside) + elif parameter.tag == "particlesperframe": + particlesperframe = int(parameter.inside) + elif parameter.tag == "particlelife": + particlelife = int(parameter.inside) + elif parameter.tag == "genspacing": + genspacing = int(parameter.inside) + elif parameter.tag == "drawtype": + drawtype = self.GetStringAsDrawtype(parameter.inside) + elif parameter.tag == "colour": + colour = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "radius": + radius = float(parameter.inside) + elif parameter.tag == "length": + length = float(parameter.inside) + elif parameter.tag == "image": + imagepath = float(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + elif parameter.tag == "particlekeyframes": + particlekeyframes = parameter.children + + newsource = self.CreateSource(pos, initspeed, initdirection, initspeedrandrange, initdirectionrandrange, particlesperframe, particlelife, genspacing, drawtype, colour, radius, length, imagepath) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "pos_x" and variable.inside != "None": + variables['pos_x'] = int(variable.inside) + elif variable.tag == "pos_y" and variable.inside != "None": + variables['pos_y'] = int(variable.inside) + elif variable.tag == "initspeed" and variable.inside != "None": + variables['initspeed'] = float(variable.inside) + elif variable.tag == "initdirection" and variable.inside != "None": + variables['initdirection'] = float(variable.inside) + elif variable.tag == "initspeedrandrange" and variable.inside != "None": + variables['initspeedrandrange'] = float(variable.inside) + elif variable.tag == "initdirectionrandrange" and variable.inside != "None": + variables['initdirectionrandrange'] = float(variable.inside) + elif variable.tag == "particlesperframe" and variable.inside != "None": + variables['particlesperframe'] = int(variable.inside) + elif variable.tag == "genspacing" and variable.inside != "None": + variables['genspacing'] = int(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newsource.CreateKeyframe(frame = frame) + newframe.variables = variables + + for keyframe in particlekeyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "colour_r" and variable.inside != "None": + variables['colour_r'] = int(variable.inside) + elif variable.tag == "colour_g" and variable.inside != "None": + variables['colour_g'] = int(variable.inside) + elif variable.tag == "colour_b" and variable.inside != "None": + variables['colour_b'] = int(variable.inside) + elif variable.tag == "radius" and variable.inside != "None": + variables['radius'] = float(variable.inside) + elif variable.tag == "length" and variable.inside != "None": + variables['length'] = float(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newsource.CreateParticleKeyframe(frame = frame) + newframe.variables = variables + newsource.PreCalculateParticles() + + elif child.tag == "directedgravity": + strength = 0.0 + strengthrandrange = 0.0 + direction = [0, 0] + + keyframes = None + + for parameter in child.children: + if parameter.tag == "strength": + strength = float(parameter.inside) + elif parameter.tag == "strengthrandrange": + strengthrandrange = float(parameter.inside) + elif parameter.tag == "direction": + direction = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + + newgrav = self.CreateDirectedGravity(strength, strengthrandrange, direction) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "strength" and variable.inside != "None": + variables['strength'] = float(variable.inside) + elif variable.tag == "strengthrandrange" and variable.inside != "None": + variables['strengthrandrange'] = float(variable.inside) + elif variable.tag == "direction_x" and variable.inside != "None": + variables['direction_x'] = float(variable.inside) + elif variable.tag == "direction_y" and variable.inside != "None": + variables['direction_y'] = float(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newgrav.CreateKeyframe(frame = frame) + newframe.variables = variables + + elif child.tag == "pointgravity": + strength = 0.0 + strengthrandrange = 0.0 + pos = (0, 0) + + keyframes = None + + for parameter in child.children: + if parameter.tag == "strength": + strength = float(parameter.inside) + elif parameter.tag == "strengthrandrange": + strengthrandrange = float(parameter.inside) + elif parameter.tag == "pos": + pos = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + + newgrav = self.CreatePointGravity(strength, strengthrandrange, pos) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "strength" and variable.inside != "None": + variables['strength'] = float(variable.inside) + elif variable.tag == "strengthrandrange" and variable.inside != "None": + variables['strengthrandrange'] = float(variable.inside) + elif variable.tag == "pos_x" and variable.inside != "None": + variables['pos_x'] = int(variable.inside) + elif variable.tag == "pos_y" and variable.inside != "None": + variables['pos_y'] = int(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newgrav.CreateKeyframe(frame = frame) + newframe.variables = variables + + elif child.tag == "vortexgravity": + strength = 0.0 + strengthrandrange = 0.0 + pos = (0, 0) + + keyframes = None + + for parameter in child.children: + if parameter.tag == "strength": + strength = float(parameter.inside) + elif parameter.tag == "strengthrandrange": + strengthrandrange = float(parameter.inside) + elif parameter.tag == "pos": + direction = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + + newgrav = self.CreateVortexGravity(strength, strengthrandrange, pos) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "strength" and variable.inside != "None": + variables['strength'] = float(variable.inside) + elif variable.tag == "strengthrandrange" and variable.inside != "None": + variables['strengthrandrange'] = float(variable.inside) + elif variable.tag == "pos_x" and variable.inside != "None": + variables['pos_x'] = int(variable.inside) + elif variable.tag == "pos_y" and variable.inside != "None": + variables['pos_y'] = int(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newgrav.CreateKeyframe(frame = frame) + newframe.variables = variables + + elif child.tag == "circle": + pos = (0, 0) + colour = (0, 0, 0) + bounce = 0.0 + radius = 0.0 + + keyframes = None + + for parameter in child.children: + if parameter.tag == "pos": + pos = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "colour": + colour = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "bounce": + bounce = float(parameter.inside) + elif parameter.tag == "radius": + radius = float(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + + newobstacle = self.CreateCircle(pos, colour, bounce, radius) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "pos_x" and variable.inside != "None": + variables['pos_x'] = int(variable.inside) + elif variable.tag == "pos_y" and variable.inside != "None": + variables['pos_y'] = int(variable.inside) + elif variable.tag == "colour_r" and variable.inside != "None": + variables['colour_r'] = int(variable.inside) + elif variable.tag == "colour_g" and variable.inside != "None": + variables['colour_g'] = int(variable.inside) + elif variable.tag == "colour_b" and variable.inside != "None": + variables['colour_b'] = int(variable.inside) + elif variable.tag == "bounce" and variable.inside != "None": + variables['bounce'] = float(variable.inside) + elif variable.tag == "radius" and variable.inside != "None": + variables['radius'] = float(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newobstacle.CreateKeyframe(frame = frame) + newframe.variables = variables + + elif child.tag == "rectangle": + pos = (0, 0) + colour = (0, 0, 0) + bounce = 0.0 + width = 0.0 + height = 0.0 + + keyframes = None + + for parameter in child.children: + if parameter.tag == "pos": + pos = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "colour": + colour = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "bounce": + bounce = float(parameter.inside) + elif parameter.tag == "width": + width = float(parameter.inside) + elif parameter.tag == "height": + height = float(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + + newobstacle = self.CreateRectangle(pos, colour, bounce, width, height) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "pos_x" and variable.inside != "None": + variables['pos_x'] = int(variable.inside) + elif variable.tag == "pos_y" and variable.inside != "None": + variables['pos_y'] = int(variable.inside) + elif variable.tag == "colour_r" and variable.inside != "None": + variables['colour_r'] = int(variable.inside) + elif variable.tag == "colour_g" and variable.inside != "None": + variables['colour_g'] = int(variable.inside) + elif variable.tag == "colour_b" and variable.inside != "None": + variables['colour_b'] = int(variable.inside) + elif variable.tag == "bounce" and variable.inside != "None": + variables['bounce'] = float(variable.inside) + elif variable.tag == "width" and variable.inside != "None": + variables['width'] = float(variable.inside) + elif variable.tag == "height" and variable.inside != "None": + variables['height'] = float(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newobstacle.CreateKeyframe(frame = frame) + newframe.variables = variables + + elif child.tag == "boundaryline": + pos = (0, 0) + colour = (0, 0, 0) + bounce = 0.0 + direction = [0.0, 0.0] + + keyframes = None + + for parameter in child.children: + if parameter.tag == "pos": + pos = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "colour": + colour = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "bounce": + bounce = float(parameter.inside) + elif parameter.tag == "normal": + normal = self.ConvertXMLTuple(parameter.inside) + elif parameter.tag == "keyframes": + keyframes = parameter.children + + newobstacle = self.CreateBoundaryLine(pos, colour, bounce, normal) + + for keyframe in keyframes: + frame = int(keyframe.meta['frame']) + variables = {} + + for variable in keyframe.children: + if variable.tag == "pos_x" and variable.inside != "None": + variables['pos_x'] = int(variable.inside) + elif variable.tag == "pos_y" and variable.inside != "None": + variables['pos_y'] = int(variable.inside) + elif variable.tag == "colour_r" and variable.inside != "None": + variables['colour_r'] = int(variable.inside) + elif variable.tag == "colour_g" and variable.inside != "None": + variables['colour_g'] = int(variable.inside) + elif variable.tag == "colour_b" and variable.inside != "None": + variables['colour_b'] = int(variable.inside) + elif variable.tag == "bounce" and variable.inside != "None": + variables['bounce'] = float(variable.inside) + elif variable.tag == "normal_x" and variable.inside != "None": + variables['normal_x'] = float(variable.inside) + elif variable.tag == "normal_y" and variable.inside != "None": + variables['normal_y'] = float(variable.inside) + elif variable.tag == "interpolationtype" and variable.inside != "None": + variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside) + + newframe = newobstacle.CreateKeyframe(frame = frame) + newframe.variables = variables + + def PropogateCurframe(self, newframe): + for source in self.sources: + source.curframe = newframe + for gravity in self.gravities: + gravity.curframe = newframe + for obstacle in self.obstacles: + obstacle.curframe = newframe + + +## Begin testing code +if __name__ == '__main__': + screen = pygame.display.set_mode((800, 600)) + pygame.display.set_caption("PyIgnition demo") + clock = pygame.time.Clock() + test = ParticleEffect(screen, (0, 0), (800, 600)) + testgrav = test.CreatePointGravity(strength = 1.0, pos = (500, 380)) + testgrav.CreateKeyframe(300, strength = 10.0, pos = (0, 0)) + testgrav.CreateKeyframe(450, strength = 10.0, pos = (40, 40)) + testgrav.CreateKeyframe(550, strength = -2.0, pos = (600, 480)) + testgrav.CreateKeyframe(600, strength = -20.0, pos = (600, 0)) + testgrav.CreateKeyframe(650, strength = 1.0, pos = (500, 380)) + anothertestgrav = test.CreateDirectedGravity(strength = 0.04, direction = [1, 0]) + anothertestgrav.CreateKeyframe(300, strength = 1.0, direction = [-0.5, 1]) + anothertestgrav.CreateKeyframe(600, strength = 1.0, direction = [1.0, -0.1]) + anothertestgrav.CreateKeyframe(650, strength = 0.04, direction = [1, 0]) + testsource = test.CreateSource((10, 10), initspeed = 5.0, initdirection = 2.35619449, initspeedrandrange = 2.0, initdirectionrandrange = 1.0, particlesperframe = 5, particlelife = 125, drawtype = DRAWTYPE_SCALELINE, colour = (255, 255, 255), length = 10.0) + testsource.CreateParticleKeyframe(50, colour = (0, 255, 0), length = 10.0) + testsource.CreateParticleKeyframe(75, colour = (255, 255, 0), length = 10.0) + testsource.CreateParticleKeyframe(100, colour = (0, 255, 255), length = 10.0) + testsource.CreateParticleKeyframe(125, colour = (0, 0, 0), length = 10.0) + + test.SaveToFile("PyIgnition test.ppe") + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + screen.fill((0, 0, 0)) + test.Update() + test.Redraw() + pygame.display.update() + clock.tick(20) diff --git a/PyIgnition.pyc b/PyIgnition.pyc Binary files differ. diff --git a/Releases/Particle engine.7z b/Releases/Particle engine.7z Binary files differ. diff --git a/Releases/PyIgnition alpha 1.7z b/Releases/PyIgnition alpha 1.7z Binary files differ. diff --git a/Releases/PyIgnition alpha 2-and-a-bit.zip b/Releases/PyIgnition alpha 2-and-a-bit.zip Binary files differ. diff --git a/Releases/PyIgnition alpha 2.zip b/Releases/PyIgnition alpha 2.zip Binary files differ. diff --git a/Releases/PyIgnition alpha 3.zip b/Releases/PyIgnition alpha 3.zip Binary files differ. diff --git a/Releases/PyIgnition beta 1.zip b/Releases/PyIgnition beta 1.zip Binary files differ. diff --git a/Releases/PyIgnition beta 2.zip b/Releases/PyIgnition beta 2.zip Binary files differ. diff --git a/Releases/PyIgnition version 1.zip b/Releases/PyIgnition version 1.zip Binary files differ. diff --git a/Screenshots and branding/Alpha 1 promo.jpg b/Screenshots and branding/Alpha 1 promo.jpg Binary files differ. diff --git a/Screenshots and branding/Alpha 1 promo.xcf b/Screenshots and branding/Alpha 1 promo.xcf Binary files differ. diff --git a/Screenshots and branding/Alpha 3 promo.jpg b/Screenshots and branding/Alpha 3 promo.jpg Binary files differ. diff --git a/Screenshots and branding/Alpha 3 promo.xcf b/Screenshots and branding/Alpha 3 promo.xcf Binary files differ. diff --git a/Screenshots and branding/Another vortex demo.jpg b/Screenshots and branding/Another vortex demo.jpg Binary files differ. diff --git a/Screenshots and branding/Beta 2 promo A.png b/Screenshots and branding/Beta 2 promo A.png Binary files differ. diff --git a/Screenshots and branding/Beta 2 promo A.xcf b/Screenshots and branding/Beta 2 promo A.xcf Binary files differ. diff --git a/Screenshots and branding/Branding image 1.xcf b/Screenshots and branding/Branding image 1.xcf Binary files differ. diff --git a/Screenshots and branding/Bubbles demo.png b/Screenshots and branding/Bubbles demo.png Binary files differ. diff --git a/Screenshots and branding/Catherine wheel.png b/Screenshots and branding/Catherine wheel.png Binary files differ. diff --git a/Screenshots and branding/Controlled Eruption.jpg b/Screenshots and branding/Controlled Eruption.jpg Binary files differ. diff --git a/Screenshots and branding/Controlled Eruption.png b/Screenshots and branding/Controlled Eruption.png Binary files differ. diff --git a/Screenshots and branding/Features list.txt b/Screenshots and branding/Features list.txt @@ -0,0 +1,19 @@ +-Fully customisable particle sources: + -Particles' starting velocities and directions can be completely controlled, and you can set random ranges for both + -Particles per generation, and the spacing between generations, can also be easily altered + +-Fully customisable particles: + -Six different drawtypes are available: point, line (of fixed length), scaleline (which scales with velocity), circle, bubble (an unfilled circle) and image (for which you can specify an arbitrary image file) + -All parameters are fully customisable, from line length to bubble colour, and you can also change the particle's drawtype in real time + +-Powerful physics system: + -Particles' paths can be influenced by an unlimited number of gravities, which can be either directed (constant in one direction), point gravity (following an inverse square law around a point) or vortex gravity (spins particles around itself whilst drawing them in). Gravity strengths, positions and directions are modifiable and you can set a random range for strength to simulate effects like blusterous wind + -Obstacles can be added to simulations which particles will deflect off, making effects more realistic as they appear to interact with their environments. Obstacles can be either circles, rectangles or boundary lines, all of which have fully customisable parameters + +-Highly versatile keyframe system: + -Pretty much every single parameter can be individually keyframed in real time, allowing you to create incredibly complex effects + -Particle keyframes can be created with sources so that they will be copied to every particle the source produces. The effects of these keyframes are then pre-calculated by the source so they needn't be worked out for every single particle, resulting in good performance even with very elaborate animations + -Further optimisations include a function for consolidating all keyframes from past frames into one single keyframe on the current frame, which when used regularly will significantly speed up animations involving large numbers of keyframes - especially when keyframes are being constantly added by the program + -Keyframes can use either linear or cosine interpolation, and can switch between the two mid-animation if needed + +-Unlimited number of independently-managed particle effects, each using its own sources, gravities and obstacles+ \ No newline at end of file diff --git a/Screenshots and branding/Fiiiire!.png b/Screenshots and branding/Fiiiire!.png Binary files differ. diff --git a/Screenshots and branding/First tangible demo.png b/Screenshots and branding/First tangible demo.png Binary files differ. diff --git a/Screenshots and branding/Flames with Physics.png b/Screenshots and branding/Flames with Physics.png Binary files differ. diff --git a/Screenshots and branding/Logo 1.png b/Screenshots and branding/Logo 1.png Binary files differ. diff --git a/Screenshots and branding/Logo 1.xcf b/Screenshots and branding/Logo 1.xcf Binary files differ. diff --git a/Screenshots and branding/Logo 2.png b/Screenshots and branding/Logo 2.png Binary files differ. diff --git a/Screenshots and branding/Logo 2.xcf b/Screenshots and branding/Logo 2.xcf Binary files differ. diff --git a/Screenshots and branding/Logo 3.png b/Screenshots and branding/Logo 3.png Binary files differ. diff --git a/Screenshots and branding/Logo 3.xcf b/Screenshots and branding/Logo 3.xcf Binary files differ. diff --git a/Screenshots and branding/Magical keyframed colours.png b/Screenshots and branding/Magical keyframed colours.png Binary files differ. diff --git a/Screenshots and branding/More physicsy fire.jpg b/Screenshots and branding/More physicsy fire.jpg Binary files differ. diff --git a/Screenshots and branding/Promo large.jpg b/Screenshots and branding/Promo large.jpg Binary files differ. diff --git a/Screenshots and branding/Promo large.xcf b/Screenshots and branding/Promo large.xcf Binary files differ. diff --git a/Screenshots and branding/PyIgnition cushion distance before-after/After.jpg b/Screenshots and branding/PyIgnition cushion distance before-after/After.jpg Binary files differ. diff --git a/Screenshots and branding/PyIgnition cushion distance before-after/Before-after.png b/Screenshots and branding/PyIgnition cushion distance before-after/Before-after.png Binary files differ. diff --git a/Screenshots and branding/PyIgnition cushion distance before-after/Before-after.xcf b/Screenshots and branding/PyIgnition cushion distance before-after/Before-after.xcf Binary files differ. diff --git a/Screenshots and branding/PyIgnition cushion distance before-after/Before.jpg b/Screenshots and branding/PyIgnition cushion distance before-after/Before.jpg Binary files differ. diff --git a/Screenshots and branding/The mad effects of gravity.png b/Screenshots and branding/The mad effects of gravity.png Binary files differ. diff --git a/Screenshots and branding/Vortex gravity!.jpg b/Screenshots and branding/Vortex gravity!.jpg Binary files differ. diff --git a/Screenshots and branding/Water.png b/Screenshots and branding/Water.png Binary files differ. diff --git a/Screenshots and branding/Wind.png b/Screenshots and branding/Wind.png Binary files differ. diff --git a/Spark.png b/Spark.png Binary files differ. diff --git a/Test load.py b/Test load.py @@ -0,0 +1,29 @@ +import pygame, PyIgnition, sys + +INFILE = "Water.ppe" +BGCOL = (255, 255, 255) + + +screen = pygame.display.set_mode((800, 600)) +pygame.display.set_caption("PyIgnition demo: file I/O :: loading from output of \'PyIgnition demo: collisions\' (Water.py)") +clock = pygame.time.Clock() + + +effect = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +effect.LoadFromFile(INFILE) +effect.sources[0].SetPos(pygame.mouse.get_pos()) + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.MOUSEMOTION: + effect.sources[0].SetPos(pygame.mouse.get_pos()) + + screen.fill(BGCOL) + effect.Update() + effect.Redraw() + + pygame.display.update() + clock.tick(30) diff --git a/Test.xml b/Test.xml @@ -0,0 +1,127 @@ +<?xml version = "1.0"?> +<?pyignition version = "1.0"?> + +<effect> + <source> + <pos>(300, 300)</pos> + <initspeed>20.000000</initspeed> + <initdirection>19.675000</initdirection> + <initspeedrandrange>0.000000</initspeedrandrange> + <initdirectionrandrange>0.500000</initdirectionrandrange> + <particlesperframe>3</particlesperframe> + <particlelife>50</particlelife> + <genspacing>0</genspacing> + <drawtype>scaleline</drawtype> + <colour>(255, 200, 200)</colour> + <radius>0.000000</radius> + <length>20.000000</length> + <imagepath>None</imagepath> + <keyframes> + <keyframe frame = "120"> + <initdirection>18.78</initdirection> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <genspacing>None</genspacing> + <particlesperframe>None</particlesperframe> + <initdirectionrandrange>None</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>None</initspeedrandrange> + <initspeed>None</initspeed> + </keyframe> + <keyframe frame = "120"> + <initdirection>18.56</initdirection> + <pos_x>300</pos_x> + <pos_y>300</pos_y> + <genspacing>0</genspacing> + <particlesperframe>3</particlesperframe> + <initdirectionrandrange>0.5</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>0.0</initspeedrandrange> + <initspeed>20.0</initspeed> + </keyframe> + <keyframe frame = "121"> + <initdirection>18.781</initdirection> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <genspacing>None</genspacing> + <particlesperframe>None</particlesperframe> + <initdirectionrandrange>None</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>None</initspeedrandrange> + <initspeed>None</initspeed> + </keyframe> + <keyframe frame = "122"> + <initdirection>19.003</initdirection> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <genspacing>None</genspacing> + <particlesperframe>None</particlesperframe> + <initdirectionrandrange>None</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>None</initspeedrandrange> + <initspeed>None</initspeed> + </keyframe> + <keyframe frame = "123"> + <initdirection>19.226</initdirection> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <genspacing>None</genspacing> + <particlesperframe>None</particlesperframe> + <initdirectionrandrange>None</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>None</initspeedrandrange> + <initspeed>None</initspeed> + </keyframe> + <keyframe frame = "124"> + <initdirection>19.45</initdirection> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <genspacing>None</genspacing> + <particlesperframe>None</particlesperframe> + <initdirectionrandrange>None</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>None</initspeedrandrange> + <initspeed>None</initspeed> + </keyframe> + <keyframe frame = "125"> + <initdirection>19.675</initdirection> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <genspacing>None</genspacing> + <particlesperframe>None</particlesperframe> + <initdirectionrandrange>None</initdirectionrandrange> + <interpolationtype>linear</interpolationtype> + <initspeedrandrange>None</initspeedrandrange> + <initspeed>None</initspeed> + </keyframe> + </keyframes> + <particlekeyframes> + </particlekeyframes> + </source> + <source> + <pos>(300, 300)</pos> + <initspeed>1.000000</initspeed> + <initdirection>0.000000</initdirection> + <initspeedrandrange>0.900000</initspeedrandrange> + <initdirectionrandrange>3.141593</initdirectionrandrange> + <particlesperframe>1</particlesperframe> + <particlelife>300</particlelife> + <genspacing>3</genspacing> + <drawtype>image</drawtype> + <colour>(0, 0, 0)</colour> + <radius>0.000000</radius> + <length>0.000000</length> + <imagepath>spark.png</imagepath> + <keyframes> + </keyframes> + <particlekeyframes> + </particlekeyframes> + </source> + <directedgravity> + <strength>0.050000</strength> + <strengthrandrange>0.000000</strengthrandrange> + <direction>(0.000000, 1.000000)</direction> + <keyframes> + </keyframes> + </directedgravity> +</effect>+ \ No newline at end of file diff --git a/Vortex gravity test.py b/Vortex gravity test.py @@ -0,0 +1,35 @@ +import pygame, PyIgnition, sys + + +screen = pygame.display.set_mode((800, 600)) +clock = pygame.time.Clock() + +effect = PyIgnition.ParticleEffect(screen) +gravity = effect.CreateVortexGravity(pos = (400, 300), strength = 1.0, strengthrandrange = 0.0) +particles = effect.CreateSource(pos = (0, 0), initspeed = 5.0, initdirectionrandrange = 0.5, particlesperframe = 5, particlelife = 200, drawtype = PyIgnition.DRAWTYPE_LINE, length = 5.0, radius = 5.0) + + +def Draw(): + screen.fill((255, 255, 255)) + + effect.Update() + effect.Redraw() + + pygame.draw.circle(screen, (255, 0, 100), (400, 300), 3) + + mpos = pygame.mouse.get_pos() + #f = gravity.GetForce(mpos) + #endpos = [mpos[0] + f[0], mpos[1] + f[1]] + + #pygame.draw.aaline(screen, (0, 0, 0), mpos, endpos) + particles.SetPos(mpos) + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + Draw() + pygame.display.update() + clock.tick(30) diff --git a/Water.ppe b/Water.ppe @@ -0,0 +1,215 @@ +<?xml version = "1.0"?> +<?pyignition version = "1.000000"?> + +<effect> + <source> + <pos>(0, 0)</pos> + <initspeed>2.000000</initspeed> + <initdirection>3.141593</initdirection> + <initspeedrandrange>1.000000</initspeedrandrange> + <initdirectionrandrange>3.141593</initdirectionrandrange> + <particlesperframe>20</particlesperframe> + <particlelife>80</particlelife> + <genspacing>0</genspacing> + <drawtype>circle</drawtype> + <colour>(100, 100, 250)</colour> + <radius>10.000000</radius> + <length>0.000000</length> + <imagepath>None</imagepath> + <keyframes> + </keyframes> + <particlekeyframes> + <keyframe frame = "60"> + <colour_r>100</colour_r> + <length>None</length> + <interpolationtype>linear</interpolationtype> + <radius>10.0</radius> + <colour_b>250</colour_b> + <colour_g>100</colour_g> + </keyframe> + <keyframe frame = "80"> + <colour_r>255</colour_r> + <length>None</length> + <interpolationtype>linear</interpolationtype> + <radius>20.0</radius> + <colour_b>255</colour_b> + <colour_g>255</colour_g> + </keyframe> + </particlekeyframes> + </source> + + <directedgravity> + <strength>0.200000</strength> + <strengthrandrange>0.000000</strengthrandrange> + <direction>(0.000000, 1.000000)</direction> + <keyframes> + </keyframes> + </directedgravity> + + <circle> + <pos>(100, 200)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <radius>50.000000</radius> + <keyframes> + </keyframes> + </circle> + + <circle> + <pos>(400, 100)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <radius>50.000000</radius> + <keyframes> + <keyframe frame = "250"> + <pos_x>400</pos_x> + <pos_y>500</pos_y> + <radius>None</radius> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>cosine</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + </keyframe> + <keyframe frame = "300"> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <radius>None</radius> + <bounce>None</bounce> + <colour_b>50</colour_b> + <interpolationtype>linear</interpolationtype> + <colour_r>0</colour_r> + <colour_g>255</colour_g> + </keyframe> + </keyframes> + </circle> + + <circle> + <pos>(300, 300)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <radius>50.000000</radius> + <keyframes> + </keyframes> + </circle> + + <circle> + <pos>(500, 250)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <radius>50.000000</radius> + <keyframes> + <keyframe frame = "200"> + <pos_x>500</pos_x> + <pos_y>250</pos_y> + <radius>None</radius> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>linear</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + </keyframe> + <keyframe frame = "230"> + <pos_x>100</pos_x> + <pos_y>300</pos_y> + <radius>None</radius> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>cosine</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + </keyframe> + </keyframes> + </circle> + + <circle> + <pos>(150, 400)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <radius>50.000000</radius> + <keyframes> + </keyframes> + </circle> + + <rectangle> + <pos>(500, 450)</pos> + <colour>(100, 200, 200)</colour> + <bounce>0.200000</bounce> + <width>250</width> + <height>100</height> + <keyframes> + <keyframe frame = "200"> + <width>400.0</width> + <pos_x>400</pos_x> + <pos_y>100</pos_y> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>cosine</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + <height>None</height> + </keyframe> + <keyframe frame = "300"> + <width>None</width> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <bounce>None</bounce> + <colour_b>0</colour_b> + <interpolationtype>linear</interpolationtype> + <colour_r>255</colour_r> + <colour_g>0</colour_g> + <height>None</height> + </keyframe> + </keyframes> + </rectangle> + + <boundaryline> + <pos>(700, 500)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <normal>(-0.707107, -0.707107)</normal> + <keyframes> + <keyframe frame = "300"> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <normal_x>-0.894427191</normal_x> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>linear</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + <normal_y>-0.4472135955</normal_y> + </keyframe> + <keyframe frame = "500"> + <pos_x>None</pos_x> + <pos_y>None</pos_y> + <normal_x>-1</normal_x> + <bounce>None</bounce> + <colour_b>None</colour_b> + <interpolationtype>linear</interpolationtype> + <colour_r>None</colour_r> + <colour_g>None</colour_g> + <normal_y>0</normal_y> + </keyframe> + </keyframes> + </boundaryline> + + <boundaryline> + <pos>(0, 600)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <normal>(0.000000, -1.000000)</normal> + <keyframes> + </keyframes> + </boundaryline> + + <boundaryline> + <pos>(0, 600)</pos> + <colour>(0, 0, 0)</colour> + <bounce>0.100000</bounce> + <normal>(1.000000, 0.000000)</normal> + <keyframes> + </keyframes> + </boundaryline> + +</effect>+ \ No newline at end of file diff --git a/Water.py b/Water.py @@ -0,0 +1,52 @@ +# Water - collisions demo + +import PyIgnition, pygame, sys, math + + +screen = pygame.display.set_mode((800, 600)) +pygame.display.set_caption("PyIgnition demo: collisions") +clock = pygame.time.Clock() + + +effect = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +source = effect.CreateSource((0, 0), initspeed = 2.0, initdirection = math.pi, initspeedrandrange = 1.0, initdirectionrandrange = math.pi, particlesperframe = 20, particlelife = 80, drawtype = PyIgnition.DRAWTYPE_CIRCLE, colour = (100, 100, 250), radius = 10.0) +grav = effect.CreateDirectedGravity(0.2, 0.0, [0, 1]) +circle1 = effect.CreateCircle((100, 200), (0, 0, 0), bounce = 0.1, radius = 50.0) +circle2 = effect.CreateCircle((400, 100), (0, 0, 0), bounce = 0.1, radius = 50.0) +circle3 = effect.CreateCircle((300, 300), (0, 0, 0), bounce = 0.1, radius = 50.0) +circle4 = effect.CreateCircle((500, 250), (0, 0, 0), bounce = 0.1, radius = 50.0) +circle5 = effect.CreateCircle((150, 400), (0, 0, 0), bounce = 0.1, radius = 50.0) +rect1 = effect.CreateRectangle((500, 450), colour = (100, 200, 200), width = 250.0, height = 100.0, bounce = 0.2) +rect1.CreateKeyframe(200, pos = (400, 100), width = 400.0, interpolationtype = PyIgnition.INTERPOLATIONTYPE_COSINE) +rect1.CreateKeyframe(300, colour = (255, 0, 0)) +circle2.CreateKeyframe(250, pos = (400, 500), interpolationtype = PyIgnition.INTERPOLATIONTYPE_COSINE) +circle2.CreateKeyframe(300, colour = (0, 255, 50)) +circle4.CreateKeyframe(200, pos = circle4.pos) +circle4.CreateKeyframe(230, pos = (100, 300), interpolationtype = PyIgnition.INTERPOLATIONTYPE_COSINE) +source.CreateParticleKeyframe(60, colour = (100, 100, 250), radius = 10.0) +source.CreateParticleKeyframe(80, colour = (255, 255, 255), radius = 20.0) +line = effect.CreateBoundaryLine((700, 500), colour = (0, 0, 0), bounce = 0.1, normal = [-1.4142, -1.4142]) +line.CreateKeyframe(300, normal = [-2, -1]) +line.CreateKeyframe(500, normal = [-1, 0]) +line2 = effect.CreateBoundaryLine((0, 600), colour = (0, 0, 0), bounce = 0.1, normal = [0, -1]) +line3 = effect.CreateBoundaryLine((0, 600), colour = (0, 0, 0), bounce = 0.1, normal = [1, 0]) + +effect.SaveToFile("Water.ppe") +#effect.LoadFromFile("Water.ppe") + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + screen.fill((255, 255, 255)) + + source.SetPos(pygame.mouse.get_pos()) + if source.curframe % 30 == 0: + source.ConsolidateKeyframes() + + effect.Update() + effect.Redraw() + pygame.display.update() + clock.tick(30) diff --git a/Wind.py b/Wind.py @@ -0,0 +1,33 @@ +# Wind - randomised gravity + +import PyIgnition, pygame, sys + + +screen = pygame.display.set_mode((800, 600)) +pygame.display.set_caption("PyIgnition demo: wind") +clock = pygame.time.Clock() + +effect = PyIgnition.ParticleEffect(screen, (0, 0), (800, 600)) +source = effect.CreateSource((400, 600), initspeed = 5.0, initdirection = 0.0, initspeedrandrange = 2.0, initdirectionrandrange = 0.2, particlesperframe = 10, particlelife = 200, drawtype = PyIgnition.DRAWTYPE_POINT, colour = (255, 255, 200)) +grav = effect.CreateDirectedGravity(0.0, 0.2, [1, 0]) +#othergrav = effect.CreateDirectedGravity(0.05, 0.0, [0, 1]) +circle = effect.CreateCircle((0, 0), (0, 0, 0), bounce = 0.4, radius = 30.0) + + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_s: + effect.SaveToFile("Test.xml") + + screen.fill((100, 125, 200)) + circle.SetPos(pygame.mouse.get_pos()) + if circle.curframe % 30 == 0: + circle.ConsolidateKeyframes() + effect.Update() + effect.Redraw() + pygame.display.update() + clock.tick(30) diff --git a/constants.py b/constants.py @@ -0,0 +1,28 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Global constants module + + +# Which version is this? +PYIGNITION_VERSION = 1.0 + +# Drawtype constants +DRAWTYPE_POINT = 100 +DRAWTYPE_CIRCLE = 101 +DRAWTYPE_LINE = 102 +DRAWTYPE_SCALELINE = 103 +DRAWTYPE_BUBBLE = 104 +DRAWTYPE_IMAGE = 105 + +# Interpolation type constants +INTERPOLATIONTYPE_LINEAR = 200 +INTERPOLATIONTYPE_COSINE = 201 + +# Gravity constants +UNIVERSAL_CONSTANT_OF_MAKE_GRAVITY_LESS_STUPIDLY_SMALL = 1000.0 # Well, Newton got one to make it less stupidly large. +VORTEX_ACCELERATION = 0.01 # A tiny value added to the centripetal force exerted by vortex gravities to draw in particles +VORTEX_SWALLOWDIST = 20.0 # Particles closer than this will be swallowed up and regurgitated in the bit bucket + +# Fraction of radius which can go inside an object +RADIUS_PERMITTIVITY = 0.3+ \ No newline at end of file diff --git a/constants.pyc b/constants.pyc Binary files differ. diff --git a/courbd.ttf b/courbd.ttf Binary files differ. diff --git a/euphemia.ttf b/euphemia.ttf Binary files differ. diff --git a/framepointer.png b/framepointer.png Binary files differ. diff --git a/gravity.py b/gravity.py @@ -0,0 +1,199 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Gravity objects + + +from math import sqrt +import keyframes, interpolate, random +from constants import * + + +def RandomiseStrength(base, range): + return base + (float(random.randrange(int(-range * 100), int(range * 100))) / 100.0) + + +class DirectedGravity: + def __init__(self, strength = 0.0, strengthrandrange = 0.0, direction = [0, 1]): + self.selected = False + self.type = "directed" + self.initstrength = strength + self.strength = strength + self.strengthrandrange = strengthrandrange + directionmag = sqrt(direction[0]**2 + direction[1]**2) + self.direction = [direction[0] / directionmag, direction[1] / directionmag] + + self.keyframes = [] + self.CreateKeyframe(0, self.strength, self.strengthrandrange, self.direction) + self.curframe = 0 + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'direction_x':self.direction[0], 'direction_y':self.direction[1]}, self.keyframes) + self.initstrength = newvars['strength'] + self.strengthrandrange = newvars['strengthrandrange'] + self.direction = [newvars['direction_x'], newvars['direction_y']] + + if self.strengthrandrange != 0.0: + self.strength = RandomiseStrength(self.initstrength, self.strengthrandrange) + + self.curframe = self.curframe + 1 + + def GetForce(self, pos): + force = [self.strength * self.direction[0], self.strength * self.direction[1]] + + return force + + def GetForceOnParticle(self, particle): + return self.GetForce(particle.pos) + + def CreateKeyframe(self, frame, strength = None, strengthrandrange = None, direction = [None, None], interpolationtype = INTERPOLATIONTYPE_LINEAR): + return keyframes.CreateKeyframe(self.keyframes, frame, {'strength':strength, 'strengthrandrange':strengthrandrange, 'direction_x':direction[0], 'direction_y':direction[1], 'interpolationtype':interpolationtype}) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'direction_x':self.direction[0], 'direction_y':self.direction[1]}) + + def SetStrength(self, newstrength): + self.CreateKeyframe(self.curframe, strength = newstrength) + + def SetStrengthRandRange(self, newstrengthrandrange): + self.CreateKeyframe(self.curframe, strengthrandrange = newstrengthrandrange) + + def SetDirection(self, newdirection): + self.CreateKeyframe(self.curframe, direction = newdirection) + + +class PointGravity: + def __init__(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)): + self.selected = False + self.type = "point" + self.initstrength = strength + self.strength = strength + self.strengthrandrange = strengthrandrange + self.pos = pos + + self.keyframes = [] + self.CreateKeyframe(0, self.strength, self.strengthrandrange, self.pos) + self.curframe = 0 + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]}, self.keyframes) + self.initstrength = newvars['strength'] + self.strengthrandrange = newvars['strengthrandrange'] + self.pos = (newvars['pos_x'], newvars['pos_y']) + + if self.strengthrandrange != 0.0: + self.strength = RandomiseStrength(self.initstrength, self.strengthrandrange) + else: + self.strength = self.initstrength + + self.curframe = self.curframe + 1 + + def GetForce(self, pos): + distsquared = (pow(float(pos[0] - self.pos[0]), 2.0) + pow(float(pos[1] - self.pos[1]), 2.0)) + if distsquared == 0.0: + return [0.0, 0.0] + + forcemag = (self.strength * UNIVERSAL_CONSTANT_OF_MAKE_GRAVITY_LESS_STUPIDLY_SMALL) / (distsquared) + + # Calculate normal vector from pos to the gravity point and multiply by force magnitude to find force vector + dist = sqrt(distsquared) + dx = float(self.pos[0] - pos[0]) / dist + dy = float(self.pos[1] - pos[1]) / dist + + force = [forcemag * dx, forcemag * dy] + + return force + + def GetForceOnParticle(self, particle): + return self.GetForce(particle.pos) + + def GetMaxForce(self): + return self.strength * UNIVERSAL_CONSTANT_OF_MAKE_GRAVITY_LESS_STUPIDLY_SMALL + + def CreateKeyframe(self, frame, strength = None, strengthrandrange = None, pos = (None, None), interpolationtype = INTERPOLATIONTYPE_LINEAR): + return keyframes.CreateKeyframe(self.keyframes, frame, {'strength':strength, 'strengthrandrange':strengthrandrange, 'pos_x':pos[0], 'pos_y':pos[1], 'interpolationtype':interpolationtype}) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]}) + + def SetStrength(self, newstrength): + self.CreateKeyframe(self.curframe, strength = newstrength) + + def SetStrengthRandRange(self, newstrengthrandrange): + self.CreateKeyframe(self.curframe, strengthrandrange = newstrengthrandrange) + + def SetPos(self, newpos): + self.CreateKeyframe(self.curframe, pos = newpos) + + +class VortexGravity(PointGravity): + def __init__(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)): + PointGravity.__init__(self, strength, strengthrandrange, pos) + self.type = "vortex" + + self.CreateKeyframe(0, self.strength, self.strengthrandrange, self.pos) + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]}, self.keyframes) + self.initstrength = newvars['strength'] + self.strengthrandrange = newvars['strengthrandrange'] + self.pos = (newvars['pos_x'], newvars['pos_y']) + + if self.strengthrandrange != 0.0: + self.strength = RandomiseStrength(self.initstrength, self.strengthrandrange) + else: + self.strength = self.initstrength + + self.curframe = self.curframe + 1 + + def GetForce(self, pos): + try: + self.alreadyshownerror + except: + print "WARNING: VortexGravity relies upon particle velocities as well as positions, and so its \ + force can only be obtained using GetForceOnParticle([PyIgnition particle object]).".replace("\t", "") + self.alreadyshownerror = True + + return [0.0, 0.0] + + def GetForceOnParticle(self, particle): + # This uses F = m(v^2 / r) (the formula for centripetal force on an object moving in a circle) + # to determine what force should be applied to keep an object circling the gravity. A small extra + # force (self.strength * VORTEX_ACCELERATION) is added in order to accelerate objects inward as + # well, thus creating a spiralling effect. Note that unit mass is assumed throughout. + + distvector = [self.pos[0] - particle.pos[0], self.pos[1] - particle.pos[1]] # Vector from the particle to this gravity + try: + distmag = sqrt(float(distvector[0] ** 2) + float(distvector[1] ** 2)) # Distance from the particle to this gravity + except: + return [0.0, 0.0] # This prevents OverflowErrors + + if distmag == 0.0: + return [0.0, 0.0] + + if distmag <= VORTEX_SWALLOWDIST: + particle.alive = False + + normal = [float(distvector[0]) / distmag, float(distvector[1]) / distmag] # Normal from particle to this gravity + + velocitymagsquared = (particle.velocity[0] ** 2) + (particle.velocity[1] ** 2) # Velocity magnitude squared + forcemag = (velocitymagsquared / distmag) + (self.strength * VORTEX_ACCELERATION) # Force magnitude = (v^2 / r) + radial acceleration + + #velparmag = (particle.velocity[0] * normal[0]) + (particle.velocity[1] * normal[1]) # Magnitude of velocity parallel to normal + #velpar = [normal[0] * velparmag, normal[1] * velparmag] # Vector of velocity parallel to normal + #velperp = [particle.velocity[0] - velpar[0], particle.velocity[1] - velpar[1]] # Vector of velocity perpendicular to normal + # + #fnpar = [-velperp[1], velperp[0]] # Force normal parallel to normal + #fnperp = [velpar[1], -velpar[0]] # Force normal perpendicular to normal + # + #force = [(fnpar[0] + fnperp[0]) * forcemag, (fnpar[1] + fnperp[1]) * forcemag] + + force = [normal[0] * forcemag, normal[1] * forcemag] # Works, but sometimes goes straight to the gravity w/ little spiraling + + return force + + def CreateKeyframe(self, frame, strength = None, strengthrandrange = None, pos = (None, None), interpolationtype = INTERPOLATIONTYPE_LINEAR): + return keyframes.CreateKeyframe(self.keyframes, frame, {'strength':strength, 'strengthrandrange':strengthrandrange, 'pos_x':pos[0], 'pos_y':pos[1], 'interpolationtype':interpolationtype}) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]}) diff --git a/gravity.pyc b/gravity.pyc Binary files differ. diff --git a/interpolate.py b/interpolate.py @@ -0,0 +1,77 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Utility module for interpolating between keyframed values + + +import math +from constants import * + + +def LinearInterpolate(val1, val2, t): + diff = val2 - val1 + dist = float(diff) * t + + return val1 + dist + +def CosineInterpolate(val1, val2, t): + amplitude = float(val2 - val1) / 2.0 + midpoint = float(val1 + val2) / 2.0 + + return (amplitude * math.cos(math.pi * (1.0 - t))) + midpoint + + +def LinearInterpolateKeyframes(curframe, key1, key2, val1, val2): + if key1 == key2: + return val2 + + factor = float(curframe - key1) / float(key2 - key1) + + return LinearInterpolate(val1, val2, factor) + +def CosineInterpolateKeyframes(curframe, key1, key2, val1, val2): + if key1 == key2: + return val2 + + factor = float(curframe - key1) / float(key2 - key1) + + return CosineInterpolate(val1, val2, factor) + + +def InterpolateKeyframes(curframe, variables, keyframes): + if len(keyframes) == 1: + return keyframes[0].variables + + finalvariables = {} + + if not ('interpolationtype' in variables): + variables['interpolationtype'] = INTERPOLATIONTYPE_LINEAR + + keys = variables.keys() + + for i in xrange(len(keys)): # Determine current keyframe and next one for this variable + key = keys[i] + curkeyframe = None + nextkeyframe = None + + for i in xrange(len(keyframes)): + try: + frame = keyframes[i] + if (frame.variables[key] != None): # If the current keyframe has a keyed value for the current variable + if frame.frame <= curframe: # If its frame is below or equal to the current, it is the current keyframe + curkeyframe = i + if (nextkeyframe == None) and (frame.frame > curframe): # If this is the first keyframe with a frame higher than the current, it is the next keyframe + nextkeyframe = i + except KeyError: + pass + + if nextkeyframe == None or key == "interpolationtype": # If there is no next key frame, maintain the value specified by the current one + finalvariables[key] = keyframes[curkeyframe].variables[key] # (Also do this if it is an interpolation type variable; they should only change once their next keyframe has been reached + + else: # Interpolate between the current and next keyframes + if keyframes[nextkeyframe].variables['interpolationtype'] == INTERPOLATIONTYPE_LINEAR: + finalvariables[key] = LinearInterpolateKeyframes(curframe, keyframes[curkeyframe].frame, keyframes[nextkeyframe].frame, keyframes[curkeyframe].variables[key], keyframes[nextkeyframe].variables[key]) + elif keyframes[nextkeyframe].variables['interpolationtype'] == INTERPOLATIONTYPE_COSINE: + finalvariables[key] = CosineInterpolateKeyframes(curframe, keyframes[curkeyframe].frame, keyframes[nextkeyframe].frame, keyframes[curkeyframe].variables[key], keyframes[nextkeyframe].variables[key]) + + return finalvariables+ \ No newline at end of file diff --git a/interpolate.pyc b/interpolate.pyc Binary files differ. diff --git a/keyframepointer.png b/keyframepointer.png Binary files differ. diff --git a/keyframes test.py b/keyframes test.py @@ -0,0 +1,48 @@ +## Keyframing test + +import keyframes, interpolate, pygame + + +screen = pygame.display.set_mode((800, 600)) +clock = pygame.time.Clock() + + +class Circle: + def __init__(self, pos, colour, radius, screen): + self.x = pos[0] + self.y = pos[1] + self.r = colour[0] + self.g = colour[1] + self.b = colour[2] + self.rad = radius + self.screen = screen + self.variables = {"x":self.x, "y":self.y, "r":self.r, "g":self.g, "b":self.b, "rad":self.rad} + self.keyframes = [] + self.keyframes.append(keyframes.Keyframe(1, self.variables)) + self.keyframes.append(keyframes.Keyframe(200, {"x":800, "y":600})) + self.keyframes.append(keyframes.Keyframe(300, {"r":255, "g":0, "b":100})) + self.keyframes.append(keyframes.Keyframe(350, {"r":0, "y":0})) + self.keyframes.append(keyframes.Keyframe(400, {"x":400, "y":300, "rad":500})) + self.curframe = 1 + + def Update(self): + self.variables = interpolate.InterpolateKeyframes(self.curframe, self.variables, self.keyframes) + self.curframe = self.curframe + 1 + + def Draw(self): + pygame.draw.circle(self.screen, (self.variables["r"], self.variables["g"], self.variables["b"]), (self.variables["x"], self.variables["y"]), self.variables["rad"]) + + +circle = Circle((0, 0), (0, 255, 0), 10, screen) + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + screen.fill((0, 0, 0)) + circle.Update() + circle.Draw() + + pygame.display.update() + clock.tick(30)+ \ No newline at end of file diff --git a/keyframes.py b/keyframes.py @@ -0,0 +1,58 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Keyframe object and generic keyframe creation function + + +from constants import * + + +def CreateKeyframe(parentframes, frame, variables): + newframe = Keyframe(frame, variables) + + # Look for duplicate keyframes and copy other defined variables + try: + oldkey = (keyframe for keyframe in parentframes if keyframe.frame == frame).next() + except StopIteration: + oldkey = None + + if oldkey != None: + for var in oldkey.variables.keys(): # For every variable defined by the old keyframe + if (var not in newframe.variables or newframe.variables[var] == None) and (oldkey.variables[var] != None): # If a variable is undefined, copy its value to the new keyframe + newframe.variables[var] = oldkey.variables[var] + + # Remove the duplicate keyframe, if it existed + for duplicate in (keyframe for keyframe in parentframes if keyframe.frame == frame): + parentframes.remove(duplicate) + break + + # Append the new keyframe then sort them all by frame + parentframes.append(newframe) + sortedframes = sorted(parentframes, key=lambda keyframe: keyframe.frame) + parentframes[:] = sortedframes + + return newframe # Return a reference to the new keyframe, in case it's needed + +def ConsolidateKeyframes(parentframes, frame, variables): + newframe = Keyframe(frame, variables) + parentframes.append(newframe) + + finallist = [] # A truncated list of keyframes + + # Append all the frames which come after the current one to the final list + for keyframe in parentframes: + if keyframe.frame >= frame: + finallist.append(keyframe) + + # Sort the keyframes and give them to the parent object + sortedframes = sorted(finallist, key=lambda keyframe: keyframe.frame) + parentframes[:] = sortedframes + +class Keyframe: + def __init__(self, frame = 0, variables = {}): + self.frame = frame + self.variables = variables + + if not ('interpolationtype' in self.variables): + self.variables['interpolationtype'] = INTERPOLATIONTYPE_LINEAR + + \ No newline at end of file diff --git a/keyframes.pyc b/keyframes.pyc Binary files differ. diff --git a/obstacles.py b/obstacles.py @@ -0,0 +1,405 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Obstacle objects + +import pygame +from math import sqrt, pow +from gravity import UNIVERSAL_CONSTANT_OF_MAKE_GRAVITY_LESS_STUPIDLY_SMALL +import keyframes, interpolate +from constants import * + + +MAXDIST = 20.0 + + +def dotproduct2d(v1, v2): + return ((v1[0] * v2[0]) + (v1[1] * v2[1])) + +def magnitude(vec): + try: + return sqrt(vec[0] ** 2 + vec[1] ** 2) + except: + return 1.0 + +def magnitudesquared(vec): + try: + return (vec[0] ** 2 + vec[1] ** 2) + except: + return 1.0 + +def normalise(vec): + mag = magnitude(vec) + return [vec[0] / mag, vec[1] / mag] + + +class Obstacle: + def __init__(self, parenteffect, pos, colour, bounce): + self.selected = False + self.parenteffect = parenteffect + self.pos = pos + self.colour = colour + self.bounce = bounce + self.maxdist = MAXDIST # The maximum (square-based, not circle-based) distance away for which forces will still be calculated + self.curframe = 0 + self.keyframes = [] + + def Draw(self, display): + pass + + def Update(self): + self.curframe = self.curframe + 1 + + def OutOfRange(self, pos): + return (abs(pos[0] - self.pos[0]) > self.maxdist) or (abs(pos[1] - self.pos[1]) > self.maxdist) + + def InsideObject(self, pos, pradius): + pass + + def GetResolved(self, pos, pradius): # Get a resolved position for a particle located inside the object + pass + + def GetDist(self, pos): + return magnitude([pos[0] - self.pos[0], pos[1] - self.pos[1]]) + + def GetNormal(self, pos): # Gets the normal relevant to a particle at the supplied potision (for example, that of the appropriate side of a squre) + pass + + def GetForceFactor(self, pos, pradius): # Gets the force as a factor of maximum available force (0.0 - 1.0), determined by an inverse cube distance law + pass + + def GetForce(self, pos, velocity, pradius = 0.0): # Gets the final (vector) force + if self.OutOfRange(pos) or self.bounce == 0.0: + return [0.0, 0.0] + + if (pos[0] == self.pos[0]) and (pos[1] == self.pos[1]): + return [0.0, 0.0] + + normal = self.GetNormal(pos) + scalingfactor = -dotproduct2d(normal, velocity) # An integer between 0.0 and 1.0 used to ensure force is maximised for head-on collisions and minimised for scrapes + + if scalingfactor <= 0.0: # The force should never be attractive, so take any negative value of the scaling factor to be zero + return [0.0, 0.0] # A scaling factor of zero always results in zero force + + forcefactor = (self.GetForceFactor(pos, pradius)) + velmag = magnitude(velocity) # Magnitude of the velocity - multiplied in the force equation + + # Force = bounce factor * velocity * distance force factor (0.0 - 1.0) * angle force factor (0.0 - 1.0), along the direction of the normal pointing away from the obstacle + return [normal[0] * forcefactor * velmag * scalingfactor * self.bounce, normal[1] * forcefactor * velmag * scalingfactor * self.bounce] + + def CreateKeyframe(self): + pass + + def SetPos(self, newpos): + self.CreateKeyframe(self.curframe, pos = newpos) + + def SetColour(self, newcolour): + self.CreateKeyframe(self.curframe, colour = newcolour) + + def SetBounce(self, newbounce): + self.CreateKeyframe(self.curframe, bounce = newbounce) + + +class Circle(Obstacle): + def __init__(self, parenteffect, pos, colour, bounce, radius): + Obstacle.__init__(self, parenteffect, pos, colour, bounce) + self.type = "circle" + self.radius = radius + self.radiussquared = self.radius ** 2 + self.maxdist = MAXDIST + self.radius + self.CreateKeyframe(0, self.pos, self.colour, self.bounce, self.radius) + + def Draw(self, display): + offset = self.parenteffect.pos + pygame.draw.circle(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), int(self.radius)) + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'colour_r':self.colour[0], 'colour_g':self.colour[1], 'colour_b':self.colour[2], 'bounce':self.bounce, 'radius':self.radius}, self.keyframes) + self.pos = (newvars['pos_x'], newvars['pos_y']) + self.colour = (newvars['colour_r'], newvars['colour_g'], newvars['colour_b']) + self.bounce = newvars['bounce'] + self.radius = newvars['radius'] + + Obstacle.Update(self) + + def InsideObject(self, pos, pradius = 0.0): + mag = magnitude([pos[0] - self.pos[0], pos[1] - self.pos[1]]) + return (((mag - pradius) ** 2) < self.radiussquared) + + def GetResolved(self, pos, pradius = 0.0): + if pos == self.pos: # If the position is at this obstacle's origin, shift it up a pixel to avoid divide-by-zero errors + return self.GetResolved([pos[0], pos[1] - 1]) + + vec = [pos[0] - self.pos[0], pos[1] - self.pos[1]] + mag = magnitude(vec) + nor = [vec[0] / mag, vec[1] / mag] + + # Split the pradius into appropriate components by multiplying the normal vector by pradius + pradiusvec = [(nor[0] * pradius), (nor[1] * pradius)] + + correctedvec = [nor[0] * (self.radius), nor[1] * (self.radius)] + + return [self.pos[0] + correctedvec[0] + pradiusvec[0], self.pos[1] + correctedvec[1] + pradiusvec[1]] + + def GetNormal(self, pos): + vec = [pos[0] - self.pos[0], pos[1] - self.pos[1]] + mag = magnitude(vec) + + return [vec[0] / mag, vec[1] / mag] + + def GetForceFactor(self, pos, pradius = 0.0): + nvec = self.GetNormal(pos) + tempradius = self.radius + vec = [tempradius * nvec[0], tempradius * nvec[1]] + newpos = [pos[0] - vec[0], pos[1] - vec[1]] + + distcubed = (abs(pow(float(newpos[0] - self.pos[0]), 3.0)) + abs(pow(float(newpos[1] - self.pos[1]), 3.0))) - (pradius * pradius * pradius) + if distcubed <= 1.0: + return 1.0 + + force = (1.0 / distcubed) + + return force + + def CreateKeyframe(self, frame, pos = (None, None), colour = (None, None, None), bounce = None, radius = None, interpolationtype = INTERPOLATIONTYPE_LINEAR): + return keyframes.CreateKeyframe(self.keyframes, frame, {'pos_x':pos[0], 'pos_y':pos[1], 'colour_r':colour[0], 'colour_g':colour[1], 'colour_b':colour[2], 'bounce':bounce, 'radius':radius, 'interpolationtype':interpolationtype}) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'colour_r':self.colour[0], 'colour_g':self.colour[1], 'colour_b':self.colour[2], 'bounce':self.bounce, 'radius':self.radius}) + + def SetRadius(self, newradius): + self.CreateKeyframe(self.curframe, radius = newradius) + + +class Rectangle(Obstacle): + def __init__(self, parenteffect, pos, colour, bounce, width, height): + Obstacle.__init__(self, parenteffect, pos, colour, bounce) + self.type = "rectangle" + self.width = width + self.halfwidth = self.width / 2.0 + self.height = height + self.halfheight = height / 2.0 + self.maxdist = max(self.halfwidth, self.halfheight) + MAXDIST + self.CreateKeyframe(0, self.pos, self.colour, self.bounce, self.width, self.height) + + def Draw(self, display): + offset = self.parenteffect.pos + pygame.draw.rect(display, self.colour, pygame.Rect(offset[0] + (self.pos[0] - self.halfwidth), offset[1] + (self.pos[1] - self.halfheight), self.width, self.height)) + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'colour_r':self.colour[0], 'colour_g':self.colour[1], 'colour_b':self.colour[2], 'bounce':self.bounce, 'width':self.width, 'height':self.height}, self.keyframes) + self.pos = (newvars['pos_x'], newvars['pos_y']) + self.colour = (newvars['colour_r'], newvars['colour_g'], newvars['colour_b']) + self.bounce = newvars['bounce'] + self.width = newvars['width'] + self.halfwidth = self.width / 2.0 + self.height = newvars['height'] + self.halfheight = self.height / 2.0 + self.maxdist = max(self.halfwidth, self.halfheight) + MAXDIST + + Obstacle.Update(self) + + def InsideObject(self, pos, pradius = 0.0): + return (((pos[0] + pradius) > (self.pos[0] - self.halfwidth)) and ((pos[0] - pradius) < (self.pos[0] + self.halfwidth)) and ((pos[1] + pradius) > (self.pos[1] - self.halfheight)) and ((pos[1] - pradius) < self.pos[1] + self.halfheight)) + + def GetResolved(self, pos, pradius = 0.0): + if pos == self.pos: # If the position is at this obstacle's origin, shift it up a pixel to avoid divide-by-zero errors + return self.GetResolved([pos[0], pos[1] - 1]) + + # Where 'triangles' within the rectangle are referred to, imagine a rectangle with diagonals drawn between its vertices. The four triangles formed by this process are the ones referred to + if pos[0] == self.pos[0]: # If it's directly above the centre of the rectangle + if pos[1] > self.pos[1]: + return [pos[0], self.pos[1] + self.halfheight + pradius] + else: + return [pos[0], self.pos[1] - (self.halfheight + pradius)] + elif pos[1] == self.pos[1]: # If it's directly to one side of the centre of the rectangle + if pos[0] > self.pos[0]: + return [self.pos[0] + self.halfwidth + pradius, pos[1]] + else: + return [self.pos[0] - (self.halfwidth + pradius), pos[1]] + elif abs(float(pos[1] - self.pos[1]) / float(pos[0] - self.pos[0])) > (float(self.height) / float(self.width)): # If it's in the upper or lower triangle of the rectangle + return [pos[0], self.pos[1] + ((self.halfheight + pradius) * ((pos[1] - self.pos[1]) / abs(pos[1] - self.pos[1])))] # Halfheight is multiplied by a normalised version of (pos[1] - self.pos[1]) - thus if (pos[1] - self.pos[1]) is negative, it should be subtracted as the point is in the upper triangle + else: # If it's in the left or right triangle of the rectangle + return [self.pos[0] + ((self.halfwidth + pradius) * ((pos[0] - self.pos[0]) / abs(pos[0] - self.pos[0]))), pos[1]] + + def GetNormal(self, pos): + if pos[1] < (self.pos[1] - self.halfheight): + return [0, -1] + elif pos[1] > (self.pos[1] + self.halfheight): + return [0, 1] + elif pos[0] < (self.pos[0] - self.halfwidth): + return [-1, 0] + elif pos[0] > (self.pos[0] + self.halfwidth): + return [1, 0] + else: + vect = [pos[0] - self.pos[0], pos[1] - self.pos[1]] + mag = magnitude(vect) + return [vect[0] / mag, vect[1] / mag] + + def GetForceFactor(self, pos, pradius = 0.0): + nor = self.GetNormal(pos) + + if nor[0] == 0: + if (pos[0] > (self.pos[0] - self.halfwidth)) and (pos[0] < (self.pos[0] + self.halfwidth)): + r = (abs(pos[1] - self.pos[1]) - self.halfheight) - pradius + else: + return 0.0 + elif nor[1] == 0: + if (pos[1] > (self.pos[1] - self.halfheight)) and (pos[1] < (self.pos[1] + self.halfheight)): + r = (abs(pos[0] - self.pos[0]) - self.halfwidth) - pradius + else: + return 0.0 + else: + return 1.0 + + if r <= 1.0: + return 1.0 + + return (1.0 / pow(float(r), 3.0)) + + def CreateKeyframe(self, frame, pos = (None, None), colour = (None, None, None), bounce = None, width = None, height = None, interpolationtype = INTERPOLATIONTYPE_LINEAR): + return keyframes.CreateKeyframe(self.keyframes, frame, {'pos_x':pos[0], 'pos_y':pos[1], 'colour_r':colour[0], 'colour_g':colour[1], 'colour_b':colour[2], 'bounce':bounce, 'width':width, 'height':height, 'interpolationtype':interpolationtype}) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'colour_r':self.colour[0], 'colour_g':self.colour[1], 'colour_b':self.colour[2], 'bounce':self.bounce, 'width':self.width, 'height':self.height}) + + def SetWidth(self, newwidth): + self.CreateKeyframe(self.curframe, width = newwidth) + + def SetHeight(self, newheight): + self.CreateKeyframe(self.curframe, height = newheight) + + +class BoundaryLine(Obstacle): + def __init__(self, parenteffect, pos, colour, bounce, normal): + Obstacle.__init__(self, parenteffect, pos, colour, bounce) + self.type = "boundaryline" + self.normal = normalise(normal) + self.edgecontacts = [] + self.hascontacts = False + self.storedw, self.storedh = None, None + self.curframe = 0 + self.CreateKeyframe(0, self.pos, self.colour, self.bounce, self.normal) + + def Draw(self, display): + offset = self.parenteffect.pos + + W = display.get_width() + H = display.get_height() + + if (W != self.storedw) or (H != self.storedh): + self.hascontacts = False + + if not self.hascontacts: + self.storedw, self.storedh = W, H + + edgecontacts = [] # Where the line touches the screen edges + + if self.normal[0] == 0.0: + edgecontacts = [[0, self.pos[1]], [W, self.pos[1]]] + + elif self.normal[1] == 0.0: + edgecontacts = [[self.pos[0], 0], [self.pos[0], H]] + + else: + pdotn = (self.pos[0] * self.normal[0]) + (self.pos[1] * self.normal[1]) + reciprocaln0 = (1.0 / self.normal[0]) + reciprocaln1 = (1.0 / self.normal[1]) + + # Left-hand side of the screen + pointl = [0, 0] + pointl[1] = pdotn * reciprocaln1 + if (pointl[1] >= 0) and (pointl[1] <= H): + edgecontacts.append(pointl) + + # Top of the screen + pointt = [0, 0] + pointt[0] = pdotn * reciprocaln0 + if (pointt[0] >= 0) and (pointt[0] <= W): + edgecontacts.append(pointt) + + # Right-hand side of the screen + pointr = [W, 0] + pointr[1] = (pdotn - (W * self.normal[0])) * reciprocaln1 + if (pointr[1] >= 0) and (pointr[1] <= H): + edgecontacts.append(pointr) + + # Bottom of the screen + pointb = [0, H] + pointb[0] = (pdotn - (H * self.normal[1])) * reciprocaln0 + if (pointb[0] >= 0) and (pointb[0] <= W): + edgecontacts.append(pointb) + + self.edgecontacts = edgecontacts + self.hascontacts = True + + tempedgecontacts = [] + + for contact in self.edgecontacts: + tempedgecontacts.append([offset[0] + contact[0], offset[1] + contact[1]]) + + if len(tempedgecontacts) >= 2: + pygame.draw.aalines(display, self.colour, True, tempedgecontacts) + else: + pass # The line must be completely outwith the boundaries of the display + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'colour_r':self.colour[0], 'colour_g':self.colour[1], 'colour_b':self.colour[2], 'bounce':self.bounce, 'normal_x':self.normal[0], 'normal_y':self.normal[1]}, self.keyframes) + self.pos = (newvars['pos_x'], newvars['pos_y']) + self.colour = (newvars['colour_r'], newvars['colour_g'], newvars['colour_b']) + self.bounce = newvars['bounce'] + oldnormal = self.normal[:] + self.normal = [newvars['normal_x'], newvars['normal_y']] + if self.normal != oldnormal: + self.hascontacts = False + + Obstacle.Update(self) + + def OutOfRange(self, pos): + return (self.GetDist(pos) > MAXDIST) + + def InsideObject(self, pos, pradius = 0.0): + if pradius == 0.0: # If the particle has no radius, just test whether its centre position has crossed the line + return (((float(pos[0] - self.pos[0]) * self.normal[0]) + (float(pos[1] - self.pos[1]) * self.normal[1])) <= 0.0) + + radialnormal = [self.normal[0] * pradius, self.normal[1] * pradius] + leftside = [pos[0] + radialnormal[0], pos[1] + radialnormal[1]] + rightside = [pos[0] - radialnormal[0], pos[1] - radialnormal[1]] + + return ((((float(leftside[0] - self.pos[0]) * self.normal[0]) + (float(leftside[1] - self.pos[1]) * self.normal[1])) <= 0.0) + or (((float(rightside[0] - self.pos[0]) * self.normal[0]) + (float(rightside[1] - self.pos[1]) * self.normal[1])) <= 0.0)) + + def GetResolved(self, pos, pradius = 0.0): + if pos == self.pos: # If the position is at this obstacle's origin, shift it up a pixel to avoid divide-by-zero errors + return self.GetResolved([pos[0], pos[1] - 1]) + + dist = abs(self.GetDist(pos, pradius)) + vec = [dist * self.normal[0], dist * self.normal[1]] + + return [pos[0] + vec[0], pos[1] + vec[1]] + + def GetNormal(self, pos): + return self.normal + + def GetDist(self, pos, pradius = 0.0): + v = [float(pos[0] - self.pos[0]), float(pos[1] - self.pos[1])] + return (v[0] * self.normal[0]) + (v[1] * self.normal[1]) - pradius + + def GetForceFactor(self, pos, pradius = 0.0): + r = self.GetDist(pos) - pradius + + if r <= 1.0: + return 1.0 + + return (1.0 / pow(r, 3.0)) + + def CreateKeyframe(self, frame, pos = (None, None), colour = (None, None, None), bounce = None, normal = [None, None], interpolationtype = INTERPOLATIONTYPE_LINEAR): + if (normal != [None, None]) and (abs(magnitudesquared(normal) - 1.0) >= 0.3): + normal = normalise(normal) + return keyframes.CreateKeyframe(self.keyframes, frame, {'pos_x':pos[0], 'pos_y':pos[1], 'colour_r':colour[0], 'colour_g':colour[1], 'colour_b':colour[2], 'bounce':bounce, 'normal_x':normal[0], 'normal_y':normal[1], 'interpolationtype':interpolationtype}) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'colour_r':self.colour[0], 'colour_g':self.colour[1], 'colour_b':self.colour[2], 'bounce':self.bounce, 'normal_x':self.normal[0], 'normal_y':self.normal[1]}) + + def SetNormal(self, newnormal): + self.CreateKeyframe(self.curframe, normal = newnormal) diff --git a/obstacles.pyc b/obstacles.pyc Binary files differ. diff --git a/particles.py b/particles.py @@ -0,0 +1,202 @@ +### EXESOFT PYIGNITION ### +# Copyright David Barker 2010 +# +# Particle and ParticleSource objects + + +import keyframes, interpolate, random, math, pygame +from constants import * + + +class Particle: + def __init__(self, parent, initpos, velocity, life, drawtype = DRAWTYPE_POINT, colour = (0, 0, 0), radius = 0.0, length = 0.0, image = None, keyframes = []): + self.parent = parent + self.pos = initpos + self.velocity = velocity + self.life = life + self.drawtype = drawtype + self.colour = colour + self.radius = radius + self.length = length + self.image = image + + self.keyframes = [] + self.keyframes.extend(keyframes[:]) + self.curframe = 0 + + self.alive = True + + def Update(self): + self.pos = [self.pos[0] + self.velocity[0], self.pos[1] + self.velocity[1]] + + if self.life != -1 and self.curframe > self.life: + self.alive = False + else: + if self.life == -1 and self.curframe >= len(self.parent.particlecache): # If the particle has infinite life and has passed the last cached frame + self.colour = (self.parent.particlecache[len(self.parent.particlecache) - 1]['colour_r'], self.parent.particlecache[len(self.parent.particlecache) - 1]['colour_g'], self.parent.particlecache[len(self.parent.particlecache) - 1]['colour_b']) + self.radius = self.parent.particlecache[len(self.parent.particlecache) - 1]['radius'] + self.length = self.parent.particlecache[len(self.parent.particlecache) - 1]['length'] + else: # Otherwise, get the values for the current frame + self.colour = (self.parent.particlecache[self.curframe]['colour_r'], self.parent.particlecache[self.curframe]['colour_g'], self.parent.particlecache[self.curframe]['colour_b']) + self.radius = self.parent.particlecache[self.curframe]['radius'] + self.length = self.parent.particlecache[self.curframe]['length'] + + self.curframe = self.curframe + 1 + + def Draw(self, display): + offset = self.parent.parenteffect.pos + + if (self.pos[0] > 10000) or (self.pos[1] > 10000) or (self.pos[0] < -10000) or (self.pos[1] < -10000): + return + + if self.drawtype == DRAWTYPE_POINT: # Point + pygame.draw.circle(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), 0) + + elif self.drawtype == DRAWTYPE_CIRCLE: # Circle + pygame.draw.circle(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), int(self.radius)) + + elif self.drawtype == DRAWTYPE_LINE: + if self.length == 0.0: + pygame.draw.circle(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), 0) + + else: + # Vector = (velocity / mag(velocity)) * length (a line of magnitude 'length' in + # direction of velocity); this is calculated as velocity / (mag(velocity) / length) + # so that parts consistent for both components in the final calculation are only calculated once + velocitymagoverlength = math.sqrt(self.velocity[0]**2 + self.velocity[1]**2) / self.length + + if velocitymagoverlength > 0.0: # Avoid division-by-zero errors by handling lines with zero velocity separately + linevec = [(self.velocity[0] / velocitymagoverlength), (self.velocity[1] / velocitymagoverlength)] + else: + linevec = [self.length, 0.0] # Draw a line pointing to the right + + endpoint = [offset[0] + int(self.pos[0] + linevec[0]), offset[1] + int(self.pos[1] + linevec[1])] + pygame.draw.aaline(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), endpoint) + + elif self.drawtype == DRAWTYPE_SCALELINE: # Scaling line (scales with velocity) + endpoint = [offset[0] + int(self.pos[0] + self.velocity[0]), offset[1] + int(self.pos[1] + self.velocity[1])] + pygame.draw.aaline(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), endpoint) + + elif self.drawtype == DRAWTYPE_BUBBLE: # Bubble + if self.radius >= 1.0: + pygame.draw.circle(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), int(self.radius), 1) + else: # Pygame won't draw circles with thickness < radius, so if radius is smaller than one don't bother trying to set thickness + pygame.draw.circle(display, self.colour, (offset[0] + int(self.pos[0]), offset[1] + int(self.pos[1])), int(self.radius)) + + elif self.drawtype == DRAWTYPE_IMAGE: # Image + if self.image != None: + size = self.image.get_size() + display.blit(self.image, (offset[0] + int(self.pos[0] - (size[1]* 0.5)), offset[1] + int(self.pos[1] - (size[1] * 0.5)))) + + def CreateKeyframe(self, frame, colour = (None, None, None), radius = None, length = None): + keyframes.CreateKeyframe(self.keyframes, frame, {'colour_r':colour[0], 'colour_g':colour[1], 'colour_b':colour[2], 'radius':radius, 'length':length}) + + +class ParticleSource: + def __init__(self, parenteffect, pos, initspeed, initdirection, initspeedrandrange, initdirectionrandrange, particlesperframe, particlelife, genspacing, drawtype = 0, colour = (0, 0, 0), radius = 0.0, length = 0.0, imagepath = None): + self.selected = False + self.parenteffect = parenteffect + self.pos = pos + self.initspeed = initspeed + self.initdirection = initdirection + self.initspeedrandrange = initspeedrandrange + self.initdirectionrandrange = initdirectionrandrange + self.particlesperframe = particlesperframe + self.particlelife = particlelife + self.genspacing = genspacing + self.colour = colour + self.drawtype = drawtype + self.radius = radius + self.length = length + self.imagepath = imagepath + if self.imagepath == None: + self.image = None + else: + self.image = pygame.image.load(self.imagepath).convert_alpha() + self.drawtype = drawtype + + self.keyframes = [] + self.CreateKeyframe(0, self.pos, self.initspeed, self.initdirection, self.initspeedrandrange, self.initdirectionrandrange, self.particlesperframe, self.genspacing) + self.particlekeyframes = [] + self.particlecache = [] + self.CreateParticleKeyframe(0, colour = self.colour, radius = self.radius, length = self.length) + self.curframe = 0 + + def Update(self): + newvars = interpolate.InterpolateKeyframes(self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'initspeed':self.initspeed, 'initdirection':self.initdirection, 'initspeedrandrange':self.initspeedrandrange, 'initdirectionrandrange':self.initdirectionrandrange, 'particlesperframe':self.particlesperframe, 'genspacing':self.genspacing}, self.keyframes) + self.pos = (newvars['pos_x'], newvars['pos_y']) + self.initspeed = newvars['initspeed'] + self.initdirection = newvars['initdirection'] + self.initspeedrandrange = newvars['initspeedrandrange'] + self.initdirectionrandrange = newvars['initdirectionrandrange'] + self.particlesperframe = newvars['particlesperframe'] + self.genspacing = newvars['genspacing'] + + particlesperframe = self.particlesperframe + + if (self.genspacing == 0) or ((self.curframe % self.genspacing) == 0): + for i in range(0, int(particlesperframe)): + self.CreateParticle() + + self.curframe = self.curframe + 1 + + def CreateParticle(self): + if self.initspeedrandrange != 0.0: + speed = self.initspeed + (float(random.randrange(int(-self.initspeedrandrange * 100.0), int(self.initspeedrandrange * 100.0))) / 100.0) + else: + speed = self.initspeed + if self.initdirectionrandrange != 0.0: + direction = self.initdirection + (float(random.randrange(int(-self.initdirectionrandrange * 100.0), int(self.initdirectionrandrange * 100.0))) / 100.0) + else: + direction = self.initdirection + velocity = [speed * math.sin(direction), -speed * math.cos(direction)] + newparticle = Particle(self, initpos = self.pos, velocity = velocity, life = self.particlelife, drawtype = self.drawtype, colour = self.colour, radius = self.radius, length = self.length, image = self.image, keyframes = self.particlekeyframes) + self.parenteffect.AddParticle(newparticle) + + def CreateKeyframe(self, frame, pos = (None, None), initspeed = None, initdirection = None, initspeedrandrange = None, initdirectionrandrange = None, particlesperframe = None, genspacing = None, interpolationtype = INTERPOLATIONTYPE_LINEAR): + return keyframes.CreateKeyframe(self.keyframes, frame, {'pos_x':pos[0], 'pos_y':pos[1], 'initspeed':initspeed, 'initdirection':initdirection, 'initspeedrandrange':initspeedrandrange, 'initdirectionrandrange':initdirectionrandrange, 'particlesperframe':particlesperframe, 'genspacing':genspacing, 'interpolationtype':interpolationtype}) + + def CreateParticleKeyframe(self, frame, colour = (None, None, None), radius = None, length = None, interpolationtype = INTERPOLATIONTYPE_LINEAR): + newframe = keyframes.CreateKeyframe(self.particlekeyframes, frame, {'colour_r':colour[0], 'colour_g':colour[1], 'colour_b':colour[2], 'radius':radius, 'length':length, 'interpolationtype':interpolationtype}) + self.PreCalculateParticles() + return newframe + + def GetKeyframeValue(self, keyframe): + return keyframe.frame + + def PreCalculateParticles(self): + self.particlecache = [] # Clear the cache + + # If the particle has infinite life, interpolate for each frame up until its last keyframe + if self.particlelife == -1: + particlelife = max(self.particlekeyframes, key = self.GetKeyframeValue).frame + else: # Otherwise, interpolate the particle variables for each frame of its life + particlelife = self.particlelife + + for i in xrange(0, particlelife + 1): + vars = interpolate.InterpolateKeyframes(i, {'colour_r':0, 'colour_g':0, 'colour_b':0, 'radius':0, 'length':0}, self.particlekeyframes) + self.particlecache.append(vars) + + def ConsolidateKeyframes(self): + keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'pos_x':self.pos[0], 'pos_y':self.pos[1], 'initspeed':self.initspeed, 'initdirection':self.initdirection, 'initspeedrandrange':self.initspeedrandrange, 'initdirectionrandrange':self.initdirectionrandrange, 'particlesperframe':self.particlesperframe, 'genspacing':self.genspacing}) + + def SetPos(self, newpos): + self.CreateKeyframe(self.curframe, pos = newpos) + + def SetInitSpeed(self, newinitspeed): + self.CreateKeyframe(self.curframe, initspeed = newinitspeed) + + def SetInitDirection(self, newinitdirection): + self.CreateKeyframe(self.curframe, initdirection = newinitdirection) + + def SetInitSpeedRandRange(self, newinitspeedrandrange): + self.CreateKeyframe(self.curframe, initspeedrandrange = newinitspeedrandrange) + + def SetInitDirectionRandRange(self, newinitdirectionrandrange): + self.CreateKeyframe(self.curframe, initdirectionrandrange = newinitdirectionrandrange) + + def SetParticlesPerFrame(self, newparticlesperframe): + self.CreateKeyframe(self.curframe, particlesperframe = newparticlesperframe) + + def SetGenSpacing(self, newgenspacing): + self.CreateKeyframe(self.curframe, genspacing = newgenspacing) diff --git a/particles.pyc b/particles.pyc Binary files differ. diff --git a/pygamedisplay.pyc b/pygamedisplay.pyc Binary files differ. diff --git a/timelinectrl.pyc b/timelinectrl.pyc Binary files differ. diff --git a/trunk/.bzr/README b/trunk/.bzr/README @@ -0,0 +1,3 @@ +This is a Bazaar control directory. +Do not change any files in this directory. +See http://bazaar-vcs.org/ for more information about Bazaar. diff --git a/trunk/.bzr/branch-format b/trunk/.bzr/branch-format @@ -0,0 +1 @@ +Bazaar-NG meta directory, format 1 diff --git a/trunk/.bzr/branch/branch.conf b/trunk/.bzr/branch/branch.conf diff --git a/trunk/.bzr/branch/format b/trunk/.bzr/branch/format @@ -0,0 +1 @@ +Bazaar Branch Format 7 (needs bzr 1.6) diff --git a/trunk/.bzr/branch/last-revision b/trunk/.bzr/branch/last-revision @@ -0,0 +1 @@ +0 null: diff --git a/trunk/.bzr/branch/tags b/trunk/.bzr/branch/tags diff --git a/trunk/.bzr/checkout/conflicts b/trunk/.bzr/checkout/conflicts @@ -0,0 +1 @@ +BZR conflict list format 1 diff --git a/trunk/.bzr/checkout/dirstate b/trunk/.bzr/checkout/dirstate Binary files differ. diff --git a/trunk/.bzr/checkout/format b/trunk/.bzr/checkout/format @@ -0,0 +1 @@ +Bazaar Working Tree Format 6 (bzr 1.14) diff --git a/trunk/.bzr/checkout/views b/trunk/.bzr/checkout/views diff --git a/wx test 2.py b/wx test 2.py @@ -0,0 +1,117 @@ +### WX TEST ### +# Copyright David Barker 2010 +# +# A simple test of using wxPython to create a gui for PyIgnition + + +import wx, sys, os, pygame, PyIgnition + +class PygameDisplay(wx.Window): + def __init__(self, parent, ID): + wx.Window.__init__(self, parent, ID) + self.parent = parent + self.hwnd = self.GetHandle() + os.environ['SDL_VIDEODRIVER'] = 'windib' + os.environ['SDL_WINDOWID'] = str(self.hwnd) + pygame.display.init() + self.screen = pygame.display.set_mode() + self.size = self.GetSizeTuple() + self.timer = wx.Timer(self) + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_TIMER, self.Update, self.timer) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.fps = 60.0 + self.timespacing = 1000.0 / self.fps + self.timer.Start(self.timespacing, False) + + self.effect = PyIgnition.ParticleEffect(self.screen, (0, 0), self.size) + self.source = self.effect.CreateSource((self.size[0] / 2, self.size[1]), initspeed = 5.0, initdirection = 0.0, initspeedrandrange = 2.0, initdirectionrandrange = 0.2, particlesperframe = 10, particlelife = 200, drawtype = PyIgnition.DRAWTYPE_CIRCLE, colour = (255, 20, 200), radius = 0.0) + self.source.CreateParticleKeyframe(100, radius = 20.0) + self.source.CreateParticleKeyframe(25, colour = (255, 0, 100)) + self.source.CreateParticleKeyframe(50, colour = (100, 255, 100)) + self.source.CreateParticleKeyframe(75, colour = (0, 100, 255)) + self.source.CreateParticleKeyframe(200, colour = (0, 0, 0)) + self.grav = self.effect.CreateDirectedGravity(0.0, 0.2, [1, 0]) + self.circle = self.effect.CreateCircle((300, 300), (255, 255, 255), 0.5, 50) + + def Update(self, event): + self.effect.Update() + self.Redraw() + if self.parent.val % 30 == 0: + self.source.ConsolidateKeyframes() + self.grav.ConsolidateKeyframes() + self.circle.ConsolidateKeyframes() + + def Redraw(self): + self.screen.fill((0, 0, 0)) + self.effect.Redraw() + pygame.display.update() + + def OnPaint(self, event): + self.Redraw() + + def OnSize(self, event): + self.size = self.GetSizeTuple() + newsourcepos = (self.size[0] / 2, self.size[1]) + self.source.SetPos(newsourcepos) + self.circle.SetPos((newsourcepos[0] - 30, newsourcepos[1] - 200)) + + def Kill(self, event): + # Make sure Pygame can't be asked to redraw /before/ quitting + # (Otherwise wx seems to call Draw between quitting Pygame and destroying the frame) + self.Unbind(event = wx.EVT_PAINT, handler = self.OnPaint) + self.Unbind(event = wx.EVT_TIMER, handler = self.Update, source = self.timer) + +class Frame(wx.Frame): + def __init__(self, parent): + wx.Frame.__init__(self, parent, -1) + self.display = PygameDisplay(self, -1) + self.statusbar = self.CreateStatusBar() + self.statusbar.SetFieldsCount(3) + self.statusbar.SetStatusWidths([-3, -4, -2]) + self.statusbar.SetStatusText("ExeSoft Obsidian", 0) + self.statusbar.SetStatusText("Look, it's a nifty status bar!!!", 1) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_CLOSE, self.Kill) + self.val = 0 + self.SetTitle("ExeSoft Obsidian") + self.gravslider = wx.Slider(self, wx.ID_ANY, 0, -50, 50, style = wx.SL_HORIZONTAL | wx.SL_LABELS) + self.gravslider.SetTickFreq(0.1, 1) + self.timer = wx.Timer(self) + self.Bind(wx.EVT_SCROLL, self.OnScroll) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_TIMER, self.Update, self.timer) + self.timer.Start((100.0 / self.display.fps)) + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.gravslider, 0, flag = wx.EXPAND) + sizer.Add(self.display, 1, flag = wx.EXPAND) + self.SetAutoLayout(True) + self.SetSizer(sizer) + self.Layout() + + def Kill(self, event): + self.display.Kill(event) + pygame.quit() + self.Destroy() + + def OnSize(self, event): + self.Layout() + + def Update(self, event): + self.val += 1 + self.statusbar.SetStatusText("Frame %i" % self.val, 2) + + def OnScroll(self, event): + self.display.grav.SetStrength(float(self.gravslider.GetValue()) / 100.0) + +class App(wx.App): + def OnInit(self): + self.frame = Frame(parent = None) + self.frame.Show() + self.SetTopWindow(self.frame) + + return True + +if __name__ == "__main__": + app = App() + app.MainLoop() diff --git a/wx test.py b/wx test.py @@ -0,0 +1,79 @@ +### WX TEST ### +# Copyright David Barker 2010 +# +# A simple test of using wxPython to create a gui for PyIgnition + + +import wx, sys, os, pygame, PyIgnition + +class Frame(wx.Frame): + def __init__(self, parent): + wx.Frame.__init__(self, parent, -1) + self.panel = wx.Panel(self, -1) + self.hwnd = self.GetChildren()[0].GetHandle() + os.environ['SDL_VIDEODRIVER'] = 'windib' + os.environ['SDL_WINDOWID'] = str(self.hwnd) + self.statusbar = self.CreateStatusBar() + self.statusbar.SetFieldsCount(3) + self.statusbar.SetStatusWidths([-3, -4, -2]) + self.statusbar.SetStatusText("ExeSoft Obsidian", 0) + self.statusbar.SetStatusText("Look, it's a nifty status bar!!!", 1) + pygame.display.init() + self.screen = pygame.display.set_mode() + self.Bind(wx.EVT_PAINT, self.Draw) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_CLOSE, self.Kill) + self.val = 0 + self.SetTitle("ExeSoft Obsidian") + self.size = self.panel.GetSizeTuple() + self.effect = PyIgnition.ParticleEffect(self.screen, (0, 0), self.size) + self.source = self.effect.CreateSource((self.size[0] / 2, self.size[1]), initspeed = 5.0, initdirection = 0.0, initspeedrandrange = 2.0, initdirectionrandrange = 0.2, particlesperframe = 10, particlelife = 200, drawtype = PyIgnition.DRAWTYPE_POINT, colour = (255, 255, 200)) + self.grav = self.effect.CreateDirectedGravity(0.0, 0.2, [1, 0]) + self.gravslider = wx.Slider(self, wx.ID_ANY, 0, -50, 50, style = wx.SL_HORIZONTAL | wx.SL_LABELS) + self.gravslider.SetTickFreq(0.1, 1) + self.Bind(wx.EVT_SCROLL, self.OnScroll) + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.gravslider, 0, flag = wx.EXPAND) + sizer.Add(self.panel, 1, flag = wx.EXPAND) + self.SetAutoLayout(True) + self.SetSizer(sizer) + self.Layout() + + def Kill(self, event): + # Make sure Pygame can't be asked to redraw /before/ quitting + # (Otherwise wx seems to call Draw between quitting Pygame and destroying the frame) + self.Unbind(event = wx.EVT_PAINT, handler = self.Draw) + pygame.quit() + self.Destroy() + + def OnSize(self, event): + self.Layout() + self.size = self.panel.GetSizeTuple() + self.source.CreateKeyframe(self.source.curframe, pos = (self.size[0] / 2, self.size[1])) + + def Draw(self, event): + self.screen.fill((0, 0, 0)) + self.effect.Update() + self.effect.Redraw() + pygame.display.update() + + self.val += 1 + self.statusbar.SetStatusText("Frame %i" % self.val, 2) + #self.statusbar.Refresh() + #self.gravslider.Refresh() + self.OnPaint(event) + + def OnScroll(self, event): + self.grav.CreateKeyframe(self.grav.curframe, strength = float(self.gravslider.GetValue()) / 100.0) + +class App(wx.App): + def OnInit(self): + self.frame = Frame(parent = None) + self.frame.Show() + self.SetTopWindow(self.frame) + + return True + +if __name__ == "__main__": + app = App() + app.MainLoop() diff --git a/xml.py b/xml.py @@ -0,0 +1,137 @@ +### EXESOFT XML PARSER ### +# Coopyright David Barker 2010 +# +# Python XML parser + + + +class XMLNode: + def __init__(self, parent, tag, meta, data, inside): + self.tag = tag + self.meta = meta + self.data = data + self.inside = inside + self.parent = parent + self.children = [] + self.parsed = False + + +class XMLParser: + def __init__(self, data): + self.data = data + self.meta = {} + self.root = None + + def ReadMeta(self): + while "<?" in self.data: + index = self.data.find("<?") # Start of tag + startindex = index + 2 # Start of tag inside + endindex = self.data.find("?>", index) # Tag end + + # Get the contents of the angular brackets and split into separate meta tags + metaraw = self.data[startindex:endindex].strip() + separated = metaraw.split("\" ") # Split like so ('|' = split off): + # thingy = "value|" |other = "whatever|" |third = "woo!" + + for splitraw in separated: + split = splitraw.split("=") + + # Add it to the dictionary of meta data + self.meta[split[0].strip()] = split[1].strip().strip('\"') + + # Remove this tag from the stored data + before = self.data[:index] + after = self.data[(endindex + 2):] + self.data = "".join([before, after]) + + def GetTagMeta(self, tag): + meta = {} + + metastart = tag.find(" ") + 1 + metaraw = tag[metastart:] + separated = metaraw.split("\" ") # Split like so ('|' = split off): + # thingy = "value|" |other = "whatever|" |third = "woo!" + + for splitraw in separated: + split = splitraw.split("=") + + # Add it to the dictionary of meta data + meta[split[0].strip()] = split[1].strip().strip('\"') + + return meta + + def StripXML(self): + # Remove comments + while "<!--" in self.data: + index = self.data.find("<!--") + endindex = self.data.find("-->", index) + before = self.data[:index] + after = self.data[(endindex + 3):] + self.data = "".join([before, after]) + + # Remove whitespace + self.data = self.data.replace("\n", "").replace("\t", "") + + def GetChildren(self, node): + pass + + def GetRoot(self): + rootstart = self.data.find("<") + rootstartclose = self.data.find(">", rootstart) + roottagraw = self.data[(rootstart + 1):rootstartclose] + + rootmeta = {} + if len(roottagraw.split("=")) > 1: + rootmeta = self.GetTagMeta(roottagraw) + + roottag = roottagraw.strip() + + rootend = self.data.find("</%s" % roottag) + rootendclose = self.data.find(">", rootend) + rootdata = self.data[rootstart:(rootendclose + 1)].strip() + rootinside = self.data[(rootstartclose + 1):rootend] + + self.root = XMLNode(parent = None, tag = roottag, meta = rootmeta, data = rootdata, inside = rootinside) + + def SearchNode(self, node): + node.parsed = True + + tempdata = node.inside + children = [] + + while "<" in tempdata: + start = tempdata.find("<") + startclose = tempdata.find(">", start) + tagraw = tempdata[(start + 1):startclose] + + meta = {} + if "=" in tagraw: + meta = self.GetTagMeta(tagraw) + + tag = tagraw.split(" ")[0] + + end = tempdata.find("</%s" % tag) + endclose = tempdata.find(">", end) + + data = tempdata[start:(endclose + 1)].strip() + inside = tempdata[(startclose + 1):end] + + newnode = XMLNode(node, tag, meta, data, inside) + children.append(newnode) + + before = tempdata[:start] + after = tempdata[(endclose + 1):] + tempdata = "".join([before, after]) + + node.children = children + + for child in node.children: + self.SearchNode(child) + + def Parse(self): + self.ReadMeta() + self.StripXML() + self.GetRoot() + self.SearchNode(self.root) + + return self.root diff --git a/xml.pyc b/xml.pyc Binary files differ.