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

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

Auteur:  G-Rom [ Dim 27/Jan/2013 15:45 ]
Sujet du message:  Simulation fluide

voici un code qui montre comment faire une zone d'eau , cela peu être intégrer facilement dans un jeu de plateforme.
pour des explications plus poussé , regardez la référence dans l'entête du code source :

code :
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 = 120
#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)

      TransformSprite3D(sprite3D,x1,y1,x2,y2,x2,y2+*w\mSizeY-(*n\mHeight - *n\mTargetHeight),x1,y1+*w\mSizeY-(*c\mHeight - *c\mTargetHeight))
      DisplaySprite3D(sprite3D,0,0,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)))
     
      RotateSprite3D(spriteDrop,-angle+90,0)
      DisplaySprite3D(spriteDrop,\mPosition\X,\mPosition\Y,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,#PB_Sprite_Texture)
SpriteID_tile = CreateSprite(#PB_Any,256,256)
Sprite3D      = CreateSprite3D(#PB_Any,SpriteID)

SpriteDropID  = CreateSprite(#PB_Any,16,16,#PB_Sprite_Texture | #PB_Sprite_AlphaBlending )
SpriteDrop3D  = CreateSprite3D(#PB_Any,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:  venom [ Dim 27/Jan/2013 16:58 ]
Sujet du message:  Re: Simulation fluide

8O
Impressionnant le rendu. Bravo G-Rom 8)







@++

Auteur:  flaith [ Dim 27/Jan/2013 18:31 ]
Sujet du message:  Re: Simulation fluide

8O Merci pour le code, surtout pour la partie 'particle' :D

Auteur:  Ar-S [ Dim 27/Jan/2013 19:03 ]
Sujet du message:  Re: Simulation fluide

Excellent, merci pour ce plouf.

Auteur:  Cool Dji [ Dim 27/Jan/2013 21:40 ]
Sujet du message:  Re: Simulation fluide

Top classe, merci G-Rom :D

Auteur:  jbernard13 [ Dim 27/Jan/2013 21:55 ]
Sujet du message:  Re: Simulation fluide

c'est trop fun

Bravo G-Rom

Auteur:  Patrick88 [ Dim 27/Jan/2013 22:30 ]
Sujet du message:  Re: Simulation fluide

plouf et glou glou sont dans un bateau....

marche impec en window 8 :wink:

bravo

Patrick

Auteur:  djes [ Lun 28/Jan/2013 17:16 ]
Sujet du message:  Re: Simulation fluide

Super joli ! :)

Auteur:  Fig [ Jeu 07/Fév/2013 20:57 ]
Sujet du message:  Re: Simulation fluide

Bravo !

Je cherche un moyen de simuler (avec un automate cellulaire peut-être ?) une surface d'eau avec des reflets mouvants (simulant les vaguelettes), quelqu'un a peut être une idée ?

Auteur:  G-Rom [ Ven 08/Fév/2013 18:59 ]
Sujet du message:  Re: Simulation fluide

en 2d ?

Auteur:  Fig [ Jeu 14/Fév/2013 17:56 ]
Sujet du message:  Re: Simulation fluide

Oui en 2d bien sûr, le but c'est d'avoir un effet de vaguelette vu de dessus,sans devoir gérer de la 3d. (je ne demande pas de vrais reflets, juste des effets de couleurs mouvantes)

Auteur:  G-Rom [ Ven 15/Fév/2013 0:26 ]
Sujet du message:  Re: Simulation fluide

Regarde dans le dossier medias de la partie 3d , la texture "caustic" devrais correspondre à tes besoins

Auteur:  Fig [ Sam 16/Fév/2013 18:51 ]
Sujet du message:  Re: Simulation fluide

C'est exactement ce que je cherchais !!

Auteur:  gildev [ Lun 18/Mar/2013 0:19 ]
Sujet du message:  Re: Simulation fluide

Punaise! C'est vraiment bien foutu.

Auteur:  Atlante [ Lun 18/Mar/2013 10:33 ]
Sujet du message:  Re: Simulation fluide

Oui, c'est vraiment bien ce petit effet.

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