Fragen zu dem so beliebten Starfield...

Übersicht BlitzBasic Allgemein

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

 

Amiganer

Betreff: Fragen zu dem so beliebten Starfield...

BeitragDi, Feb 14, 2012 23:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo!

Einleitung (kann auch übersprungen werden):
Ich bin nur durch Zufall auf BlitzBasic gestoßen. Persönlich habe ich Blitz3D und versuche mich seit Jahren das erste Mal an Programmierung. Als alter Amiganer *wink* bin ich sehr darauf aus, schöne, mit wenig Farben gezeichnete 2D-Spiele zu erstellen. Das erste wird sicherlich ein Ableger von Project X von Team 17. Die Grafik bzw. die Bitmaps sowie die musikalische Untermalung stellen dabei kein Problem dar. Wichtig ist jedoch das vom Amiga bekannte Parallax-Scrolling. Wobei hier die gewollten Sterne nicht aus Bitmaps bestehen soll, sondern die grafischen Fähigkeiten von Blitz3D (oder BlitzBasic) genutzt werden sollen (writePixel bzw Plot usw).

Erläuterung:
Es gibt mitgelieferte Beispiele bei Blitz3D mit dem Starfield (stardemo.bb und stars.bb). Das Ergebnis sieht gut aus, aber leider leider ist es extrem CPU-lastig (E8400 auf gut 50%). Mit meinem selbst geschriebenen Quellcode habe ich derzeit mehrere Probleme. Deshalb bediente ich mich eines anderen Quellcodes, der als Tutorial angeboten wurde. Er war ebenfalls sehr CPU-lastig. Diesen habe ich etwas umgeschrieben und erweitert, sodass ich mit knappp 4% CPU-Beanspruchung leben kann.


aktueller Quelltext:
BlitzMax: [AUSKLAPPEN]
resX = 800
resY = 600
bits = 16
mode = 2
Graphics resX,resY,bits,mode
feldgroesse = 800
sterne1 = 2
sterne2 = 10
sterne3 = 15
sterne4 = 20
sterne5 = 40
moveX = 0
fps = CreateTimer(60)

sternenlayer1 = CreateImage(feldgroesse,feldgroesse)
sternenlayer2 = CreateImage(feldgroesse,feldgroesse)
sternenlayer3 = CreateImage(feldgroesse,feldgroesse)
sternenlayer4 = CreateImage(feldgroesse,feldgroesse)
sternenlayer5 = CreateImage(feldgroesse,feldgroesse)

SetBuffer ImageBuffer(sternenlayer1)
For i=1 To sterne1
farbe = Rand (200,250) ; Helligkeit zufallsgesteuert
Color farbe,farbe,farbe ; Helligkeitswert zugewiesen
Rect Rand(feldgroesse), Rand(feldgroesse),1,1 ; zeichnet im Sternenfeld
Next

SetBuffer ImageBuffer(sternenlayer2)
For i=1 To sterne2
farbe = Rand (100,150)
Color farbe,farbe,farbe
Rect Rand(feldgroesse), Rand(feldgroesse),1,1
Next

SetBuffer ImageBuffer(sternenlayer3)
For i=1 To sterne3
farbe = Rand (50,70)
Color farbe,farbe,farbe
Rect Rand(feldgroesse), Rand(feldgroesse),1,1
Next

SetBuffer ImageBuffer(sternenlayer4)
For i=1 To sterne4
farbe = Rand (40,60)
Color farbe,farbe,farbe
Rect Rand(feldgroesse), Rand(feldgroesse),1,1
Next

SetBuffer ImageBuffer(sternenlayer5)
For i=1 To sterne5
farbe = Rand (20,40)
Color farbe,farbe,farbe
Rect Rand(feldgroesse), Rand(feldgroesse),1,1
Next

SetBuffer BackBuffer()
While Not KeyDown(1)
Cls
TileImage sternenlayer1,moveX*5,0
TileImage sternenlayer2,moveX,0
TileImage sternenlayer3,moveX/2,0
TileImage sternenlayer4,moveX/3,0
TileImage sternenlayer4,moveX/4,0

moveX = moveX-1
Flip(0) ; Flip wird ausgesetzt
WaitTimer fps
Wend


Problem:
1) Ich bekomme es nicht hin, dass die Sterne eine unterschiedliche Helligkeit aufweisen (oder gar pulsieren).
2) Die Sterne werden pro Layer als ein Bild gezeichnet und wiederholen sich. Dabei ist die Konstellation der Sterne immer gleich.
3) Die Konstellation der Sterne ist sogar layerübergreifend gleich.

