diff --git a/Python/ch1_vectors/NOC_1_10_motion101_acceleration.py b/Python/ch1_vectors/NOC_1_10_motion101_acceleration.py new file mode 100644 index 00000000..75c13fbd --- /dev/null +++ b/Python/ch1_vectors/NOC_1_10_motion101_acceleration.py @@ -0,0 +1,59 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint,uniform + +def setup(): + p.size(400,400) + p.smooth() + global mover + mover = Mover() + +def draw(): + p.background(255) + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + topspeed = 5 + + def __init__(self): + self.location = p.PVector(width/2, height/2) + self.velocity = p.PVector(0, 0) + + def update(self): + mouse = p.PVector(p.mouse.x,p.mouse.y) + acceleration = p.PVector.sub(mouse,self.location) + acceleration.normalize() + acceleration.mult(0.2) + + self.velocity.add(acceleration) + # pyprocessing PVector has no 'limit' method + if self.velocity.x > self.topspeed: self.velocity.x = self.topspeed + if self.velocity.y > self.topspeed: self.velocity.y = self.topspeed + self.location.add(self.velocity) + + def display(self): + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(self.location.x, self.location.y, 48, 48) + + def checkEdges(self): + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = 0 + elif self.location.y < 0: + self.location.y = height + +p.run() diff --git a/Python/ch1_vectors/NOC_1_11_motion101_acceleration_array.py b/Python/ch1_vectors/NOC_1_11_motion101_acceleration_array.py new file mode 100644 index 00000000..695c381b --- /dev/null +++ b/Python/ch1_vectors/NOC_1_11_motion101_acceleration_array.py @@ -0,0 +1,60 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform + +def setup(): + p.size(600,600) + p.smooth() + global movers + movers = [Mover() for i in range(0,20)] + +def draw(): + p.background(255) + for mover in movers: + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + topspeed = 5 + + def __init__(self): + self.location = p.PVector(uniform(0,width), uniform(0,height)) + self.velocity = p.PVector(0, 0) + + def update(self): + mouse = p.PVector(p.mouse.x,p.mouse.y) + acceleration = p.PVector.sub(mouse,self.location) + acceleration.normalize() + acceleration.mult(0.2) + + self.velocity.add(acceleration) + # pyprocessing PVector has no 'limit' method + if self.velocity.x > self.topspeed: self.velocity.x = self.topspeed + if self.velocity.y > self.topspeed: self.velocity.y = self.topspeed + self.location.add(self.velocity) + + def display(self): + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(self.location.x, self.location.y, 48, 48) + + def checkEdges(self): + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = 0 + elif self.location.y < 0: + self.location.y = height + +p.run() diff --git a/Python/ch1_vectors/NOC_1_1_bouncingball_novectors.py b/Python/ch1_vectors/NOC_1_1_bouncingball_novectors.py new file mode 100644 index 00000000..e9cb882a --- /dev/null +++ b/Python/ch1_vectors/NOC_1_1_bouncingball_novectors.py @@ -0,0 +1,35 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p + +x = 100 +y = 100 +xspeed = 1. +yspeed = 3.3 + +def setup(): + p.size(800,200) + p.smooth() + p.frameRate(60) + +def draw(): + global x,y,xspeed,yspeed + p.background(255) + + x += xspeed + y += yspeed + + if x > width or x < 0: + xspeed *= -1 + if y > height or y < 0: + yspeed *= -1 + + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(x, y, 48, 48) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_2_bouncingball_vectors.py b/Python/ch1_vectors/NOC_1_2_bouncingball_vectors.py new file mode 100644 index 00000000..c0a5b168 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_2_bouncingball_vectors.py @@ -0,0 +1,38 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-2: Bouncing Ball, with PVector! + +import pyprocessing as p + +def setup(): + p.size(800,200) + p.smooth() + p.background(255) + + global location, velocity + location = p.PVector(100,100) + velocity = p.PVector(2.5,5) + + +def draw(): + p.noStroke() + p.fill(255,10) + p.rect(0,0,width,height) + + # add current speed to location + location.add(velocity) + + if location.x > width or location.x < 0: + velocity.x *= -1 + if location.y > height or location.y < 0: + velocity.y *= -1 + + # display circle at location + p.stroke(0) + p.fill(175) + p.ellipse(location.x, location.y, 16, 16) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_3_vector_multiplication.py b/Python/ch1_vectors/NOC_1_3_vector_multiplication.py new file mode 100644 index 00000000..86d29e71 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_3_vector_multiplication.py @@ -0,0 +1,29 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-4: Vector multiplication +# Note: although using p.PVector is possible, here numpy arrays are substituted + +import pyprocessing as p +from numpy import array + +def setup(): + p.size(800,200) + p.smooth() + +def draw(): + p.background(255) + + mouse = array([p.mouse.x, p.mouse.y]) + center = array([width/2, height/2]) + mouse -= center + mouse *= 0.5 + + p.translate(width/2, height/2) + p.strokeWeight(2) + p.stroke(0) + p.line(0, 0, mouse[0], mouse[1]) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_3_vector_subtraction.py b/Python/ch1_vectors/NOC_1_3_vector_subtraction.py new file mode 100644 index 00000000..bd3da114 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_3_vector_subtraction.py @@ -0,0 +1,28 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-3: Vector subtraction +# Note: although using p.PVector is possible, here numpy arrays are substituted + +import pyprocessing as p +import numpy as np + +def setup(): + p.size(400,400) + p.smooth() + +def draw(): + p.background(255) + + mouse = np.array([p.mouse.x, p.mouse.y]) + center = np.array([width/2, height/2]) + mouse = mouse - center + + p.translate(width/2, height/2) + p.strokeWeight(2) + p.stroke(0) + p.line(0, 0, mouse[0], mouse[1]) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_4_vector_multiplication.py b/Python/ch1_vectors/NOC_1_4_vector_multiplication.py new file mode 100644 index 00000000..47b242e6 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_4_vector_multiplication.py @@ -0,0 +1,29 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-4: Vector multiplication +# Note: although using p.PVector is possible, here numpy arrays are substituted + +import pyprocessing as p +import numpy as np + +def setup(): + p.size(400,400) + p.smooth() + +def draw(): + p.background(255) + + mouse = np.array([p.mouse.x, p.mouse.y]) + center = np.array([width/2, height/2]) + mouse -= center + mouse *= 0.5 + + p.translate(width/2, height/2) + p.strokeWeight(2) + p.stroke(0) + p.line(0, 0, mouse[0], mouse[1]) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_5_vector_magnitude.py b/Python/ch1_vectors/NOC_1_5_vector_magnitude.py new file mode 100644 index 00000000..a93cc2ad --- /dev/null +++ b/Python/ch1_vectors/NOC_1_5_vector_magnitude.py @@ -0,0 +1,33 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-5: Vector magnitude +# Note: although using p.PVector is possible, here numpy arrays are substituted + +import pyprocessing as p +import numpy as np + +def setup(): + p.size(400,400) + p.smooth() + +def draw(): + p.background(255) + + mouse = np.array([p.mouse.x, p.mouse.y]) + center = np.array([width/2, height/2]) + mouse -= center + + m = np.linalg.norm(mouse) + p.fill(0) + p.noStroke() + p.rect(0,0,m,10) + + p.translate(width/2, height/2) + p.strokeWeight(2) + p.stroke(0) + p.line(0, 0, mouse[0], mouse[1]) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_6_vector_normalize.py b/Python/ch1_vectors/NOC_1_6_vector_normalize.py new file mode 100644 index 00000000..47bcf0c4 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_6_vector_normalize.py @@ -0,0 +1,37 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-6: Demonstration of normalizing a vector (sets its length to 1) +# Note: although using p.PVector is possible, here numpy arrays are substituted + +import pyprocessing as p +import numpy as np + +def setup(): + p.size(400,400) + p.smooth() + +def draw(): + p.background(255) + + # vector that points to the mouse location + mouse = np.array([p.mouse.x, p.mouse.y], dtype=float) + # vector that points to the center of the window + center = np.array([width/2, height/2]) + # subtract center from mouse, gives vector pointing from center to mouse + mouse -= center + + # normalize the vector + mouse /= np.linalg.norm(mouse) + # multiply length + mouse *= 150 + + # draw the resulting vector + p.translate(width/2, height/2) + p.strokeWeight(2) + p.stroke(0) + p.line(0, 0, mouse[0], mouse[1]) + +p.run() diff --git a/Python/ch1_vectors/NOC_1_7_motion101.py b/Python/ch1_vectors/NOC_1_7_motion101.py new file mode 100644 index 00000000..3ede33a5 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_7_motion101.py @@ -0,0 +1,50 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +# Example 1-7: Motion 101 + +import pyprocessing as p +from random import randint,uniform + +def setup(): + p.size(400,400) + p.smooth() + global mover + mover = Mover() + +def draw(): + p.background(255) + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + def __init__(self): + self.location = p.PVector(randint(0,width), randint(0,height)) + self.velocity = p.PVector(uniform(-2,2), uniform(-2,2)) + + def update(self): + self.location.add(self.velocity) + + def display(self): + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(self.location.x, self.location.y, 48, 48) + + def checkEdges(self): + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = 0 + elif self.location.y < 0: + self.location.y = height + +p.run() diff --git a/Python/ch1_vectors/NOC_1_8_motion101_acceleration.py b/Python/ch1_vectors/NOC_1_8_motion101_acceleration.py new file mode 100644 index 00000000..0c9aabf4 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_8_motion101_acceleration.py @@ -0,0 +1,55 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint + +def setup(): + p.size(400,400) + p.smooth() + global mover + mover = Mover() + +def draw(): + p.background(255) + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + topspeed = 10 + + def __init__(self): + self.location = p.PVector(width/2, height/2) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(-0.001, 0.01) + + def update(self): + self.velocity.add(self.acceleration) + # pyprocessing PVector has no 'limit' method + if self.velocity.x > self.topspeed: self.velocity.x = self.topspeed + if self.velocity.y > self.topspeed: self.velocity.y = self.topspeed + self.location.add(self.velocity) + + def display(self): + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(self.location.x, self.location.y, 48, 48) + + def checkEdges(self): + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = 0 + elif self.location.y < 0: + self.location.y = height + +p.run() diff --git a/Python/ch1_vectors/NOC_1_9_motion101_acceleration.py b/Python/ch1_vectors/NOC_1_9_motion101_acceleration.py new file mode 100644 index 00000000..111d3f20 --- /dev/null +++ b/Python/ch1_vectors/NOC_1_9_motion101_acceleration.py @@ -0,0 +1,58 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint,uniform + +def setup(): + p.size(400,400) + p.smooth() + global mover + mover = Mover() + +def draw(): + p.background(255) + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + topspeed = 6 + + def __init__(self): + self.location = p.PVector(width/2, height/2) + self.velocity = p.PVector(0, 0) + + def update(self): + acceleration = p.PVector(uniform(-1,1), uniform(-1,1)) + acceleration.normalize() + acceleration.mult(uniform(0,2)) + + self.velocity.add(acceleration) + # pyprocessing PVector has no 'limit' method + if self.velocity.x > self.topspeed: self.velocity.x = self.topspeed + if self.velocity.y > self.topspeed: self.velocity.y = self.topspeed + self.location.add(self.velocity) + + def display(self): + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(self.location.x, self.location.y, 48, 48) + + def checkEdges(self): + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = 0 + elif self.location.y < 0: + self.location.y = height + +p.run() diff --git a/Python/ch2_forces/NOC_2_1_forces.py b/Python/ch2_forces/NOC_2_1_forces.py new file mode 100644 index 00000000..de313d82 --- /dev/null +++ b/Python/ch2_forces/NOC_2_1_forces.py @@ -0,0 +1,68 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint,uniform + +def setup(): + p.size(800,200) + p.smooth() + global m + m = Mover() + +def draw(): + p.background(255) + + wind = p.PVector(0.01,0) + gravity = p.PVector(0,0.1) + m.applyForce(wind) + m.applyForce(gravity) + + m.update() + m.checkEdges() + m.display() + +class Mover: + + def __init__(self): + """Creates new mover instance.""" + self.location = p.PVector(30, 30) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(0, 0) + self.mass = 1 + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(127) + p.ellipse(self.location.x, self.location.y, 48, 48) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = width + self.velocity.x *= -1 + elif self.location.x < 0: + self.location.x = 0 + self.velocity.x *= -1 + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() diff --git a/Python/ch2_forces/NOC_2_2_forces_many.py b/Python/ch2_forces/NOC_2_2_forces_many.py new file mode 100644 index 00000000..491a267f --- /dev/null +++ b/Python/ch2_forces/NOC_2_2_forces_many.py @@ -0,0 +1,70 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint,uniform + +def setup(): + p.size(800,200) + p.smooth() + global movers + movers = [Mover(uniform(0.1,4),0,0) for i in range(0,20)] + +def draw(): + p.background(255) + + wind = p.PVector(0.01,0) + gravity = p.PVector(0,0.1) + + for mover in movers: + mover.applyForce(wind) + mover.applyForce(gravity) + + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + def __init__(self, mass, x, y): + """Creates new mover instance.""" + self.location = p.PVector(x, y) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(0, 0) + self.mass = mass + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, self.mass*16, self.mass*16) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = width + self.velocity.x *= -1 + elif self.location.x < 0: + self.location.x = 0 + self.velocity.x *= -1 + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() diff --git a/Python/ch2_forces/NOC_2_3_forces_many_realgravity.py b/Python/ch2_forces/NOC_2_3_forces_many_realgravity.py new file mode 100644 index 00000000..06134bb3 --- /dev/null +++ b/Python/ch2_forces/NOC_2_3_forces_many_realgravity.py @@ -0,0 +1,72 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint,uniform + +def setup(): + p.size(800,200) + p.smooth() + global movers + movers = [Mover(uniform(1,4),0,0) for i in range(0,20)] + +def draw(): + p.background(255) + + for mover in movers: + + wind = p.PVector(0.01,0) + gravity = p.PVector(0,0.1*mover.mass) + + mover.applyForce(wind) + mover.applyForce(gravity) + + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + def __init__(self, mass, x, y): + """Creates new mover instance.""" + self.location = p.PVector(x, y) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(0, 0) + self.mass = mass + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, self.mass*16, self.mass*16) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = width + self.velocity.x *= -1 + elif self.location.x < 0: + self.location.x = 0 + self.velocity.x *= -1 + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() + diff --git a/Python/ch2_forces/NOC_2_4_forces_friction.py b/Python/ch2_forces/NOC_2_4_forces_friction.py new file mode 100644 index 00000000..52c673c9 --- /dev/null +++ b/Python/ch2_forces/NOC_2_4_forces_friction.py @@ -0,0 +1,79 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform + +def setup(): + p.size(800,200) + p.smooth() + global movers + movers = [Mover(uniform(1,4), uniform(0,width), 0) for i in range(0,5)] + +def draw(): + p.background(255) + c = 0.05 + + for mover in movers: + + wind = p.PVector(0.01,0) + gravity = p.PVector(0,0.1*mover.mass) + friction = mover.velocity.get() + friction.mult(-1) + if friction.mag() > 0: + friction.normalize() + friction.mult(c) + + mover.applyForce(wind) + mover.applyForce(gravity) + mover.applyForce(friction) + + mover.update() + mover.checkEdges() + mover.display() + +class Mover: + + def __init__(self, mass, x, y): + """Creates new mover instance.""" + self.location = p.PVector(x, y) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(0, 0) + self.mass = mass + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, self.mass*16, self.mass*16) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = width + self.velocity.x *= -1 + elif self.location.x < 0: + self.location.x = 0 + self.velocity.x *= -1 + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() + diff --git a/Python/ch2_forces/NOC_2_5_fluidresistance.py b/Python/ch2_forces/NOC_2_5_fluidresistance.py new file mode 100644 index 00000000..a5ec3f18 --- /dev/null +++ b/Python/ch2_forces/NOC_2_5_fluidresistance.py @@ -0,0 +1,118 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform + +def setup(): + p.size(800,200) + p.smooth() + global movers, liquid + reset() + liquid = Liquid(0, height/2, width, height/2, 0.1) + +def draw(): + p.background(255) + liquid.display() + + for mover in movers: + + if liquid.contains(mover): + dragForce = liquid.drag(mover) + mover.applyForce(dragForce) + + gravity = p.PVector(0,0.1*mover.mass) + mover.applyForce(gravity) + + mover.update() + mover.checkEdges() + mover.display() + p.fill(0) + p.text("click mouse to reset", 10, 30) + +def mousePressed(): + reset() + +def reset(): + global movers + movers = [Mover(uniform(1,4), uniform(0,width), 0) for i in range(0,5)] + + +class Liquid: + + def __init__(self, x, y, w, h, c): + self.x = x + self.y = y + self.w = w + self.h = h + self.c = c + + def contains(self, m): + if m.location.x > self.x and \ + m.location.x < self.x + self.w and \ + m.location.y > self.y and \ + m.location.y < self.y + self.h: + return True + else: + return False + + def drag(self, m): + speed = m.velocity.mag() + dragMagnitude = self.c*speed**2 + + dragForce = m.velocity.get() + dragForce.mult(-1) + dragForce.normalize() + dragForce.mult(dragMagnitude) + return dragForce + + def display(self): + p.noStroke() + p.fill(50) + p.rect(self.x,self.y,self.w,self.h) + +class Mover: + + def __init__(self, mass, x, y): + """Creates new mover instance.""" + self.location = p.PVector(x, y) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(0, 0) + self.mass = mass + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, self.mass*16, self.mass*16) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = width + self.velocity.x *= -1 + elif self.location.x < 0: + self.location.x = 0 + self.velocity.x *= -1 + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() + diff --git a/Python/ch2_forces/NOC_2_6_attraction.py b/Python/ch2_forces/NOC_2_6_attraction.py new file mode 100644 index 00000000..7453aa80 --- /dev/null +++ b/Python/ch2_forces/NOC_2_6_attraction.py @@ -0,0 +1,130 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform + +def setup(): + p.size(800,200) + p.smooth() + global m, a + m = Mover() + a = Attractor() + +def draw(): + p.background(255) + + force = a.attract(m) + m.applyForce(force) + m.update() + + a.drag() + a.hover(p.mouse.x, p.mouse.y) + + a.display() + m.display() + +def mousePressed(): + a.clicked(p.mouse.x, p.mouse.y) + +def mouseReleased(): + a.stopDragging() + + +class Attractor: + + def __init__(self): + self.location = p.PVector(width/2,height/2) + self.mass = 20 + self.G = 1 + self.dragOffset = p.PVector(0.,0.,0.) + self.dragging = False + self.rollover = False + + def attract(self, m): + force = p.PVector.sub(self.location, m.location) + d = force.mag() + d = p.constrain(d,5.,25.) + force.normalize() + strength = self.G*(self.mass*m.mass)/(d**2) + force.mult(strength) + + return force + + def display(self): + p.ellipseMode(p.CENTER) + p.strokeWeight(4) + p.stroke(0) + if self.dragging: + p.fill(50) + elif self.rollover: + p.fill(100) + else: + p.fill(175,200) + p.ellipse(self.location.x, self.location.y, self.mass*2, self.mass*2) + + def clicked(self,mx,my): + d = p.dist(mx,my,self.location.x,self.location.y) + if d < self.mass: + self.dragging = True + self.dragOffset.x = self.location.x-mx + self.dragOffset.y = self.location.y-my + + def hover(self,mx,my): + d = p.dist(mx,my,self.location.x,self.location.y) + if d < self.mass: + self.rollover = True + else: + self.rollover = False + + def stopDragging(self): + self.dragging = False + + def drag(self): + if self.dragging: + self.location.x = p.mouse.x + self.dragOffset.x + self.location.y = p.mouse.y + self.dragOffset.y + +class Mover: + + def __init__(self): + """Creates new mover instance.""" + self.location = p.PVector(400, 50) + self.velocity = p.PVector(1, 0) + self.acceleration = p.PVector(0, 0) + self.mass = 1 + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, 16, 16) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() + diff --git a/Python/ch2_forces/NOC_2_7_attraction_many.py b/Python/ch2_forces/NOC_2_7_attraction_many.py new file mode 100644 index 00000000..b0be6979 --- /dev/null +++ b/Python/ch2_forces/NOC_2_7_attraction_many.py @@ -0,0 +1,130 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform + +def setup(): + p.size(800,200) + p.smooth() + global movers, a + movers = [Mover(uniform(0.1,2), uniform(0,width), uniform(0,height)) for i in range(0,10)] + a = Attractor() + +def draw(): + p.background(255) + + a.drag() + a.hover(p.mouse.x, p.mouse.y) + a.display() + + for m in movers: + force = a.attract(m) + m.applyForce(force) + m.update() + m.display() + +def mousePressed(): + a.clicked(p.mouse.x, p.mouse.y) + +def mouseReleased(): + a.stopDragging() + + +class Attractor: + + def __init__(self): + self.location = p.PVector(width/2,height/2) + self.mass = 20 + self.G = 1 + self.dragOffset = p.PVector(0.,0.,0.) + self.dragging = False + self.rollover = False + + def attract(self, m): + force = p.PVector.sub(self.location, m.location) + d = force.mag() + d = p.constrain(d,5.,25.) + force.normalize() + strength = self.G*(self.mass*m.mass)/(d**2) + force.mult(strength) + + return force + + def display(self): + p.ellipseMode(p.CENTER) + p.strokeWeight(4) + p.stroke(0) + if self.dragging: + p.fill(50) + elif self.rollover: + p.fill(100) + else: + p.fill(175,200) + p.ellipse(self.location.x, self.location.y, self.mass*2, self.mass*2) + + def clicked(self,mx,my): + d = p.dist(mx,my,self.location.x,self.location.y) + if d < self.mass: + self.dragging = True + self.dragOffset.x = self.location.x-mx + self.dragOffset.y = self.location.y-my + + def hover(self,mx,my): + d = p.dist(mx,my,self.location.x,self.location.y) + if d < self.mass: + self.rollover = True + else: + self.rollover = False + + def stopDragging(self): + self.dragging = False + + def drag(self): + if self.dragging: + self.location.x = p.mouse.x + self.dragOffset.x + self.location.y = p.mouse.y + self.dragOffset.y + +class Mover: + + def __init__(self, mass, x, y): + """Creates new mover instance.""" + self.location = p.PVector(x, y) + self.velocity = p.PVector(1, 0) + self.acceleration = p.PVector(0, 0) + self.mass = mass + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, self.mass*25, self.mass*25) + + def checkEdges(self): + """Reverses velocity if past edge of window.""" + + if self.location.x > width: + self.location.x = 0 + elif self.location.x < 0: + self.location.x = width + + if self.location.y > height: + self.location.y = height + self.velocity.y *= -1 + +p.run() + diff --git a/Python/ch2_forces/NOC_2_8_mutual_attraction.py b/Python/ch2_forces/NOC_2_8_mutual_attraction.py new file mode 100644 index 00000000..cc985682 --- /dev/null +++ b/Python/ch2_forces/NOC_2_8_mutual_attraction.py @@ -0,0 +1,71 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform +from itertools import combinations + +G = 0.4 + +def setup(): + p.size(600,600) + p.smooth() + global movers + movers = [Mover(uniform(0.1,2), uniform(0,width), uniform(0,height)) for i in range(0,10)] + +def draw(): + p.background(255) + + # rather than a double-nested loop, taking advantage of itertools' combination + # method to give all possible pairs with no repeats + for (m1,m2) in combinations(movers,2): + force = m1.attract(m2) + m2.applyForce(force) + # flip the force and apply it back (avoids duplicate calculations) + force.mult(-1.) + m1.applyForce(force) + + for m in movers: + m.update() + m.display() + +class Mover: + + def __init__(self, mass, x, y): + """Creates new mover instance.""" + self.location = p.PVector(x, y) + self.velocity = p.PVector(0, 0) + self.acceleration = p.PVector(0, 0) + self.mass = mass + + def applyForce(self,force): + """Adds force to acceleration vector.""" + f = p.PVector.div(force,self.mass) + self.acceleration.add(f) + + def update(self): + """Updates velocity & location.""" + self.velocity.add(self.acceleration) + self.location.add(self.velocity) + self.acceleration.mult(0) + + def display(self): + """Displays mover as circle.""" + p.stroke(0) + p.strokeWeight(2) + p.fill(0,127) + p.ellipse(self.location.x, self.location.y, self.mass*25, self.mass*25) + + def attract(self, m): + force = p.PVector.sub(self.location, m.location) + d = force.mag() + d = p.constrain(d,5.,25.) + force.normalize() + strength = G*(self.mass*m.mass)/(d**2) + force.mult(strength) + return force + +p.run() + diff --git a/Python/introduction/NOC_I_1_RandomWalkTraditional.py b/Python/introduction/NOC_I_1_RandomWalkTraditional.py new file mode 100644 index 00000000..3d01d682 --- /dev/null +++ b/Python/introduction/NOC_I_1_RandomWalkTraditional.py @@ -0,0 +1,46 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +from pyprocessing import * +from random import randint + +def setup(): + size(800,200) + background(255) + global w + w = Walker() + +def draw(): + w.step() + w.render() + +class Walker: + + def __init__(self): + self.x = width/2 + self.y = height/2 + + def render(self): + stroke(0) + point(self.x, self.y) + + def step(self): + """Randomly move up, down, left, right or stay in one place.""" + + choice = randint(0,3) + + if choice is 0: + self.x += 1 + elif choice is 1: + self.x -= 1 + elif choice is 2: + self.y += 1 + elif choice is 3: + self.y -= 1 + + self.x = constrain(self.x, 0, width-1); + self.y = constrain(self.y, 0, height-1); + +run() diff --git a/Python/introduction/NOC_I_2_RandomDistribution.py b/Python/introduction/NOC_I_2_RandomDistribution.py new file mode 100644 index 00000000..2a3165ba --- /dev/null +++ b/Python/introduction/NOC_I_2_RandomDistribution.py @@ -0,0 +1,31 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import randint + +def setup(): + p.size(800,200); + global randomCounts + randomCounts = [0]*20 + +def draw(): + p.background(255) + + # pick a random number and increase the count + index = randint(0,len(randomCounts)-1) + randomCounts[index] += 1 + + # draw a rectangle to graph results + p.stroke(0); + p.strokeWeight(2); + p.fill(127); + + w = width/len(randomCounts) + + for x in range(0,len(randomCounts)): + p.rect(x*w, height-randomCounts[x], w-1, randomCounts[x]) + +p.run() diff --git a/Python/introduction/NOC_I_3_RandomWalkTendsToRight.py b/Python/introduction/NOC_I_3_RandomWalkTendsToRight.py new file mode 100644 index 00000000..99d291aa --- /dev/null +++ b/Python/introduction/NOC_I_3_RandomWalkTendsToRight.py @@ -0,0 +1,45 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import random + +def setup(): + p.size(800,200) + p.background(255) + global w + w = Walker() + +def draw(): + w.step() + w.render() + +class Walker: + + def __init__(self): + self.x = width/2 + self.y = height/2 + + def render(self): + p.stroke(0) + p.point(self.x, self.y) + + def step(self): + """Randomly move up, down, left, right or stay in one place.""" + + choice = random() + if choice < 0.4: + self.x += 1 + elif choice < 0.6: + self.x -= 1 + elif choice < 0.8: + self.y += 1 + else: + self.y -= 1 + + self.x = p.constrain(self.x, 0, width-1); + self.y = p.constrain(self.y, 0, height-1); + +p.run() diff --git a/Python/introduction/NOC_I_4_Gaussian.py b/Python/introduction/NOC_I_4_Gaussian.py new file mode 100644 index 00000000..de24207e --- /dev/null +++ b/Python/introduction/NOC_I_4_Gaussian.py @@ -0,0 +1,24 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import gauss + +def setup(): + p.size(800,200) + p.background(255) + p.smooth() + +def draw(): + + sd = 60 # standard deviation + mean = width/2 # mean + xloc = gauss(mean, sd) # gets gaussian random number + + p.noStroke() + p.fill(0,10) + p.ellipse(xloc, height/2, 16,16) # draw ellipse at our random location + +p.run() diff --git a/Python/introduction/NOC_I_5_NoiseWalk.py b/Python/introduction/NOC_I_5_NoiseWalk.py new file mode 100644 index 00000000..05a6bdd4 --- /dev/null +++ b/Python/introduction/NOC_I_5_NoiseWalk.py @@ -0,0 +1,43 @@ +# The Nature of Code +# Daniel Shiffman +# http://natureofcode.com +# ported to pyprocessing by Greg Meess + +import pyprocessing as p +from random import uniform +from numpy import array + +def setup(): + p.size(800,200) + p.smooth() + p.frameRate(30) + + global w + w = Walker() + +def draw(): + p.background(255) + w.walk() + w.display() + +class Walker: + + def __init__(self): + self.location = array([width/2, height/2]) + self.noff = array([uniform(0,1000), uniform(0,1000)]) + + def display(self): + p.strokeWeight(2) + p.fill(127) + p.stroke(0) + p.ellipse(self.location[0], self.location[1], 48, 48) + + def walk(self): + """Randomly move up, down, left, right or stay in one place.""" + # NOTE: pyprocessing perlin noise functionality appears to be glitchy + # (it freezes at exactly 0 for a series of steps) + self.location[0] = p.map(p.noise(self.noff[0]), -1, 1, 0, width) + self.location[1] = p.map(p.noise(self.noff[1]), -1, 1, 0, height) + self.noff += 0.01 + +p.run()