Metaballs 2d

Programmation avancée de jeux en PureBasic
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Metaballs 2d

Message par G-Rom »

Voici un code qui montre l'utilisation de metaballs 2D.
l'effet est obtenu graphiquement en appliquant un filtre de niveau :

Image

Code : Tout sélectionner

; ------------------------------------------------------------------------------------------
; MetaBalls 2D par G-Rom
; ------------------------------------------------------------------------------------------

Structure Pixel
  Pixel.l
EndStructure

; ------------------------------------------------------------------------------------------
;
; ------------------------------------------------------------------------------------------
Structure sVector2 
  X.f
  Y.f
EndStructure

; ------------------------------------------------------------------------------------------
;
; ------------------------------------------------------------------------------------------
Structure sParticle
  mPosition.sVector2
  mOldPosition.sVector2
  mOrigin.sVector2
  mAngle.f
  mVitesse.f
  mPhysic_Timer.f
EndStructure

Global NewList particle.sParticle()

; ------------------------------------------------------------------------------------------
;
; ------------------------------------------------------------------------------------------
#SURFACE_RENDERING_WIDTH    = 640
#SURFACE_RENDERING_HEIGHT   = 480
#GRAVITY                    = 9.8
#FRAME_RATE_RENDERING       = 120

; ------------------------------------------------------------------------------------------
; initialisation
; ------------------------------------------------------------------------------------------
InitSprite() : InitKeyboard() : InitSprite3D()