mein Verdacht ist, dass die unterschiedliche Helligkeit bzw. das Pulsieren nicht möglich ist, weil das Bild ja nur einmal erstellt wird und dann nur wiederholt. Aber ich wüsste jetzt keine Lösung, dies zu umgehen. Warum aber die Verteilung der Sterne zumindest bei mir layerübergreifend gleich ist (besonders Layer 3-5) ist mir ein Rätsel.



Mit meinem ursprünglichen Quellcode (der wiederum ist im Grundgerüst aus einem Anfänger Buch) bekomme ich zwar das Random der Sterne hin, dafür aber nicht die verschiedenen Layer und schon gar nicht das Flackern (die anderen Layer habe ich rausgelöscht, weil nix funktionierte):

BlitzMax: [AUSKLAPPEN]
resX   = 800
resY = 600
bits = 16 ; 16 Mio Farben
bildmodus = 2 ; Bildschirmmodus 1-Vollbild, 2-Fenster
anzahl3 = 15 ; Anzahl Sterne Layer 3
fps = CreateTimer(60) ; FPS

Graphics resX,resY,bits,bildmodus ; Aufloesung Fenstermodus
SetBuffer BackBuffer() ; nicht sichtbarer Bildschirm


; Sterne merken
Dim sterne3(anzahl3,1)
For i=1 To anzahl3
sterne3(i,0)=Rand(0,resX)
sterne3(i,1)=Rand(0,resY)

Next

; Sterne bewegen y->0
Repeat
Cls
; Sterne flackern
farbe3 = Rand(50,150)
Color farbe3,farbe3,farbe3 ; Farbe fuer Sterne RGB
; Bewegung
For i=1 To anzahl3
If sterne3(i,0)<>0
sterne3(i,0)=sterne3(i,0)-1
Else
sterne3(i,0)=resX
sterne3(i,1)=Rand(0,resY)
EndIf

Plot sterne3(i,0), sterne3(i,1) ; Sterne zeichnen
Next



Flip 0 ; Wartet ueber WaitTimer (Ressourcenschonend)
WaitTimer fps ; wartet auf letzte Zeit vom CreateTimer(xxx)
Until KeyHit(1)


Vielleicht hat jemand von euch tatsächlich einen Tipp. Derzeit tue ich mir noch schwer mit der Sprache. Auch der Plot-Befehl scheint etwas zu ressourcenfressend zu sein. Ich dachte schon, man könnte es ja mit writepixel versuchen.

Mein Anliegen ist:

Relativ ressourcenschonenden Code zu schreiben. Und wenn's Monate dauert. Ein alter Amiga hat mit seinen 7 MHz ein Grafikfeuerwerk gezaubert, da wird es doch möglich sein, auf einem überdimensionierten PC ein paar Pixel durch die Gegend schieben zu können.
mein Name ist Hans, das L steht für Gefahr

Xeres

Moderator

BeitragDi, Feb 14, 2012 23:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Das Problem wird sein, dass BlitzBasic nicht für moderne PCs gemacht ist. DirektX 7 ist veraltet und wird wenn nur langsam (und stellenweise nur sporadisch) emuliert. Mit BB kannst du auch nicht wirklich Lowlevel arbeiten, da bliebe höchstens noch die Flucht nach Vorn: BlitzMax ist sehr zu empfehlen, mit OpenGL kann man viel anstellen (oder DirektX 9) und du kannst alle Vorteile einer Grafikkarte nutzen.

Mit Flip(0) & Waittimer kannst du zumindest die ständige CPU Belastung runter drehen, aber Alpha, Blendmodes usw. von BlitzMax sind höchstens noch mit extra-userlibs wie hectics Draw3D zu erreichen (die auch 3D/Grafikkarten benutzen).
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Midimaster

BeitragMi, Feb 15, 2012 3:20
Antworten mit Zitat
Benutzer-Profile anzeigen
ich glaube, man muss einfach lange herumprobieren, bis so ein Tiefeneefekt und das Funkeln der Sterne ensteht

BlitzBasic: [AUSKLAPPEN]
; erst unter Fullscreen zeigt sich die Leistung:
Graphics 800,600,16,1

SetBuffer BackBuffer()

Type SternTyp
Field x#,y#,z#,c
End Type

For i=0 To 2500
Stern.SternTyp=New SternTyp
Stern\x=Rnd(0,800)
; die "Tiefe"
Stern\z=Rnd(Rnd(Rnd(5)))

;die Helligkeit:
Stern\c=50+Rand(Stern\z*40)

