PureBasic
https://www.purebasic.fr/french/

Simulation fluide
https://www.purebasic.fr/french/viewtopic.php?f=2&t=13455
Page 2 sur 2

Auteur:  Backup [ Lun 18/Mar/2013 14:02 ]
Sujet du message:  Re: Simulation fluide

je trouve qu'on gagne en réalisme si on utilise ces parametres

Code:
#DAMPENING            = 0.00025
#TENSION              = 0.025
#SPREAD               = 0.25
#FRAME_RATE_RENDERING = 120
#GRAVITY              = 9.8


et qu'on remplace la ligne 423
Code:
setMouseWave(*water,500)


par

Code:
setMouseWave(*water,5000)


:)

l'eau parait plus "fluide" et sur "actions" a different endroits, et plus raprochée on obtient un meilleurs rendu du "Chaos" comme dans une bassine :)
de plus l'eau met plus de temps a se stabiliser ... ce qui ressemble plus a la réalité :)

Tres beau code , Bravo G-Rom :)

Auteur:  G-Rom [ Mer 02/Aoû/2017 17:57 ]
Sujet du message:  Re: Simulation fluide

Code mis à jour pour la version actuelle de PB :

Code:
; ------------------------------------------------------------------------------------------
; Water2D par G-Rom
;
; Reference :
; http://gamedev.tutsplus.com/tutorials/implementation/make-a-splash-With-2d-water-effects/
;
; ------------------------------------------------------------------------------------------

#DAMPENING            = 0.025
#TENSION              = 0.025
#SPREAD               = 0.25
#FRAME_RATE_RENDERING = 60
#GRAVITY              = 9.8

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
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()
; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Structure sWaterColumn
  mTargetHeight.f
  mHeight.f
  mSpeed.f
EndStructure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Structure sWaterZone
  mPositionX.f
  mPositionY.f
  mSizeX.f
  mSizeY.f
  List mColumns.sWaterColumn()
