Skip to content

Instantly share code, notes, and snippets.

@nickcharlton
Created April 18, 2013 10:50
Show Gist options
  • Save nickcharlton/5411856 to your computer and use it in GitHub Desktop.
Save nickcharlton/5411856 to your computer and use it in GitHub Desktop.
This is the Seek example from The Nature of Code reimplemented with a custom Vector class (also included) and done in Python with Pygame.
import sys
from vector import Vector
import pygame
import pygame.gfxdraw
class Vehicle():
def __init__(self, x, y):
self.location = Vector(x, y)
self.velocity = Vector(0, 0)
self.acceleration = Vector(0, 0)
self.maxSpeed = 4
self.maxForce = 0.1
def update(self):
self.velocity.add(self.acceleration)
self.velocity.limit(self.maxSpeed)
self.location.add(self.velocity)
self.acceleration.mult(0)
def applyForce(self, force):
self.acceleration.add(force)
def seek(self, target):
desired = Vector.subtraction(target, self.location)
desired.normalize()
desired.mult(self.maxSpeed)
steer = Vector.subtraction(desired, self.velocity)
steer.limit(self.maxForce)
self.applyForce(steer)
def draw(self, surface):
pygame.gfxdraw.aacircle(surface, int(self.location.x), int(self.location.y), 10, [0, 0, 0])
# setup
pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("PyGame: Simple Animation")
# background
screen.fill([255, 255, 255])
# items
vehicle = Vehicle(320, 240)
# run loop
while True:
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit
sys.exit(0)
# blank the screen
screen.fill([255, 255, 255])
# move items
vehicle.update()
mouse_x, mouse_y = pygame.mouse.get_pos()
vehicle.seek(Vector(mouse_x, mouse_y))
# draw items
vehicle.draw(screen)
# update the screen
pygame.display.flip()
import math
class Vector:
"""
A reimplementation of Processing's PVector class in Python.
<br>
This provides a simple 2D vector class, with the sole intention of making
it easy to port code over.
<br>
This is essentially transliterated from the Processing project, and as
such, should be Licensed under the 2.1 version of the GPL.
<br>
Copyright (c) 2008 Dan Shiffman
Copyright (c) 2008-10 Ben Fry and Casey Reas
Copyright (c) 2013 Nick Charlton
"""
def __init__(self, x, y):
self.x = x
self.y = y
# this holds the state for the iterable.
self.index = 0
def add(self, v):
"""
Add another vector to this.
"""
self.y = self.y + v.y
self.x = self.x + v.x
@staticmethod
def addition(one, two):
"""
Add two vectors. Returning the new one.
"""
x = one.x + two.x
y = one.y + two.y
return Vector(x, y)
def sub(self, v):
"""
Subtract a vector from this.
"""
self.x = self.x - v.x
self.y = self.y - v.y
@staticmethod
def subtraction(one, two):
"""
Subtract a vector from another.
"""
x = one.x - two.x
y = one.y - two.y
return Vector(x, y)
def mult(self, n):
"""
Scale (multiply) this vector by a scalar.
"""
self.x = self.x * n
self.y = self.y * n
@staticmethod
def multiply(one, n):
"""
Scale (multiply) a vector by a scalar.
"""
x = one.x * n
y = one.y * n
return Vector(x, y)
def div(self, d):
"""
Scale (divide) this vector by a scalar.
"""
self.x = self.x / d
self.y = self.y / d
@staticmethod
def divide(one, d):
"""
Scale (divide) a vector by a scalar.
"""
x = one.x / d
y = one.y / d
return Vector(x, y)
def mag(self):
"""
Return the magnitude of the vector.
"""
return math.sqrt(self.x * self.x + self.y * self.y)
def magSquare(self):
"""
Return the magnitude squared.
"""
return (self.x * self.x + self.y * self.y)
def normalize(self):
"""
Normalize the vector.
"""
m = self.mag()
if (m != 0):
self.div(m)
def limit(self, max):
"""
Limit the magnitude by a given scalar.
"""
if (self.magSquare() > max * max):
self.normalize()
self.mult(max)
def dot(self, v):
"""
Return the dot product this and a given vector.
"""
return self.x * v.x + self.y * v.y
def heading(self):
"""
The heading of the vector represented as an angle.
"""
angle = math.atan2(-self.y, self.x)
return -1 * angle
def rotate(self, theta):
"""
Rotate the vector by a given angle.
"""
xTemp = self.x
self.x = self.x * math.cos(theta) - self.y * math.sin(theta)
self.y = xTemp * math.sin(theta) + self.y * math.cos(theta)
def __repr__(self):
return "[%f, %f]" % (self.x, self.y)
def __iter__(self):
return self
def next(self):
if self.index > 1:
self.index = 0
raise StopIteration
self.index = self.index + 1
if self.index == 1:
return self.x
else:
return self.y
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment