2D particles engine

BlitzMax Forums/BlitzMax Programming/2D particles engine

Here's a 2D particles engine module for win32.
Some parameters missing, but I'm still working on it.
PartEngine Beta 0.5

How come only for win32?

[ERROR]: c:\blitzmaxbeta101\bin\ld: cannot find c:/blitzmaxbeta101/mod/ftbass.mod/ftbass.mod/ftbass.a

ftbass: It's not a module if it isn't classified as one in the source code.

Pert: You have to build it after classifying it as a module (putting 'Module ftbass.ftparticle' at the top of the file then sticking it in a folder that represents the module structure).

@AngelDaniel :
I built it on Windows, and didn't test it on other OS.
I think I have to built it again for Linux, and Mac.

@Noel Cower :
In the source code, there is :
Module ftbass.partengine

ModuleInfo "Name: PartEngine"
ModuleInfo "Description: Moteur de particules 2D"
ModuleInfo "Auteur: ftbass"

Import BRL.LinkedList
Import BRL.System
Import BRL.Random
Import BRL.Max2D

so I think it's classified as a module.

It works fine on my PC, and another one too...

Does it work anywhere else than on these 2 PC ??? Or maybe can anyone tell me what is missing ?

thx

Hm, seems mine didn't download entirely. Weird, but you are right- it is there (well, it is after downloading it a second time).

My apologies.

np :)

@ftbass
Doesn't work here - I get a Compile Error: "Identifier 'TEmetteur' not found" when BMax is trying to compile it.
Tried it with Demo and with Tutorial7
There is no .bmx file in the ftbass.mod folder - just another folder "partengine.mod" with 2 files (partengine.a and partengine.i) and a .bmx folder - is that right?

I get the same error as RaGR ok here are the files in the "PartEngine.mod"

1. Folder = .bmx
2. File = partengine.a
3. File = partengine.i

you cannot compile it or import it because you have missing files.

Oh and can you create a english version.

Oops... sorry I am really late :/
here is a version of the module built with BlitzMax 1.06.
I hope this will solve problems.

PartEngine Beta 0.6

Some parameters missing, but still working on it :)

Please let me know if it works (or not).
some friends of mine tested it, and there was no matter.

Many thanks :)

Works now - possibly it was okay before, too

But I made the mistake to put ftbass.mod into the pub.mod folder (had somehow in mind that there are Blitz Research Mods - brl.mod and public mods - pub.mod - so I expected your module has to go into the public one...)

Okay now I have copied it direct into the mod folder and its okay

Thank you

"Identifier 'TEmetteur' not found" (tested it on a Mac)

Just tried it very nice. You still have a problem with the mods the compiler is trying to find Debug version while you have the Release version.

@Kamashin : this module was compiled with Windows, so it can't work on Mac.
I'll try to find a way to compile it on Mac.

@Sarge : here's a new version correctly built (I hope :))

PartEngine Beta 0.6

Thanks for feed back :)

Send me the source and I'll see what I can do, ftbass. Just tell me what you did to compile yours (I have no experience with modules); it probably just requires me doing the same thing on the Mac, unless it's in C++ or something.

Actually, you really should just distribute the source. It would be easier on everyone that way.

if it's just about compiling, I could do it if I had the source... But I guess you don't want to make the source public... (d ailleurs t es francais non??? vu ke toute la doc et les commentaires du .bmx de test sont en francais :)
hop, un compatriote :) )

Well... I decided to post the source code of PartEngine.
You can do whatever you want of it. Just share your improvements if you're doing some.
And please let me know if you use this engine in some prod ;)

	'######################################################################'
	'#	PartEngine Beta v0.6.1
	'#	
	'#	par Julien COIGNET aka ftbass
	'#	email : breddabasse@...
	'######################################################################'

	' A FAIRE :
	' - 
	'----------------------------

Rem
################################################################
# Pour en faire un module, enlever les commentaires d'ici...

Strict


Module ftbass.partengine

