Example #1
0
class FlxLayer(FlxCore):
    def __init__(self):
        FlxCore.__init__(self)
        self._children = FlxArray()

    #@desc		Adds a new FlxCore subclass (FlxSprite, FlxBlock, etc) to the list of children
    #@param	Core	The object you want to add
    def add(self, Core):
        #Layer.add(self,Core)
        return self._children.add(Core)

    #@desc		Automatically goes through and calls update on everything you added, override this function to handle custom input and perform collisions
    def update(self):
        FlxCore.update(self)
        for i in range(len(self._children)):

            if ((self._children[i] != None) and self._children[i].exists
                    and self._children[i].active):
                self._children[i].update()

    #@desc		Automatically goes through and calls render on everything you added, override this loop to do crazy graphical stuffs I guess?
    def render(self):
        FlxCore.render(self)
        for i in range(len(self._children)):
            if ((self._children[i] != None) and self._children[i].exists
                    and self._children[i].visible):
                self._children[i].render()

    #@desc		Override this function to handle any deleting or "shutdown" type operations you might need (such as removing traditional Flash children like Sprite objects)
    def destroy(self):
        self._children.clear()
Example #2
0
class FlxLayer(FlxCore):

    def __init__(self):
        FlxCore.__init__(self)
        self._children = FlxArray();
    
    #@desc		Adds a new FlxCore subclass (FlxSprite, FlxBlock, etc) to the list of children
    #@param	Core	The object you want to add
    def add(self,Core):
        #Layer.add(self,Core)
        return self._children.add(Core)
    
    #@desc		Automatically goes through and calls update on everything you added, override this function to handle custom input and perform collisions
    def update(self):
        FlxCore.update(self);
        for i in range( len(self._children)):
           
            if((self._children[i] != None) and self._children[i].exists and self._children[i].active):
                self._children[i].update();
    
    #@desc		Automatically goes through and calls render on everything you added, override this loop to do crazy graphical stuffs I guess?
    def render(self):
        FlxCore.render(self);
        for  i in  range(len(self._children)):
            if((self._children[i] != None) and self._children[i].exists and self._children[i].visible):
                self._children[i].render();
    
    #@desc		Override this function to handle any deleting or "shutdown" type operations you might need (such as removing traditional Flash children like Sprite objects)
    def destroy(self): 
        self._children.clear()
