The starfield! I broke it :(

Everything else that doesn't fall into one of the other PB categories.
Nituvious
Addict
Addict
Posts: 1033
Joined: Sat Jul 11, 2009 4:57 am
Location: United States

The starfield! I broke it :(

Post by Nituvious »

I got to thinking "how do those guys make their particle engines? They look so neat!" and figured the first step would be the common starfield program. So I gave it shot. At first I was going to use a list, but failed. Then I used an array and failed with results.

It makes some pretty neat effects but it's definitely not a random particle generator. I don't know why, I guess this is because I am unable to generate a random float. How would I make a Random float, anyway?

Code: Select all

If Not InitSprite()
	End
EndIf

Declare Stars(count.l)
mainWindow = OpenWindow(#PB_Any, 0,0,500,500,"Failed Starfield", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(mainWindow), 0,0,500,500,1,0,0)

Repeat : Delay(1)
	eventID = WaitWindowEvent(1)
	ClearScreen(RGB(0,0,0))
	
	Stars(2000)
	
	FlipBuffers()

Until eventID = #PB_Event_CloseWindow

Procedure Stars(count.l)
	Structure obj
		a.f
		x.l
		layer.b
		y.l
		speed.f
	EndStructure
	Static Dim Star.obj(1)
	Static initiated.l,sprite0,sprite1,sprite2, sprite3, circumference
	ReDim Star.obj(count.l)
	
	If initiated.l = #True		
		For y = 0 To count.l-1
			If Star(y)\x <= 490 And Star(y)\x >= 10 And Star(y)\y <= 490 And Star(y)\y >= 10
				Star(y)\x = Star(y)\x + (Star(y)\speed * Cos(Star(y)\a.f))
				Star(y)\y = Star(y)\y + (Star(y)\speed * Sin(Star(y)\a.f))
			Else
				Star(y)\a = 0.01 + Random(360) / 47.123
				Star(y)\speed = 1+Random(10)
				Star(y)\x = 250
				Star(y)\y = 250
			EndIf
			If Star(y)\layer = 0 : DisplaySprite(sprite0,Star(y)\x, Star(y)\y)
			ElseIf Star(y)\layer = 1 : DisplaySprite(sprite1,Star(y)\x, Star(y)\y)
			ElseIf Star(y)\layer = 2 : DisplaySprite(sprite2,Star(y)\x, Star(y)\y)
			ElseIf Star(y)\layer = 3 : DisplaySprite(sprite3,Star(y)\x, Star(y)\y)
			EndIf
		Next y

	Else
		sprite0 = CreateSprite(#PB_Any, 2,2)
		StartDrawing(SpriteOutput(sprite0)) : Box(0,0,2,2,RGB(255,255,255)) : StopDrawing()
		sprite1 = CreateSprite(#PB_Any, 2,2)
		StartDrawing(SpriteOutput(sprite1)) : Box(0,0,2,2,RGB(200,200,200)) : StopDrawing()
		sprite2 = CreateSprite(#PB_Any, 2,2)
		StartDrawing(SpriteOutput(sprite2)) : Box(0,0,2,2,RGB(150,150,150)) : StopDrawing()
		sprite3 = CreateSprite(#PB_Any, 2,2)
		StartDrawing(SpriteOutput(sprite3)) : Box(0,0,2,2,RGB(100,100,100)) : StopDrawing()

		For z = 0 To count.l-1
			Star(z)\layer = Random(3)
			Star(z)\speed = 0.1+Random(10)
			Star(z)\a = 0.01 + Random(360) / 47.123
		Next z
		initiated.l = #True
	EndIf
EndProcedure
▓▓▓▓▓▒▒▒▒▒░░░░░
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: The starfield! I broke it :(

Post by TomS »

First of all, I would use Sin() and Cos().
So that you get a nice circle.

Second: The "stars" need to get faster towards the edge. Right now they have a linear speed.
Think of it like a racing car that drives by in front of you with 200 M/h and another car with the same speed, but several miles away.

Having never done something like this before, this are the only contributions I can make right now.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: The starfield! I broke it :(

Post by djes »

It's nice to see that, it makes me fly in the past :)

The only thing to know to achieve this effect is a simple perspective algo. The easiest comes from a formula

Code: Select all

XScreen = X / Z
YScreen = Y / Z
Actually, we can go farther (by memory) :

Code: Select all

XScreen = (X * DistFromCamera) / (DistFromCamera + PerspectiveRatio + Z) 
YScreen = (Y * DistFromCamera) / (DistFromCamera + PerspectiveRatio + Z) 
I let you do the rest by yourself :)
User avatar
Demivec
Addict
Addict
Posts: 4283
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: The starfield! I broke it :(

Post by Demivec »

Nituvious wrote:It makes some pretty neat effects but it's definitely not a random particle generator. I don't know why, I guess this is because I am unable to generate a random float. How would I make a Random float, anyway?
Random float

Code: Select all

x.f = Offset.f + Random(Range) * Scale.f    ;formula
y.f = Random(500) * 1/1000                  ;example use of formula
User avatar
Kukulkan
Addict
Addict
Posts: 1422
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: The starfield! I broke it :(

Post by Kukulkan »

This is what I did a few years ago (forum search helped me to find):

Code: Select all

; 3D-Stars (V. Schmid) 
Dim Punkte.f(2000,3)    ; Punkte mit X,Y und Z Koordinaten 
Dim BildPixel.l(2000,2) ; Berechnete Bildpunkte 
Dim d.l(3)              ; Hilfsvariable 
Dim Fluchtpunkt.f(3)    ; Fluchtpunktkoordinaten (X,Y,Z) 
; 
Global PKTAnz.l 
Global Counter.f 
; 
PKTAnz.l = 2000 
; Sterne generieren (zufällige Koordinaten) 
For x.l = 1 To PKTAnz.l 
  Punkte(x.l, 1) = Random(2000) - 1000 ; X 
  Punkte(x.l, 2) = Random(2000) - 1000 ; Y 
  Punkte(x.l, 3) = Random(2000) ; Z 
Next 
; 
If InitKeyboard() = 0 Or InitMouse() = 0 Or InitSprite() = 0 
  MessageRequester("Error", "Kann nicht initialisieren!") 
  End 
EndIf 
; 
; Initialisieren 
Fluchtpunkt(1) = 0    ; X 
Fluchtpunkt(2) = 0    ; Y 
Fluchtpunkt(3) = 2000 ; Z 
ZEbene.l = 1540 
; Welche Richtung wird gerade bewegt? 
BewegeX.b = 0 
BewegeY.b = 0 
BewegeZ.b = 1 
; 
If OpenScreen(1024, 768, 16, "Stars") 
  xOffset.l = 512 
  yOffset.l = 384 
  ExamineKeyboard()
  While KeyboardPushed(#PB_Key_Escape) = 0 
    FlipBuffers() 
    ClearScreen(RGB(0,0,0))

    ; Sterne bewegen 
    For x.l = 1 To PKTAnz.l 
      ; Z-Koordinaten der Sterne 
      If BewegeZ.b = 1 
        Punkte(x.l, 3) = Punkte(x.l, 3) + 5 
        If Punkte(x.l, 3) > 2000: Punkte(x.l, 3) = 0: EndIf 
      EndIf 
      ; Y-Koordinaten der Sterne 
      If BewegeY.b = 1 
        Punkte(x.l, 2) = Punkte(x.l, 2) + 5 
        If Punkte(x.l, 2) > 1000: Punkte(x.l, 2) = -1000: EndIf 
      EndIf 
      ; X-Koordinaten der Sterne 
      If BewegeX.b = 1 
        Punkte(x.l, 1) = Punkte(x.l, 1) - 5 
        If Punkte(x.l, 1) < -1000: Punkte(x.l, 1) = 1000: EndIf 
      EndIf 
    Next 
    
    ; Transfer der Sterne nach 2D 
    For x.l = 1 To PKTAnz.l 
      For j.l = 1 To 3 
        d(j.l) = Fluchtpunkt(j.l) - Punkte(x.l, j.l) 
      Next 
      Lambda.f = (ZEbene.l - Punkte(x.l, 3)) / d(3) 
      BildPixel(x.l, 1) = xOffset.l + Punkte(x.l, 1) + Lambda.f * d(1) ; X 
      BildPixel(x.l, 2) = yOffset.l + Punkte(x.l, 2) + Lambda.f * d(2) ; Y 
    Next 
    
    ; Zeichnen der Sterne 
    StartDrawing(ScreenOutput()) 
    
    
    Counter.f = Counter.f + 0.005; only used, if you uncomment the three lines later...
     
    If Counter.f > 3.1415 * 2: Counter.f = 0: EndIf 
    For x.l = 1 To PKTAnz.l 
      If BildPixel(x.l, 1) > 0 And BildPixel(x.l, 1) < 1023 And BildPixel(x.l, 2) > 0 And BildPixel(x.l, 2) < 767 
        Farbe.l = Punkte(x.l, 3) / 8 
        If Farbe.l > 100 
          ; Stern 
          Farbwert2.l = RGB(Farbe.l - 60,Farbe.l - 60,Farbe.l - 60) 
          Plot(BildPixel(x.l, 1), BildPixel(x.l, 2), RGB(Farbe.l, Farbe.l, Farbe.l)) 
          Plot(BildPixel(x.l, 1) - 1, BildPixel(x.l, 2), Farbwert2.l) 
          Plot(BildPixel(x.l, 1) + 1, BildPixel(x.l, 2), Farbwert2.l) 
          Plot(BildPixel(x.l, 1), BildPixel(x.l, 2) - 1, Farbwert2.l) 
          Plot(BildPixel(x.l, 1), BildPixel(x.l, 2) + 1, Farbwert2.l) 
        Else 
          ; Punkt 
          Plot(BildPixel(x.l, 1), BildPixel(x.l, 2), RGB(Farbe.l, Farbe.l, Farbe.l)) 
        EndIf 
      EndIf 
    Next 
    StopDrawing() 
    
    ; Tasten für Ein-Auschalten der Richtungen 
    
    ;--------- these control left, right up down movement
    If KeyboardPushed(#PB_Key_X) 
      BewegeX.b = BewegeX.b + 1: If BewegeX.b = 2: BewegeX.b = 0:EndIf 
      Delay(150) 
    EndIf 
    
    If KeyboardPushed(#PB_Key_Y) 
      BewegeY.b = BewegeY.b + 1: If BewegeY.b = 2: BewegeY.b = 0:EndIf 
      Delay(150) 
    EndIf 
    
    If KeyboardPushed(#PB_Key_Z) 
      BewegeZ.b = BewegeZ.b + 1: If BewegeZ.b = 2: BewegeZ.b = 0:EndIf 
      Delay(150) 
    EndIf 
    
    ; Fluchtpunkt nach Maus ausrichten 
    ;------- this controls the stars by the mouse
    Fluchtpunkt(1) = Fluchtpunkt(1) + MouseDeltaX() 
    Fluchtpunkt(2) = Fluchtpunkt(2) + MouseDeltaY() 
    
    ; Fluchtpunkt(1) = Fluchtpunkt(1) + Sin(Counter.f)*2 
    ; Fluchtpunkt(2) = Fluchtpunkt(2) + Cos(Counter.f)*2 
    ; Fluchtpunkt(3) = Fluchtpunkt(3) + Sin(Counter.f)*2 
    
    ; Tastatur abfragen 
    ExamineKeyboard() 
    ExamineMouse() 
  Wend 
  CloseScreen() 
  End 
Else 
  MessageRequester("Error", "Kann Bildschirm nicht öffnen!") 
EndIf
Runs out of the box on 4.51. Sadly, the comments are in german...

Kukulkan
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: The starfield! I broke it :(

Post by Rook Zimbabwe »

RANDOM FLOAT GENERATOR
This is my heavy handed method!

Code: Select all

Enumeration
  #Window_0
EndEnumeration
;}
;{ Gadgets
Enumeration
  #Button_0
  #String_1
EndEnumeration
;}
Define.l Event, EventWindow, EventGadget, EventType, EventMenu
;}
Procedure OpenWindow_Window_0()
  If OpenWindow(#Window_0, 450, 200, 400, 164, "Window_0", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
    ButtonGadget(#Button_0, 10, 80, 370, 60, "FLOAT ME")
    StringGadget(#String_1, 10, 15, 365, 30, "Gadget_1")
  EndIf
EndProcedure

OpenWindow_Window_0()

;{- Event loop
Repeat
  Event = WaitWindowEvent()
  Select Event
    ; ///////////////////
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
      EventType = EventType()
      If EventGadget = #Button_0
        num1 = Random(100)
        num2 = Random(10)
        num$ = Str(num1)
        numSTR$ = "0."+num$
        newvalu.f = ValF(numSTR$)
        newfloat.f = num2+newvalu.f
        output$ = StrF(newfloat.f,3)
        SetGadgetText(#String_1, output$)
      EndIf
    ; ////////////////////////
    Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = #Window_0
        CloseWindow(#Window_0)
        Break
      EndIf
  EndSelect
ForEver
Coded in PureFORM
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
kenmo
Addict
Addict
Posts: 2083
Joined: Tue Dec 23, 2003 3:54 am

Re: The starfield! I broke it :(

Post by kenmo »

Rook Zimbabwe wrote:RANDOM FLOAT GENERATOR
This is my heavy handed method!
So heavy! Why not something like

Code: Select all

output$ = StrF(Random(10000)/1000,3)
Nituvious
Addict
Addict
Posts: 1033
Joined: Sat Jul 11, 2009 4:57 am
Location: United States

Re: The starfield! I broke it :(

Post by Nituvious »

kenmo wrote:
Rook Zimbabwe wrote:RANDOM FLOAT GENERATOR
This is my heavy handed method!
So heavy! Why not something like

Code: Select all

output$ = StrF(Random(10000)/1000,3)
Hi Kenmo! I took your code and turned it into a function like the original Random.

Code: Select all

Procedure.f RandomF(max.l)
	result.f = ValF(StrF(Random(max.l*1000)/1000))
	ProcedureReturn result.f	
EndProcedure

Repeat
	r.f = Randomf(10) ; 100)
	Debug r.f
Until r.f >= 9.9 ; 99.9)
Debug "done"
▓▓▓▓▓▒▒▒▒▒░░░░░
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: The starfield! I broke it :(

Post by djes »

Believe me, you don't want a "good" random function. Why? Because no random function can assure you that two stars will not be next each other. What you want is a linear function assuring you that stars are at a sufficient distance one from the others, and a random sort to disperse them.
User avatar
kenmo
Addict
Addict
Posts: 2083
Joined: Tue Dec 23, 2003 3:54 am

Re: The starfield! I broke it :(

Post by kenmo »

@djes - That's a good point. But if you are using a large number of stars (100? 1000? more???) I think the distribution might be fine, since a few next to each other wouldn't really be noticeable (especially in motion).

@Nituvious - You could include an offset too, like Demivec posted above, or even a Min and Max, like I posted in this thread: http://www.purebasic.fr/english/viewtop ... ndom+float
Nituvious
Addict
Addict
Posts: 1033
Joined: Sat Jul 11, 2009 4:57 am
Location: United States

Re: The starfield! I broke it :(

Post by Nituvious »

kenmo wrote:@Nituvious - You could include an offset too, like Demivec posted above, or even a Min and Max, like I posted in this thread: http://www.purebasic.fr/english/viewtop ... ndom+float

Code: Select all

10+RandomF(20)
:twisted:
▓▓▓▓▓▒▒▒▒▒░░░░░
Post Reply