Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add support for multiple bullets.

  • Loading branch information...
commit d33186a6ae51d98895ae194b332532f74c94af57 1 parent bdb64d2
Al Sweigart authored August 10, 2012

Showing 35 changed files with 2,979 additions and 25 deletions. Show diff stats Hide diff stats

  1. 7  ghost-safety-squad/.gitignore
  2. 40  ghost-safety-squad/LICENSE
  3. BIN  ghost-safety-squad/Profaisal-EliteRiqaV1.0.ttf
  4. 31  ghost-safety-squad/README
  5. 2,327  ghost-safety-squad/euclid.py
  6. 548  ghost-safety-squad/game.py
  7. BIN  ghost-safety-squad/images/background.png
  8. BIN  ghost-safety-squad/images/car.png
  9. BIN  ghost-safety-squad/images/collider.png
  10. BIN  ghost-safety-squad/images/deadperson1.png
  11. BIN  ghost-safety-squad/images/deadperson2.png
  12. BIN  ghost-safety-squad/images/deadperson3.png
  13. BIN  ghost-safety-squad/images/gameover.png
  14. BIN  ghost-safety-squad/images/motorbike.png
  15. BIN  ghost-safety-squad/images/person1.png
  16. BIN  ghost-safety-squad/images/person2.png
  17. BIN  ghost-safety-squad/images/person3.png
  18. BIN  ghost-safety-squad/images/personstepleft1.png
  19. BIN  ghost-safety-squad/images/personstepleft2.png
  20. BIN  ghost-safety-squad/images/personstepleft3.png
  21. BIN  ghost-safety-squad/images/personstepright1.png
  22. BIN  ghost-safety-squad/images/personstepright2.png
  23. BIN  ghost-safety-squad/images/personstepright3.png
  24. BIN  ghost-safety-squad/images/player.png
  25. BIN  ghost-safety-squad/images/tram.png
  26. BIN  ghost-safety-squad/images/truck.png
  27. BIN  ghost-safety-squad/images/win.png
  28. BIN  ghost-safety-squad/sound/carbrakehorn.ogg
  29. BIN  ghost-safety-squad/sound/ghostsquishies.ogg
  30. BIN  ghost-safety-squad/sound/motorbikebrakehorn.ogg
  31. BIN  ghost-safety-squad/sound/splat.ogg
  32. BIN  ghost-safety-squad/sound/trambell.ogg
  33. BIN  ghost-safety-squad/sound/truckbrakehorn.ogg
  34. BIN  ghost-safety-squad/sound/yell.ogg
  35. 51  square-shooter/square-shooter_makeover.py
7  ghost-safety-squad/.gitignore
... ...
@@ -0,0 +1,7 @@
  1
+*.pyc
  2
+.dropbox
  3
+*.kate-swp
  4
+images/art
  5
+sound/raw
  6
+sound/beginning animation
  7
+builds
40  ghost-safety-squad/LICENSE
... ...
@@ -0,0 +1,40 @@
  1
+Code
  2
+====================================
  3
+by Daniel Kinsman
  4
+Ghost Safety Squad, a video game
  5
+Copyright (C) 2012  Daniel Kinsman
  6
+
  7
+This program is free software: you can redistribute it and/or modify
  8
+it under the terms of the GNU General Public License as published by
  9
+the Free Software Foundation, either version 3 of the License, or
  10
+(at your option) any later version.
  11
+
  12
+This program is distributed in the hope that it will be useful,
  13
+but WITHOUT ANY WARRANTY; without even the implied warranty of
  14
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15
+GNU General Public License for more details.
  16
+
  17
+You should have received a copy of the GNU General Public License
  18
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19
+
  20
+Art
  21
+====================================
  22
+by Natasha de Bakker and Rebecca Knight
  23
+This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Australia License.
  24
+To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/au/
  25
+or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
  26
+
  27
+
  28
+Music
  29
+====================================
  30
+by Nathan "Derris-Kharlan" Antony
  31
+This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Australia License.
  32
+To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/3.0/au/
  33
+or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
  34
+
  35
+Font
  36
+====================================
  37
+profaisal-eliteriqav1-0
  38
+Original by Jamil-ur-Rahman and Astigmatic, Merged by Faisal Abbas
  39
+http://openfontlibrary.org/en/font/profaisal-eliteriqav1-0
  40
