Ces jours-ci, je viens de retrouver une vieux code que j'avais programmé pour un Pong que j'avais fait.
Il n'y a rien d'exceptionnel dans le code.
C'est un système très rudimentaire, mais qui fonctionne.
Il permet de créer des particules sans utiliser le moteur 3D.
Notez qu'à l'époque, je n'utilisais pas les Structures, et il y a sûrement d'autres petits défauts de ce genre.
J'ai traduit la majorité des commentaires en Anglais, pour faciliter la lecture à la majorité des gens.
Le code source de la librairie, à nommer particles2d.pb (pour le fichier de test qui suit)
Code : Tout sélectionner
;
; particles2d.pbi (particles without the 3D Engine)
; by retro-bruno
;
; (c) 2013-2019, royalty free, and free for freedom of the free french frees :) (i know, it means nothing)
;
; http://retro-bruno.fr
;
; Version 1.1.1
;
#MaximumEmittersCount = 1000
#MaximumParticlesCountByEmitter = 1000
Global Dim Emitter2d.f(17, #MaximumEmittersCount) ; x, y, w, h, sprite, rate, count, maxlife, startwidth, startheight, growspeed, colorfilter, active( 1 / 0 )
Global Dim Particles2D(4, #MaximumParticlesCountByEmitter, #MaximumEmittersCount) ; x, y, life (from 1 to n, or 0 for disabled), angle
Global Dim FilteredSprite(#MaximumEmittersCount)
; create a new particles emitter, and return its handle number, else, return -1 (in case of error)
;
; *** ! DO NOT create a particle emitter in a startdrawing/stopdrawing block ! ***
Procedure CreateParticlesEmitter2D(x, y, w, h, spr, rate, count, maxlife, startwidth, startheight, growspeed.f, colorfilter, rayspeed.f = 0, roundspeed.f = 0, dirangle1 = 0, dirangle2 = 359)
; Sprite utilisé par l'émétteur
If IsSprite(spr) = 0
ProcedureReturn -1
EndIf
; x, y, w, h = emission area
; rate = appearing speed of the new particles
; count = maximum amout of particles that coexist together
; maxlife = maximum life length of a particle
; startwidth et startheight = start size, or '0' to keep the sprite size
; growspeed = growing speed (or ingrowing speed, with a negative value)
; colorfilter = if different of '0', apply a color filter and an alpha transparency (colorfilter = RGBA(r, g, b, a))
; rayspeed is the speed the particles use to get out of their source center (must be superior or equal to '0')
; roundspeed is the gravity speed aroud their source center (positive, negative or '0')
; dirangle1 and dirangle2 = angles d'ouverture du champs de propagation des particules (par défaut de 0 à 359) : TRANSLATE ME !!! :)
If w <= 0 Or h <= 0 Or rate <= 0 Or count <= 0 Or maxlife <= 0 Or startwidth < 0 Or startheight < 0 Or rayspeed < 0
ProcedureReturn -1
EndIf
; get the default sprite size
If startwidth = 0
startwidth = SpriteWidth(spr)
EndIf
If startheight = 0
startheight = SpriteHeight(spr)
EndIf
For i = 1 To #MaximumEmittersCount
If Emitter2D(17, i) = 0
Emitter2D(17, i) = 1
Emitter2D(1, i) = x
Emitter2D(2, i) = y
Emitter2D(3, i) = w
Emitter2D(4, i) = h
Emitter2D(5, i) = spr
Emitter2D(6, i) = rate
Emitter2D(7, i) = count
Emitter2D(8, i) = maxlife
Emitter2D(9, i) = startwidth
Emitter2D(10, i) = startheight
Emitter2D(11, i) = growspeed
Emitter2D(12, i) = colorfilter
Emitter2D(13, i) = rayspeed
Emitter2D(14, i) = roundspeed
a1 = Mod(dirangle1, 360)
a2 = Mod(dirangle2, 360)
Emitter2D(15, i) = a1
Emitter2D(16, i) = a2
FilteredSprite(i) = CopySprite(spr, #PB_Any, #PB_Sprite_AlphaBlending)
If colorfilter > 0
StartDrawing(SpriteOutput(FilteredSprite(i)))
DrawingMode(#PB_2DDrawing_AllChannels)
For y = 0 To SpriteHeight(FilteredSprite(i)) - 1
For x = 0 To SpriteWidth(FilteredSprite(i)) - 1
col = Point(x,y)
r = (Red(col) * Red(colorfilter)) / 255
g = (Green(col) * Green(colorfilter)) / 255
b = (Blue(col) * Blue(colorfilter)) / 255
a = Alpha(col)
;a = (Alpha(col) * Alpha(colorfilter)) / 255 ?
Plot(x, y, RGBA(r, g, b, a))
Next
Next
StopDrawing()
EndIf
For j = 1 To #MaximumParticlesCountByEmitter
Particles2D(3, j, i) = 0
Next
ProcedureReturn i
EndIf
Next
ProcedureReturn -1
EndProcedure
; particles update procedure
Procedure Update2DParticles()
; is this needed ?
RandomSeed(ElapsedMilliseconds())
; creation, life and destruction of particles
For i = 1 To #MaximumEmittersCount
If Emitter2D(17, i) = 1
rate = Emitter2D(6, i)
x1 = Emitter2D(1, i)
y1 = Emitter2D(2, i)
x2 = x1 + Emitter2D(3, i) - 1
y2 = y1 + Emitter2D(4, i) - 1
; update the life of particle + create and destroy them
count = Emitter2D(7, i)
For j = 1 To #MaximumParticlesCountByEmitter
If Particles2D(3, j, i) > 0
Particles2D(3, j, i) + 1
If Particles2D(3, j, i) = Emitter2D(8, i)
Particles2D(3, j, i) = 0
EndIf
EndIf
If Particles2D(3, j, i) = 0 And rate > 0
Particles2D(3, j, i) = 1
vx = 0
If x1 < 0
vx = Abs(x1)
EndIf
If x2 + vx < 0
vx + Abs(x2 + vx)
EndIf
vy = 0
If y1 < 0
vy = Abs(y1)
EndIf
If y2 + vy < 0
vy + Abs(y2 + vy)
EndIf
Particles2D(1, j, i) = Random(x2 + vx, x1 + vx) - vx
Particles2D(2, j, i) = Random(y2 + vy, y1 + vy) - vy
If Emitter2D(15, i) < 0 Or Emitter2D(16, i) < 0
Emitter2d(15, i) + 360
Emitter2d(16, i) + 360
EndIf
Particles2D(4, j, i) = Mod(Random(Emitter2D(16, i),Emitter2D(15, i)), 360)
rate - 1
EndIf
; show the particles
If Particles2D(3, j, i) > 0
w = Emitter2D(9, i) + (Emitter2D(11, i) * Particles2D(3, j, i))
h = Emitter2D(10, i) + (Emitter2D(11, i) * Particles2D(3, j, i))
If w <= 0 Or h <= 0
Particles2D(3, j, i) = 0
Else
If count > 0
x = Particles2D(1, j, i) - Int(w / 2)
y = Particles2D(2, j, i) - Int(h / 2)
tmpspr = CopySprite(FilteredSprite(i), #PB_Any, #PB_Sprite_AlphaBlending)
ZoomSprite(tmpspr, w, h)
roundspeed = Mod(Emitter2D(14, i) * Particles2D(3, j, i), 360)
rayspeed = Emitter2D(13, i) * Particles2D(3, j, i)
angle = Mod(roundspeed + Particles2D(4, j, i), 360)
DisplayTransparentSprite(tmpspr, x + (rayspeed * Cos(Radian(angle))), y + (rayspeed * Sin(Radian(angle))), Alpha(Emitter2D(12, i)))
FreeSprite(tmpspr)
count - 1
EndIf
EndIf
EndIf
Next
EndIf
Next
EndProcedure
; move an emitter
Procedure MoveEmitter2d(n, x, y)
Emitter2D(1, n) = x
Emitter2D(2, n) = y
EndProcedure
; free an emitter
Procedure FreeEmitter2d(n)
Emitter2d(17,n) = 0
EndProcedure
Code : Tout sélectionner
;
; particles2d_test.pb
;
IncludeFile "particles2d.pbi"
; frame speed of the particles system
#FPS = 30
If InitSprite() = 0
End
EndIf
If InitMouse() = 0
End
EndIf
If InitKeyboard() = 0
End
EndIf
; open the screen
If OpenScreen(800, 600, 32, "2D Particles Test") = 0
MessageRequester("Error","Can't open the screen !", #PB_MessageRequester_Error)
End
EndIf
; create demo sprite1
sprite = CreateSprite(#PB_Any, 128, 128, #PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(sprite))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0, 0, 128, 128, RGBA(0, 0, 0, 0))
DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient)
CircularGradient(80,48,46)
FrontColor(RGBA(255,255,255,255))
BackColor(RGBA(127,127,127,255))
Circle(64,64,63)
StopDrawing()
; create demo sprite2
sprite2 = CreateSprite(#PB_Any, 128, 128, #PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(sprite2))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0, 0, 128, 128, RGBA(0, 0, 0, 0))
DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient)
CircularGradient(80,48,46)
FrontColor(RGBA(255,64,0,255))
BackColor(RGBA(255,255,0,255))
Circle(64,64,63)
StopDrawing()
screen = CreateSprite(#PB_Any, 800, 600, #PB_Sprite_AlphaBlending)
angle = 0
angle2 = 0
pe1 = CreateParticlesEmitter2D(400 + (100 * Cos(Radian(angle))), 295 + (100 * Sin(Radian(angle))), 1, 10, sprite, 4, 64, 24, 8, 4, 1.0, RGBA(0,128,0,20), 7, 0, 260, 280)
If pe1 = 0
CloseScreen()
MessageRequester("Erreur","Particles not created !")
End
EndIf
pe2 = CreateParticlesEmitter2D(440, 320, 10, 1, sprite, 4, 64, 20, 1, 1, 0.5, RGBA(0,128,255,20), 7, 5, -10, 10)
If pe2 = 0
CloseScreen()
MessageRequester("Erreur","Particles not created !")
End
EndIf
pe3 = CreateParticlesEmitter2D(360, 320, 10, 1, sprite, 4, 64, 20, 1, 1, 0.5, RGBA(0,128,255,20), 7, -5, 170, 190)
If pe3 = 0
CloseScreen()
MessageRequester("Erreur","Particles not created !")
End
EndIf
pe4 = CreateParticlesEmitter2D(395, 295, 10, 10, sprite2, 8, 128, 16, 4, 1, 4, RGBA(255,255,255,70), 10, 0, 250, 290)
If pe4 = 0
CloseScreen()
MessageRequester("Erreur","Particles not created !")
End
EndIf
; left click to quit (or push escape key)
testEnd = #False
While testEnd = #False
t = ElapsedMilliseconds()
ClearScreen(RGB(0, 0, 0))
DisplaySprite(screen, 0 ,0)
; update the created particles
Update2DParticles()
; we move an emitter
angle2 + 10
angle + Int(10.00 * Sin(Radian(angle2))) - 5
angle = Mod(angle, 360)
angle2 = Mod(angle2, 360)
; move the green emittor
MoveEmitter2d(pe1, 400 + (100 * Cos(Radian(angle))), 295 + (100 * Sin(Radian(angle))))
FlipBuffers()
; slow down the frame rate
While ElapsedMilliseconds() - t < 1000 / #FPS
ExamineKeyboard()
ExamineMouse()
If MouseButton(#PB_MouseButton_Left) Or KeyboardPushed(#PB_Key_Escape)
testEnd = #True
; quit immediatly
Break(2)
EndIf
Delay(1)
Wend
Wend
FreeEmitter2d(pe1)
FreeEmitter2d(pe2)
FreeEmitter2d(pe3)
FreeEmitter2d(pe4)
CloseScreen()
End