fx stuff

Blitz3D Forums/Blitz3D Programming/fx stuff

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

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.