+MIT Licence (http://opensource.org/licenses/mit-license.php)
BIN  ghost-safety-squad/Profaisal-EliteRiqaV1.0.ttf
Binary file not shown
31  ghost-safety-squad/README
... ...
@@ -0,0 +1,31 @@
  1
+Ghost Safety Squad. It's a game!
  2
+
  3
+Made by Daniel Kinsman, Natasha de Bakker, Rebecca Knight and Nathan "Derris-Kharlan" Antony.
  4
+See LICENCE file for details.
  5
+
  6
+Made in 2 and a bit days at tigjam australia 2012.
  7
+
  8
+You are a ghost.
  9
+Move around with WSAD or the arrow keys (up down left right).
  10
+Possess people with the spacebar.
  11
+Try to save them from getting killed.
  12
+
  13
+-==Installation and running==-
  14
+Linux:
  15
+    Install python and pygame (e.g. sudo apt-get install python pygame)
  16
+    Run game.py (./game.py)
  17
+
  18
+Mac OSX:
  19
+    Not sure as I don't have a mac.
  20
+    Make sure your version of python is up to date (need version at least 2.7.x)
  21
+    Then try installing pygame from http://www.pygame.org/download.shtml
  22
+    Then run game.py
  23
+
  24
+Windows:
  25
+    Unzip the zip file and run game.exe
  26
+    (Make sure you are using the prepackaged windows binary
  27
+    from http://github.com/DanielKinsman/ghost-safety-squad-tigjamau/downloads)
  28
+
  29
+Have fun!
  30
+
  31
+danielkinsman+gss@gmail.com
2,327  ghost-safety-squad/euclid.py
... ...
@@ -0,0 +1,2327 @@
  1
+#!/usr/bin/env python
  2
+#
  3
+# euclid graphics maths module
  4
+#
  5
+# Copyright (c) 2006 Alex Holkner
  6
+# Alex.Holkner@mail.google.com
  7
+#
  8
+# This library is free software; you can redistribute it and/or modify it
  9
+# under the terms of the GNU Lesser General Public License as published by the
  10
+# Free Software Foundation; either version 2.1 of the License, or (at your
  11
+# option) any later version.
  12
+# 
  13
+# This library is distributed in the hope that it will be useful, but WITHOUT
  14
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  16
+# for more details.
  17
+# 
  18
+# You should have received a copy of the GNU Lesser General Public License
  19
+# along with this library; if not, write to the Free Software Foundation,
  20
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
  21
+
  22
+'''euclid graphics maths module
  23
+
  24
+Documentation and tests are included in the file "euclid.txt", or online
  25
+at http://code.google.com/p/pyeuclid
  26
+'''
  27
+
  28
+__docformat__ = 'restructuredtext'
  29
+__version__ = '$Id: euclid.py 37 2011-08-21 22:24:05Z elfnor@gmail.com $'
  30
+__revision__ = '$Revision: 37 $'
  31
+
  32
+import math
  33
+import operator
  34
+import types
  35
+
  36
+# Some magic here.  If _use_slots is True, the classes will derive from
  37
+# object and will define a __slots__ class variable.  If _use_slots is
  38
+# False, classes will be old-style and will not define __slots__.
  39
+#
  40
+# _use_slots = True:   Memory efficient, probably faster in future versions
  41
+#                      of Python, "better".
  42
+# _use_slots = False:  Ordinary classes, much faster than slots in current
  43
+#                      versions of Python (2.4 and 2.5).
  44
+_use_slots = True
  45
+
  46
+# If True, allows components of Vector2 and Vector3 to be set via swizzling;
  47
+# e.g.  v.xyz = (1, 2, 3).  This is much, much slower than the more verbose
  48
+# v.x = 1; v.y = 2; v.z = 3,  and slows down ordinary element setting as
  49
+# well.  Recommended setting is False.
  50
+_enable_swizzle_set = False
  51
+
  52
+# Requires class to derive from object.
  53
+if _enable_swizzle_set:
  54
+    _use_slots = True
  55
+
  56
+# Implement _use_slots magic.
  57
+class _EuclidMetaclass(type):
  58
+    def __new__(cls, name, bases, dct):
  59
+        if '__slots__' in dct:
  60
+            dct['__getstate__'] = cls._create_getstate(dct['__slots__'])
  61
+            dct['__setstate__'] = cls._create_setstate(dct['__slots__'])
  62
+        if _use_slots:
  63
+            return type.__new__(cls, name, bases + (object,), dct)
  64
+        else:
  65
+            if '__slots__' in dct:
  66
+                del dct['__slots__']
  67
+            return types.ClassType.__new__(types.ClassType, name, bases, dct)
  68
+
  69
+    @classmethod
  70
+    def _create_getstate(cls, slots):
  71
+        def __getstate__(self):
  72
+            d = {}
  73
+            for slot in slots:
  74
+                d[slot] = getattr(self, slot)
  75
+            return d
  76
+        return __getstate__
  77
+
  78
+    @classmethod
  79
+    def _create_setstate(cls, slots):
  80
+        def __setstate__(self, state):
  81
+            for name, value in state.items():
  82
+                setattr(self, name, value)
  83
+        return __setstate__
  84
+
  85
+__metaclass__ = _EuclidMetaclass
  86
+
  87
+class Vector2:
  88
+    __slots__ = ['x', 'y']
  89
+    __hash__ = None
  90
+
  91
+    def __init__(self, x=0, y=0):
  92
+        self.x = x
  93
+        self.y = y
  94
+
  95
+    def __copy__(self):
  96
+        return self.__class__(self.x, self.y)
  97
+
  98
+    copy = __copy__
  99
+
  100
+    def __repr__(self):
  101
+        return 'Vector2(%.2f, %.2f)' % (self.x, self.y)
  102
+
  103
+    def __eq__(self, other):
  104
+        if isinstance(other, Vector2):
  105
+            return self.x == other.x and \
  106
+                   self.y == other.y
  107
+        else:
  108
+            assert hasattr(other, '__len__') and len(other) == 2
  109
+            return self.x == other[0] and \
  110
+                   self.y == other[1]
  111
+
  112
+    def __ne__(self, other):
  113
+        return not self.__eq__(other)
  114
+
  115
+    def __nonzero__(self):
  116
+        return self.x != 0 or self.y != 0
  117
+
  118
+    def __len__(self):
  119
+        return 2
  120
+
  121
+    def __getitem__(self, key):
  122
+        return (self.x, self.y)[key]
  123
+
  124
+    def __setitem__(self, key, value):
  125
+        l = [self.x, self.y]
  126
+        l[key] = value
  127
+        self.x, self.y = l
  128
+
  129
+    def __iter__(self):
  130
+        return iter((self.x, self.y))
  131
+
  132
+    def __getattr__(self, name):
  133
+        try:
  134
+            return tuple([(self.x, self.y)['xy'.index(c)] \
  135
+                          for c in name])
  136
+        except ValueError:
  137
+            raise AttributeError, name
  138
+
  139
+    if _enable_swizzle_set:
  140
+        # This has detrimental performance on ordinary setattr as well
  141
+        # if enabled
  142
+        def __setattr__(self, name, value):
  143
+            if len(name) == 1:
  144
+                object.__setattr__(self, name, value)
  145
+            else:
  146
+                try:
  147
+                    l = [self.x, self.y]
  148
+                    for c, v in map(None, name, value):
  149
+                        l['xy'.index(c)] = v
  150
+                    self.x, self.y = l
  151
+                except ValueError:
  152
+                    raise AttributeError, name
  153
+
  154
+    def __add__(self, other):
  155
+        if isinstance(other, Vector2):
  156
+            # Vector + Vector -> Vector
  157
+            # Vector + Point -> Point
  158
+            # Point + Point -> Vector
  159
+            if self.__class__ is other.__class__:
  160
+                _class = Vector2
  161
+            else:
  162
+                _class = Point2
  163
+            return _class(self.x + other.x,
  164
+                          self.y + other.y)
  165
+        else:
  166
+            assert hasattr(other, '__len__') and len(other) == 2
  167
+            return Vector2(self.x + other[0],
  168
+                           self.y + other[1])
  169
+    __radd__ = __add__
  170
+
  171
+    def __iadd__(self, other):
  172
+        if isinstance(other, Vector2):
  173
+            self.x += other.x
  174
+            self.y += other.y
  175
+        else:
  176
+            self.x += other[0]
  177
+            self.y += other[1]
  178
+        return self
  179
+
  180
+    def __sub__(self, other):
  181
+        if isinstance(other, Vector2):
  182
+            # Vector - Vector -> Vector
  183
+            # Vector - Point -> Point
  184
+            # Point - Point -> Vector
  185
+            if self.__class__ is other.__class__:
  186
+                _class = Vector2
  187
+            else:
  188
+                _class = Point2
  189
+            return _class(self.x - other.x,
  190
+                          self.y - other.y)
  191
+        else:
  192
+            assert hasattr(other, '__len__') and len(other) == 2
  193
+            return Vector2(self.x - other[0],
  194
+                           self.y - other[1])
  195
+
  196
+   
  197
+    def __rsub__(self, other):
  198
+        if isinstance(other, Vector2):
  199
+            return Vector2(other.x - self.x,
  200
+                           other.y - self.y)
  201
+        else:
  202
+            assert hasattr(other, '__len__') and len(other) == 2
  203
+            return Vector2(other.x - self[0],
  204
+                           other.y - self[1])
  205
+
  206
+    def __mul__(self, other):
  207
+        assert type(other) in (int, long, float)
  208
+        return Vector2(self.x * other,
  209
+                       self.y * other)
  210
+
  211
+    __rmul__ = __mul__
  212
+
  213
+    def __imul__(self, other):
  214
+        assert type(other) in (int, long, float)
  215
+        self.x *= other
  216
+        self.y *= other
  217
+        return self
  218
+
  219
+    def __div__(self, other):
  220
+        assert type(other) in (int, long, float)
  221
+        return Vector2(operator.div(self.x, other),
  222
+                       operator.div(self.y, other))
  223
+
  224
+
  225
+    def __rdiv__(self, other):
  226
+        assert type(other) in (int, long, float)
  227
+        return Vector2(operator.div(other, self.x),
  228
+                       operator.div(other, self.y))
  229
+
  230
+    def __floordiv__(self, other):
  231
+        assert type(other) in (int, long, float)
  232
+        return Vector2(operator.floordiv(self.x, other),
  233
+                       operator.floordiv(self.y, other))
  234
+
  235
+
  236
+    def __rfloordiv__(self, other):
  237
+        assert type(other) in (int, long, float)
  238
+        return Vector2(operator.floordiv(other, self.x),
  239
+                       operator.floordiv(other, self.y))
  240
+
  241
+    def __truediv__(self, other):
  242
+        assert type(other) in (int, long, float)
  243
+        return Vector2(operator.truediv(self.x, other),
  244
+                       operator.truediv(self.y, other))
  245
+
  246
+
  247
+    def __rtruediv__(self, other):
  248
+        assert type(other) in (int, long, float)
  249
+        return Vector2(operator.truediv(other, self.x),
  250
+                       operator.truediv(other, self.y))
  251
+    
  252
+    def __neg__(self):
  253
+        return Vector2(-self.x,
  254
+                        -self.y)
  255
+
  256
+    __pos__ = __copy__
  257
+    
  258
+    def __abs__(self):
  259
+        return math.sqrt(self.x ** 2 + \
  260
+                         self.y ** 2)
  261
+
  262
+    magnitude = __abs__
  263
+
  264
+    def magnitude_squared(self):
  265
+        return self.x ** 2 + \
  266
+               self.y ** 2
  267
+
  268
+    def normalize(self):
  269
+        d = self.magnitude()
  270
+        if d:
  271
+            self.x /= d
  272
+            self.y /= d
  273
+        return self
  274
+
  275
+    def normalized(self):
  276
+        d = self.magnitude()
  277
+        if d:
  278
+            return Vector2(self.x / d, 
  279
+                           self.y / d)
  280
+        return self.copy()
  281
+
  282
+    def dot(self, other):
  283
+        assert isinstance(other, Vector2)
  284
+        return self.x * other.x + \
  285
+               self.y * other.y
  286
+
  287
+    def cross(self):
  288
+        return Vector2(self.y, -self.x)
  289
+
  290
+    def reflect(self, normal):
  291
+        # assume normal is normalized
  292
+        assert isinstance(normal, Vector2)
  293
+        d = 2 * (self.x * normal.x + self.y * normal.y)
  294
+        return Vector2(self.x - d * normal.x,
  295
+                       self.y - d * normal.y)
  296
+
  297
+    def angle(self, other):
  298
+        """Return the angle to the vector other"""
  299
+        return math.acos(self.dot(other) / (self.magnitude()*other.magnitude()))
  300
+
  301
+    def project(self, other):
  302
+        """Return one vector projected on the vector other"""
  303
+        n = other.normalized()
  304
+        return self.dot(n)*n
  305
+
  306
+class Vector3:
  307
+    __slots__ = ['x', 'y', 'z']
  308
+    __hash__ = None
  309
+
  310
+    def __init__(self, x=0, y=0, z=0):
  311
+        self.x = x
  312
+        self.y = y
  313
+        self.z = z
  314
+
  315
+    def __copy__(self):
  316
+        return self.__class__(self.x, self.y, self.z)
  317
+
  318
+    copy = __copy__
  319
+
  320
+    def __repr__(self):
  321
+        return 'Vector3(%.2f, %.2f, %.2f)' % (self.x,
  322
+                                              self.y,
  323
+                                              self.z)
  324
+
  325
+    def __eq__(self, other):
  326
+        if isinstance(other, Vector3):
  327
+            return self.x == other.x and \
  328
+                   self.y == other.y and \
  329
+                   self.z == other.z
  330
+        else:
  331
+            assert hasattr(other, '__len__') and len(other) == 3
  332
+            return self.x == other[0] and \
  333
+                   self.y == other[1] and \
  334
+                   self.z == other[2]
  335
+
  336
+    def __ne__(self, other):
  337
+        return not self.__eq__(other)
  338
+
  339
+    def __nonzero__(self):
  340
+        return self.x != 0 or self.y != 0 or self.z != 0
  341
+
  342
+    def __len__(self):
  343
+        return 3
  344
+
  345
+    def __getitem__(self, key):
  346
+        return (self.x, self.y, self.z)[key]
  347
+
  348
+    def __setitem__(self, key, value):
  349
+        l = [self.x, self.y, self.z]
  350
+        l[key] = value
  351
+        self.x, self.y, self.z = l
  352
+
  353
+    def __iter__(self):
  354
+        return iter((self.x, self.y, self.z))
  355
+
  356
+    def __getattr__(self, name):
  357
+        try:
  358
+            return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \
  359
+                          for c in name])
  360
