fx stuff

Blitz3D Forums/Blitz3D Programming/fx stuff

Ruz(Posted 2004) [#1]
I was trying to do that thing where when your player puts his feet down he throws up dust like in jak and daxter.
what would be the best approach to this.
My plan was to to parent some animated polys planes to his feet and do it this way. i have made it work a little , but not very convincing.
on grass he will throw up grass particles, on dirt he will throw up dust or bits of dirt etc


Or would a smoke/dust generator do the job better

Obviously it has to be framerate friendly.


poopla(Posted 2004) [#2]
Particle system for sure. With very little code you can have a basic sprite or single surface particle system to do a broad array of effects.


Ruz(Posted 2004) [#3]
cheers , i will look into this


N(Posted 2004) [#4]
He's right. Just for organization's sake, you might want to write a basic 'FX system' (I won't mention that I stuck one in Vein- oops). Basically, you'd use that to coordinate those small things, if conditions (fps, how many things are being processed and whether or not it'll cause a slow down, etc.) are right create the FX event/object and update it accordingly.

Just my take on it though, just attaching a single emitter (or one for each foot) to the player would be enough to get the desired effect most likely.


Ruz(Posted 2004) [#5]
so can i use your vein emitter noel?. I was using rossc 's
particle system whihc is nice ,but there is a weird glitch about the particles not facing the camera.


N(Posted 2004) [#6]
It's there for the taking. This hack should work:

Edit: Wait, no, it won't work. You'll still have to alter it so UpdateParticles() takes a camera entity as the argument instead of a Player object, and you'll also need to copy a few more functions (I think just UpdateVector and Vec_Copy), can't get the source at the moment (on my parent's PC) so I can't edit this so it works properly.

; The Flag object is used by Vein to store and retrieve variables.
; A good example of its use can be found under c_particle.bb or c_sspart.bb
Type Flags
	Field UFlag#   [32]   ;user flags, can be modified via the scripting engine
	Field VFlag#   [32]   ;flags set by functions in Vein
	Field BitFlag% [31] ;bit flags, these should only be set as 0 or 1, because that's what they'll get turned into the instant they're saved
End Type

; The Vector object is used by Vein to store position, acceleration, velocity, angles, etc.
; There are also functions to modify/return these objects (such as CrossProduct, Magnitude, and Vec_Dist)
Type Vector
     Field X#,Y#,Z#                               ;World position
     Field Pan#,Tilt#,Roll#                       ;Absolute Angles
     Field Vel_Pan#,Vel_Tilt#,Vel_Roll#           ;Angle velocity
     Field Accel_Pan#,Accel_Tilt#,Accel_Roll#     ;Angle acceleration
     Field Vel_X#,Vel_Y#,Vel_Z#                   ;Local velocity
     Field Accel_X#,Accel_Y#,Accel_Z#             ;Local acceleration
End Type

;Particle Object
;Used to record and update particles created by emitters.
Type  Particle
	Field Vert               ;The upper-left corner vertex of the particle's triangle.
	;Field Piv
	Field Life%              ;The life of the particle before it dies.
	Field Alpha#             ;The particle's current alpha.
	Field Size#              ;The particle's current size.
	Field V.Vector           ;The particle's position and velocity.  This is copied from its parent emitter.
	Field Parent.Emitter     ;The particle's parent emitter.
	Field Roll#              ;The particle's current angle (roll).
End Type

;Emitter Object
;Used to record and update emitters.
Type Emitter
	Field Child.Emitter      ;The emitter's child
	Field V.Vector           ;The position, velocity, angle, and acceleration of the particles the emitter creates
	Field F.Flags            ;Emitter flags
	Field Piv                ;The pivot used to create the particles.
	Field Parent.Emitter     ;The parent of the emitter.
	Field Bmap%              ;The handle of the texture it uses.
	Field Mesh%              ;The mesh it uses to store the particles.
	Field Surface%           ;The surface that stores the particle triangles and vertices.
End Type

;Particle Magnet object
;Used to alter the position and velocity of particles
Type Magnet
	Field V.Vector	;Position
	Field Enabled  ;Enabled?
	Field Rad#	;Radius of affection
	Field Mag#	;Magnitude
	Field Falloff% ;Falloff flag
End Type

Const SSPARENT = 5
Const SSCHILD = 4

Global P_TIMEBETWEEN = 4

; Creates an emitter.
; Almost all of the parameters are self explanatory.
; P = The Parent of this emitter.  Pass Null to this argument if it isn't a child.
; Blend = The blend mode of the particles.  Valid constants are: B_ADD, B_MUL, B_ALF.
; Life = How long before a particle dies, regardless of the circumstances.
; SizeR = The amount by which the size of particles is reduced per frame.
; AlphaR = The amount by which the alpha of particles is reduced per frame.
; AlphaD = The distance before the particles begin to fade out.
; ARR = Toggles whether to set a random roll for the particles.
; FE = True if particles are emitted only once per so many frames, or False if particles are to be created every frame.
; return = An Emitter object if successful, Null if not.
Function CreateEmitter.Emitter( V.Vector,  Bmap,  P.Emitter,  Blend=B_ADD,  Life=200,  Size#=1,  Alpha#=1,  SizeR#=0,  AlphaR#=.2,  AlphaD#=1000,  ARR=False,  FE=False,  Enabled=True)
     If Not V <> Null Or BMap <> 0 Then Return Null
	E.Emitter = New Emitter
		E\V.Vector = V.Vector
		E\Bmap = Bmap	;Color+Alpha+ClampedU+ClampedV
		If E\Bmap <> 0 Then
			E\Mesh = CreateMesh()	;create the mesh
			E\Surface = CreateSurface(E\Mesh)
			EntityTexture E\Mesh, E\Bmap
			EntityBlend E\Mesh, Blend
			EntityFX E\Mesh, 1+2+32			;Full bright + Vertex Colors + Forced Alpha

			E\Piv = CreatePivot()
			PositionEntity E\Piv, E\V\X, E\V\Y, E\V\Z, True

			E\F.Flags = New Flags
				E\F\VFlag[1] = Blend
				E\F\VFlag[2] = Life
				E\F\VFlag[3] = Size
				E\F\VFlag[4] = Alpha
				E\F\VFlag[5] = SizeR
				E\F\VFlag[6] = AlphaR
				E\F\VFlag[7] = AlphaD
				E\F\VFlag[8] = ARR
				E\F\VFlag[9] = FE
				E\F\VFlag[10]= Enabled
				E\F\VFlag[11]= SSPARENT
				If P.Emitter <> Null Then
					P\Child.Emitter = E.Emitter
					E\F\VFlag[11] = SSCHILD
				EndIf
			Return E
		Else
			Delete E
			Return Null
		EndIf
End Function

; Adds a particle that is a child of the emitter.
; E = The parent of the particle.
; F = If a particle, upon death, has a child emitter then pass that particle to this argument.
; return = A Particle object.  Nobody keeps track of them, why should you?
Function AddParticle.Particle(E.Emitter,  F.Particle)
	P.Particle = New Particle
		;P\Piv = CreatePivot()
		If F <> Null Then
			P\Parent = F\Parent\Child
			P\V = Vec_Copy(F\V)
			P\V\X = P\V\X + P\Parent\V\X
			P\V\Y = P\V\Y + P\Parent\V\Y
			P\V\Z = P\V\Z + P\Parent\V\Z
		Else
			P\Parent = E
			P\V = Vec_Copy(P\Parent\V)
		EndIf
		P\Size = P\Parent\F\VFlag[3]
		P\Alpha = P\Parent\F\VFlag[4]
		P\Life = P\Parent\F\VFlag[2]
		;PositionEntity P\Piv, P\V\X, P\V\Y, P\V\Z

		P\Parent\F\VFlag[32] = P\Parent\F\VFlag[32] + 1

		If P\Parent\F\VFlag[8] = True Then
			SeedRnd(MilliSecs())
			P\Roll# = Rnd(0.000, 360.000)
		Else
		     P\Roll# = P\V\Roll
		EndIf
End Function

; Updates all particles.
; Pl = The Player object that the particles should face.
; return = True if successful, False if not.
Function UpdateParticles(Pl.Player)
	If Not Pl <> Null Then
		Pl = First Player
		If Not Pl <> Null Then Return False
	EndIf
	For E.Emitter = Each Emitter
		ClearSurface E\Surface

		If E\F\VFlag[10] And E\F\VFlag[11] = SSPARENT And E\F\VFlag[15] = P_TIMEBETWEEN Then
			E\F\VFlag[15] = 0
			AddParticle E, Null
		EndIf

		If E\F\VFlag[9] Then
			E\F\VFlag[15] = Max(E\F\VFlag[15] + 1,P_TIMEBETWEEN)
		Else
			E\F\VFlag[15] = P_TIMEBETWEEN
		EndIf
	Next

	For P.Particle = Each Particle
		If P\Parent <> Null Then
			P\Life = P\Life - 1
			P\Alpha = P\Alpha + P\Parent\F\VFlag[6]
			P\Size = P\Size + P\Parent\F\VFlag[5]
		If (P\Parent\F\VFlag[6] <= 0 And P\Alpha <= 0) Or (P\Parent\F\VFlag[6] => 1 And P\Alpha => 1) Or (P\Parent\F\VFlag[5] <= 0 And P\Size# <= 0) Or (P\Life = 0) Then
			If P\Parent\Child.Emitter <> Null Then
				AddParticle(P\Parent\Child,  P)
			EndIf
			P\Parent\F\VFlag[32] = P\Parent\F\VFlag[32] - 1	;decrease particle count for the object
			Delete P\V
			Delete P
		Else
		    For M.Magnet = Each Magnet
		          Distance# = Min(Vec_Dist(P\V,M\V),1)
				If M\Enabled And Distance < M\Rad Then
				     If M\Falloff = True Then Distance = M\Rad - Distance
					L.Vector = Vec_Diff(P\V,M\V)
					X_Factor# = L\X/Distance
					Y_Factor# = L\Y/Distance
					Z_Factor# = L\Z/Distance
					P\V\X = P\V\X - ( X_Factor*M\Mag )
					P\V\Y = P\V\Y - ( Y_Factor*M\Mag )
					P\V\Z = P\V\Z - ( Z_Factor*M\Mag )
					Delete L
				EndIf
			Next
               P\Roll = P\Roll + P\Parent\V\Vel_Roll
			UpdateVector P\V
			PositionEntity P\Parent\Piv,  P\V\X,  P\V\Y,  P\V\Z
			TranslateEntity P\Parent\Piv, P\V\Vel_X, P\V\Vel_Y, P\V\Vel_Z

			P\V\X = EntityX(P\Parent\Piv,True)
			P\V\Y = EntityY(P\Parent\Piv,True)
			P\V\Z = EntityZ(P\Parent\Piv,True)

			PointEntity P\Parent\Piv, Pl\Camera
			TurnEntity P\Parent\Piv, 180, 0, 0
			RotateEntity P\Parent\Piv, EntityPitch(P\Parent\Piv), EntityYaw(P\Parent\Piv), P\Roll
			MoveEntity P\Parent\Piv, -Abs(P\Size#), -Abs(P\Size#), 0
			P\Vert = AddVertex(P\Parent\Surface,  EntityX(P\Parent\Piv, True),  EntityY(P\Parent\Piv, True),  EntityZ(P\Parent\Piv, True),  0,  1)
			If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1
			MoveEntity P\Parent\Piv, 0, Abs(P\Size#)*2, 0
			AddVertex(P\Parent\Surface,  EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 0, 0)
			If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1
			MoveEntity P\Parent\Piv, Abs(P\Size#)*2, 0, 0
			AddVertex(P\Parent\Surface,  EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 1, 0)
			If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1
			MoveEntity P\Parent\Piv, 0, -Abs(P\Size#)*2, 0
			AddVertex(P\Parent\Surface,  EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 1, 1)
			If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1
			MoveEntity P\Parent\Piv, -Abs(P\Size#), Abs(P\Size#), 0
			If Not F = 4
				AddTriangle(P\Parent\Surface,  P\Vert, P\Vert+1, P\Vert+2)
				AddTriangle(P\Parent\Surface,  P\Vert+2, P\Vert+3, P\Vert)
			EndIf
			F = 0

			For X = 0 To 3
				VertexColor P\Parent\Surface, P\Vert+X, 255, 255, 255, Min(Max(P\Alpha, 1), 0)
			Next
			P\V\X = EntityX(P\Parent\Piv, True) : P\V\Y = EntityY(P\Parent\Piv, True) : P\V\Z = EntityZ(P\Parent\Piv, True)
		EndIf
		Else
		Delete P
		EndIf
	Next

	For E.Emitter = Each Emitter
		UpdateNormals E\Mesh
	Next
	Return True
End Function

; Frees an Emitter object.
; E = The emitter to be freed.
; return = True if successful, False if not.
Function KillEmitter(E.Emitter)
     If E <> Null Then
          FreeTexture E\BMap
          FreeEntity E\Piv
          FreeEntity E\Mesh
          Delete E\F
          Delete E\V
          Delete E
          Return True
     EndIf
     Return False
End Function

; Creates a Magnet object.
; Magnets affect a particle movement and speed.  They typically pull particles toward them.
; V = The position of the magnet.
; Radius = The distance particles must be within before they are affected.
; Mag = The magnitude of the magnet.
; Falloff = Whether or not there's a falloff to how much the magnet affects particles.
; Enabled = True if the particles are affected by the magnet, False if not.
; return = A Magnet object, Null if not.
Function CreateMagnet.Magnet(V.Vector,Radius#,Mag#,Falloff = True,Enabled=True)
	M.Magnet = New Magnet
	If V.Vector <> Null
		M\V = V
		M\Rad = Radius
		M\Mag = Mag
		M\Enabled = Enabled
		M\Falloff = Falloff
		Return M
	Else
		Delete M
		Return Null
	EndIf
End Function

; Creates a vector.
; All parameters represent the fields of a Vector object.
; return = A Vector object.
Function Vec.Vector(X#=0,Y#=0,Z#=0,Vel_X#=0,Vel_Y#=0,Vel_Z#=0,Accel_X#=0,Accel_Y#=0,Accel_Z#=0,Pan#=0,Tilt#=0,Roll#=0)	;a duplicate of CreateVector, except it has a shorter name which means it's more convenient to use in cases
		;slowly the old name will become deprecated and left in only a few modules, which will open up complete replacement of it with Vec
	V.Vector = New Vector
		V\X = X
		V\Y = Y
		V\Z = Z

		V\Pan = Pan
		V\Tilt = Tilt
		V\Roll = Roll

		V\Vel_X = Vel_X
		V\Vel_Y = Vel_Y
		V\Vel_Z = Vel_Z

		V\Accel_X = Accel_X
		V\Accel_Y = Accel_Y
		V\Accel_Z = Accel_Z
	Return V.Vector
End Function


Long paste. Hm.


DarkEagle(Posted 2004) [#7]
you guys should take a look at particle candy, im playing with it now... its great!


Ruz(Posted 2004) [#8]
cheers Noel/DarkEagle I will look at this next week, its on my list of things to do. i am currently trying to animate a sheep!!

But it would look damn nice if I got it working properly.
i will basically limit it to two types of particles. grass and dust.


Gabriel(Posted 2004) [#9]
you guys should take a look at particle candy, im playing with it now... its great!


It sure is. I'm working on an effects designer for it. Might even release it if it's usable enough.


DarkEagle(Posted 2004) [#10]
sounds good, even doing it in code is super easy (apart from the time my particles were bouncing as soon as i created them and always going upwards... tha got me for a while...)


Gabriel(Posted 2004) [#11]
Lol yeah, it is very easy, I just wanted a tool so that I can tweak the values, textures, etc and see the effect live. Makes it easier to come up with new effects. Or at least, I hope it does. We'll soon see, cuz Filax has just sent me my Registered copy of BCF3 so I can update the GUI and finish it.


DarkEagle(Posted 2004) [#12]
hooray! will this be freeware? i hope so, it sounds kick ass!


Gabriel(Posted 2004) [#13]
As long as it's worth releasing, and providing Mike gives me permission to release it. I won't be charging for it, it's only gonna be a couple of days work and I needed it anyway.


Ross C(Posted 2004) [#14]
Ruz, i'm gonna give my particle system a good rewrite. I've learned alot since then, so it should be alot better :)


Kozmi(Posted 2004) [#15]
@DarkEagle


you guys should take a look at particle candy, im playing with it now... its great!


This may be a dumb question here... But since I havn't visited the Code Archive as of yet!! Is it in there?

Or could you post a link to particle candy? Id' appreciate it very much so...


sigi(Posted 2004) [#16]
Here is the Link,

http://www.x-pressive.com/ParticleCandy/


Kozmi(Posted 2004) [#17]
Thank's man.. I appreciate that!


Mustang(Posted 2004) [#18]
Holy...! ParticleCandy looked real ace - who did this? I have missed the whole thing totally and this was new to me. But I guess that since our 2-month old baby takes so much of my time I browse these boards less often than before I could have missed it easily.

Anyways, NICE. I'll DL the demos and if it is really as good as it looks they got a new customer.


RetroBooster(Posted 2004) [#19]
Sounds like your using additive blending (blend 3) on smoke Ruz, that's a bad thing to do, use a different blend and implement a sorting algo for your particles that use a non additive blend. (or their order will be messed up)


Ruz(Posted 2004) [#20]
ahh ok i will look into that, have n't really looked at sprites and such much anyway.
anyway 'mr gore' let me use his nice particle system.
gonna try that out today


Gabriel(Posted 2004) [#21]
anyway 'mr gore' let me use his nice particle system.


I wondered what happened to him after he lost the election.


Ruz(Posted 2004) [#22]
LOL


Rob Farley(Posted 2004) [#23]
I just downloaded the particle candy demo and quite frankly doesn't look that great. I'm always slightly dubious about these over 'simplified' systems (which to me seem much more complex) as they must have an impact on performance. And personally, I like keeping things simple.

My own particle system has 2 commands;
Spawnparticle(x,y,z,delx,dely,delz,etc etc etc)
This creates a particle and shoots it off in the direction you want, also allows you to set how gravity effects it, it's life length, start scale, end scale, start colour, end colour and loads of other stuff.

and

Updateparticles(max_particles)
Which updates all the positions, alphas, colours etc of all the particles.

That's it.

If you want to create an explosion you create your own function
function explode (x,y,z)
spawnparticle (x,y,z,blah blah blah)
spawnparticle (x,y,z,blah blah blah)
spawnparticle (x,y,z,blah blah blah)
end function
Anyway, I'm not suggesting my system is better or worse than particle candy but to me it just makes more sense.


Techlord(Posted 2004) [#24]
Particle Candy is very nice and fast, just a tad too pricy. However, I desire similar spiral and helix movement in my non-single surface particle system. Heres my Particle Structure:
Type particle
	entity%
	texture%
	position.vector[2] ;from-to (vector = x#,y#,z#)
	angle.vector[2] ;from-to
	scale.vector[2] ;from-to
	speed.vector[2] ;velocity ;from-to
	color.color[2] ;from-to
	alpha#[2];from-to
	frame%
	life%
	state%
End Type

I update each living particle with a particleEffect Function.
Function particleUpdate()
For this.particle = Each particle
	If this\state%
		this\life%=this\life%-1
		If this\life%
			particleEffect(this);<-- performs movement, rotation, scale, color, alpha transitions
		Else
			particleDelete(this)
		EndIf
	EndIf
Next
End Function

The particleEffect is where I like to put code to manipulate particles with spiral and helix movement. I will glady modify the Particle structure to meet the need. Any assistance is valued.


Danny(Posted 2004) [#25]
He Ruz, check out the Dynamic Water functions I just posted in the Code Archives....

With very little tweaking it could be used to have your character leave ripples when it's walking through water, mud, etc.

Perhaps you can use it?!??

Danny


Rob Farley(Posted 2004) [#26]
For want of not comparing particle systems...

; spawn_particle function
;
; Usage: spawn_particle(x#,y#,z#,delx#,dely#,delz#
;                       start_rot,rot#,life,
;                       start_scale#,end_scale#,
;                       gravity#,graphic,fx$,name$="")


; set up particle type
Type particle
Field mesh				 ;sprite
Field xd#				 ;x delta
Field yd#				 ;y delta
Field zd#				 ;z delta
Field rot				 ;rotation
Field rot_speed#		 ;rotation speed
Field life				 ; life
Field max_life			 ; total life
Field scale#			 ; scale
Field grav_fx#			 ; effect of gravity
Field growth#			 ; scale delta
Field priority			 ; is a priority particle (true/false)
Field alpha				 ; alpha fade (true/false)
Field colour			 ; colour fade (true/false)
Field red#				 ; red component (for colour fading)
Field green#			 ; green component (for colour fading)
Field blue#				 ; blue component (for colour fading)
Field red_delta#		 ; red component delta (for colour fading)
Field green_delta#		 ; green component delta (for colour fading)
Field blue_delta#		 ; blue component delta (for colour fading)
Field name$				 ; death name for death list
Field sound
End Type

Type death
Field name$
Field x#
Field y#
Field z#
Field xd#
Field yd#
Field zd#
End Type


If a particle is given a name when it dies it gets added to the death list... you can then spawn another bunch of particles or whatever from the contents of the death list.

The FX string tells you about if it alpha fades, colour fades or not... for example AC0F0F00 will alpha fade and fade from green to red.


Ruz(Posted 2004) [#27]
Danny I will have a look, cheers.
I have another system up and running now and I have the jak and daxter style clouds of dust spot on perfect now.

When my player runs on grass surface he kicks up grass particles,dust on dirt surfaces etc.
thanks to Adam Gore for that.


Techlord(Posted 2004) [#28]
I notice that many others use live/dead list. I'm not really sure why this is necessary when you can limit the max number of particles processed from the start. Can someone explain the logic behind this. Thanks

Also, I'm not convinced that single surface systems are faster then non single-surface systems. I have tested both on different machines and video cards. Some non single-surface systems actually perfrom better than single-surface systems. Has anyone else had similar results.


Ross C(Posted 2004) [#29]
Well, if it's dead, and you want to respawn more particle, you check the "Alive" list for dead particles, and use them. So you recycling your particles, without creating and deleting types all the time. That my own personal usage for them.

Even more important in single surface stuff i think, as you can't delete vertexs, instead, you have to rebuild the mesh. Sometimes this can be faster. Depends on how many particles you have. (i'm talkin 10,000 odd)


Techlord(Posted 2004) [#30]
Ross C,

Thanks, for sheding some light. I recycle my particles using a FILO stack to 'pop' unused particles off, 'push' dead particles on.