; die Y-Achgse mit ein bißchen Milchstraße -Effekt
Stern\y=250 + Rnd(-77,77)*Stern\z^1.5 + Stern\X/10
; Stern\y=Rand(600)
Next
;fps=CreateTimer(30)
Repeat
zeit=MilliSecs()
Color 1,1,1
Rect 0,0,800,600
For Stern.SternTyp=Each SternTyp
If Rand(100)<98 ; 98% ohne Glitzer
c=stern\c
Else
c=255 ;2% Glitzern
EndIf
Color c,c,c
Oval Stern\x, Stern\y, Stern\z,Stern\z

Stern\x=Stern\X-.1*stern\z
If Stern\x<0 Then Stern\X=800
Next
Zeit= MilliSecs()-zeit
; Color 255,0,0
; Text 100,100,zeit
Flip 0
; WaitTimer fps
Until KeyHit(1)
WaitKey
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
 

Amiganer

BeitragMi, Feb 15, 2012 10:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Ersteinmal danke euch beiden! Idea

Wegen BlitzMax muss ich tatsächlich mal schauen. Wenn ich tatsächlich nicht genug hardwarenah programmiere, wird ein trickreicher Code wohl keine signifikante Besserung bringen. Aber dennoch will ich's versuchen. Irgend einen Trick muss es doch einfach geben Cool

@ Midimaster: Dein Beispiel ist vom rein Visuellen genau das, was ich meine Wink Sieht echt genial aus. Aber wie gesagt, die Prozessorlast steigt ins Unermessliche Shocked

Aber klasse siehts aus! Werd mich mal in den Quelltext einlesen Smile


Vielleicht ist mein Unterfangen ja nicht von Erfolg gekrönt, aber das muss ich tatsächlich mal ausprobieren. Wäre doch gelacht, wenn ich schon an einem kleinen Sternenfeld scheitern sollte. *Blitz3D vor!* Idea
mein Name ist Hans, das L steht für Gefahr

ozzi789

BeitragMi, Feb 15, 2012 10:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Verwende Waittimer und schon hast du ne CPU Last von 4% (auf einer 2.4 GHZ Core)
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Midimaster

BeitragMi, Feb 15, 2012 10:55
Antworten mit Zitat
Benutzer-Profile anzeigen
bei meinem uralt notebook kamen gerade mal 50% Auslastung bei eingeschaltem WaitTimer() raus. Da ist eine SIS-Grafikkarte drin. Ich denke mal, das dürfte auf moderneren Systemen wesentlich besser laufen. Und das Beispiel war mit schon 2500 Sternen.

Was ich Dir damit sagen wollte ist, dass Du wahrscheinlich das Ganze auf BB hinbekommen wirst. Ich checke mal eben, wie es unter BlitzMax performed...

[EDIT]

also... Während ich unter BB immer 8msec für einen Druchlauf benötige, komme ich unter Bmax auf Durchlaufzeiten von über 32msec. Das wäre jetzt 4x langsamer als unter BB...

Hier das BMax-Programm:
BlitzMax: [AUSKLAPPEN]

'; erst unter Fullscreen zeigt sich die Leistung:
Graphics 800,600,32,60


Global SternListe:TList=New TList

Type SternTyp
Field x#,y#,z#,c
End Type

For i=0 To 2500
Print i
Local Stern:SternTyp = New SternTyp
Print "N"
Stern.x=Rnd(0,800)
'; die "Tiefe"
Stern.z=Rnd(Rnd(Rnd(5)))

';die Helligkeit:
Stern.c=50+Rand(Stern.z*40)

'; die Y-Achse mit ein bißchen Milchstraße -Effekt
Stern.y=250 + Rnd(-77,77)*Stern.z^1.5 + Stern.X/10
Print "E"
ListAddLast SternListe,Stern
Next
Print "Mitte"
'fps=CreateTimer(30)
Repeat
zeit=MilliSecs()
Cls
'SetColor 1,1,1
'DrawRect 0,0,800,600
For Stern:SternTyp = EachIn SternListe
If Rand(100)<98 '; 98% ohne Glitzer
c=stern.c
Else
c=255 ';2% Glitzern
EndIf
SetColor c,c,c
DrawOval Stern.x, Stern.y, Stern.z,Stern.z

Stern.x=Stern.X-.1*stern.z
If Stern.x<0 Then Stern.X=800
Next
Zeit= MilliSecs()-zeit
z:+1
sum=sum+zeit
SetColor 1,1,1
DrawRect 100,100,100,20
SetColor 255,0,0
DrawText zeit+ " " + Int(sum/z),100,100
Flip 0
' WaitTimer fps
Until KeyHit(Key_Escape)
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
  • Zuletzt bearbeitet von Midimaster am Mi, Feb 15, 2012 11:26, insgesamt 2-mal bearbeitet