ModuleInfo "Name: PartEngine"
ModuleInfo "Description: Moteur de particules 2D"
ModuleInfo "Auteur: ftbass"

Import BRL.LinkedList
Import BRL.System
Import BRL.Random
Import BRL.Max2D

# ... a ici.
################################################################
EndRem


Global P2D_ListeEmet:TList = New TList		' Liste des émetteurs


'################################################################
' Type Emetteur
'################################################################
Type TEmetteur

	Field listePart:TList			' Liste des particules creees par cet emetteur
	
	Field image					' Image affichée par les particules
	Field x:Float, y:Float			' Position de l'emetteur
	Field ecartX:Float			' Ecart de la position en Y des particules a la creation
	Field ecartY:Float			' Ecart de la position en Y des particules a la creation
	Field dx:Float, dy:Float		' Vitesse
	Field accX:Float, accY:Float	' Accélération
	Field age:Int					' Age de l'emetteur
	Field heureCreation:Int		' Heure de creation de l'emetteur
	Field longevite:Int			' Duree apres laquel l'emetteur sera supprime
	Field angle:Float				' Angle d'emission des particules
	Field nbPartFrame:Float		' Nb de particules créé par frame
	Field nbFramePourEmt:Float		' Nb de frames entre chaque emission de particules (si nbPartFrame < 0)
	Field nbFrameRestant:Int		' Nb de frames avant emission (si nbPartFrame < 0)
	Field nbPartCourant:Int		' Nb de particules actuellement en activité
	Field echelleXIni:Float		' Scale X initial
	Field echelleYIni:Float		' Scale Y initial
	Field ecartEchelleXIni:Float	' Ecar(t en X du scale initial
	Field ecartEchelleYIni:Float	' Ecar(t en Y du scale initial
	Field dEchelleX:Float			' Modification du scale X
	Field dEchelleY:Float			' Modification du scale Y
	Field alphaIni:Float			' Alpha initial
	Field ecartAlpha:Float			' Ecart alpha initial
	Field dAlpha:Float			' Evolution de l'alpha
	Field ecartDAlpha:Float		' Ecart dans l'evolution de l'alpha
	Field typeEmt:String			' Type de l'emetteur : alpha / light
	Field viePart:Int				' Duree de vie d'une particule
	Field ecartViePart:Int			' Ecart pour la durée de vie des particules
	
	Field etat:String				' Etat de l'emetteur : actif / supprime
	
	'-----------------------------------------------------------
	' Mise à jour de l'emetteur
	'-----------------------------------------------------------
	Method Update()
	
		Local i:Int
		Local p:TParticule = New TParticule
	
		If longevite = -1 Then
			Select etat
				Case "actif"
					' On met à jour l'age de l'emetteur
					age = (MilliSecs() - heureCreation) / 1000
					If nbPartFrame >= 1 Then
						For i = 1 To nbPartFrame
							p = P2D_CreatePart(Self, image, x, y, rnd(ecartX) - (ecartX / 2), rnd(ecartY) - (ecartY / 2))', 0, -1, 0, 0)
							p.ReglerEchelle(echelleXIni + (rnd(ecartEchelleXIni) - (ecartEchelleXIni/2)), echelleYIni + (rnd(ecartEchelleYIni) - (ecartEchelleYIni/2)), dEchelleX:Float, dEchelleY:Float)
							p.ReglerAlpha(alphaIni + (rnd(ecartAlpha)  - (ecartAlpha / 2)), dAlpha + (rnd(ecartDAlpha) - (ecartDAlpha /2)))
							p.ReglerVelocite(dx, dy, accX, accY)
							p.ReglerVie(viePart, ecartViePart)
						Next
					Else
						If nbFrameRestant < 0 Then
							p = P2D_CreatePart(Self, image, x, y, rnd(ecartX) - (ecartX / 2), rnd(ecartY) - (ecartY / 2))', 0, -1, 0, 0)
							p.ReglerEchelle(echelleXIni + (rnd(ecartEchelleXIni) - (ecartEchelleXIni/2)), echelleYIni + (rnd(ecartEchelleYIni) - (ecartEchelleYIni/2)), dEchelleX:Float, dEchelleY:Float)
							p.ReglerAlpha(alphaIni + (rnd(ecartAlpha)  - (ecartAlpha / 2)), dAlpha + (rnd(ecartDAlpha) - (ecartDAlpha /2)))
							p.ReglerVelocite(dx, dy, accX, accY)
							p.ReglerVie(viePart, ecartViePart)
							
							nbFrameRestant = nbFramePourEmt
						Else
							nbFrameRestant = nbFrameRestant - 1
						End If
					End If

				Case "supprime"
					If CountList(listePart) = 0 Then
						ListRemove(P2D_listeEmet, Self)
					End If
			End Select
		Else
			Select etat
				Case "actif"
					' On met à jour l'age de l'emetteur
					age = (MilliSecs() - heureCreation) / 1000
					'On compare l'age à la longevite 
					If age => longevite Then
						' Si il a fait son temps, on le supprime
						If CountList(listePart) = 0 Then
							ListRemove(P2D_listeEmet, Self)
						End If
					Else
						' Sinon, on genere les particules
						If nbPartFrame >= 1 Then
							For i = 1 To nbPartFrame
								p = P2D_CreatePart(Self, image, x, y, rnd(ecartX) - (ecartX / 2), rnd(ecartY) - (ecartY / 2))', 0, -1, 0, 0)
								p.ReglerEchelle(echelleXIni + (rnd(ecartEchelleXIni) - (ecartEchelleXIni/2)), echelleYIni + (rnd(ecartEchelleYIni) - (ecartEchelleYIni/2)), dEchelleX:Float, dEchelleY:Float)
								p.ReglerAlpha(alphaIni + (rnd(ecartAlpha)  - (ecartAlpha / 2)), dAlpha + (rnd(ecartDAlpha) - (ecartDAlpha /2)))
								p.ReglerVelocite(dx, dy, accX, accY)
								p.ReglerVie(viePart, ecartViePart)
							Next
						Else
							If nbFrameRestant < 0 Then
								p = P2D_CreatePart(Self, image, x, y, rnd(ecartX) - (ecartX / 2), rnd(ecartY) - (ecartY / 2))', 0, -1, 0, 0)
								p.ReglerEchelle(echelleXIni + (rnd(ecartEchelleXIni) - (ecartEchelleXIni/2)), echelleYIni + (rnd(ecartEchelleYIni) - (ecartEchelleYIni/2)), dEchelleX:Float, dEchelleY:Float)
								p.ReglerAlpha(alphaIni + (rnd(ecartAlpha)  - (ecartAlpha / 2)), dAlpha + (rnd(ecartDAlpha) - (ecartDAlpha /2)))
								p.ReglerVelocite(dx, dy, accX, accY)
								p.ReglerVie(viePart, ecartViePart)
								
								nbFrameRestant = nbFramePourEmt
							Else
								nbFrameRestant = nbFrameRestant - 1
							End If
						End If
					End If
				Case "supprime"
				
			End Select		
		End If

	End Method
	
	'-----------------------------------------------------------
	' Suppression d'un emetteur
	'-----------------------------------------------------------
	Method Supprimer(flag:Int = 0)
		
		Local p:TParticule = New TParticule
		
		Select flag
			Case 0
				etat = "supprime"
			Case 1
				etat = "supprime"
				For p=EachIn listePart
					ListRemove(listePart, p)
				Next
				ListRemove(P2D_listeEmet, Self)
		End Select
	
	End Method
	
	'-----------------------------------------------------------
	' Positionnement d'un emmetteur en x y
	'-----------------------------------------------------------
	Method SetPosition(x:Int, y:Int)
		
		Self.x = x
		Self.y = y
		
	End Method
	
	'-----------------------------------------------------------
	' Reglage de l'echelle
	'-----------------------------------------------------------
	Method ReglerEchelle(echelleXIni:Float, echelleYIni:Float, ecartEchelleXIni:Float, ecartEchelleYIni:Float, dEchelleX:Float, dEchelleY:Float)
		
		Self.echelleXIni = echelleXIni
		Self.echelleYIni = echelleYIni
		Self.ecartEchelleXIni = ecartEchelleXIni
		Self.ecartEchelleYIni = ecartEchelleYIni
		Self.dEchelleX = dEchelleX
		Self.dEchelleY = dEchelleY
		
	End Method
	
	
	'-----------------------------------------------------------
	' Reglage de la velocite
	'-----------------------------------------------------------
	Method ReglerVelocite(dx:Float, dy:Float, accX:Float, accY:Float)
	
		Self.dx = dx
		Self.dy = dy
		Self.accX = accX
		Self.accY = accY
		
	End Method
	
	'-----------------------------------------------------------
	' Reglage de l'alpha
	'-----------------------------------------------------------
	Method ReglerAlpha(alphaIni:Float, ecartAlpha:Float, dAlpha:Float, ecartDAlpha:Float)
		
		Self.alphaIni = alphaIni
		Self.ecartAlpha = ecartAlpha
		Self.dAlpha = dAlpha
		Self.ecartDAlpha = ecartDAlpha
		
	End Method
	
	
	'-----------------------------------------------------------
	' Reglage de la duree de vie des particules
	'-----------------------------------------------------------
	Method ReglerVie(viePart:Int, ecartViePart:Int)
		
		Self.viePart = viePart
		Self.ecartViePart = ecartViePart 
		
	End Method