+        except ValueError:
  361
+            raise AttributeError, name
  362
+
  363
+    if _enable_swizzle_set:
  364
+        # This has detrimental performance on ordinary setattr as well
  365
+        # if enabled
  366
+        def __setattr__(self, name, value):
  367
+            if len(name) == 1:
  368
+                object.__setattr__(self, name, value)
  369
+            else:
  370
+                try:
  371
+                    l = [self.x, self.y, self.z]
  372
+                    for c, v in map(None, name, value):
  373
+                        l['xyz'.index(c)] = v
  374
+                    self.x, self.y, self.z = l
  375
+                except ValueError:
  376
+                    raise AttributeError, name
  377
+
  378
+
  379
+    def __add__(self, other):
  380
+        if isinstance(other, Vector3):
  381
+            # Vector + Vector -> Vector
  382
+            # Vector + Point -> Point
  383
+            # Point + Point -> Vector
  384
+            if self.__class__ is other.__class__:
  385
+                _class = Vector3
  386
+            else:
  387
+                _class = Point3
  388
+            return _class(self.x + other.x,
  389
+                          self.y + other.y,
  390
+                          self.z + other.z)
  391
+        else:
  392
+            assert hasattr(other, '__len__') and len(other) == 3
  393
+            return Vector3(self.x + other[0],
  394
+                           self.y + other[1],
  395
+                           self.z + other[2])
  396
+    __radd__ = __add__
  397
+
  398
+    def __iadd__(self, other):
  399
+        if isinstance(other, Vector3):
  400
+            self.x += other.x
  401
+            self.y += other.y
  402
+            self.z += other.z
  403
+        else:
  404
+            self.x += other[0]
  405
+            self.y += other[1]
  406
+            self.z += other[2]
  407
+        return self
  408
+
  409
+    def __sub__(self, other):
  410
+        if isinstance(other, Vector3):
  411
+            # Vector - Vector -> Vector
  412
+            # Vector - Point -> Point
  413
+            # Point - Point -> Vector
  414
+            if self.__class__ is other.__class__:
  415
+                _class = Vector3
  416
+            else:
  417
+                _class = Point3
  418
+            return Vector3(self.x - other.x,
  419
+                           self.y - other.y,
  420
+                           self.z - other.z)
  421
+        else:
  422
+            assert hasattr(other, '__len__') and len(other) == 3
  423
+            return Vector3(self.x - other[0],
  424
+                           self.y - other[1],
  425
+                           self.z - other[2])
  426
+
  427
+   
  428
+    def __rsub__(self, other):
  429
+        if isinstance(other, Vector3):
  430
+            return Vector3(other.x - self.x,
  431
+                           other.y - self.y,
  432
+                           other.z - self.z)
  433
+        else:
  434
+            assert hasattr(other, '__len__') and len(other) == 3
  435
+            return Vector3(other.x - self[0],
  436
+                           other.y - self[1],
  437
+                           other.z - self[2])
  438
+
  439
+    def __mul__(self, other):
  440
+        if isinstance(other, Vector3):
  441
+            # TODO component-wise mul/div in-place and on Vector2; docs.
  442
+            if self.__class__ is Point3 or other.__class__ is Point3:
  443
+                _class = Point3
  444
+            else:
  445
+                _class = Vector3
  446
+            return _class(self.x * other.x,
  447
+                          self.y * other.y,
  448
+                          self.z * other.z)
  449
+        else: 
  450
+            assert type(other) in (int, long, float)
  451
+            return Vector3(self.x * other,
  452
+                           self.y * other,
  453
+                           self.z * other)
  454
+
  455
+    __rmul__ = __mul__
  456
+
  457
+    def __imul__(self, other):
  458
+        assert type(other) in (int, long, float)
  459
+        self.x *= other
  460
+        self.y *= other
  461