ozzi789

BeitragMi, Feb 15, 2012 11:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Mit Flip 0 wirst du auf allen Systemen eine grosse Auslastung haben....
Die einen halt mit mehr FPS die anderen mit weniger Wink
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

BladeRunner

Moderator

BeitragMi, Feb 15, 2012 14:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Code ist ja auch recht inperformant, Midimaster.
ad 1: warum verschachtelst Du 3*Rnd? Zufälliger als zufällig geht es nicht, und den Pseudozufall von Programmiersprachen kriegst Du so auch nicht behoben (beachte dabei die Funktionsweise von Rand - jede generierte Zufallszahl ist der seed der nächsten. Daher ist bei einem dreimal verschachtelten Rnd das Ergebnis schon absolut klar beim ersten Aufruf, da der Seed sich ja linear ändert).
ad 2: Stilsache, aber: Sternliste ist ein Object, Du solltest es auch so nutzen:
sternliste.addlast(stern) statt listaddlast (sternliste,stern). Spart einem auch zumindest mal einen gewrappten Funktionsaufruf (Denn nichts anderes ist ListAddLast).

Diese beiden betrafen zwar nur die Initialisierung und fallen daher für die Ausführungszeit nicht ins Gewicht, aber dennoch sollte man solche Stricke bedenken.

ad 3: Drawoval ist lahm - generell ist es wesentlich günstiger Texturen zu blitten, daher generiere dein Sternchen einmal als Image und benutze Setscale um es verschieden groß erscheinen zu lassen (sämtliche Set-Funktionen sind quasi kostenlos, da sie auf der GPU ausgeführt werden, und die ist da rasend schnell).
ad 4: Selbiges gilt eigentlich für den kompletten Sternenhimmel, ich würde also in der Tat statt jedem Stern sein eigenes z zuzuweisen eine Handvoll Layer generieren, die einmal vorgerendert werden und dann im kompletten über den Bildschirm bewegt werden. Es dürfte dann immer noch wesentlich schneller sein die blinkenden Sterne nochmal separat auf einen Layer zu pinseln und den mit angepasstem setColor / setalpha einzeichnen zu lassen.
Wenn der Zufall vorher vernünftig per seedrand initialisiert wurde und man ausreichend unterschiedlich schnell sich bewegende Layer benutzt sollte auch kein festes Muster erkennbar sein. Der Trick ist dabei die Laufgeschwindigkeiten auf unterschiedliche Primen(2,3,5,7...) zu legen, so dass nicht zwei Layer immer wieder die selbe Schnittmenge bilden.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Xeres

Moderator

BeitragMi, Feb 15, 2012 14:31
Antworten mit Zitat
Benutzer-Profile anzeigen
BladeRunner hat Folgendes geschrieben:
warum verschachtelst Du 3*Rnd?
Das macht es unwahrscheinlicher, den Maximalwert zu erreichen und gibt öfters kleinere Werte - ungleiche Verteilung.

edit:
Midimaster hat Folgendes geschrieben:
Während ich unter BB immer 8msec für einen Druchlauf benötige, komme ich unter Bmax auf Durchlaufzeiten von über 32msec.
SuperStrict+Releasemodus würde ich eher vergleichen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
  • Zuletzt bearbeitet von Xeres am Mi, Feb 15, 2012 14:42, insgesamt einmal bearbeitet

BladeRunner

Moderator

BeitragMi, Feb 15, 2012 14:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Einen gewichteten Zufall würde ich eher als solchen implementieren wollen, aber zugegeben, es ist ein Argument.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Midimaster

BeitragMi, Feb 15, 2012 16:57
Antworten mit Zitat
Benutzer-Profile anzeigen
@BladeRunner:

einige deiner Behauptungen sind falsch oder entbehren jeder Relevanz zum Thema Performance. Nur um mal eines rauszugreifen: Natürlich macht es einen Unterschied, ob man den RAND() einmal setzt oder verschachtelt:
BlitzMax: [AUSKLAPPEN]
Graphics 800,600

Global Wert[101], WertB[101]

For i=0 To 3000
Zufall=Rand(30)
Wert[Zufall]:+1
Next
SetColor 255,0,0
For i=0 To 30
DrawRect i*20,200,8,-Wert[i]
Next


For i=0 To 3000
Zufall=Rand(Rand(Rand(30)))
Wert[Zufall]:+1
Next
SetColor 0,255,0
For i=0 To 30
DrawRect i*20+10,500,8,-Wert[i]
Next

Flip 1
WaitKey


