Created
April 18, 2013 10:50
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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