+        self.z *= other
  462
+        return self
  463
+
  464
+    def __div__(self, other):
  465
+        assert type(other) in (int, long, float)
  466
+        return Vector3(operator.div(self.x, other),
  467
+                       operator.div(self.y, other),
  468
+                       operator.div(self.z, other))
  469
+
  470
+
  471
+    def __rdiv__(self, other):
  472
+        assert type(other) in (int, long, float)
  473
+        return Vector3(operator.div(other, self.x),
  474
+                       operator.div(other, self.y),
  475
+                       operator.div(other, self.z))
  476
+
  477
+    def __floordiv__(self, other):
  478
+        assert type(other) in (int, long, float)
  479
+        return Vector3(operator.floordiv(self.x, other),
  480
+                       operator.floordiv(self.y, other),
  481
+                       operator.floordiv(self.z, other))
  482
+
  483
+
  484
+    def __rfloordiv__(self, other):
  485
+        assert type(other) in (int, long, float)
  486
+        return Vector3(operator.floordiv(other, self.x),
  487
+                       operator.floordiv(other, self.y),
  488
+                       operator.floordiv(other, self.z))
  489
+
  490
+    def __truediv__(self, other):
  491
+        assert type(other) in (int, long, float)
  492
+        return Vector3(operator.truediv(self.x, other),
  493
+                       operator.truediv(self.y, other),
  494
+                       operator.truediv(self.z, other))
  495
+
  496
+
  497
+    def __rtruediv__(self, other):
  498
+        assert type(other) in (int, long, float)
  499
+        return Vector3(operator.truediv(other, self.x),
  500
+                       operator.truediv(other, self.y),
  501
+                       operator.truediv(other, self.z))
  502
+    
  503
+    def __neg__(self):
  504
+        return Vector3(-self.x,
  505
+                        -self.y,
  506
+                        -self.z)
  507
+
  508
+    __pos__ = __copy__
  509
+    
  510
+    def __abs__(self):
  511
+        return math.sqrt(self.x ** 2 + \
  512
+                         self.y ** 2 + \
  513
+                         self.z ** 2)
  514
+
  515
+    magnitude = __abs__
  516
+
  517
+    def magnitude_squared(self):
  518
+        return self.x ** 2 + \
  519
+               self.y ** 2 + \
  520
+               self.z ** 2
  521
+
  522
+    def normalize(self):
  523
+        d = self.magnitude()
  524
+        if d:
  525
+            self.x /= d
  526
+            self.y /= d
  527
+            self.z /= d
  528
+        return self
  529
+
  530
+    def normalized(self):
  531
+        d = self.magnitude()
  532
+        if d:
  533
+            return Vector3(self.x / d, 
  534
+                           self.y / d, 
  535
+                           self.z / d)
  536
+        return self.copy()
  537
+
  538
+    def dot(self, other):
  539
+        assert isinstance(other, Vector3)
  540
+        return self.x * other.x + \
  541
+               self.y * other.y + \
  542
+               self.z * other.z
  543
+
  544
+    def cross(self, other):
  545
+        assert isinstance(other, Vector3)
  546
+        return Vector3(self.y * other.z - self.z * other.y,
  547
+                       -self.x * other.z + self.z * other.x,
  548
+                       self.x * other.y - self.y * other.x)
  549
+
  550
+    def reflect(self, normal):
  551
+        # assume normal is normalized
  552
+        assert isinstance(normal, Vector3)
  553
+        d = 2 * (self.x * normal.x + self.y * normal.y + self.z * normal.z)
  554
+        return Vector3(self.x - d * normal.x,
  555
+                       self.y - d * normal.y,
  556
+                       self.z - d * normal.z)
  557
+
  558
+    def rotate_around(self, axis, theta):
  559
+        """Return the vector rotated around axis through angle theta. Right hand rule applies"""
  560
+
  561
+        # Adapted from equations published by Glenn Murray.
  562
+        # http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html
  563
+        x, y, z = self.x, self.y,self.z
  564
+        u, v, w = axis.x, axis.y, axis.z
  565
+
  566
+        # Extracted common factors for simplicity and efficiency
  567
+        r2 = u**2 + v**2 + w**2
  568
+        r = math.sqrt(r2)
  569
+        ct = math.cos(theta)
  570
+        st = math.sin(theta) / r
  571
+        dt = (u*x + v*y + w*z) * (1 - ct) / r2
  572
+        return Vector3((u * dt + x * ct + (-w * y + v * z) * st),
  573
+                       (v * dt + y * ct + ( w * x - u * z) * st),
  574
+                       (w * dt + z * ct + (-v * x + u * y) * st))
  575
+
  576
+    def angle(self, other):
  577
+        """Return the angle to the vector other"""
  578
+        return math.acos(self.dot(other) / (self.magnitude()*other.magnitude()))
  579
+
  580
+    def project(self, other):
  581
+        """Return one vector projected on the vector other"""
  582
+        n = other.normalized()
  583
+        return self.dot(n)*n
  584
+
  585
+# a b c 
  586
+# e f g 
  587
+# i j k 
  588
+
  589
+class Matrix3:
  590
+    __slots__ = list('abcefgijk')
  591
+
  592
+    def __init__(self):
  593
+        self.identity()
  594
+
  595
+    def __copy__(self):
  596
+        M = Matrix3()
  597
+        M.a = self.a
  598
+        M.b = self.b
  599
+        M.c = self.c
  600
+        M.e = self.e 
  601
+        M.f = self.f
  602
+        M.g = self.g
  603
+        M.i = self.i
  604
+        M.j = self.j
  605
+        M.k = self.k
  606
+        return M
  607
+
  608
+    copy = __copy__
  609
+    def __repr__(self):
  610