Erst nachdenken, bevor man draufhaut!
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

BladeRunner

Moderator

BeitragMi, Feb 15, 2012 17:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Was ich ja selbst auf den Einwand von Xeres schon zugegeben habe. Erst lesen bevor man (fraglich) zurückhaut?
Welche meiner Anmerkungen sind sonst noch zu beanstanden?
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragMi, Feb 15, 2012 18:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Zum Rand-Problem:

Rnd(0.0, 1.0) liefert Realisierungen einer (Pseudo-)Zufallsgröße X, die über (0, 1] gleichverteilt ist.
Für die Verteilungsfunktion F(x) = P({e: X(e) <= x}) gilt: F(x) = x.

Die Zufallsgröße Y = Rand(Rand(Rand(30))) lässt sich in etwa so dann formulieren:
Seien X1, X2, X2 (0, 1]-gleichverteilte Zufallsgrößen.
Y = (Floor(Floor(30 * X3) * X2) * X1)
ignoriert man die Ganzzahligkeit gilt also
Y = (((30 * X3) * X2) * X1) = 30 * X3 * X2 * X1

Wenn man für Y eine Verteilungsfunktion G(x) bestimmen kann, die stetig und streng monoton wachsend ist, könnte man das Problem auf eine (1,0]-gleichverteilte Zufallsgröße Z beschränken. Für eine Realisierung z von Z, also ein Rückgabewert von Rnd(0.0, 1.0), würde dann gelten: y = G^-1(z). Wobei y hier eine Relaisierung von Y ist.

Existiert also G(x), dann reicht ein einziger Aufruf von Rnd.
vertex.dreamfall.at | GitHub

Midimaster

BeitragMi, Feb 15, 2012 23:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Es gibt natürlich eine Grund, warum ich die Zufallsvariable 3x rufe. Und um dies zu erreichen genügt nicht ein einziger Aufruf.

Ein einfacher Aufruf erzeugt ein gleichmäßige Verteilung der Zufallszahlen.

Ein mehrfacher Aufruf zerstört diese Gleichmäßigkeit und erzeugt ein ungleichmäßig verteiltes Feld. Und genau das ist, was ich hier brauche.

Es sollen nicht 2500 Sterne gleichmäßig verteilt werden, sondern je weiter sie weg sind, desto häufiger sollen sie vorkommen.

Mal auf Ganzzahlen vereinfacht:

Rnd(5) erzeugt gleichmäßig viele 1er, 2er, 3er, 4er, 5er:

12345

Die Ergebnisse sind nun die Basis für die 2. Interation
Rnd(Rnd(5))

und führen zu solchen Zufallsfindungen:

Rnd(1)
Rnd(2)
Rnd(3)
Rnd(4)
Rnd(5)

daraus ergeben sich gleich viele
1
12
123
1234
12345
------------------------------
und unter dem Strich eine Gewichtung:
112123123412345
oder so:
111112222333445

und ich habe das ganze um eine 3.Iteration erweitert, da sich erst dann die für meinen Zweck nötige parabelähnliche Verteilung ergibt.


Mit dem DrawOval wollte ich eben BEWUSST zeigen, dass selbst mit einfachen Zeichenbefehlen ein funkelnder Sternenhimmel möglich ist. Mit 8msec bleibt die Zeit selbst bei 2500 Sternen 50% unter der 1/60sec und lässt noch Raum für andere Aktionen. Und das auf meinem Notenbook. Möglicherweise ist das ja auf einem guten Rechner noch schneller. Wozu dann mit Kanonen auf Spatzen schießen? Und so bleibt auch das Funkeln "individuell zauberhaft" und tritt nicht für eine ganze Ebene synchron auf.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Vertex

BeitragDo, Feb 16, 2012 3:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Von der Performance sollte es keine wesentliche Rolle spielen. In meinem Kryptologiebuch steht, dass die rand-Funktion im ANSI C einfach ein sogenannter Linear Congruential Generator ist:
Code: [AUSKLAPPEN]
s0 = seed
s_(i+1) = a * s_i + b mod m

mit festgelegten Konstanten a, b und m. Hat also konstante Komplexität, auch wenn man sie drei Mal anwendet.

Aber um den Effekt zu erzeugen, dass bestimmte Werte häufiger vorkommen, als andere, würde ich dennoch eine Exponentialverteilung berechnen. Mittels der oben beschriebenen Inversionsmethode, also die Umkehrfunktion auf die Realisierung der (0,1]-gleichverteilten Zufallsgröße anwenden, kann man in Blitz auch exponentialverteilte Zufallsgrößen in simulieren:

