A faster starfield

BlitzMax Forums/BlitzMax Programming/A faster starfield

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

I'd just keep a screens-worth of stars in memory and when one moves off the screen randomly place it the other side. Also I'd set up a Star type containing the X, Y, Speed and Colour variables and use an array of those. Calculate the colours during the update phase and store this with the actual stars, might be worth generating a dynamic list of stars with the same colour and drawing all stars with the same colour together.

DrawRect rather than DrawOval too.

Here's a Starfield that I've been working on for a Crazy Comets-alike game. I can happily get several thousand stars on screen with no slowdown.

Framework BRL.GLMax2D
Import BRL.Random
Import BRL.Math

SetGraphicsDriver GLMax2DDriver()
			
Type TStar
	Const SPREAD:Int = 800
	
	Field x:Float
	Field y:Float
	Field z:Float
	Field sx:Float
	Field sy:Float
	Field size:Int

	Function create:TStar()
		Local n:TStar = New TStar
		n.ResetPosition()
		z = Rand( 1, 255 )
		Return n
	EndFunction

	Method ResetPosition()
		x = Rand( -1000, 1000 )
		y = Rand( -1000, 1000 )
		z = 500
		size = Rand( 1, 3 )
	EndMethod

	Method Rotate( theta:Float )
		x = Cos( theta ) * x - Sin( theta ) * y
		y = Sin( theta ) * x + Cos( theta ) * y
	EndMethod

	Method Move( speed:Float )
 		If z < speed
			resetposition()
		Else
			z :- speed	
		EndIf
	EndMethod

	Method Translate()
  		sx = ( x * SPREAD ) / ( z ) + CentreX
  		sy = ( y * SPREAD ) / ( z ) + CentreY
  		If sx < 0 Or sx > Width Or sy < 0 Or sy > Height
			ResetPosition()
		EndIf
	EndMethod
	
	Method Draw()
		SetColor( Rand(32,255), Rand(32,255), Rand(32,255) )
		DrawRect( sx, sy, size, size )
	EndMethod
EndType

Type TStarfield
	Const NUM_OF_STARS:Int = 800
	Field stars:TStar[NUM_OF_STARS]
	Field rotating:Int = False
	Field rotateTarget:Int = 100
	Field rotateCurrent:Int = 0
	Field rotateSpeed:Int = 1
	Field changeDelay:Int = 0
	Field speed:Float = 8.0
	
	Function create:TStarfield()
		Local n:TStarfield = New TStarfield
		For Local i:Int = 0 To NUM_OF_STARS - 1
			n.stars[i] = TStar.Create()
		Next
		Return n
	EndFunction
	
	Method Update()
		If rotating = False
			If Rand(1,100) <= 10
				rotating = True
				rotateTarget = Rand( -250, 250 )
				changeDelay = Rand(0,150)
			EndIf
		Else
			If rotateTarget = rotateCurrent
				If rotateTarget <> 0
					rotateTarget = 0
				Else
					changeDelay :- 1
					If changeDelay = 0 Then rotating=False
				EndIf
			Else
				If rotateCurrent < rotateTarget
					rotateCurrent :+ rotateSpeed
				Else
					rotateCurrent :- rotateSpeed
				EndIf
			EndIf
		EndIf
		
		For Local i:TStar = EachIn stars
			i.Move( speed )
			i.Rotate( Float( rotateCurrent/100.0 ) )
			i.Translate()
		Next
	EndMethod
	
	Method Draw()
		SetAlpha( 0.8 )
		For Local i:Tstar = EachIn stars
			i.Draw()
		Next
		SetAlpha 1.0
		SetColor( 255,255,255 )
	EndMethod
EndType

Graphics 1024,768,0,60

SetBlend alphablend

Global Width:Int = GraphicsWidth()
Global Height:Int = GraphicsHeight()
Global CentreX:Int = Width/2
Global CentreY:Int = Height/2

Global starfield:Tstarfield = TStarfield.Create()

SeedRnd( MilliSecs() )

While Not KeyHit( KEY_ESCAPE )
	Cls
	starfield.Update()
	starfield.Draw()
	If KeyHit( KEY_F1 ) Then DebugStop
	Flip 1
Wend


HTH

Muttley