End Type


'################################################################
' Type Particule
'################################################################
Type TParticule

	Field pere:TEmetteur				' Emetteur à l'origine de la particule
	Field image
	Field x:Float, y:Float				' Position
	Field ecartX:Float, ecartY:Float
	Field dx:Float, dy:Float			' Vitesse
	Field accX:Float, accY:Float		' Accélération
	Field EchelleX:Float
	Field EchelleY:Float
	Field dEchelleX:Float				' Modification du scale X
	Field dEchelleY:Float				' Modification du scale Y
	Field Alpha:Float					'
	Field dAlpha:Float
	Field heureCreation:Int			' Heure de cration de la particule
	Field age:Int						' Age de la particule
	Field vie:Int						' Duree de vie de la particule
	
	'-----------------------------------------------------------
	' Mise à jour des particules
	'-----------------------------------------------------------
	Method Update()
	
		dx = dx + accX
		dy = dy + accY
		x = x + dx
		y = y + dy
		echelleX :+ dEchelleX
		echelleY :+ dEchelleY
		
		' Si la particule n'est plus visible, on la supprime
		If (echelleX < 0) Or (echelleY < 0) Then
			ListRemove(pere.listePart, Self)
			pere.nbPartCourant :- 1
		End If
		
		' Si la particule a fait son temps, on la supprime
		If (heureCreation + vie) < MilliSecs() Then
			ListRemove(pere.listePart, Self)
			pere.nbPartCourant :- 1
		End If
		
		
		Select pere.typeEmt
			' Mise à jour de l'alpha
			Case "alpha"
				alpha = alpha + dAlpha
				If dAlpha < 0
					If alpha < .0000 Then
						ListRemove(pere.listePart, Self)
						pere.nbPartCourant :- 1
					End If
				Else
					If dAlpha > 0 Then
						If alpha > 1 Then
							alpha = 1
						End If
					End If
				End If
			Case "light"
				alpha = alpha + dAlpha
				If dAlpha < 0
					If alpha < .0000 Then
						ListRemove(pere.listePart, Self)
						pere.nbPartCourant :- 1
					End If
				Else
					If dAlpha > 0 Then
						If alpha > 1 Then
							alpha = 1
						End If
					End If
				End If
		End Select
		
	End Method
	
	'-----------------------------------------------------------
	' Affichage de la particule
	'-----------------------------------------------------------
	Method Draw()

		Select pere.typeEmt
			Case "alpha"
				SetBlend ALPHABLEND
				SetAlpha(alpha)
			Case "light"
				SetBlend LIGHTBLEND
				SetAlpha(alpha)
		End Select
		
		SetScale(echelleX, echelleY)
		DrawImage image, x, y
		SetScale(1, 1)
		SetAlpha(1)
		SetBlend MASKBLEND
		
	End Method
	
	'-----------------------------------------------------------
	' Reglage de l'echelle
	'-----------------------------------------------------------
	Method ReglerEchelle(echelleXIni:Float, echelleYIni:Float, dEchelleX:Float, dEchelleY:Float)
		
		Self.echelleX = echelleXIni
		Self.echelleY = echelleYIni
		Self.dEchelleX = dEchelleX
		Self.dEchelleY = dEchelleY
		
	End Method
	
	'-----------------------------------------------------------
	' Reglage de l'alpha
	'-----------------------------------------------------------
	Method ReglerAlpha(alpha:Float, dAlpha:Float)
		
		Self.alpha = alpha
		Self.dAlpha = dAlpha
		
	End Method
	
	
	'-----------------------------------------------------------
	' Reglage de la duree de vie des particules
	'-----------------------------------------------------------
	Method ReglerVie(viePart:Int, ecartViePart:Int)
		
		Self.vie = viePart + (Rand(ecartViePart) - (ecartViePart / 2))
		Self.heureCreation = MilliSecs()
		
	End Method
	
	
	'-----------------------------------------------------------
	' Reglage de la velocite
	'-----------------------------------------------------------
	Method ReglerVelocite(dx:Float, dy:Float, accX:Float, accY:Float)
	
		Self.dx = dx
		Self.dy = dy
		Self.accX = accX
		Self.accY = accY
		
	End Method

	
