def test_ParticleEngine(self): engine = particles.ParticleEngine() self.assertIsInstance(engine, particles.ParticleEngine) self.assertTrue(particles.Particle in engine.componenttypes) self.assertIsNone(engine.createfunc) self.assertIsNone(engine.deletefunc) self.assertIsNone(engine.updatefunc)
def test_ParticleEngine_process(self): def cfunc(w, c): self.assertEqual(len(c), w["runs"]) for p in c: self.assertLessEqual(p.life, 0) def ufunc(w, c): self.assertEqual(len(c), 100 - w["runs"]) for p in c: self.assertGreaterEqual(p.life, 1) def dfunc(w, c): self.assertEqual(len(c), w["runs"]) for p in c: self.assertLessEqual(p.life, 0) plist = [] for x in range(2, 102): plist.append(particles.Particle(x, x, x - 1)) engine = particles.ParticleEngine() engine.createfunc = cfunc engine.updatefunc = ufunc engine.deletefunc = dfunc world = {"runs": 1} engine.process(world, plist) world["runs"] = 2 engine.process(world, plist)
def test_ParticleEngine(self): engine = particles.ParticleEngine() assert isinstance(engine, particles.ParticleEngine) assert particles.Particle in engine.componenttypes assert engine.createfunc is None assert engine.deletefunc is None assert engine.updatefunc is None
def test_ParticleEngine_process(self): def cfunc(w, c): assert len(c) == w["runs"] for p in c: assert p.life <= 0 def ufunc(w, c): assert len(c) == 100 - w["runs"] for p in c: assert p.life >= 1 def dfunc(w, c): assert len(c) == w["runs"] for p in c: assert p.life <= 0 plist = [] for x in range(2, 102): plist.append(particles.Particle(x, x, x - 1)) engine = particles.ParticleEngine() engine.createfunc = cfunc engine.updatefunc = ufunc engine.deletefunc = dfunc world = {"runs": 1} engine.process(world, plist) world["runs"] = 2 engine.process(world, plist)
def test_ParticleEngine_updatefunc(self): def func(w, c): pass engine = particles.ParticleEngine() self.assertIsNone(engine.updatefunc) engine.updatefunc = func self.assertEqual(engine.updatefunc, func) def setf(x, f): x.updatefunc = f self.assertRaises(TypeError, setf, engine, None) self.assertRaises(TypeError, setf, engine, "Test") self.assertRaises(TypeError, setf, engine, 1234)
def test_ParticleEngine_updatefunc(self): def func(w, c): pass engine = particles.ParticleEngine() assert engine.updatefunc is None engine.updatefunc = func assert engine.updatefunc == func def setf(x, f): x.updatefunc = f with pytest.raises(TypeError): setf(engine, None) with pytest.raises(TypeError): setf(engine, "Test") with pytest.raises(TypeError): setf(engine, 1234)
def run(): # Create the environment, in which our particles will exist. world = sdl2ext.World() # Set up the globally available information about the current mouse # position. We use that information to determine the emitter # location for new particles. world.mousex = 400 world.mousey = 300 # Create the particle engine. It is just a simple System that uses # callback functions to update a set of components. engine = particles.ParticleEngine() # Bind the callback functions to the particle engine. The engine # does the following on processing: # 1) reduce the life time of each particle by one # 2) create a list of particles, which's life time is 0 or below. # 3) call createfunc() with the world passed to process() and # the list of dead particles # 4) call updatefunc() with the world passed to process() and the # set of particles, which still are alive. # 5) call deletefunc() with the world passed to process() and the # list of dead particles. deletefunc() is respsonible for # removing the dead particles from the world. engine.createfunc = createparticles engine.updatefunc = updateparticles engine.deletefunc = deleteparticles world.add_system(engine) # We create all particles at once before starting the processing. # We also could create them in chunks to have a visually more # appealing effect, but let's keep it simple. createparticles(world, None, 300) # Initialize the video subsystem, create a window and make it visible. sdl2ext.init() window = sdl2ext.Window("Particles", size=(800, 600)) window.show() # Create a hardware-accelerated sprite factory. The sprite factory requires # a rendering context, which enables it to create the underlying textures # that serve as the visual parts for the sprites. renderer = sdl2ext.RenderContext(window) factory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) # Create a set of images to be used as particles on rendering. The # images are used by the ParticleRenderer created below. images = (factory.from_image(RESOURCES.get_path("circle.png")), factory.from_image(RESOURCES.get_path("square.png")), factory.from_image(RESOURCES.get_path("star.png"))) # Center the mouse on the window. We use the SDL2 functions directly # here. Since the SDL2 functions do not know anything about the # sdl2.ext.Window class, we have to pass the window's SDL_Window to it. SDL_WarpMouseInWindow(window.window, world.mousex, world.mousey) # Hide the mouse cursor, so it does not show up - just show the # particles. SDL_ShowCursor(0) # Create the rendering system for the particles. This is somewhat # similar to the SoftSpriteRenderer, but since we only operate with # hundreds of particles (and not sprites with all their overhead), # we need an own rendering system. particlerenderer = ParticleRenderer(renderer, images) world.add_system(particlerenderer) # The almighty event loop. You already know several parts of it. running = True while running: for event in sdl2ext.get_events(): if event.type == SDL_QUIT: running = False break if event.type == SDL_MOUSEMOTION: # Take care of the mouse motions here. Every time the # mouse is moved, we will make that information globally # available to our application environment by updating # the world attributes created earlier. world.mousex = event.motion.x world.mousey = event.motion.y # We updated the mouse coordinates once, ditch all the # other ones. Since world.process() might take several # milliseconds, new motion events can occur on the event # queue (10ths to 100ths!), and we do not want to handle # each of them. For this example, it is enough to handle # one per update cycle. SDL_FlushEvent(SDL_MOUSEMOTION) break world.process() SDL_Delay(1) sdl2ext.quit() return 0