Page 2 sur 2

Re: Simulation fluide

Publié : lun. 18/mars/2013 14:02
par Backup
je trouve qu'on gagne en réalisme si on utilise ces parametres

Code : Tout sélectionner

#DAMPENING            = 0.00025
#TENSION              = 0.025
#SPREAD               = 0.25
#FRAME_RATE_RENDERING = 120
#GRAVITY              = 9.8
et qu'on remplace la ligne 423

Code : Tout sélectionner

setMouseWave(*water,500)
par

Code : Tout sélectionner

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

Re: Simulation fluide

Publié : mer. 02/août/2017 17:57
par G-Rom
Code mis à jour pour la version actuelle de PB :

Code : Tout sélectionner

; ------------------------------------------------------------------------------------------
; 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

Re: Simulation fluide

Publié : jeu. 03/août/2017 8:43
par Micoute
Grand merci G-Rom.

Re: Simulation fluide

Publié : jeu. 03/août/2017 16:40
par Kwai chang caine
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)

Re: Simulation fluide

Publié : jeu. 03/août/2017 18:30
par Fig
L'effet est super satisfaisant... On pourrait regarder ça des heures presque :mrgreen:
Un beau boulot. :idea:

Re: Simulation fluide

Publié : ven. 04/août/2017 19:20
par Kwai chang caine
On pourrait regarder ça des heures presque
Mouaaaaihh !!! ..manque quand même un peu de poiscaille pour ça :? :lol:

Re: Simulation fluide

Publié : sam. 05/août/2017 11:31
par Ar-S
Merci, c'est fluide à souhait. Les particles des projections sont un peu grosse. ^^

Re: Simulation fluide

Publié : sam. 05/août/2017 17:10
par JohnJohnsonSHERMAN
Trés trés beau, j'adore :P

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

Re: Simulation fluide

Publié : mar. 03/juil./2018 22:34
par threedslider
Cool sa va m'aider pour mon projet et merci bcp pour ton code sympa !