End Type


'----------------------------------------------------------------
' Creation d'une particule
'----------------------------------------------------------------
Function P2D_CreatePart:TParticule(pere:TEmetteur, image, x#, y#, ecartX%, ecartY%)', dx#, dy#, accX#, accY#)

	Local p:TParticule = New TParticule

	pere.nbPartCourant :+ 1

	p.pere = pere
	p.image = image
	MidHandleImage(p.image)
	p.x = x + (rnd(ecartX) - (ecartX/2))
	p.y = y + (rnd(ecartY) - (ecartY/2))
	ListAddFirst pere.listePart, p

	Return p

End Function
	


'----------------------------------------------------------------
' Creation d'un emetteur
'----------------------------------------------------------------
Function P2D_CreateEmetteur:TEmetteur(image, longevite:Int, x:Float, y:Float, ecartX:Float, ecartY:Float, angle:Float, nbPartFrame:Float, typeEmt:String = "light")
	
	Local e:TEmetteur = New TEmetteur

	e.image = image
	e.longevite = longevite
	e.heureCreation = MilliSecs()
	e.x = x
	e.y = y
	e.ecartX = ecartX
	e.ecartY = ecartY
	e.angle = angle
	e.nbPartFrame = nbPartFrame
	If e.nbPartFrame < 1 Then
		e.nbFramePourEmt = 1 / nbPartFrame		' Nb de frames entre chaque emission de particules (si nbPartFrame < 0)
		e.nbFrameRestant = 0
	End If
	e.typeEmt = typeEmt
	e.etat = "actif"
	e.listePart:TList = New TList
	ListAddFirst P2D_ListeEmet, e
	
	Return e
	
End Function

'----------------------------------------------------------------
' Mise à jour de l'ensemble des particules / emetteurs
'----------------------------------------------------------------
Function P2D_Update()

	Local e:TEmetteur = New TEmetteur
	Local p:TParticule = New TParticule
	
	For e=EachIn P2D_ListeEmet
		e.Update()
		For p=EachIn e.listePart
			p.Update()
		Next
	Next

End Function


'----------------------------------------------------------------
' Affichage de l'ensemble des particules
'----------------------------------------------------------------
Function P2D_Afficher()

	Local e:TEmetteur = New TEmetteur
	Local p:TParticule = New TParticule
	
	For e=EachIn P2D_ListeEmet
		For p=EachIn e.ListePart
			p.Draw()
		Next
	Next

End Function


'----------------------------------------------------------------
' Positionnement d'un emetteur en x y
'----------------------------------------------------------------
Function P2D_ReglerPosition(e:TEmetteur, x:Int, y:Int)
	
	e.x = x
	e.y = y
	
End Function


'-----------------------------------------------------------
' Reglage de l'echelle
'-----------------------------------------------------------
Function P2D_ReglerEchelle(e:TEmetteur, echelleXIni:Float, echelleYIni:Float, ecartEchelleXIni:Float, ecartEchelleYIni:Float, dEchelleX:Float, dEchelleY:Float)
	
	e.echelleXIni = echelleXIni
	e.echelleYIni = echelleYIni
	e.ecartEchelleXIni = ecartEchelleXIni
	e.ecartEchelleYIni = ecartEchelleYIni
	e.dEchelleX = dEchelleX
	e.dEchelleY = dEchelleY
		
End Function


'-----------------------------------------------------------
' Reglage de l'alpha
'-----------------------------------------------------------
Function P2D_ReglerAlpha(e:TEmetteur, alphaIni:Float, ecartAlpha:Float, dAlpha:Float, ecartDAlpha:Float)
		
	e.alphaIni = alphaIni
	e.ecartAlpha = ecartAlpha
	e.dAlpha = dAlpha
	e.ecartDAlpha = ecartDAlpha
	
End Function


'-----------------------------------------------------------
' Reglage de la velocite
'-----------------------------------------------------------
Function P2D_ReglerVelocite(e:TEmetteur, dx:Float, dy:Float, accX:Float, accY:Float)
		
	e.dx = dx
	e.dy = dy
	e.accX = accX
	e.accY = accY
	
End Function


'-----------------------------------------------------------
' Reglage de la vie des particules
'-----------------------------------------------------------
Function P2D_ReglerVie(e:TEmetteur, viePart:Int, ecartViePart:Int)
		
		e.viePart = viePart
		e.ecartViePart = ecartViePart 
		
End Function



'----------------------------------------------------------------
' Suppression d'un emetteur
'----------------------------------------------------------------
Function P2D_SupprEmt(e:TEmetteur, flag:Int = 0)

	Local p:TParticule = New TParticule
		
	Select flag
		Case 0
			e.etat = "supprime"
		Case 1
			e.etat = "supprime"
			For p=EachIn e.listePart
				ListRemove(e.listePart, p)
			Next
			ListRemove(P2D_listeEmet, e)
	End Select

End Function


see ya :)

