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