BlitzBasic: [AUSKLAPPEN]
Graphics(1024, 768, 0, 2)
SetBuffer(BackBuffer())

Const WHITE = $FFFFFFFF
Const RED = $FFFF0000
Const GREEN = $FF00FF00

Const LAMBDA# = 1.0 / 40.0

LockBuffer()

Local x, y
For x = 0 To GraphicsWidth() - 1
Local value#

; Mit drei Zufallsgrößen (rote Punkte)
value = 300.0 * Rnd(0.0, 1.0) * Rnd(0.0, 1.0) * Rnd(0.0, 1.0)
y = GraphicsHeight() - value
WritePixel(x, y, RED)

; Mit einer Zufallsgröße (grüne Punkte)

; Die Verteilungsfunktion der Exponentialverteilung ist:
; F(x) = 1 - e^(-lambda * x)
; Der Erwartungswert ist 1/lambda
; Die Umkehrfunktion ist:
; F^-1(x) = - 1/lambda * ln(1 - x)
; Wenn X ~ (0,1]-gleichverteilt und Y = F^-1(X), dann ist Y ~ F(x)
; (Mittels Inversionsmethode)
value = -(1.0 / LAMBDA) * Log(1.0 - Rnd(0.0, 1.0))
y = GraphicsHeight() - value
WritePixel(x, y, GREEN)
Next

UnlockBuffer()
Flip()
WaitKey()


Rot mit Verschachtelung, Grün mit der exponentialverteilten Zufallsgröße.

Ciao Olli
vertex.dreamfall.at | GitHub

PSY

BeitragDo, Feb 16, 2012 5:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Vertex hat Folgendes geschrieben:
Hat also konstante Komplexität, auch wenn man sie drei Mal anwendet.

ich glaub ihr redet hier aneinander vorbei Very Happy oder ihr tuts nicht, aber ich denke aus irgendnem grund dass ihrs trotzdem tut Embarassed
3x hintereinander ne random ausfuehren bringt gegenueber 1x ausfuehren keinen vorteil, stimmt. wird auch nicht zufaelliger.
aber midimaster macht ja was ganz anderes, er erstellt bestimmte werte mit einer hoeheren wahrscheinlichkeit als andere.


Code: [AUSKLAPPEN]
Stern.z=Rnd(Rnd(Rnd(5)))

der code wird von "innen" nach "aussen" aufgeloest!
zum einfacheren verstaendnis nehmen wir mal Code: [AUSKLAPPEN]
wert = rand(rand(rand(5)))

damit werden nur ganze zufallszahlen zwischen 1 und 5 erzeugt
1. zuerst wird rand(5) abgearbeitet. damit wird eine der folgenden zahlen mit 20% wahrscheinlichkeit erzeugt (1,2,3,4,5)
2. beim zweiten aufruf wird eine zahl zwischen 1 und der zahl aus dem 1. schritt erzeugt. das ist mit 20% wahrscheinlichkeit wieder eine zahl zwischen 1 und 5, mit 80% wahrscheinlichkeit aber eine zahl zwischen 1 und einer zahl <5. genauer gesagt, beim 2. schritt ist es bereits relativ unwahrscheinlich, dass die 5 ueberhaupt noch gezogen werden KANN
3. siehe 2, die gezogenen zahlen werden mit grosser wahrscheinlichkeit weiter kleiner...

pro schritt sinkt also die wahrscheinlichkeit, dass der maximalwert wie im 1. schritt 5 ist.
je mehr schritte, desto geringer die wahrscheinlichkeit. beim 4 oder 5 randoms kommen fast ausschliesslich 1en raus.
deswegen spuckt die funktion statistisch gesehen am oeftesten 1en aus, danach 2en, danach 3en usw.
die 5 kommt am seltensten vor.

sieht man auch ganz leicht an diesem code: (edit: linke spalte mit verschachtelung, rechte ohne)
Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
SetBuffer BackBuffer()
For i=1 To 15
   Text 10,i*10,Rand(Rand(Rand(Rand(5))))
   Text 50,i*10,Rand(5)
Next
Flip
WaitKey


fuer den sternencode eignet sich das vorgehen bestens. ist sehr schnell, und sehr simpel.

dein ansatz
Code: [AUSKLAPPEN]
value = 300.0 * Rnd(0.0, 1.0) * Rnd(0.0, 1.0) * Rnd(0.0, 1.0)

ist aber auch sehr geil, um ungleichmaessig verteilte werte zu erstellen. da muss man erstmal drauf kommen.
und die log-func werd ich mal notieren, danke fuer den hinweis! sowas kann man immer mal brauchen...


l8er,
PSY
PSY LABS Games
Coders don't die, they just gosub without return
  • Zuletzt bearbeitet von PSY am Fr, Feb 17, 2012 0:38, insgesamt einmal bearbeitet

BladeRunner

Moderator

Betreff: 1dq

BeitragDo, Feb 16, 2012 10:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
aber midimaster macht ja was ganz anderes, er erstellt bestimmt werte mit einer hoeheren wahrscheinlichkeit als andere.

Das sollte eigentlich allen seit Xeres' Posting klar sein, Vertex erklärt ja auch schön eine alternierende Methode zur Gewichtung des Zufalls, worauf Midimaster erklärt er möchte den Zufall gewichten (was ja allen seit Xeres' Post ...), und ab da beisst sich die Katze in den Schwanz.

Zitat:
Mit dem DrawOval wollte ich eben BEWUSST zeigen, dass selbst mit einfachen Zeichenbefehlen ein funkelnder Sternenhimmel möglich ist. Mit 8msec bleibt die Zeit selbst bei 2500 Sternen 50% unter der 1/60sec und lässt noch Raum für andere Aktionen. Und das auf meinem Notenbook. Möglicherweise ist das ja auf einem guten Rechner noch schneller. Wozu dann mit Kanonen auf Spatzen schießen? Und so bleibt auch das Funkeln "individuell zauberhaft" und tritt nicht für eine ganze Ebene synchron auf.

Dazu ein weiterer Quote von Dir:
Zitat:
also... Während ich unter BB immer 8msec für einen Druchlauf benötige, komme ich unter Bmax auf Durchlaufzeiten von über 32msec. Das wäre jetzt 4x langsamer als unter BB...

Mit meinem Posting habe ich nichts anderes getan als auf potentielle Gründe für den Performanceeinbruch unter BMax hinzuweisen. 32ms sind ja wohl ein wenig langsamer als die benötigte Zeit, und Drawoval ist nunmal unter BMax ein Flaschenhals. Das individuelle Funkeln ist mit Texturen allein(ohne extra Layertextur) ja auch noch möglich und sollte dennoch deutlich schneller sein als mit Drawoval.
Übrigens verstehe ich die Aufregung um Rnd nicht, denn ich habe ebenfalls in meinem initialen Post schon drauf hingewiesen dass es hier für die Performance nichts zur Sache tut, noch dazu wo ich den Sinn des verschachtelten Rnd selbst 2 Posts später schon eingeräumt habe. Weshalb Du dich also so auf den Schlips getreten fühlst kann ich nur raten.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

BladeRunner

Moderator

BeitragDo, Feb 16, 2012 19:51
Antworten mit Zitat
Benutzer-Profile anzeigen
So, ausnahmsweise mal ein Doublepost:
Code: [AUSKLAPPEN]
SuperStrict
'; erst unter Fullscreen zeigt sich die Leistung:
Graphics 800,600,32,60
Global img:TImage = CreateImage(32 , 32 , 1 ,FILTEREDIMAGE|MIPMAPPEDIMAGE|MASKEDIMAGE )

DrawOval(0 , 0 , 31 , 31)

GrabImage(img,0,0,0)

   Global SternListe:TList=New TList

Type SternTyp
   Field x#,y#,z#,c:Int
End Type

For Local i:Int=0 To 2500
   Print i
   Local Stern:SternTyp = New SternTyp
   Print "N"
   Stern.x=Rnd(0,800)
   '; die "Tiefe"
   Stern.z=Rnd(Rnd(Rnd(.75)))

   ';die Helligkeit:
   Stern.c=50+Rand(Stern.z*320)
   
   '; die Y-Achse mit ein bißchen Milchstraße -Effekt
   Stern.y=250 + Rnd(-377,377)*Stern.z^1.5 + Stern.X/10
   Print "E"
   ListAddLast  SternListe,Stern
Next
Print "Mitte"
'fps=CreateTimer(30)
Local z:Int
Local sum:Int
Local c:Int
Repeat
   Local zeit:Int=MilliSecs()
   Cls
   'SetColor 1,1,1
   'DrawRect 0,0,800,600
   For Local Stern:SternTyp = EachIn SternListe
      If Rand(100)<98  '; 98% ohne Glitzer
         c=stern.c
      Else
         c=255 ';2% Glitzern      
      EndIf
      SetColor c,c,c
      'DrawOval Stern.x, Stern.y, Stern.z,Stern.z
      SetScale stern.z,stern.z
      DrawImage img , stern.x , stern.y
      SetScale 1,1
      Stern.x=Stern.X-.1*stern.z
      If Stern.x<0 Then Stern.X=800
   Next
   Zeit= MilliSecs()-zeit
   z:+1
   sum=sum+zeit
   SetColor 1,1,1
   DrawRect 100,100,100,20
   SetColor 255,0,0
   DrawText zeit+ " " + Int(sum/z),100,100
   Flip 0