Example #3
0
class FlxEmitter(FlxCore):
    # public var minVelocity:Point;
    # public var maxVelocity:Point;
    # private var _minRotation;
    # private var _maxRotation;
    # private var _gravity;
    # private var _drag;
    # private var _delay;
    # private var _timer;
    # private var self._sprites:FlxArray;
    # private var _particle;
    
    #@desc		Constructor
    #@param	X				The X position of the emitter
    #@param	Y				The Y position of the emitter
    #@param	Width			The width of the emitter (particles are emitted from a random position inside this box)
    #@param	Height			The height of the emitter
    #@param	Sprites			A pre-configured FlxArray of FlxSprite objects for the emitter to use (optional)
    #@param	Delay			A negative number defines the lifespan of the particles that are launched all at once.  A positive number tells it how often to fire a  particle.
    #@param	MinVelocityX	The minimum X velocity of the particles
    #@param	MaxVelocityX	The maximum X velocity of the particles (every particle will have a random X velocity between these values)
    #@param	MinVelocityY	The minimum Y velocity of the particles
    #@param	MaxVelocityY	The maximum Y velocity of the particles (every particle will have a random Y velocity between these values)
    #@param	MinRotation		The minimum angular velocity of the particles
    #@param	MaxRotation		The maximum angular velocity of the particles (you guessed it)
    #@param	Gravity			How much gravity should affect the particles
    #@param	Drag			Sets both the X and Y "Drag" or deceleration on the particles
    #@param	Graphics		If you opted to not pre-configure an array of FlxSprite objects, you can simply pass in a particle image or sprite sheet (ignored if you pass in an array)
    #@param	Quantity		The number of particles to generate when using the "create from image" option (ignored if you pass in an array)
    #@param	Multiple		Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!)
    def __init__(self,X, Y, Width, Height, Sprites=None, Delay=-1, MinVelocityX=-100, MaxVelocityX=100, MinVelocityY=-100, MaxVelocityY=100, MinRotation=-360, MaxRotation=360, Gravity=500, Drag=0, Graphics=None, Quantity=0, Multiple=false, Parent=None):
        FlxCore.__init__(self);
        
        self.visible = false;
        self.x = X;
        self.y = Y;
        self.width = Width;
        self.height = Height;
        
        self.minVelocity =  FlxPoint(MinVelocityX,MinVelocityY);
        self.maxVelocity =  FlxPoint(MaxVelocityX,MaxVelocityY);
        self._minRotation = MinRotation;
        self._maxRotation = MaxRotation;
        self._gravity = Gravity;
        self._drag = Drag;
        self._delay = Delay;
        self._timer=0
        self._particle = 0;
        if(Graphics != None):
            self._sprites =  FlxArray();
            for  i in range(Quantity):
                if(Multiple):
                    (self._sprites.add( FlxSprite(Graphics,0,0,true))).randomFrame();
                else:
                    self._sprites.add( FlxSprite(Graphics));
            for  i in range(len(self._sprites)):
                if(Parent == None):
                    FlxG.state.add(self._sprites[i]);
                else:
                    Parent.add(self._sprites[i]);
        else:
            self._sprites = Sprites;
        self.kill();
        if(self._delay > 0):
            self.reset();
    
    #@desc		Called automatically by the game loop, decides when to launch particles and when to "die"
    def update(self):
        self._timer += FlxG.elapsed;
        if(self._delay < 0):
            if(self._timer > -self._delay) : 
                self.kill(); 
                return; 
            if(not self._sprites[0].exists):
                for i in range(len(self._sprites)):
                    self.emit();
            return;
        while(self._timer > self._delay):
            self._timer -= self._delay; 
            self.emit();
    
    #@desc		Call this function to reset the emitter (if you used a negative delay, calling this function "Explodes" the emitter again)
    def reset(self):
        self.active = true;
        self._timer = 0;
        self._particle = 0;
    
    #@desc		This function can be used both internally and externally to emit the next particle
    def emit(self):
        s = self._sprites[self._particle];
        s.exists = true;
        s.x = self.x - (s.width>>1);
        if(self.width != 0): 
            s.x += Math.random()*self.width;
        s.y = self.y - (s.height>>1);
        if(self.height != 0): 
            s.y += Math.random()*self.height;
        s.velocity.x = self.minVelocity.x;
        if(self.minVelocity.x != self.maxVelocity.x): 
            s.velocity.x += Math.random()*(self.maxVelocity.x-self.minVelocity.x);
        s.velocity.y = self.minVelocity.y;
        if(self.minVelocity.y != self.maxVelocity.y):
            s.velocity.y += Math.random()*(self.maxVelocity.y-self.minVelocity.y);
        s.acceleration.y = self._gravity;
        s.angularVelocity = self._minRotation;
        if(self._minRotation != self._maxRotation): 
            s.angularVelocity += Math.random()*(self._maxRotation-self._minRotation);
        if(s.angularVelocity != 0): 
            s.angle = Math.random()*360-180;
        s.drag.x = self._drag;
        s.drag.y = self._drag;
        self._particle+=1
        if(self._particle >= len(self._sprites)):
            self._particle = 0;
        s.onEmit();
    
    #@desc		Call this function to turn off all the particles and the emitter
    def kill(self):
        active = false;
        for i in range( len(self._sprites)):
            self._sprites[i].exists = false;
