# Add the upper directory (where the nodebox module is) to the search path. import os, sys; sys.path.insert(0, os.path.join("..","..")) from nodebox.graphics import * from nodebox.graphics.physics import System, Emitter, Particle, MASS # 1) An emitter will be firing particles with a constant velocity. # 2) Drag in the system slows down the particles. # 3) Gravity then becomes greater than the particles' velocity and they are pulled down. s = System(gravity=(0, 1.0), drag=0.01) # The emitter is positioned centrally at the bottom, # and fires particles upwards in a 30-degrees angle range. e = Emitter(x=200, y=0, angle=90, strength=10.0, spread=30) for i in range(100): # Particles have random mass and lifespan to make it more interesting and diverse. # The MASS constant means that we want the radius of the visual particle # to be initialized with the same value as its mass (it's a convenience trick). # This way we can observe how heavier particles respond. e.append(Particle(0, 0, mass=random(10,50), radius=MASS, life=random(50,250))) s.append(e) # Install the emitter in the system. # Add an obstacle that other particles want to stay away from. class Obstacle(Particle): def draw(self): # The only way to style individual particles is to redefine draw() in a subclass. # Set the fill color directly for this ellipse, i.e. don't use fill(), # because this sets the state and then other particles might use this color too. ellipse(self.x, self.y, self.radius*2, self.radius*2, fill=(0,0,0.3,0.1))
# Add the upper directory (where the nodebox module is) to the search path. import os, sys sys.path.insert(0, os.path.join("..", "..")) from nodebox.graphics import * from nodebox.graphics.physics import Particle, Force, System # This example demonstrates the Animation object, # which can be used to store and replay a sequence of image frames. # This is useful for caching pre-rendered effects, like a spell or an explosion. # This is just the explosion system from the previous example in a more condensed form. s = System(gravity=(0, 1.0)) for i in range(80): s.append(Particle(x=200, y=250, mass=random(5.0, 10.0), radius=5, life=30)) s.force(strength=4.5, threshold=70) # Instead of drawing the system directly to the canvas, # we render each step offscreen as an image, # and then gather the images in an animation loop. explosion = Animation(duration=0.75, loop=False) for i in range(30): s.update(limit=20) img = render(s.draw, 400, 400) explosion.append(img) # This can take several seconds: # - calculating forces in the system is costly (if possible, load Psyco to speed them up), # - rendering each image takes time (specifically, initialising a new empty image). # If possible, reduce the image frames in size (smaller images = faster rendering).
import os, sys sys.path.insert(0, os.path.join("..","..")) from nodebox.graphics.context import * from nodebox.graphics import * from nodebox.graphics.physics import Particle, Force, System from nodebox.graphics.shader import render # This example demonstrates the Animation object, # which can be used to store and replay a sequence of image frames. # This is useful for caching pre-rendered effects, like a spell or an explosion. # This is just the explosion system from the previous example in a more condensed form. s = System(gravity=(0, 1.0)) for i in range(80): s.append(Particle(x=200, y=250, mass=random(5.0,10.0), radius=5, life=30)) s.force(strength=4.5, threshold=70) # Instead of drawing the system directly to the canvas, # we render each step offscreen as an image, # and then gather the images in an animation loop. explosion = Animation(duration=0.75, loop=False) for i in range(30): s.update(limit=20) img = render(s.draw, 400, 400) explosion.append(img) # This can take several seconds: # - calculating forces in the system is costly (if possible, load Psyco to speed them up),
from nodebox.graphics.context import * from nodebox.graphics import * from nodebox.graphics.physics import Particle, Force, System # BANG! # Here is a short example of how the Particle class # can be subclassed with a custom draw() method: class Spark(Particle): def draw(self): r = self.radius * (1-self.age) ellipse(self.x, self.y, r*2, r*2) s = System(gravity=(0, 2.5)) # Pull the particles to the bottom edge. for i in range(80): s.append( Spark( x = 300, y = 400, mass = random(5.0,10.0), # Heavier particles are repulsed harder. radius = 5, # But doesn't mean they appear bigger. life = 200 # Particles whither away after 200 frames. )) # A repulsive force between all particles. # When particles are very close to each other, forces can be very strong, # causing particles to move offscreen before anything can be observed. # This can be tweaked with the threshold ( # which is the minimum distance at which the force operates).
# Add the upper directory (where the nodebox module is) to the search path. import os, sys; sys.path.insert(0, os.path.join("..","..")) from nodebox.graphics import * from nodebox.graphics.physics import Particle, Spring, System # A "particle system" is used to simulate effects such as explosions, smoke, water, ... # It consists of object with a mass (particles) that are subjected to forces # (attractive, repulsive, spring-based). # In this case, # the system is a grid (net/tissue) of particles arranged in rows and columns. s = System() x = 65 # Horizontal offset. y = 65 # Vertical offset. d = 40 # Distance between each particle. m = 10 # Number of rows. n = 10 # Number of columns. for i in range(n): for j in range(m): s.append( Particle( x = x + i*d, y = y + j*d, radius=5)) # Spring forces operate on all particles, # so that when we drag one particle all others are indirectly dragged as well. # The strength of each spring defines the flexibilty of the resulting fabric. for i in range(n): for j in range(m): p1 = s.particles[i*m + j]
# Add the upper directory (where the nodebox module is) to the search path. import os, sys sys.path.insert(0, os.path.join("..", "..")) from nodebox.graphics import * from nodebox.graphics.physics import Particle, Spring, System # A "particle system" is used to simulate effects such as explosions, smoke, water, ... # It consists of object with a mass (particles) that are subjected to forces # (attractive, repulsive, spring-based). # In this case, # the system is a grid (net/tissue) of particles arranged in rows and columns. s = System() x = 65 # Horizontal offset. y = 65 # Vertical offset. d = 40 # Distance between each particle. m = 10 # Number of rows. n = 10 # Number of columns. for i in range(n): for j in range(m): s.append(Particle(x=x + i * d, y=y + j * d, radius=5)) # Spring forces operate on all particles, # so that when we drag one particle all others are indirectly dragged as well. # The strength of each spring defines the flexibilty of the resulting fabric. for i in range(n): for j in range(m): p1 = s.particles[i * m + j] if i < (n - 1): p2 = s.particles[(i + 1) * m + j + 0] # Particle to the right.
from nodebox.graphics import * from nodebox.graphics.physics import Particle, Force, System # BANG! # Here is a short example of how the Particle class # can be subclassed with a custom draw() method: class Spark(Particle): def draw(self): r = self.radius * (1 - self.age) ellipse(self.x, self.y, r * 2, r * 2) s = System(gravity=(0, 2.5)) # Pull the particles to the bottom edge. for i in range(80): s.append( Spark( x=300, y=400, mass=random(5.0, 10.0), # Heavier particles are repulsed harder. radius=5, # But doesn't mean they appear bigger. life=200 # Particles whither away after 200 frames. )) # A repulsive force between all particles. # When particles are very close to each other, forces can be very strong, # causing particles to move offscreen before anything can be observed. # This can be tweaked with the threshold ( # which is the minimum distance at which the force operates).
import os, sys sys.path.insert(0, os.path.join("..","..")) from nodebox.graphics.context import * from nodebox.graphics import * from nodebox.graphics.physics import System, Emitter, Particle, MASS # 1) An emitter will be firing particles with a constant velocity. # 2) Drag in the system slows down the particles. # 3) Gravity then becomes greater than the particles' velocity and they are pulled down. s = System(gravity=(0, 1.0), drag=0.01) # The emitter is positioned centrally at the bottom, # and fires particles upwards in a 30-degrees angle range. e = Emitter(x=200, y=0, angle=90, strength=10.0, spread=30) for i in range(100): # Particles have random mass and lifespan to make it more interesting and diverse. # The MASS constant means that we want the radius of the visual particle # to be initialized with the same value as its mass (it's a convenience trick). # This way we can observe how heavier particles respond. e.append(Particle(0, 0, mass=random(10,50), radius=MASS, life=random(50,250))) s.append(e) # Install the emitter in the system. # Add an obstacle that other particles want to stay away from. class Obstacle(Particle): def draw(self): # The only way to style individual particles is to redefine draw() in a subclass. # Set the fill color directly for this ellipse, i.e. don't use fill(),