'   WaitTimer fps
Until KeyHit(Key_Escape)

Ich habe, um nicht nur mit Worten da zu stehen, deinen Code genommen und statt der Drawoval ein im Code generiertes Image verwendet. Ansonsten ist er bis auf kleine Anpassungen um die Imagegröße auszugleichen im wesentlichen unverändert, daher ist die Optik weit von perfekt, es ging mir ja aber mehr ums Prinzip.

Bei mir war der Performanceschub gewaltig:
Vorher: 9-10ms Debug, ca. 5 Release.
Nachher: 3-4 ms Debug, 0-1 Release. Ein anheben von 2500 auf 25000 Sterne sorgte dafür dass ich auch release 8ms brauchte, wohingegen bei Drawoval und 25000 Sternen gute 40ms pro Frame vergehen.
Im Schnitt scheint die Zeitentwicklung also linear zu sein und das umsteigen auf Images hat um den Faktor 4 beschleunigt.
Zudem sind die Images auf 32*32 Pixel ausgelegt, genug für eine hübsche Bitmap, es wäre also problemlos möglich ein paar schöne Sterne zu malen und diese dann beim erstellen der Sterne zufallsgesteuert zuzuweisen. Im Endeffekt also potentiell hübschere Optik und bessere Performance für 3 Zeilen mehr Code.
Auch ein höherskalieren der Imagegröße bleibt weitestgehend zeitkostenneutral - ich habe es mit 256² Imagegröße versucht ohne dass sich an der Performance was geändert hätte. Die Ovale brauchen da dann schon wieder deutlich mehr Zeit.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

PSY

Betreff: Re: 1dq

BeitragFr, Feb 17, 2012 0:44
Antworten mit Zitat
Benutzer-Profile anzeigen
BladeRunner hat Folgendes geschrieben:
aber midimaster macht ja was ganz anderes, er erstellt bestimmt werte mit einer hoeheren wahrscheinlichkeit als andere.
omg, hier hab ich auch noch n schreibfehler drin, bestimmt statt bestimmte, habs editiert und korrigiert.


BladeRunner hat Folgendes geschrieben:

Das sollte eigentlich allen seit Xeres' Posting klar sein

ja klar, aber irgendwie hat mich der satz
Zitat:
Hat also konstante Komplexität, auch wenn man sie drei Mal anwendet.

irritiert, weil er irgendwie -wenn auch unterbewusst- suggeriert, dass es nix nutzt, die RND func 3x anzuwenden. ich dachte das koennte verwirrung ausloesen und wollte nur ein wenig eruieren. bestimmt bin ich aber wieder der einzige, der das so aufgefasst hat, sorry dann Wink kommt in letzter zeit iwie oefter vor Oo...

l8er,
PSY
PSY LABS Games
Coders don't die, they just gosub without return

Vertex

Betreff: Re: 1dq

BeitragSa, Feb 18, 2012 3:25
Antworten mit Zitat
Benutzer-Profile anzeigen
PSY hat Folgendes geschrieben:

BladeRunner hat Folgendes geschrieben:

Das sollte eigentlich allen seit Xeres' Posting klar sein

ja klar, aber irgendwie hat mich der satz
Zitat:
Hat also konstante Komplexität, auch wenn man sie drei Mal anwendet.

irritiert, weil er irgendwie -wenn auch unterbewusst- suggeriert, dass es nix nutzt, die RND func 3x anzuwenden. ich dachte das koennte verwirrung ausloesen und wollte nur ein wenig eruieren. bestimmt bin ich aber wieder der einzige, der das so aufgefasst hat, sorry dann Wink kommt in letzter zeit iwie oefter vor Oo...

Ich wollte damit sagen, dass es von der Performance unerheblich ist, ob sie dreimal oder einmal aufgerufen wird. Drei Aufrufe haben die selbe Zeitkomplexität wie ein Aufruf, nämliche konstante Komplexität.

Mich hat das weiter beschäftigt, wie man die Verteilungsfunktion berechnen könnte. Das Ergebnis:
user posted image
Das Blöde ist, ich bekomme die Umkehrfunktion der Verteilungsfunktion von Y nicht ermittelt. Damit entfällt die Inversionsmethode und damit die Berechnung der dreifach Aufgerufenen RNDs mit einem RND-Aufruf.

Ciao Olli
vertex.dreamfall.at | GitHub

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group