Wellenberechnung in 2D

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Noobody

Betreff: Wellenberechnung in 2D

BeitragFr, Apr 10, 2009 0:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Passend zu der Wellensimulation in 3D (*klick*) kommt jetzt die 2D - Variante, allerdings auf einem anderen Prinzip basierend. Spiele wie World of Goo und Gunsheep machen es vor, weswegen es mich gereizt hat, etwas ähnliches nachzuprogrammieren.

Es funktioniert so, dass man sich das Wasser als einen Faden vorstellt, der aus untereinander mit Gummibändern verbundenen Punkten besteht. Wird ein Punkt nach unten gezogen, zieht er seine Nachbarn ebenfalls mit, was eine Welle entstehen lässt. Gleichzeitig wird der Punkt aber von seiner Ruhelage angezogen, so dass er irgendwann wieder zur Ruhe kommt.

Die Berechnungen dazu sind relativ simpel, wodurch das Wasser auch bei grossen Flächen nicht allzuviel Rechenzeit verschlingen sollte. Lediglich die Zeichenfunktion könnte kritisch werden, ich empfehle daher bei grösseren Wasserflächen, das Wasser durch ein Mesh darstellen zu lassen (da könnte man auch noch eine Textur draufbringen, wenn man es grafisch ansprechend will).

BlitzBasic: [AUSKLAPPEN]
Const GWIDTH = 800
Const GHEIGHT = 600

Graphics 800, 600, 0, 2
SetBuffer BackBuffer()

Const STEPSIZE = 5 ;Mit diesem Wert hier kann man rumspielen, um das Beste Aussehen zu erzielen

Dim Wave#( GWIDTH/STEPSIZE )
Dim Speed#( GWIDTH/STEPSIZE )

Timer = CreateTimer( 60 )

While Not KeyHit( 1 )
Cls

If MouseHit( 1 ) Then
StartX = MouseX()/Float( STEPSIZE )
For i = StartX - 50/STEPSIZE To StartX + 50/STEPSIZE
If i > 0 And i < GWIDTH/STEPSIZE - 1 Then
Dist# = Abs( StartX - i ) + 1
Disturbance# = ( 50/STEPSIZE - Dist# )*10

Wave#( i ) = Wave#( i ) - Disturbance#
EndIf
Next
EndIf

UpdateWave()
RenderWave()

Flip 0
WaitTimer Timer
Wend
End

Function UpdateWave()
For X = 1 To GWIDTH/STEPSIZE - 2
Average# = ( Wave#( X - 1 ) + Wave#( X + 1 ) )/2.1
Speed#( X ) = ( ( Average# - Wave#( X ) ) + Speed#( X ) )*0.99
Next

For X = 1 To GWIDTH/STEPSIZE - 2
Wave#( X ) = Wave#( X ) + Speed#( X )
Next
End Function

Function RenderWave()
LockBuffer BackBuffer()

Color 255, 255, 255

For X = 0 To GWIDTH
Tile = X/STEPSIZE

Ratio# = 1 - ( X Mod STEPSIZE )/Float( STEPSIZE )

If Tile < GWIDTH/STEPSIZE - 1 Then
Line X, Wave#( Tile )*Ratio# + Wave#( Tile + 1 )*( 1 - Ratio# ) + 300, X, GHEIGHT
Else
Line X, Wave#( Tile )*Ratio# + 300, X, GHEIGHT
EndIf
Next

UnlockBuffer BackBuffer()
End Function


Mit linker Maustaste kann man neue Wellen setzen.
  • Zuletzt bearbeitet von Noobody am So, Apr 19, 2009 19:18, insgesamt 2-mal bearbeitet

Thunder

BeitragFr, Apr 10, 2009 9:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Also bei mir kommt es da zu einem "Array Index out of Bounds"-Error, ich habe das Problem aber gelöst indem ich das -1 bei folgenden Zeilen entfernt habe:
Code: [AUSKLAPPEN]
Dim Wave#( GWIDTH/STEPSIZE - 1 )
Dim Speed#( GWIDTH/STEPSIZE - 1 )


ansonsten finde ich es relativ schnell und auch realistisch genug. Very Happy
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

Nicdel

BeitragFr, Apr 10, 2009 9:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei mir kommt kein Fehler, ist aber auf jeden Fall ein schöner Effekt.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

Noobody

BeitragFr, Apr 10, 2009 12:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Thunder hat Folgendes geschrieben:
Also bei mir kommt es da zu einem "Array Index out of Bounds"-Error

Seltsam, bei mir läuft es fehlerlos.
Ich habe trotzdem mal sicherheitshalber die -1 entfernt.

Danke fürs Feedback!
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Nicdel

BeitragFr, Apr 10, 2009 13:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Fehlermeldung kommt nur wenn der Debugger an ist.
Ich hab einfach mal was damit gemacht:
user posted image

Ich hatte es auch mit Draw3D probiert (für Transparenz), aber es waren zu viele Linien.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