ps: a wysiwyg editor coming as soon as the BlitzMax release is available :)

Nice idea, ftbass
I have made a quick change to the Demo and your Tutorial.
Try this and add it if you think it looks better, too
Edited I was not shure what would be the better solution: Globals or Typefields
If BotShips (random / not steered by user) are on screen maybe Typefields would be better.

Some Lines added in DemoPartEngine05.bmx
' Type TJoueur hérité du type TVaisseau
Type TJoueur Extends TVaisseau

	Method Update()
		RelativeFlag=1	'This Line for Demo usage - could be made a Functionparameter
		RelativeX=0		'To place the particles relative to the ship movement
		RelativeY=0
		If KeyDown(KEY_LEFT) And X >= -10 Then
			X = X - 3 * Vitesse
			If RelativeFlag<>0 RelativeX = -3*Vitesse
		EndIf
		If KeyDown(KEY_RIGHT) And X <= (LARGEUR - 112) Then
			X = X + 3 * Vitesse
			If RelativeFlag<>0 RelativeX = 3*Vitesse
		EndIf
		If KeyHit(KEY_UP) And Not(KeyDown(KEY_DOWN))
			DirV = "haut"
			NumImage = 11
			Timer = MilliSecs()
		End If
		If KeyDown(KEY_UP)
			If Y >= -40 Then
				Y = Y - 3 * Vitesse
				If RelativeFlag<>0 RelativeY= -3 * Vitesse
			End If
			If (Timer + Tempo < MilliSecs()) And (NumImage < 21) Then
				NumImage = NumImage + 1
				Timer = MilliSecs()
			End If
		EndIf
		If KeyHit(KEY_DOWN) And Not(KeyDown(KEY_UP))
			DirV = "bas"
			NumImage = 0
			Timer = MilliSecs()
		End If
		If KeyDown(KEY_DOWN)
			If Y <= 680 Then
				Y = Y + 3 * Vitesse
				If RelativeFlag<>0 RelativeY = 3*Vitesse
			End If
			If (Timer + Tempo < MilliSecs()) And (NumImage < 10) Then
				NumImage = NumImage + 1
				Timer = MilliSecs()
			End If
		EndIf
		If Not(KeyDown(KEY_DOWN) Or KeyDown(KEY_UP))
			Select DirV
				Case "haut"
					If (Timer + Tempo < MilliSecs()) And (NumImage > 11) Then
						NumImage = NumImage - 1
						Timer = MilliSecs()
					ElseIf NumImage = 11 Then
						DirV = "null"
					End If
				Case "bas"
					If (Timer + Tempo < MilliSecs()) And (NumImage > 0) Then
						NumImage = NumImage - 1
						Timer = MilliSecs()
					ElseIf NumImage = 0 Then
						DirV = "null"
					End If
			End Select
		End If
	End Method
	
