Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Simple Particle Engine — Gideros Forum

Simple Particle Engine

andronandron Member
edited January 2012 in Code snippets
Here is very simple example of particle engine. I ported it from ActionScript and original author is in credits.
I hope it would be handy while we are waiting for Particle Engine implemented in SDK. This version uses ugly stars drawn by code, but if you change that for image it would became more atractive :)

-- main.lua
-- main file
 
application:setBackgroundColor(0x000000)
 
local container = Sprite.new()
stage:addChild(container)
container:setPosition(100, 100)
 
local HEIGHT = 400		-- container height
local WIDTH = 400		-- container width
local COUNT = 200		-- number of particles
 
local particles	= {}	-- particle table
local spare	= {}		-- spare particle table
 
function enterFrameHandler()
	updateParticles()
	addParticles(10);
end
 
-- update existing particles
function updateParticles()
	local particle
 
	-- check if we hit limit
	if #particles > COUNT then
		particle = table.remove(particles, 1)
		particle:disable()
		table.insert(spare, particle)
	end
 
	-- go through the array of particles...
	local i = 1
	local len = #particles
	local flag = len > 1
 
	while flag do
		-- ... and update each one
 
		particle = particles[i]
		if not particle.disabled then
			particle:update()
			if particle.sprite:getWidth() < 2 then
				particle:disable()
				table.insert(spare, table.remove(particles, i))
				-- table size has changed, reflect that in variables
				len = len - 1
				i = i - 1
			end
 
		end
 
		i = i + 1
		-- check whether we reached end of the table
		if i > len then 
			flag = false 
		end
	end
end
 
-- add specified number of new particles
function addParticles(count)
	local spark
	for i = 1, count do
		spark = createParticle(math.random(0, WIDTH), math.random(0, 40))
		table.insert(particles, spark)
	end
end
 
-- draw spark shape, or use image as a particle
function createParticle(x, y)
	local particle
 
	if #spare == 0 then
 
		-- draw new particle
		local shape = Shape.new()
		shape:setLineStyle(1, 0xffff00)
		shape:setFillStyle(Shape.SOLID, 0xffff00, 0.5)
 
		shape:beginPath()
		shape:moveTo(18, 0)
		shape:lineTo(20, 13)
		shape:lineTo(38, 16)
		shape:lineTo(21, 20)
		shape:lineTo(18, 35)
		shape:lineTo(15, 21)
		shape:lineTo(0, 17)
		shape:lineTo(15, 14)
		shape:lineTo(18, 0)
		shape:closePath()
		shape:endPath()
 
		-- or use image
		--local shape = Bitmap.new(Texture.new("spark.png"))
 
		container:addChild(shape)
		shape:setPosition(x, y);
		particle = cParticle.new(shape)
	else 
		-- reuse particle
		particle = table.remove(spare, 1)
		particle.sprite:setPosition(x, y)
		particle:enable()
	end
 
	particle:setVel(math.random(-1,1),math.random(0,5))
	particle:setScale(0.7)
	particle.shrink = 0.9
	particle.gravity = 2
	particle.drag = 0.7
 
	return particle
end
 
container:addEventListener(Event.ENTER_FRAME, enterFrameHandler);
-- cParticle.lua
-- PARTICLE EXPERIMENTS
-- Author : Seb Lee-Delisle
-- Blog : www.sebleedelisle.com
-- Company : www.pluginmedia.net
--
-- This work is licensed under a Creative Commons  2.0 License.
 
-- Full details at
-- http:--creativecommons.org/licenses/by/2.0/uk/
 
-- You may re-use this code as you wish, but a credit would be
-- appreciated. And I'd love to see what you do with it!
-- mail me : seb@sebleedelisle.com
 
 
cParticle = gideros.class(EventDispatcher)
 
function cParticle:init(sprite)
	self.sprite = sprite			-- sprite for the particle
 
	self.xVel = 0					-- the x and y velocity of the particle
	self.yVel = 0
 
	self.drag = 1					-- the drag factor between 0 and 1, where 1 is no drag, and 0 is max drag.
	self.fade = 1					-- the fade factor, works as a multiplier.
	self.shrink	= 0					-- another multiplier that changes the size.
									-- If < 1 then the particle graphic shrinks, >1 and the particle grows.
 
	self.gravity = 0				-- the amount of gravity to add to the yVelocity every frame. 
									-- If < 0 then gravity goes upwards.
 
	self.directionRotate = false	-- if true then the particle points in the direction it's moving
 
	self.disabled = true			-- for disabling the particle so we can reuse it.
 
	self:enable();
end
 
function cParticle:setVel(xvel, yvel)
	self.xVel = xvel
	self.yVel = yvel
end
 
function cParticle:setScale(scale)
	self.sprite:setScale(scale, scale)
end
 