EndStructure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure UpdateWaterColumn(*w.sWaterColumn, dampening.f, tension.f)
  Protected x.f = *w\mTargetHeight - *w\mHeight
  *w\mSpeed + tension * x - *w\mSpeed * dampening
  *w\mHeight + *w\mSpeed
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure.i NewWaterZone(x.f, y.f, width.f, height.f, column.i = 64)
  *w.sWaterZone = AllocateMemory(SizeOf(sWaterZone))
  InitializeStructure(*w,sWaterZone)
 
  If *w
   
    *w\mPositionX = x
    *w\mPositionY = y
   
    *w\mSizeX = width
    *w\mSizeY = height
   
    For i = 0 To column-1
      AddElement(*w\mColumns())
      *w\mColumns()\mHeight       = height
      *w\mColumns()\mTargetHeight = height
      *w\mColumns()\mSpeed        = 0
    Next
   
    ProcedureReturn *w
  EndIf
 
  ProcedureReturn #Null
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure updateWater(*w.sWaterZone)
  If *w
   
    ForEach *w\mColumns()
        UpdateWaterColumn( *w\mColumns(), #DAMPENING , #TENSION)
    Next
   
    Protected Dim lDeltas.f( ListSize(*w\mColumns() ))
    Protected Dim rDeltas.f( ListSize(*w\mColumns() ))
   
    For j = 0 To 7
      For i = 0 To ListSize(*w\mColumns())-1
        If i>0
          *c.sWaterColumn = SelectElement(*w\mColumns(),i)
          *p.sWaterColumn = SelectElement(*w\mColumns(),i-1)
          lDeltas(i) = #SPREAD * (*c\mHeight - *p\mHeight)
          *p\mSpeed + lDeltas(i)
        EndIf
        If i<ListSize(*w\mColumns())-1
          *c.sWaterColumn = SelectElement(*w\mColumns(),i)
          *n.sWaterColumn = SelectElement(*w\mColumns(),i+1)
          rDeltas(i) = #SPREAD * (*c\mHeight - *n\mHeight)
          *n\mSpeed + rDeltas(i)
        EndIf
      Next
      For i = 0 To ListSize(*w\mColumns())-1
        If i>0
          *p.sWaterColumn = SelectElement(*w\mColumns(),i-1)
          *p\mHeight + lDeltas(i)
        EndIf
        If i<ListSize(*w\mColumns())-1
          *n.sWaterColumn = SelectElement(*w\mColumns(),i+1)
          *n\mHeight + rDeltas(i)
        EndIf
      Next
    Next
   
  EndIf
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure drawWater(*w.sWaterZone, output.i)
 
  color.i = RGBA(64,128,255,64)
 
  StartDrawing(output)
  Box(0,0,1024,768,0)
 
  DrawingMode(#PB_2DDrawing_AlphaChannel)
  Box(*w\mPositionX,*w\mPositionY,*w\mSizeX,*w\mSizeY,RGBA(0,0,0,255))
 
  cWidth.f = *w\mSizeX / (ListSize(*w\mColumns())-1)
 
    For i = 0 To ListSize(*w\mColumns())-1
     
      *c.sWaterColumn = SelectElement(*w\mColumns(),i)
      *n.sWaterColumn = SelectElement(*w\mColumns(),i+1)
     
      If *n = 0
        *n = SelectElement(*w\mColumns(),0)
      EndIf
     
      x1.f = *w\mPositionX + (cWidth*i)
      y1.f = *w\mPositionY + (*c\mHeight - *c\mTargetHeight)
     
      x2.f = *w\mPositionX + (cWidth*i) + cWidth
      y2.f = *w\mPositionY + (*n\mHeight - *n\mTargetHeight)

     DrawingMode(#PB_2DDrawing_AlphaBlend)
 
     LineXY(x1,y1,x2,y2,color)
     
     For ep = 0 To 5
        LineXY(x1,y1-ep,x2,y2-ep,RGB(92,192,255))
     Next

    Next
   
     *c.sWaterColumn = SelectElement(*w\mColumns(),0)
   
     LineXY(*w\mPositionX,*w\mPositionY+(*c\mHeight-*c\mTargetHeight) ,*w\mPositionX,*w\mPositionY + *w\mSizeY,color)
     LineXY(*w\mPositionX+*w\mSizeX,*w\mPositionY+(*c\mHeight-*c\mTargetHeight) ,*w\mPositionX+*w\mSizeX,*w\mPositionY + *w\mSizeY,color)
     LineXY(*w\mPositionX,*w\mPositionY+*w\mSizeY,*w\mPositionX+*w\mSizeX,*w\mPositionY+*w\mSizeY,color)
     
;       FillArea(*w\mPositionX+1,*w\mPositionY+*w\mSizeY - 1 , -1 , color)
     
  StopDrawing()
 
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure drawWater2(*w.sWaterZone, sprite3D.i)
 
  color.i = RGBA(64,128,255,64)
 
 
  cWidth.f = *w\mSizeX / (ListSize(*w\mColumns())-1)
 
    For i = 0 To ListSize(*w\mColumns())-1
     
      *c.sWaterColumn = SelectElement(*w\mColumns(),i)
      *n.sWaterColumn = SelectElement(*w\mColumns(),i+1)
     
      If *n = 0
        *n = SelectElement(*w\mColumns(),0)
      EndIf
     
      x1.f = *w\mPositionX + (cWidth*i)
      y1.f = *w\mPositionY + (*c\mHeight - *c\mTargetHeight)
     
      x2.f = *w\mPositionX + (cWidth*i) + cWidth
      y2.f = *w\mPositionY + (*n\mHeight - *n\mTargetHeight)

      TransformSprite(sprite3D,x1,y1,x2,y2,x2,y2+*w\mSizeY-(*n\mHeight - *n\mTargetHeight),x1,y1+*w\mSizeY-(*c\mHeight - *c\mTargetHeight))
      DisplayTransparentSprite(sprite3D,0,0,128);,128)
 
    Next
   

EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure.f getWaterAngle(*w.sWaterZone, x.f)
  If x > *w\mPositionX And x < (*w\mPositionX + *w\mSizeX)-1
    Protected scale.i = *w\mSizeX / ListSize(*w\mColumns())
    Protected index.i = x/scale
   
    If SelectElement(*w\mColumns(),index-1)
     x1.f = x - scale
     y1.f = *w\mPositionY + *w\mColumns()\mHeight
    EndIf
   
    If SelectElement(*w\mColumns(),index+1)
     x2.f = x + scale
     y2.f = *w\mPositionY + *w\mColumns()\mHeight
    EndIf
   
    ProcedureReturn Degree(ATan2((y2-y1),(x2-x1)))
   
  EndIf
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure.f getWaterHeight(*w.sWaterZone, x.f)
  If x > *w\mPositionX And x < (*w\mPositionX + *w\mSizeX)-1
    Protected scale.i = *w\mSizeX / ListSize(*w\mColumns())
    If SelectElement(*w\mColumns(),x / scale)
      ProcedureReturn *w\mColumns()\mHeight + (*w\mPositionY - *w\mSizeY)
    EndIf
   
  EndIf
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure setMouseWave(*w.sWaterZone, force.f)
  x.i = MouseX()
  If x > *w\mPositionX And x < (*w\mPositionX + *w\mSizeX)-1
    Protected scale.i = *w\mSizeX / ListSize(*w\mColumns())
    If SelectElement(*w\mColumns(),Int(x / scale))
      *w\mColumns()\mHeight + force
    EndIf
  EndIf
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure setWave(*w.sWaterZone, x.f, force.f)
  If x > *w\mPositionX And x < (*w\mPositionX + *w\mSizeX)-1
    Protected scale.i = *w\mSizeX / ListSize(*w\mColumns())
    If SelectElement(*w\mColumns(),Int(x / scale))
      *w\mColumns()\mHeight + force
    EndIf
  EndIf
EndProcedure

; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
Procedure createParticle(x.f,y.f,angle.f=90, randomAngle.f = 70,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(*w.sWaterZone, spriteDrop.i)
  ForEach particle()
    With particle()
     
      \mOldPosition\x = \mPosition\x
      \mOldPosition\y = \mPosition\y
     
      \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.3

      angle.f = Degree(ATan2((\mPosition\Y - \mOldPosition\y),( \mPosition\X - \mOldPosition\x)))
     
      RotateSprite(spriteDrop,-angle+90,0)
      DisplayTransparentSprite(spriteDrop,\mPosition\X,\mPosition\Y,64);,64)
     
      If \mPosition\X < 0 Or \mPosition\X>4096 Or \mPosition\Y > getWaterHeight(*w,\mPosition\X)
        setWave(*w,\mPosition\X,8)
        DeleteElement(particle(),1)
      EndIf

    EndWith
  Next
 
EndProcedure



; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
InitSprite() : InitKeyboard() : InitMouse() : ;InitSprite3D()
ExamineDesktops()

OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"WaterDemo",#PB_Screen_NoSynchronization)


Define Run.b = #True , offset.i = 0
Define Font.i = LoadFont(#PB_Any,"Arial",18,#PB_Font_HighQuality)
Define.i LPS,LPS_C,LPS_T,CheckTime = ElapsedMilliseconds()
Define.i FPS,FPS_C,FPS_T,flag
Define.i SpriteID,Sprite3D,imageID
Define.i SpriteDropID,SpriteDrop3D
Define.i SpriteID_tile,Sprite3D_tile
Define.i nbX=(DesktopWidth(0)/256)+2
Define.i nbY=(DesktopHeight(0)/256)+2


SpriteID      = CreateSprite(#PB_Any,256,256)
SpriteID_tile = CreateSprite(#PB_Any,256,256)
Sprite3D      = SpriteID

SpriteDropID  = CreateSprite(#PB_Any,16,16,#PB_Sprite_AlphaBlending )
SpriteDrop3D  = SpriteDropID

*Water = NewWaterZone(0,DesktopHeight(0)/2,DesktopWidth(0),DesktopHeight(0)/2,256)

ImageID = CreateImage(#PB_Any,256,256)

StartDrawing(ImageOutput(ImageID))
  DrawingMode(#PB_2DDrawing_Gradient)
  BackColor(RGB(64,128,255))
  FrontColor(RGB(8,16,32))
   GradientColor(0.0001,$FFFFFF)
  GradientColor(0.01,RGB(64,128,255))
  LinearGradient(0, 0, 0, 256)   
  Box(0,0,256,256)
StopDrawing()

StartDrawing(SpriteOutput(SpriteID))
  DrawImage(ImageID(ImageID),0,0)
StopDrawing()

StartDrawing(SpriteOutput(SpriteDropID))
    DrawingMode(#PB_2DDrawing_Default)
    Box(0,0,16,16,RGB(0,0,0))
    Circle(8,12,4,RGB(64,128,255)) 
    Circle(8,10,2,RGB(64,128,255)) 
    Circle(8,8,1, RGB(64,128,255)) 
StopDrawing()

TransparentSpriteColor(SpriteDropID,0)

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()

While Run
 
 
  If LPS_T < ElapsedMilliseconds()
    LPS_T = ElapsedMilliseconds() + 1000
    LPS = LPS_C
    FPS = FPS_C
    LPS_C = 0
    FPS_C = 0
  Else
    LPS_C + 1
  EndIf
 
 
  ExamineKeyboard()
  ExamineMouse()
 
  If KeyboardPushed(#PB_Key_Escape)
    Run = #False
  EndIf
 
    If MouseButton(1) = 1 And flag = 0
    flag = 1
   
    For i = 0 To 49
      For j = - 10 To 10
        createParticle(MouseX()+(j*2) , getWaterHeight(*Water,MouseX()))
      Next
     
    Next
   
    setMouseWave(*water,500)

  EndIf
 
  If MouseButton(1) = 0 And flag = 1
    flag = 0
  EndIf
 
 
  If (ElapsedMilliseconds() > CheckTime + 1000 / #FRAME_RATE_RENDERING)
  CheckTime = ElapsedMilliseconds()
     
    FPS_C + 1

    ClearScreen(0)

    updateWater(*Water)
   
    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()
      drawWater2(*Water,Sprite3D)
      updateParticle(*Water,SpriteDrop3D)
;     Stop3D()
   
    StartDrawing(ScreenOutput())
   
    Circle(MouseX(),MouseY(),8,$FFFFFF)
    Circle(MouseX(),MouseY(),6,0)
    Circle(MouseX(),MouseY(),2,$FFFFFF)
   
   
      DrawingMode(#PB_2DDrawing_Transparent)
        DrawingFont(FontID(Font))
          DrawText(10,10,"Water Demo by G-Rom",$5A5A5A)
          DrawText(10,50,"Click for make wave",$5A5A5A)
          DrawText(10,90,"Loop per second : "+Str(LPS),$5A5A5A)
          DrawText(10,130,"Frame rate : "+Str(FPS),$5A5A5A)
          DrawText(10,170,"Particles : "+Str(ListSize(particle())),$5A5A5A)
    StopDrawing()
   
    FlipBuffers()
     
   EndIf
 
Wend
  CloseScreen()
End

Auteur:  Micoute [ Jeu 03/Aoû/2017 8:43 ]
Sujet du message:  Re: Simulation fluide

Grand merci G-Rom.

Auteur:  Kwai chang caine [ Jeu 03/Aoû/2017 16:40 ]
Sujet du message:  Re: Simulation fluide

Ca porte bien son nom, ce code
C'est fluide dans tous les sens du terme 8O
Je l'avais pas vu, l'effet est super classe, merci du partage 8)

Auteur:  Fig [ Jeu 03/Aoû/2017 18:30 ]
Sujet du message:  Re: Simulation fluide

L'effet est super satisfaisant... On pourrait regarder ça des heures presque :mrgreen:
Un beau boulot. :idea:

Auteur:  Kwai chang caine [ Ven 04/Aoû/2017 19:20 ]
Sujet du message:  Re: Simulation fluide

Citation:
On pourrait regarder ça des heures presque
Mouaaaaihh !!! ..manque quand même un peu de poiscaille pour ça :? :lol:

Auteur:  Ar-S [ Sam 05/Aoû/2017 11:31 ]
Sujet du message:  Re: Simulation fluide

Merci, c'est fluide à souhait. Les particles des projections sont un peu grosse. ^^

Auteur:  JohnJohnsonSHERMAN [ Sam 05/Aoû/2017 17:10 ]
Sujet du message:  Re: Simulation fluide

Trés trés beau, j'adore :P

Pouvoir régler la force des vagues serait un plus trés intéressant :)

Auteur:  threedslider [ Mar 03/Juil/2018 22:34 ]
Sujet du message:  Re: Simulation fluide

Cool sa va m'aider pour mon projet et merci bcp pour ton code sympa !

Page 2 sur 2 Heures au format UTC + 1 heure
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/