Chrise

BeitragFr, Apr 10, 2009 13:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Nicdel hat Folgendes geschrieben:

Ich hatte es auch mit Draw3D probiert (für Transparenz), aber es waren zu viele Linien.


Wäre es nicht klüger, wenn man das mit Quad3D macht, anstatt mit Linien?
Llama 1 Llama 2 Llama 3
Vielen Dank an Pummelie, der mir auf seinem Server einen Platz für LlamaNet bietet.
 

#Reaper

Newsposter

BeitragFr, Apr 10, 2009 14:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Finde deine Codes (auch die andere Wellensimulation) echt toll. Very Happy
Nette spielerei. Very Happy

Eine kleine Anmerkung noch: Das Wasser ist jeweils an dem linken und rechten Rand fest. Hast du vermutlich gemacht, damit die Wellen am Rand reflektieren (nennt man das da so?). Normal sollte das ja aber anders sein. Wink Finde es aber echt nett. Smile
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Noobody

BeitragFr, Apr 10, 2009 16:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab das Ganze mal umgeschrieben, so dass es ein Mesh zum Rendern benutzt. Damit besteht auch die Möglichkeit, das Wasser noch mit einer Textur zu versehen.

BlitzBasic: [AUSKLAPPEN]
Const GWIDTH = 800
Const GHEIGHT = 600

Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()

Const STEPSIZE = 5 ;Mit diesem Wert hier kann man rumspielen, um das Beste Aussehen zu erzielen

Dim Wave#( GWIDTH/STEPSIZE )
Dim Speed#( GWIDTH/STEPSIZE )

Global WaveSurf

InitWave()

Timer = CreateTimer( 60 )

While Not KeyHit( 1 )
Cls

If MouseHit( 1 ) Then
StartX = MouseX()/Float( STEPSIZE )
For i = StartX - 50/STEPSIZE To StartX + 50/STEPSIZE
If i > 0 And i < GWIDTH/STEPSIZE - 1 Then
Dist# = Abs( StartX - i ) + 1
Disturbance# = ( 50/STEPSIZE - Dist# )*10

Wave#( i ) = Wave#( i ) - Disturbance#
EndIf
Next
EndIf

UpdateWave()
RenderWave()

WireFrame KeyDown( 57 )

RenderWorld

Flip 0
WaitTimer Timer
Wend
End

Function InitWave()
Cam = CreateCamera()
CameraProjMode Cam, 2
CameraZoom Cam, 2./GWIDTH

WaveMesh = CreateMesh()
WaveSurf = CreateSurface( WaveMesh )
WaveTex = LoadTexture( "Water.png" )

EntityTexture WaveMesh, WaveTex
EntityFX WaveMesh, 1
TurnEntity WaveMesh, 180, 0, 0
PositionEntity WaveMesh, -GWIDTH/2., GHEIGHT/2., 5, True

XRatio# = TextureWidth( WaveTex )/Float( GWIDTH )

For i = 0 To GWIDTH
V1 = AddVertex( WaveSurf, i, GHEIGHT/2., 0, ( i Mod TextureWidth( WaveTex ) )/Float( TextureWidth( WaveTex ) ), 0 )
V2 = AddVertex( WaveSurf, i, GHEIGHT, 0, ( i Mod TextureWidth( WaveTex ) )/Float( TextureWidth( WaveTex ) ), 1 )

If i > 0 Then
AddTriangle WaveSurf, OldV1, V1, V2
AddTriangle WaveSurf, OldV1, V2, OldV2
EndIf

OldV1 = V1
OldV2 = V2
Next
End Function

Function UpdateWave()
For X = 1 To GWIDTH/STEPSIZE - 2
Average# = ( Wave#( X - 1 ) + Wave#( X + 1 ) )/2.1
Speed#( X ) = ( ( Average# - Wave#( X ) ) + Speed#( X ) )*0.99
Next

For X = 1 To GWIDTH/STEPSIZE - 2
Wave#( X ) = Wave#( X ) + Speed#( X )
Next
End Function

Function RenderWave()
For X = 0 To GWIDTH
Tile = X/STEPSIZE

Ratio# = 1 - ( X Mod STEPSIZE )/Float( STEPSIZE )

If Tile < GWIDTH/STEPSIZE - 1 Then
Vertex = X*2

Y# = Wave#( Tile )*Ratio# + Wave#( Tile + 1 )*( 1 - Ratio# ) + 300

VertexCoords WaveSurf, Vertex, X, Y#, 0
VertexTexCoords WaveSurf, Vertex, VertexU( WaveSurf, Vertex ), ( Y# - 300 )/Float( GHEIGHT/2. )
EndIf
Next
End Function


Der Code braucht noch eine Textur - man kann natürlich irgendeine nehmen, ich habe diese hier verwendet:
user posted image

Das ganze gibt es auch als Archiv mit dem Code, der Textur und einer Exe, hier zu finden.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group