+        return ('Matrix3([% 8.2f % 8.2f % 8.2f\n'  \
  611
+                '         % 8.2f % 8.2f % 8.2f\n'  \
  612
+                '         % 8.2f % 8.2f % 8.2f])') \
  613
+                % (self.a, self.b, self.c,
  614
+                   self.e, self.f, self.g,
  615
+                   self.i, self.j, self.k)
  616
+
  617
+    def __getitem__(self, key):
  618
+        return [self.a, self.e, self.i,
  619
+                self.b, self.f, self.j,
  620
+                self.c, self.g, self.k][key]
  621
+
  622
+    def __setitem__(self, key, value):
  623
+        L = self[:]
  624
+        L[key] = value
  625
+        (self.a, self.e, self.i,
  626
+         self.b, self.f, self.j,
  627
+         self.c, self.g, self.k) = L
  628
+
  629
+    def __mul__(self, other):
  630
+        if isinstance(other, Matrix3):
  631
+            # Caching repeatedly accessed attributes in local variables
  632
+            # apparently increases performance by 20%.  Attrib: Will McGugan.
  633
+            Aa = self.a
  634
+            Ab = self.b
  635
+            Ac = self.c
  636
+            Ae = self.e
  637
+            Af = self.f
  638
+            Ag = self.g
  639
+            Ai = self.i
  640
+            Aj = self.j
  641
+            Ak = self.k
  642
+            Ba = other.a
  643
+            Bb = other.b
  644
+            Bc = other.c
  645
+            Be = other.e
  646
+            Bf = other.f
  647
+            Bg = other.g
  648
+            Bi = other.i
  649
+            Bj = other.j
  650
+            Bk = other.k
  651
+            C = Matrix3()
  652
+            C.a = Aa * Ba + Ab * Be + Ac * Bi
  653
+            C.b = Aa * Bb + Ab * Bf + Ac * Bj
  654
+            C.c = Aa * Bc + Ab * Bg + Ac * Bk
  655
+            C.e = Ae * Ba + Af * Be + Ag * Bi
  656
+            C.f = Ae * Bb + Af * Bf + Ag * Bj
  657
+            C.g = Ae * Bc + Af * Bg + Ag * Bk
  658
+            C.i = Ai * Ba + Aj * Be + Ak * Bi
  659
+            C.j = Ai * Bb + Aj * Bf + Ak * Bj
  660
+            C.k = Ai * Bc + Aj * Bg + Ak * Bk
  661
+            return C
  662
+        elif isinstance(other, Point2):
  663
+            A = self
  664
+            B = other
  665
+            P = Point2(0, 0)
  666
+            P.x = A.a * B.x + A.b * B.y + A.c
  667
+            P.y = A.e * B.x + A.f * B.y + A.g
  668
+            return P
  669
+        elif isinstance(other, Vector2):
  670
+            A = self
  671
+            B = other
  672
+            V = Vector2(0, 0)
  673
+            V.x = A.a * B.x + A.b * B.y 
  674
+            V.y = A.e * B.x + A.f * B.y 
  675
+            return V
  676
+        else:
  677
+            other = other.copy()
  678
+            other._apply_transform(self)
  679
+            return other
  680
+
  681
+    def __imul__(self, other):
  682
+        assert isinstance(other, Matrix3)
  683
+        # Cache attributes in local vars (see Matrix3.__mul__).
  684
+        Aa = self.a
  685
+        Ab = self.b
  686
+        Ac = self.c
  687
+        Ae = self.e
  688
+        Af = self.f
  689
+        Ag = self.g
  690
+        Ai = self.i
  691
+        Aj = self.j
  692
+        Ak = self.k
  693
+        Ba = other.a
  694
+        Bb = other.b
  695
+        Bc = other.c
  696
+        Be = other.e
  697
+        Bf = other.f
  698
+        Bg = other.g
  699
+        Bi = other.i
  700
+        Bj = other.j
  701
+        Bk = other.k
  702
+        self.a = Aa * Ba + Ab * Be + Ac * Bi
  703
+        self.b = Aa * Bb + Ab * Bf + Ac * Bj
  704
+        self.c = Aa * Bc + Ab * Bg + Ac * Bk
  705
+        self.e = Ae * Ba + Af * Be + Ag * Bi
  706
+        self.f = Ae * Bb + Af * Bf + Ag * Bj
  707
+        self.g = Ae * Bc + Af * Bg + Ag * Bk
  708
+        self.i = Ai * Ba + Aj * Be + Ak * Bi
  709
+        self.j = Ai * Bb + Aj * Bf + Ak * Bj
  710
+        self.k = Ai * Bc + Aj * Bg + Ak * Bk
  711
+        return self
  712
+
  713
+    def identity(self):
  714
+        self.a = self.f = self.k = 1.
  715
+        self.b = self.c = self.e = self.g = self.i = self.j = 0
  716
+        return self
  717
+
  718
+    def scale(self, x, y):
  719
+        self *= Matrix3.new_scale(x, y)
  720
+        return self
  721
+
  722
+    def translate(self, x, y):
  723
+        self *= Matrix3.new_translate(x, y)
  724
+        return self 
  725
+
  726
+    def rotate(self, angle):
  727
+        self *= Matrix3.new_rotate(angle)
  728
+        return self
  729
+
  730
+    # Static constructors
  731
+    def new_identity(cls):
  732
+        self = cls()
  733
+        return self
  734
+    new_identity = classmethod(new_identity)
  735
+
  736
+    def new_scale(cls, x, y):
  737
+        self = cls()
  738
+        self.a = x
  739
+        self.f = y
  740
+        return self
  741
+    new_scale = classmethod(new_scale)
  742
+
  743
+    def new_translate(cls, x, y):
  744
+        self = cls()
  745
+        self.c = x
  746
+        self.g = y
  747
+        return self
  748