Example #4
0
class FlxSprite(FlxCore):
    LEFT= false;
    RIGHT = true;
    
    # #@desc If you changed the size of your sprite object to shrink the bounding box, you might need to offset the new bounding box from the top-left corner of the sprite
    # public var offset:Point;
    # public var self.velocity:Point;
    # public var aself.acceleration:Point;
    # #@desc    This isn't self.drag exactly, more like deceleration that is only applied when aself.acceleration is not affecting the sprite
    # public var self.drag:Point;
    # public var maxself.velocity:Point;
    # #@desc WARNING: rotating sprites decreases rendering performance for this sprite by a factor of 10x!
    # public var self.angle:Number;
    # public var self.angularself.velocity:Number;
    # public var self.angularAself.acceleration:Number;
    # public var self.angularDrag:Number;
    # public var self.maxAngular:Number;
    # #@desc    If you want to do Asteroids style stuff, check out self.thrust (instead of directly accessing the object's self.velocity or aself.acceleration)
    # public var self.thrust:Number;
    # public var maxself.thrust:Number;
    # public var health:Number;
    # #@desc    self.scale doesn't currently affect collisions automatically, you will need to adjust the width, height and offset manually.  WARNING: scaling sprites decreases rendering performance for this sprite by a factor of 10x!
    # public var self.scale:Point;
    
    # #@desc    Whether the current animation has finished its first (or only) loop
    # public var finished:Boolean;
    # private var self._animations:FlxArray;
    # private var _flipped:uint;
    # protected var self._curAnim:FlxAnim;
    # protected var self._curFrame:uint;
    # private var self._frameTimer:Number;
    # private var _callback:Function;
    # private var self._facing:Boolean;
    
    # #helpers
    # private var self._bw:uint;
    # private var self._bh:uint;
    # private var _r:Rectself.angle;
    # private var self._p:Point;
    # private var self._pZero:Point;
    # public var pixels:BitmapData;
    # private var self._pixels:BitmapData;
    # private var self._alpha:Number;
    
    #@desc        Constructor
    #@param    Graphic        The image you want to use
    #@param    X            The initial X position of the sprite
    #@param    Y            The initial Y position of the sprite
    #@param    Animated    Whether the Graphic parameter is a single sprite or a row of sprites
    #@param    Reverse        Whether you need this class to generate horizontally flipped versions of the animation frames
    #@param    Width        If you opt to NOT use an image and want to generate a colored block, or your sprite's frames are not square, you can specify a width here 
    #@param    Height        If you opt to NOT use an image you can specify the height of the colored block here (ignored if Graphic is not null)
    #@param    Color        Specifies the color of the generated block (ignored if Graphic is not null)
    def __init__(self,Graphic=None,X=0,Y=0,Animated=false,Reverse=false,Width=0,Height=0,Color=0):
        
        if(Graphic != None):
            #image = pyglet.resource.image(Graphic)
            self.pixels = Graphic;
            pass
        else:
            self.pixels= pygame.image.load("data/logo.png")
            #pixels = FlxG.createBitmap(Width,Height,Color);
        FlxCore.__init__(self)
        
        #self.position=(X,FlxG.height-Y);
        #self.anchor=(0,0)
        #print dir(self.pixels)
        self.x = X;
        self.y = Y;
        
        if(Width == 0):
            if(Animated):
                Width = self.pixels.height;
            else:
                Width = self.pixels.width;
        self.width =Width 
        self._bw = Width;
        self.height = self.pixels.height;
        self._bh = self.height;
        self.offset = FlxPoint();
        
        self.velocity = FlxPoint();
        self.acceleration = FlxPoint();
        self.drag = FlxPoint();
        self.maxVelocity = FlxPoint(10000,10000);
        
        self.angle = 0;
        self.angularVelocity = 0;
        self.angularAacceleration = 0;
        self.angularDrag = 0;
        self.maxAngular = 10000;
        
        self.thrust = 0;
        
        self.scale = FlxPoint(1,1);
        
        self.finished = false;
        self._facing = true;
        self._animations = FlxArray();
        if(Reverse):
            #pass
            self._flipped = self.pixels.width>>1;
        else:
            self._flipped = 0;
        
        self._curAnim = None;
        self._curFrame = 0;
        self._frameTimer = 0;
        
        self._p = FlxPoint(self.x,self.y);
        self._pZero = FlxPoint();
        self._r = FlxRect(0,0,self._bw,self._bh);
        #self._pixels = BitmapData(width,height);
        #print self._bw,self._bh
        
        #raw_input()
        self._pixels=self.pixels.get_region(0,0,self._bw,self._bh)#,self._pZero);
        
        self.health = 1;
        self._alpha = 1;
        
        self._callback = None;
    
    #@desc        Called by game loop, handles animation and physics
    def update(self):
        self.last.x=self.x
        self.last.y=self.y
        #print "last",self,self.last.x,self.last.y
        FlxCore.update(self);
        
        if(not self.active): 
            return;
        
        #animation
        if((self._curAnim != None) and (self._curAnim.delay > 0) and (self._curAnim.looped or not self.finished)):
            self._frameTimer += FlxG.elapsed;
            #print self._frameTimer,self._curAnim.delay,FlxG.elapsed
            #raw_input()
            if(self._frameTimer > self._curAnim.delay):
                self._frameTimer -= self._curAnim.delay;
                if(self._curFrame == len(self._curAnim.frames)-1):
                    if(self._curAnim.looped):
                        self._curFrame = 0;
                    self.finished = true;
                else:
                    self._curFrame+=1;
                self.calcFrame();
                #print "curframe",self._curFrame
        
        #motion + physics
        self.angularVelocity = FlxG.computeVelocity(self.angularVelocity,self.angularAacceleration,self.angularDrag,self.maxAngular)
        self.angle += (self.angularVelocity)*FlxG.elapsed;
        self.thrustComponents=FlxPoint();
        if(self.thrust != 0):
            self.thrustComponents = FlxG.rotatePoint(-self.thrust,0,0,0,self.angle);
            maxComponents = FlxG.rotatePoint(-maxself.thrust,0,0,0,self.angle);
            maxself.velocity.x = Math.abs(maxComponents.x);
            maxself.velocity.y = Math.abs(maxComponents.y);
        else:
            self.thrustComponents = self._pZero;
        self.velocity.x = FlxG.computeVelocity(self.velocity.x,self.acceleration.x+self.thrustComponents.x,self.drag.x,self.maxVelocity.x)
        self.x += (self.velocity.x)*FlxG.elapsed;
        self.velocity.y = FlxG.computeVelocity(self.velocity.y,self.acceleration.y+self.thrustComponents.y,self.drag.y,self.maxVelocity.y)
        self.y += (self.velocity.y)*FlxG.elapsed;
        #print "x,y",self,self.x,self.y
    #@desc        Called by game loop, blits current frame of animation to the screen (and handles rotation)
    def render(self):
        if(not self.visible):
            return;
        self.getScreenXY(self._p);
        #ma todo
        # if((self.angle != 0) or (self.scale.x != 1) or (self.scale.y != 1)):
            # mtx = Matrix();
            # mtx.translate(-(self._bw>>1),-(self._bh>>1));
            # mtx.self.scale(self.scale.x,self.scale.y);
            # if(self.angle != 0):mtx.rotate(Math.PI * 2 * (self.angle / 360));
            # mtx.translate(self._p.x+(self._bw>>1),self._p.y+(self._bh>>1));
            # FlxG.buffer.draw(self._pixels,mtx);
            # return;
        #print dir(FlxG.buffer)
        #print dir(self._pixels)
        #print self._r,dir(self._r)
        r=FlxRect(self._p.x,self._p.y,self._r.width,self._r.height)
        #FlxG.buffer.blit(self._pixels,r);
        self._pixels.blit(self._p.x,self._p.y)
        #r=Rect(self._p.x,self._p.y,self._r.width,self._r.height)
        #FlxG.buffer.blit(self.pixels,r);
    
    #@desc        Checks to see if a point in 2D space overlaps this FlxCore object
    #@param    X            The X coordinate of the point
    #@param    Y            The Y coordinate of the point
    #@param    PerPixel    Whether or not to use per pixel collision checking
    #@return    Whether or not the point overlaps this object
    def overlapsPoint(self,X,Y,PerPixel = false):
        tx = self.x;
        ty = self.y;
        if((self.scrollFactor.x != 1) or (self.scrollFactor.y != 1)):
            tx -= Math.floor(FlxG.scroll.x*self.scrollFactor.x);
            ty -= Math.floor(FlxG.scroll.y*self.scrollFactor.y);
        if(PerPixel):
            return self._pixels.hitTest(Point(0,0),0xFF,Point(X-tx,Y-ty));
        elif((X <= tx) or (X >= tx+self.width) or (Y <= ty) or (Y >= ty+self.height)):
            return false;
        return true;
    
    #@desc        Called when this object collides with a FlxBlock on one of its sides
    #@return    Whether you wish the FlxBlock to collide with it or not
    def hitWall(self):
        self.velocity.x = 0; 
        return true; 
    
    #@desc        Called when this object collides with the top of a FlxBlock
    #@return    Whether you wish the FlxBlock to collide with it or not
    def hitFloor(self):
        self.velocity.y = 0; 
        return true; 
    
    #@desc        Called when this object collides with the bottom of a FlxBlock
    #@return    Whether you wish the FlxBlock to collide with it or not
    def hitCeiling(self):
        self.velocity.y = 0; 
        return true;
    
    #@desc        Call this function to "damage" (or give health bonus) to this sprite
    #@param    Damage        How much health to take away (use a negative number to give a health bonus)
    def hurt(self,Damage):
        self.health -= Damage
        if(self.health<= 0):
            self.kill();
    
    #@desc        Called if/when this sprite is launched by a FlxEmitter
    def onEmit(self):
        pass
    
    #@desc        Adds a animation to the sprite
    #@param    Name        What this animation should be called (e.g. "run")
    #@param    Frames        An array of numbers indicating what frames to play in what order (e.g. 1, 2, 3)
    #@param    FrameRate    The speed in frames per second that the animation should play at (e.g. 40 fps)
    #@param    Looped        Whether or not the animation is looped or just plays once
    def addAnimation(self,Name, Frames, FrameRate=30, Looped=true):
        self._animations.add(FlxAnim(Name,Frames,FrameRate,Looped));
    
    #@desc        Pass in a function to be called whenever this sprite's animation changes
    #@param    AnimationCallback        A function that has 3 parameters: a string name, a uint frame number, and a uint frame index
    def addAnimationCallback(self,AnimationCallback):
        self._callback = AnimationCallback;
    
    #@desc        Plays an existing animation (e.g. "run") - if you call an animation that is already playing it will be ignored
    #@param    AnimName    The string name of the animation you want to play
    #@param    Force        Whether to force the animation to restart
    def play(self,AnimName,Force=false):
        if(not Force and (self._curAnim != None) and (AnimName == self._curAnim.name)): 
            return;
        self._curFrame = 0;
        self._frameTimer = 0;
        for i in range( len(self._animations)):
            if(self._animations[i].name == AnimName):
                self.finished = false;
                self._curAnim = self._animations[i];
                self.calcFrame();
                return;
    
    #@desc        Tell the sprite which way to face (you can just set 'facing' but this function also updates the animation instantly)
    #@param    Direction        True is Right, False is Left (see static const members RIGHT and LEFT)        
    def setfacing(self,Direction):
        c = self._facing != Direction;
        self._facing = Direction;
        if(c): 
            self.calcFrame();
    
    #@desc        Get the direction the sprite is facing
    #@return    True means facing right, False means facing left (see static const members RIGHT and LEFT)
    def getfacing(self):
        return self._facing;
    
    #@desc        Tell the sprite to change to a random frame of animation (useful for instantiating particles or other weird things)
    def randomFrame(self):
        self._pixels=self.pixels.get_region(Math.floor(Math.random()*(self.pixels.width/self._bw))*self._bw,0,self._bw,self._bh)
    
    #@desc        Tell the sprite to change to a specific frame of animation (useful for instantiating particles)
    #@param    Frame    The frame you want to display
    def specificFrame(self,Frame):
        self._pixels=self.pixels.get_region(Frame*self._bw,0,self._bw,self._bh);
    
    #@desc        Call this function to figure out the post-scrolling "screen" position of the object
    #@param    P    Takes a Flash Point object and assigns the post-scrolled X and Y values of this object to it
    def getScreenXY(self,P):
        P.x = Math.floor(self.x-self.offset.x)+Math.floor(FlxG.scroll.x*self.scrollFactor.x);
        P.y = Math.floor(self.y-self.offset.y)+Math.floor(FlxG.scroll.y*self.scrollFactor.y);
    
    #@desc        Internal function to update the current animation frame
    def calcFrame(self):
        if(self._curAnim == None):
            self._pixels=self.pixels.get_region(self._r.x,self._r.y,self._r.width,self._r.height)#,self._pZero);
        else:
            rx = self._curAnim.frames[self._curFrame]*self._bw;
            if(not self._facing and (self._flipped > 0)):
                rx = (self._flipped<<1)-rx-self._bw;
            #print rx,self._bw,self._bh;
            #raw_input()
            self._pixels=self.pixels.get_region(rx,0,self._bw,self._bh)
        #if(self._alpha != 1): self._pixels.colorTransform(_r,ColorTransform(1,1,1,self._alpha));
        if(self._callback != None): 
            self._callback(self._curAnim.name,self._curFrame,self._curAnim.frames[self._curFrame]);
    
    #@desc        The setter for alpha
    #@param    Alpha    The opacity value of the sprite (between 0 and 1)
    def setalpha(self,Alpha):
        if(Alpha > 1): 
            Alpha = 1;
        if(Alpha < 0):
            Alpha = 0;
        self._alpha = Alpha;
        self.calcFrame();
    
    #@desc        The getter for alpha
    #@return    The value of this sprite's opacity
    def getalpha(self):
        return self._alpha;