function cParticle:update()
	if not self.disabled then
		-- add the velocity to the particle's position...
		self.sprite:setX(self.sprite:getX() + self.xVel)
		self.sprite:setY(self.sprite:getY() + self.yVel)
 
		-- apply drag
		self.xVel = self.xVel * self.drag
		self.yVel = self.yVel * self.drag
 
		-- fade out
		self.sprite:setAlpha(((self.sprite:getAlpha()*1000)*self.fade)/1000)
 
		-- scale
		local scale = self.sprite:getScaleX() * self.shrink
		self.sprite:setScale(scale, scale)
 
		-- gravity
		self.yVel = self.yVel + self.gravity
 
		if self.directionRotate then
			self:updateRotation()
		end
	end
end
 
function cParticle:restart(x, y)
	self:initDefaults()
	self:enable()
	self.sprite:setPosition(x, y)
end
 
function cParticle:updateRotation()
	self.sprite:setRotation(math.atan2(self.yVel, self.xVel))	--Math.atan2(yVel,xVel)*(180/Math.PI)
end
 
function cParticle:disable()
	self.sprite:setVisible(false);
	self.disabled = true;
end
 
function cParticle:enable()
	self.sprite:setVisible(true);
	self.disabled = false;
end

Likes: gorkem, atilim

Tagged:
+1 -1 (+2 / -0 )Share on Facebook

Comments

  • DaveyJJDaveyJJ Member
    edited January 2012
    I get an error ...

    main.lua:3: attempt to call method 'setBackgroundColor' (a nil value)
    stack traceback:
    main.lua:3: in main chunk

    Thoughts?

    (Oops. I'm using beta 3. It might be that. -- Yes, it was. Works fine under beta 8. Thanks.)

    Likes: gorkem

    +1 -1 (+1 / -0 )Share on Facebook
  • fawzmafawzma Member
    edited February 2012
    Here's an unfinished updated based off cocos2d particle system, and uses a plist format modified to an LUA table. It can easily be modified from a Particle Designer pex file.

    still need to do the rotation, color, scale, etc..

    update* size, color, scale, rotation added, just need to optimize it now. especially with the way the particle is reset.
    zip
    zip
    particles.zip
    12K

    Likes: atilim

    +1 -1 (+1 / -0 )Share on Facebook
  • sorry but the zip posted do not works for me!

    (part.lua and utils.lua missing)

    i'm missing something?
    :-((
    TNT ENGiNE for Gideors Studio - Particle Engine, Virtual Pad, Animator Studio, Collision Engine - DOWNLOAD NOW !!! IT'S FREE!!! -
    www.tntengine.com
  • sorry, realized when you save the project it doesn't move the referenced file in with the rest of the project. Try now
  • ok. now works.!
    nice! example!.
    i'm also working on particle engine... ;)

    TNT ENGiNE for Gideors Studio - Particle Engine, Virtual Pad, Animator Studio, Collision Engine - DOWNLOAD NOW !!! IT'S FREE!!! -
    www.tntengine.com
  • fawzmafawzma Member
    edited February 2012
    updated version using an emitter approach, rotation finally works right.
    zip
    zip
    pTest2.zip
    12K
  • gorkemgorkem Maintainer
    Just a small note - gproj file needs a bit tweaking (again) to reference the correct files ;-)
  • haha fixed. Is there a plan to add a feature when you go to add an existing file you can either reference it or make a copy?
  • fawzmafawzma Member
    edited February 2012
    Here's a version with ptype2 working (radial particles) and blendFunc

    Consolidated down to the following commands for use in your own programs.

    emitter = cEmitter.new(particletable)

    emitter:start() --duration part not implemented yet, use this to active the emitter

    emitter:stop()

    emitter:play(event.deltaTime,particle x pos,particle y pos,override table)

    added an override table, in the latest example, it will use the device angle to modify the emitter angle

    updated with a gravity well type

    zip
    zip
    pTest2.zip
    13K
  • gorkemgorkem Maintainer
    @fawzma yes, we discussed this and will show a popup asking whether to reference or copy the corresponding file. :)
  • Sorry andron for hijacking this thread :)

    Here's a 3rd Particle sample, using linked lists. This one is even faster than what I was currently working on.

    Greg, I suspect this is what you are doing as well.
    zip
    zip
    LinkedParticle.zip
    8K
  • GregBUGGregBUG Guru
    edited February 2012
    no. (almost for now) :P
    i'm not really sure that linked list (implemented in lua) is more fast of tables... (managed by C lua core)
    in your example you are however browsing all particles array if i correctly understood your code:

    in "function Emitter:run()"
    for a = 1, self.TotalParticles do repeat
    investigating now...

    [edit correction]

    no. i'm implementing now a double linked list. for add and removal efficiency.
    next i'll converting in native code (if I can!)

    [edit2]
    i'm back to tables... after some test... i prefer the "super speed" of lua tables

    (PS: i'm not a lua expert coder BTW)

    Dislikes: anefiox, JuanZambrano

    TNT ENGiNE for Gideors Studio - Particle Engine, Virtual Pad, Animator Studio, Collision Engine - DOWNLOAD NOW !!! IT'S FREE!!! -
    www.tntengine.com
    +1 -1 (+0 / -2 )Share on Facebook
Sign In or Register to comment.