+    new_translate = classmethod(new_translate)
  749
+
  750
+    def new_rotate(cls, angle):
  751
+        self = cls()
  752
+        s = math.sin(angle)
  753
+        c = math.cos(angle)
  754
+        self.a = self.f = c
  755
+        self.b = -s
  756
+        self.e = s
  757
+        return self
  758
+    new_rotate = classmethod(new_rotate)
  759
+
  760
+    def determinant(self):
  761
+        return (self.a*self.f*self.k 
  762
+                + self.b*self.g*self.i 
  763
+                + self.c*self.e*self.j 
  764
+                - self.a*self.g*self.j 
  765
+                - self.b*self.e*self.k 
  766
+                - self.c*self.f*self.i)
  767
+
  768
+    def inverse(self):
  769
+        tmp = Matrix3()
  770
+        d = self.determinant()
  771
+
  772
+        if abs(d) < 0.001:
  773
+            # No inverse, return identity
  774
+            return tmp
  775
+        else:
  776
+            d = 1.0 / d
  777
+
  778
+            tmp.a = d * (self.f*self.k - self.g*self.j)
  779
+            tmp.b = d * (self.c*self.j - self.b*self.k)
  780
+            tmp.c = d * (self.b*self.g - self.c*self.f)
  781
+            tmp.e = d * (self.g*self.i - self.e*self.k)
  782
+            tmp.f = d * (self.a*self.k - self.c*self.i)
  783
+            tmp.g = d * (self.c*self.e - self.a*self.g)
  784
+            tmp.i = d * (self.e*self.j - self.f*self.i)
  785
+            tmp.j = d * (self.b*self.i - self.a*self.j)
  786
+            tmp.k = d * (self.a*self.f - self.b*self.e)
  787
+
  788
+            return tmp
  789
+
  790
+# a b c d
  791
+# e f g h
  792
+# i j k l
  793
+# m n o p
  794
+
  795
+class Matrix4:
  796
+    __slots__ = list('abcdefghijklmnop')
  797
+
  798
+    def __init__(self):
  799
+        self.identity()
  800
+
  801
+    def __copy__(self):
  802
+        M = Matrix4()
  803
+        M.a = self.a
  804
+        M.b = self.b
  805
+        M.c = self.c
  806
+        M.d = self.d
  807
+        M.e = self.e 
  808
+        M.f = self.f
  809
+        M.g = self.g
  810
+        M.h = self.h
  811
+        M.i = self.i
  812
+        M.j = self.j
  813
+        M.k = self.k
  814
+        M.l = self.l
  815
+        M.m = self.m
  816
+        M.n = self.n
  817
+        M.o = self.o
  818
+        M.p = self.p
  819
+        return M
  820
+
  821
+    copy = __copy__
  822
+
  823
+
  824
+    def __repr__(self):
  825
+        return ('Matrix4([% 8.2f % 8.2f % 8.2f % 8.2f\n'  \
  826
+                '         % 8.2f % 8.2f % 8.2f % 8.2f\n'  \
  827
+                '         % 8.2f % 8.2f % 8.2f % 8.2f\n'  \
  828
+                '         % 8.2f % 8.2f % 8.2f % 8.2f])') \
  829
+                % (self.a, self.b, self.c, self.d,
  830
+                   self.e, self.f, self.g, self.h,
  831
+                   self.i, self.j, self.k, self.l,
  832
+                   self.m, self.n, self.o, self.p)
  833
+
  834
+    def __getitem__(self, key):
  835
+        return [self.a, self.e, self.i, self.m,
  836
+                self.b, self.f, self.j, self.n,
  837
+                self.c, self.g, self.k, self.o,
  838
+                self.d, self.h, self.l, self.p][key]
  839
+
  840
+    def __setitem__(self, key, value):
  841
+        L = self[:]
  842
+        L[key] = value
  843
+        (self.a, self.e, self.i, self.m,
  844
+         self.b, self.f, self.j, self.n,
  845
+         self.c, self.g, self.k, self.o,
  846
+         self.d, self.h, self.l, self.p) = L
  847
+
  848
+    def __mul__(self, other):
  849
+        if isinstance(other, Matrix4):
  850
+            # Cache attributes in local vars (see Matrix3.__mul__).
  851
+            Aa = self.a
  852
+            Ab = self.b
  853
+            Ac = self.c
  854
+            Ad = self.d
  855
+            Ae = self.e
  856
+            Af = self.f
  857
+            Ag = self.g
  858
+            Ah = self.h
  859
+            Ai = self.i
  860
+            Aj = self.j
  861
+            Ak = self.k
  862
+            Al = self.l
  863
+            Am = self.m
  864
+            An = self.n
  865
+            Ao = self.o
  866
+            Ap = self.p
  867
+            Ba = other.a
  868
+            Bb = other.b
  869
+            Bc = other.c
  870
+            Bd = other.d
  871
+            Be = other.e
  872
+            Bf = other.f
  873
+            Bg = other.g
  874
+            Bh = other.h
  875
+            Bi = other.i
  876
+            Bj = other.j
  877
+            Bk = other.k
  878
+            Bl = other.l
  879
+            Bm = other.m
  880
+            Bn = other.n
  881
+            Bo = other.o
  882
+            Bp = other.p
  883
+            C = Matrix4()
  884
+            C.a = Aa * Ba + Ab * Be + Ac * Bi + Ad * Bm
  885
+            C.b = Aa * Bb + Ab * Bf + Ac * Bj + Ad * Bn
  886
+            C.c = Aa * Bc + Ab * Bg + Ac * Bk + Ad * Bo
  887
+            C.d = Aa * Bd + Ab * Bh + Ac * Bl + Ad * Bp
  888
+            C.e = Ae * Ba + Af * Be + Ag * Bi + Ah * Bm
  889