End Type

This at top of "former Module" now an IncludeFile "ftbass_ParticleEngine.bmx" (makes quicker changes possible)
Global RelativeFlag, RelativeX , RelativeY

And change the 2 Lines in
Type TParticule

	'-----------------------------------------------------------
	' Mise à jour des particules
	'-----------------------------------------------------------
	Method Update()
	
		dx = dx + accX
		dy = dy + accY
		x = x + dx + RelativeX		'Line changed
		y = y + dy + RelativeY		'Line changed
		echelleX :+ dEchelleX
		echelleY :+ dEchelleY


In the Tutorial instead of too many Ifs
Function NumImage:Int(Char:String)
	If ( Char >= "a" And Char <= "z" ) Or ( Char >= "A" And Char <= "Z" ) Return (Asc(char) & 95)-65
	If ( Char >= "0" And Char <= "9" ) Return Asc(Char)-16
	Local Posit=Instr("'.,-!?",Char)
	If Posit>0 Return Posit+25
	If char=" " Return 42
End Function

Hope you can use it :-)

@ftbass:
j ai compilé ton mod pour Mac et j ai le plaisir d annoncer ke ca marche impec :)
donc si t'as un mail a me filer, j peux t envoyer le mod compilé en version debug et release...
le 1er test tourne dans les 20 fps et le second dans les 30 (1 ou 2 emetteurs ca change rien), mais bon... j ai une vieille brouette comme machine :)

@RaGR:
Thx for suggestions. I'll try that later :)

@KamaShin:
The code is now available, so I don't think I have to distribute the modules. Peoples who want to use this code
can make a module theirself, of simpler, use it as an include.

ps: Kamashin, this is the official forum, so I think we have to try to speak english (even if my english is really
bad)... If you want to speak french, you can vist the french community at www.blitz3dfr.com you'll be welcome :)

lol... I guess you re right :) no need for distributing the mod if anyone can compile it... Anyway, it does work fine on Mac :)

version 0.6.1 of PartEngine now available

- Bug fixed in the LIGHTBLEND mode rendering
- Can now create less than 1 particle per frame

Cool :)

HI

because?

ftbass-is there a english mode to your site?

no sorry, there is no english mod for the moment. It's a quite confidential site actually.
Do you want to have some informations about a precise subject ?