If ExamineDesktops()
  Global sWidth   = DesktopWidth(0)
  Global sHeight  = DesktopHeight(0)
  Global window   = OpenWindow(#PB_Any,0,0,sWidth,sHeight,"MetaBalls2D par G-Rom")
;   OpenWindowedScreen(WindowID(window),0,0,sWidth,sHeight,1,0,0,#PB_Screen_SmartSynchronization)
  OpenScreen(sWidth,sHeight,DesktopDepth(0),"MetaBalls2D par G-Rom",#PB_Screen_SmartSynchronization)
Else
  MessageRequester("Error","Error when examine desktop resolution")
  End
EndIf 

; ------------------------------------------------------------------------------------------
; Create target sprite
; ------------------------------------------------------------------------------------------
Global rtt_sprite = CreateSprite(#PB_Any,#SURFACE_RENDERING_WIDTH,#SURFACE_RENDERING_HEIGHT,#PB_Sprite_Texture)
If rtt_sprite = 0
  MessageRequester("Error","Can't create sprite : "+Str(#SURFACE_RENDERING_WIDTH)+"x"+Str(#SURFACE_RENDERING_HEIGHT))
  End
EndIf
Global rtt_sprite3d = CreateSprite3D(#PB_Any,rtt_sprite)
ZoomSprite3D(rtt_sprite3d,sWidth,sHeight)

; ------------------------------------------------------------------------------------------
; Create metaball image
; ------------------------------------------------------------------------------------------
Global metaball_image = CreateImage(#PB_Any,32,32,32)

StartDrawing(ImageOutput(metaball_image))
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0,0,32,32,RGBA(0,0,0,0))
DrawingMode(#PB_2DDrawing_AlphaBlend)

For r = 0 To 16
  Circle(16,16,16-r,RGBA(255,255,255,8))
Next 

StopDrawing()


; ------------------------------------------------------------------------------------------
; 
; ------------------------------------------------------------------------------------------
SpriteID_tile = CreateSprite(#PB_Any,256,256)

StartDrawing(SpriteOutput(SpriteID_tile))
Box(0,0,256,256,$0A0A0A)
For y = 0 To 256 Step 64
  For x = 0 To 256 Step 64
    Box(x,y,32,32,$1A1A1A)
    Box(x+32,y+32,32,32,$1A1A1A)
  Next
Next
StopDrawing()

nbX = (sWidth / 256)+2
nbY = (sHeight / 256)+2

font = LoadFont(#PB_Any,"IMPACT",14,#PB_Font_HighQuality)

Declare updateParticle(image.i)
Declare createParticle(x.f,y.f,angle.f=90, randomAngle.f = 45,speed.f = 40)

; ------------------------------------------------------------------------------------------
; main loop
; ------------------------------------------------------------------------------------------
While 1
  ExamineKeyboard()
  
  If KeyboardPushed(#PB_Key_F1) And flag1 = 0
    flag1 = 1
    thresold+1  
    thresold%2  
  EndIf  
  
  If Not KeyboardPushed(#PB_Key_F1) And flag1 = 1
    flag1 = 0
  EndIf 
  
  If KeyboardPushed(#PB_Key_F2) And flag2 = 0
    flag2 = 1
    colorGradient+1  
    colorGradient%2  
  EndIf  
  
  If Not KeyboardPushed(#PB_Key_F2) And flag2 = 1
    flag2 = 0
  EndIf 
  
  If KeyboardPushed(#PB_Key_Escape)
    Break
  EndIf 
  
;   If WindowEvent() = #PB_Event_CloseWindow
;     Break
;   EndIf 
  
  If timer < ElapsedMilliseconds()
    timer = ElapsedMilliseconds() + 50
    
    emitterX.f = ((#SURFACE_RENDERING_WIDTH / 2) - 16) + (((#SURFACE_RENDERING_WIDTH / 2) - 16)/2) * Cos(ElapsedMilliseconds()/1000)
    If ListSize(particle())<50
      For i = 0 To 5
        createParticle(emitterX,(#SURFACE_RENDERING_HEIGHT / 2) - 16,90,30,20)
      Next 
    EndIf 
  EndIf 
  
  If (ElapsedMilliseconds() > CheckTime + 1000 / #FRAME_RATE_RENDERING)
    CheckTime = ElapsedMilliseconds() 
  ; ----------------------------------------------------------------------------------------
  ; Draw metaballs
  ; ----------------------------------------------------------------------------------------
  StartDrawing(SpriteOutput(rtt_sprite))
  DrawingMode(#PB_2DDrawing_Default)
  Box(0,0,#SURFACE_RENDERING_WIDTH,#SURFACE_RENDERING_HEIGHT,RGBA(0,0,0,255))
  updateParticle(metaball_image)
  StopDrawing()
  
  ; ----------------------------------------------------------------------------------------
  ; apply thresold on all metaball for hard edge
  ; ----------------------------------------------------------------------------------------
  
  StartDrawing(SpriteOutput(rtt_sprite))
  DrawingMode(#PB_2DDrawing_Default)
  Buffer      = DrawingBuffer()             
  Pitch       = DrawingBufferPitch()        
  PixelFormat = DrawingBufferPixelFormat() 
  If thresold = 0
    For y = 0 To #SURFACE_RENDERING_HEIGHT-1
      *Line.Pixel = Buffer+Pitch*y ; next line
      For x = 0 To #SURFACE_RENDERING_WIDTH-1
        
        color.i = *Line\Pixel
        r       = Red(color)
        g       = Green(color)
        b       = Blue(color)
        gray    = (r+g+b) / 3
        
        
        If colorGradient = 0
          If gray > 107
            *Line\Pixel = RGBA(255,255,255,255)
          ElseIf gray > 54 And gray < 108
            *Line\Pixel = RGBA(180, 84, 4,255)
          ElseIf gray > 50 And gray < 55
            *Line\Pixel = RGBA(255, 64, 64,255)
          Else
            *Line\Pixel = RGBA(0,0,0,0)
          EndIf
          
        Else
          
          If gray > 50 
            *Line\Pixel = RGBA(255, 255, 255,255)
          Else
            *Line\Pixel = RGBA(0,0,0,0)
          EndIf
          
        EndIf 
        
        
        *Line + 4 ; next pixel
      Next
    Next
  EndIf
  StopDrawing()
  
 
  ClearScreen(0)
  
  
  offset + 1
  offset%256
  For y = 0 To nbY
    For x = 0 To nbX
      DisplaySprite(Spriteid_tile,(x*256)-offset,(y*256)-offset)
    Next
  Next 
  
  Start3D()
  DisplaySprite3D(rtt_sprite3d,0,0,200)
  Stop3D()
  
  StartDrawing(ScreenOutput())
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(font))
  DrawText(10,10,"METABALLS 2D BY G-ROM")
  DrawText(10,30,"F1 FOR THRESOLD : "+Str(1-thresold))
  DrawText(10,50,"F2 FOR COLOR GRADIENT : "+Str(1-colorGradient))
  DrawText(10,70,"PARTICLES : "+Str(ListSize(particle())))
  StopDrawing()
  
  FlipBuffers()
Else
  Delay(1)
  EndIf 
Wend 
End 

; ------------------------------------------------------------------------------------------
;
; ------------------------------------------------------------------------------------------
Procedure createParticle(x.f,y.f,angle.f=90, randomAngle.f = 45,speed.f = 40)
  AddElement(particle())
  
  With particle()
    \mOrigin\X = x
    \mOrigin\Y = y
    \mAngle    = angle - Random(randomAngle) + Random(randomAngle)
    \mVitesse  = speed+Random(speed)
  EndWith
  
EndProcedure

; ------------------------------------------------------------------------------------------
;
; ------------------------------------------------------------------------------------------
Procedure updateParticle(image.i)
  
  ForEach particle()
    With particle()
      
      \mPosition\X = \mOrigin\X + (\mVitesse*Cos((360-\mAngle)*#PI/180)*\mPhysic_Timer)
      \mPosition\Y = \mOrigin\Y + (\mVitesse*Sin((360-\mAngle)*#PI/180)*\mPhysic_Timer)+(0.5*#GRAVITY*(\mPhysic_Timer*\mPhysic_Timer))
      \mPhysic_Timer + 0.1
      
      DrawAlphaImage(ImageID(image),\mPosition\X,\mPosition\Y)
      
      If \mPosition\X < -64 Or \mPosition\X>#SURFACE_RENDERING_WIDTH Or \mPosition\Y > #SURFACE_RENDERING_HEIGHT
        DeleteElement(particle(),1)
      EndIf
      
    EndWith 
  Next
  
EndProcedure
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Metaballs 2d

Message par venom »

Excellent exemple comme toujours. :wink:







@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Fred
Site Admin
Messages : 2652
Inscription : mer. 21/janv./2004 11:03

Re: Metaballs 2d

Message par Fred »

Joli :)
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Metaballs 2d

Message par Fig »

Pour ma culture perso, y a t il une raison particulière au peu commun while 1/break/wend substitué au classique repeat/break/forever ?

Merci pour ce partage en tout cas !!
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Metaballs 2d

Message par G-Rom »

non, on vas dire que c'est un style ;)
Avatar de l’utilisateur
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: Metaballs 2d

Message par GallyHC »

Bonjour,

Y en a qui on du talent tout de même :). C'est vraiment sympa et merci pour ce partage.

Cordialement,
GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
jbernard13
Messages : 1501
Inscription : dim. 18/avr./2004 15:04
Localisation : sud de la france

Re: Metaballs 2d

Message par jbernard13 »

du trés boulot G-Rom , j'aime beaucoup
Jbernard13
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Metaballs 2d

Message par Ar-S »

Est-ce normal que ça rame tout de même énormément ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Metaballs 2d

Message par G-Rom »

desactive le debbuger , l'inconvenient aussi c'est que les shaders ne sont pas supporté pour les sprites , j'ai une version de ce code en c++ / sfml , ca toupine par rapport à pb.
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Metaballs 2d

Message par Ar-S »

G-Rom a écrit :desactive le debbuger , l'inconvenient aussi c'est que les shaders ne sont pas supporté pour les sprites , j'ai une version de ce code en c++ / sfml , ca toupine par rapport à pb.
Effectivement ça va tout de même beaucoup mieux.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Metaballs 2d

Message par Ar-S »

étant inculte en la matière, est-il possible via ce système de générer un morphing d'après un calques prédéfinit ?

en gros on a un LOGO Blanc en guise de masque et les balls se fonderaient dans ce masque. Dans l'idée ça pourrait donner ça.

Image

Comment procéder si c'est possible ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Metaballs 2d

Message par G-Rom »

Faire l'effet inverse ?
si oui , un simple "blur" devrais suffire , la recherche sur le forum devrais te donner des résultats.
Répondre