+            C.f = Ae * Bb + Af * Bf + Ag * Bj + Ah * Bn
  890
+            C.g = Ae * Bc + Af * Bg + Ag * Bk + Ah * Bo
  891
+            C.h = Ae * Bd + Af * Bh + Ag * Bl + Ah * Bp
  892
+            C.i = Ai * Ba + Aj * Be + Ak * Bi + Al * Bm
  893
+            C.j = Ai * Bb + Aj * Bf + Ak * Bj + Al * Bn
  894
+            C.k = Ai * Bc + Aj * Bg + Ak * Bk + Al * Bo
  895
+            C.l = Ai * Bd + Aj * Bh + Ak * Bl + Al * Bp
  896
+            C.m = Am * Ba + An * Be + Ao * Bi + Ap * Bm
  897
+            C.n = Am * Bb + An * Bf + Ao * Bj + Ap * Bn
  898
+            C.o = Am * Bc + An * Bg + Ao * Bk + Ap * Bo
  899
+            C.p = Am * Bd + An * Bh + Ao * Bl + Ap * Bp
  900
+            return C
  901
+        elif isinstance(other, Point3):
  902
+            A = self
  903
+            B = other
  904
+            P = Point3(0, 0, 0)
  905
+            P.x = A.a * B.x + A.b * B.y + A.c * B.z + A.d
  906
+            P.y = A.e * B.x + A.f * B.y + A.g * B.z + A.h
  907
+            P.z = A.i * B.x + A.j * B.y + A.k * B.z + A.l
  908
+            return P
  909
+        elif isinstance(other, Vector3):
  910
+            A = self
  911
+            B = other
  912
+            V = Vector3(0, 0, 0)
  913
+            V.x = A.a * B.x + A.b * B.y + A.c * B.z
  914
+            V.y = A.e * B.x + A.f * B.y + A.g * B.z
  915
+            V.z = A.i * B.x + A.j * B.y + A.k * B.z
  916
+            return V
  917
+        else:
  918
+            other = other.copy()
  919
+            other._apply_transform(self)
  920
+            return other
  921
+
  922
+    def __imul__(self, other):
  923
+        assert isinstance(other, Matrix4)
  924
+        # Cache attributes in local vars (see Matrix3.__mul__).
  925
+        Aa = self.a
  926
+        Ab = self.b
  927
+        Ac = self.c
  928
+        Ad = self.d
  929
+        Ae = self.e
  930
+        Af = self.f
  931
+        Ag = self.g
  932
+        Ah = self.h
  933
+        Ai = self.i
  934
+        Aj = self.j
  935
+        Ak = self.k
  936
+        Al = self.l
  937
+        Am = self.m
  938
+        An = self.n
  939
+        Ao = self.o
  940
+        Ap = self.p
  941
+        Ba = other.a
  942
+        Bb = other.b
  943
+        Bc = other.c
  944
+        Bd = other.d
  945
+        Be = other.e
  946
+        Bf = other.f
  947
+        Bg = other.g
  948
+        Bh = other.h
  949
+        Bi = other.i
  950
+        Bj = other.j
  951
+        Bk = other.k
  952
+        Bl = other.l
  953
+        Bm = other.m
  954
+        Bn = other.n
  955
+        Bo = other.o
  956
+        Bp = other.p
  957
+        self.a = Aa * Ba + Ab * Be + Ac * Bi + Ad * Bm
  958
+        self.b = Aa * Bb + Ab * Bf + Ac * Bj + Ad * Bn
  959
+        self.c = Aa * Bc + Ab * Bg + Ac * Bk + Ad * Bo
  960
+        self.d = Aa * Bd + Ab * Bh + Ac * Bl + Ad * Bp
  961
+        self.e = Ae * Ba + Af * Be + Ag * Bi + Ah * Bm
  962
+        self.f = Ae * Bb + Af * Bf + Ag * Bj + Ah * Bn
  963
+        self.g = Ae * Bc + Af * Bg + Ag * Bk + Ah * Bo
  964
+        self.h = Ae * Bd + Af * Bh + Ag * Bl + Ah * Bp
  965
+        self.i = Ai * Ba + Aj * Be + Ak * Bi + Al * Bm
  966
+        self.j = Ai * Bb + Aj * Bf + Ak * Bj + Al * Bn
  967
+        self.k = Ai * Bc + Aj * Bg + Ak * Bk + Al * Bo
  968
+        self.l = Ai * Bd + Aj * Bh + Ak * Bl + Al * Bp
  969
+        self.m = Am * Ba + An * Be + Ao * Bi + Ap * Bm
  970
+        self.n = Am * Bb + An * Bf + Ao * Bj + Ap * Bn
  971
+        self.o = Am * Bc + An * Bg + Ao * Bk + Ap * Bo
  972
+        self.p = Am * Bd + An * Bh + Ao * Bl + Ap * Bp
  973
+        return self
  974
+
  975
+    def transform(self, other):
  976
+        A = self
  977
+        B = other
  978
+        P = Point3(0, 0, 0)
  979
+        P.x = A.a * B.x + A.b * B.y + A.c * B.z + A.d
  980
+        P.y = A.e * B.x + A.f * B.y + A.g * B.z + A.h
  981
+        P.z = A.i * B.x + A.j * B.y + A.k * B.z + A.l
  982
+        w =   A.m * B.x + A.n * B.y + A.o * B.z + A.p
  983
+        if w != 0:
  984
+            P.x /= w
  985
+            P.y /= w
  986
+            P.z /= w
  987
+        return P
  988
+
  989
+    def identity(self):
  990
+        self.a = self.f = self.k = self.p = 1.
  991
+        self.b = self.c = self.d = self.e = self.g = self.h = \
  992
+        self.i = self.j = self.l = self.m = self.n = self.o = 0
  993
+        return self