Example #5
0
class FlxEmitter(FlxCore):
    # public var minVelocity:Point;
    # public var maxVelocity:Point;
    # private var _minRotation;
    # private var _maxRotation;
    # private var _gravity;
    # private var _drag;
    # private var _delay;
    # private var _timer;
    # private var self._sprites:FlxArray;
    # private var _particle;

    #@desc		Constructor
    #@param	X				The X position of the emitter
    #@param	Y				The Y position of the emitter
    #@param	Width			The width of the emitter (particles are emitted from a random position inside this box)
    #@param	Height			The height of the emitter
    #@param	Sprites			A pre-configured FlxArray of FlxSprite objects for the emitter to use (optional)
    #@param	Delay			A negative number defines the lifespan of the particles that are launched all at once.  A positive number tells it how often to fire a  particle.
    #@param	MinVelocityX	The minimum X velocity of the particles
    #@param	MaxVelocityX	The maximum X velocity of the particles (every particle will have a random X velocity between these values)
    #@param	MinVelocityY	The minimum Y velocity of the particles
    #@param	MaxVelocityY	The maximum Y velocity of the particles (every particle will have a random Y velocity between these values)
    #@param	MinRotation		The minimum angular velocity of the particles
    #@param	MaxRotation		The maximum angular velocity of the particles (you guessed it)
    #@param	Gravity			How much gravity should affect the particles
    #@param	Drag			Sets both the X and Y "Drag" or deceleration on the particles
    #@param	Graphics		If you opted to not pre-configure an array of FlxSprite objects, you can simply pass in a particle image or sprite sheet (ignored if you pass in an array)
    #@param	Quantity		The number of particles to generate when using the "create from image" option (ignored if you pass in an array)
    #@param	Multiple		Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!)
    def __init__(self,
                 X,
                 Y,
                 Width,
                 Height,
                 Sprites=None,
                 Delay=-1,
                 MinVelocityX=-100,
                 MaxVelocityX=100,
                 MinVelocityY=-100,
                 MaxVelocityY=100,
                 MinRotation=-360,
                 MaxRotation=360,
                 Gravity=500,
                 Drag=0,
                 Graphics=None,
                 Quantity=0,
                 Multiple=false,
                 Parent=None):
        FlxCore.__init__(self)

        self.visible = false
        self.x = X
        self.y = Y
        self.width = Width
        self.height = Height

        self.minVelocity = FlxPoint(MinVelocityX, MinVelocityY)
        self.maxVelocity = FlxPoint(MaxVelocityX, MaxVelocityY)
        self._minRotation = MinRotation
        self._maxRotation = MaxRotation
        self._gravity = Gravity
        self._drag = Drag
        self._delay = Delay
        self._timer = 0
        self._particle = 0
        if (Graphics != None):
            self._sprites = FlxArray()
            for i in range(Quantity):
                if (Multiple):
                    (self._sprites.add(FlxSprite(Graphics, 0, 0,
                                                 true))).randomFrame()
                else:
                    self._sprites.add(FlxSprite(Graphics))
            for i in range(len(self._sprites)):
                if (Parent == None):
                    FlxG.state.add(self._sprites[i])
                else:
                    Parent.add(self._sprites[i])
        else:
            self._sprites = Sprites
        self.kill()
        if (self._delay > 0):
            self.reset()

    #@desc		Called automatically by the game loop, decides when to launch particles and when to "die"
    def update(self):
        self._timer += FlxG.elapsed
        if (self._delay < 0):
            if (self._timer > -self._delay):
                self.kill()
                return
            if (not self._sprites[0].exists):
                for i in range(len(self._sprites)):
                    self.emit()
            return
        while (self._timer > self._delay):
            self._timer -= self._delay
            self.emit()

    #@desc		Call this function to reset the emitter (if you used a negative delay, calling this function "Explodes" the emitter again)
    def reset(self):
        self.active = true
        self._timer = 0
        self._particle = 0

    #@desc		This function can be used both internally and externally to emit the next particle
    def emit(self):
        s = self._sprites[self._particle]
        s.exists = true
        s.x = self.x - (s.width >> 1)
        if (self.width != 0):
            s.x += Math.random() * self.width
        s.y = self.y - (s.height >> 1)
        if (self.height != 0):
            s.y += Math.random() * self.height
        s.velocity.x = self.minVelocity.x
        if (self.minVelocity.x != self.maxVelocity.x):
            s.velocity.x += Math.random() * (self.maxVelocity.x -
                                             self.minVelocity.x)
        s.velocity.y = self.minVelocity.y
        if (self.minVelocity.y != self.maxVelocity.y):
            s.velocity.y += Math.random() * (self.maxVelocity.y -
                                             self.minVelocity.y)
        s.acceleration.y = self._gravity
        s.angularVelocity = self._minRotation
        if (self._minRotation != self._maxRotation):
            s.angularVelocity += Math.random() * (self._maxRotation -
                                                  self._minRotation)
        if (s.angularVelocity != 0):
            s.angle = Math.random() * 360 - 180
        s.drag.x = self._drag
        s.drag.y = self._drag
        self._particle += 1
        if (self._particle >= len(self._sprites)):
            self._particle = 0
        s.onEmit()

    #@desc		Call this function to turn off all the particles and the emitter
    def kill(self):
        active = false
        for i in range(len(self._sprites)):
            self._sprites[i].exists = false