# bmaland/spaceswarm

Switch branches/tags
Nothing to show
Fetching contributors…
Cannot retrieve contributors at this time
340 lines (261 sloc) 8.08 KB
 # This file is taken from Will McGugan's gameobjects library # http://code.google.com/p/gameobjects/ from math import sqrt from math import pi def format_number(n, accuracy=6): """Formats a number in a friendly manner (removes trailing zeros and unneccesary point.""" fs = "%."+str(accuracy)+"f" str_n = fs%float(n) if '.' in str_n: str_n = str_n.rstrip('0').rstrip('.') if str_n == "-0": str_n = "0" #str_n = str_n.replace("-0", "0") return str_n def lerp(a, b, i): """Linear enterpolate from a to b.""" return a+(b-a)*i class Vector2(object): __slots__ = ('_v',) def __init__(self, x=0., y=0.): """Initialise a vector x -- The x value (defaults to 0.), or a container of 2 values y -- The y value (defaults to 0.) """ if hasattr(x, "__getitem__"): x, y = x self._v = [float(x), float(y)] else: self._v = [float(x), float(y)] def _get_length(self): x, y = self._v return sqrt(x*x + y*y) def _set_length(self, length): v = self._v try: x, y = v l = length / sqrt(x*x +y*y) except ZeroDivisionError: v[0] = 0.0 v[1] = 0.0 return self v[0] *= l v[1] *= l length = property(_get_length, _set_length, None, "Length of the vector") @classmethod def from_floats(cls, x, y): vec = cls.__new__(cls, object) vec._v = [x, y] return vec @classmethod def from_iter(cls, iterable): """Creates a Vector2 object from an iterable. iterable -- An iterable of at least 2 numeric values """ next = iter(iterable).next vec = cls.__new__(cls, object) vec._v = [float(next()), float(next())] return vec @classmethod def from_points(cls, p1, p2): """Creates a Vector2 object between two points. p1 -- First point p2 -- Second point """ v = cls.__new__(cls, object) x, y = p1 xx, yy = p2 v._v = [float(xx-x), float(yy-y)] return v def copy(self): """Returns a copy of this object.""" vec = self.__new__(self.__class__, object) vec._v = self._v[:] return vec def get_x(self): return self._v[0] def set_x(self, x): assert isinstance(x, float), "Must be a float" self._v[0] = x x = property(get_x, set_x, None, "x component.") def get_y(self): return self._v[1] def set_y(self, y): assert isinstance(x, float), "Must be a float" self._v[1] = y y = property(get_y, set_y, None, "y component.") u = property(get_x, set_y, None, "u component (alias for x).") v = property(get_y, set_y, None, "v component (alias for y).") def __str__(self): x, y = self._v return "(%s, %s)" % (format_number(x), format_number(y)) def __repr__(self): x, y = self._v return "Vector2(%s, %s)" % (x, y) def __iter__(self): return iter(self._v[:]) def __len__(self): return 2 def __getitem__(self, index): """Gets a component as though the vector were a list.""" try: return self._v[index] except IndexError: raise IndexError, "There are 2 values in this object, index should be 0 or 1" def __setitem__(self, index, value): """Sets a component as though the vector were a list.""" assert isinstance(value, float), "Must be a float" try: self._v[index] = value except IndexError: raise IndexError, "There are 2 values in this object, index should be 0 or 1!" def __eq__(self, rhs): x, y = self._v xx, yy = rhs return x == xx and y == yy def __ne__(self, rhs): x, y = self._v xx, yy, = rhs return x != xx or y != yy def __hash__(self): return hash(tuple(self._v)) def __add__(self, rhs): x, y = self._v xx, yy = rhs return Vector2.from_floats(x+xx, y+yy) def __iadd__(self, rhs): xx, yy = rhs v = self._v v[0] += xx v[1] += yy return self def __radd__(self, lhs): x, y = self._v xx, yy = lhs return self.from_floats(x+xx, y+yy) def __sub__(self, rhs): x, y = self._v xx, yy = rhs return Vector2.from_floats(x-xx, y-yy) def __rsub__(self, lhs): x, y = self._v xx, yy = lhs return self.from_floats(xx-x, yy-y) def _isub__(self, rhs): xx, yy = rhs v = self._v v[0] -= xx v[1] -= yy return self def __mul__(self, rhs): """Return the result of multiplying this vector with a scalar or a vector-list object.""" x, y = self._v if hasattr(rhs, "__getitem__"): xx, yy = rhs return Vector2.from_floats(x*xx, y*yy) else: return Vector2.from_floats(x*rhs, y*rhs) def __imul__(self, rhs): """Multiplys this vector with a scalar or a vector-list object.""" if hasattr(rhs, "__getitem__"): xx, yy = rhs v = self._v v[0] *= xx v[1] *= yy else: v = self._v v[0] *= rhs v[1] *= rhs return self def __rmul__(self, lhs): x, y = self._v if hasattr(lhs, "__getitem__"): xx, yy = lhs else: xx = lhs yy = lhs return self.from_floats(x*xx, y*yy) def __div__(self, rhs): """Return the result of dividing this vector by a scalar or a vector-list object.""" x, y = self._v if hasattr(rhs, "__getitem__"): xx, yy, = rhs return Vector2.from_floats(x/xx, y/yy) else: return Vector2.from_floats(x/rhs, y/rhs) def __idiv__(self, rhs): """Divides this vector with a scalar or a vector-list object.""" if hasattr(rhs, "__getitem__"): xx, yy = rhs v = self._v v[0] /= xx v[1] /= yy else: v = self._v v[0] /= rhs v[1] /= rhs return self def __rdiv__(self, lhs): x, y = self._v if hasattr(lhs, "__getitem__"): xx, yy = lhs else: xx = lhs yy = lhs return self.from_floats(xx/x, yy/x) def __neg__(self): """Return the negation of this vector.""" x, y = self._v return Vector2.from_floats(-x, -y) def __pos__(self): return self.copy() def __nonzero__(self): x, y = self._v return x and y def __call__(self, keys): """Used to swizzle a vector. keys -- A string containing a list of component names i.e. vec = Vector(1, 2) vec('yx') --> (2, 1) """ ord_x = ord('x') v = self._v return tuple( v[ord(c) - ord_x] for c in keys ) def as_tuple(self): """Converts this vector to a tuple.""" return tuple(self._v) def get_length(self): """Returns the length of this vector.""" x, y = self._v return sqrt(x*x +y*y) get_magnitude = get_length def normalise(self): """Normalises this vector.""" v = self._v x, y = v l = sqrt(x*x +y*y) try: v[0] /= l v[1] /= l except ZeroDivisionError: v[0] = 0. v[1] = 0. return self normalize = normalise def get_normalised(self): x, y = self._v l = sqrt(x*x +y*y) return Vector2.from_floats(x/l, y/l) get_normalized = get_normalised def get_distance_to(self, p): """Returns the distance to a point. p -- A Vector2 or list-like object with at least 2 values.""" x, y = self._v xx, yy = p dx = xx-x dy = yy-y return sqrt( dx*dx + dy*dy ) if __name__ == "__main__": v1 = Vector2(1, 2) print v1('yx') print Vector2.from_points((5,5), (10,10))