local Starfield={}
Starfield.stars={}
Starfield.numStars=81000
Starfield.fov=0
Starfield.width=0
Starfield.height=0
Starfield.elapsedTime=0
Starfield.speedMultiplier=0.00001
Starfield.cameraActive=false
Starfield.cameraAngle=0
Starfield.transitionTimer=0
Starfield.transitionFactor=0
Starfield.hyperspaceFactor=0
Starfield.currentCameraOffsetX=0
Starfield.currentCameraOffsetY=0
function Starfield.load(a,b,c)
local numStars,width,height
if type(a)=="table" then
numStars=a.numStars or a.count or Starfield.numStars or 108000
width=a.width
height=a.height
else
numStars=a or Starfield.numStars or 108000
width=b
height=c end
if not width then width=(love.graphics.getWidth and love.graphics.getWidth()) or 1920 end
if not height then height=(love.graphics.getHeight and love.graphics.getHeight()) or 1080 end
if width<=0 then width=1920 end
if height<=0 then height=1080 end
if not numStars or numStars<1 then numStars=108000 end
Starfield.numStars=numStars
Starfield.width,Starfield.height=width,height
Starfield.fov=width/2
Starfield.stars={x={},y={},z={},speed={},brightness={},size={},dx={},dy={}}
for i=1,Starfield.numStars do
Starfield.stars.x[i]=math.random(-Starfield.width,Starfield.width)
Starfield.stars.y[i]=math.random(-Starfield.height,Starfield.height)
Starfield.stars.z[i]=math.random(1,Starfield.width)
Starfield.stars.speed[i]=math.random(20,150)
Starfield.stars.brightness[i]=math.random()
Starfield.stars.size[i]=math.random(2,5)
Starfield.stars.dx[i]=0
Starfield.stars.dy[i]=0 end
Starfield.cameraAngle=math.random()*math.pi*2 end
function Starfield.update(dt)
Starfield.elapsedTime=Starfield.elapsedTime+dt
if Starfield.elapsedTime<4.00 then
Starfield.speedMultiplier=0.0001+(Starfield.elapsedTime/4.00)*(5.0-0.0001)
else
Starfield.speedMultiplier=5.0
if not Starfield.cameraActive then
Starfield.cameraActive=true
Starfield.transitionTimer=0
Starfield.transitionFactor=0 end
if Starfield.cameraActive and Starfield.transitionFactor<1 then
Starfield.transitionTimer=Starfield.transitionTimer+dt
local t=Starfield.transitionTimer/19
if t>1 then t=1 end
Starfield.transitionFactor=math.sin(t*(math.pi/2)) end
Starfield.cameraAngle=Starfield.cameraAngle+((2*math.pi)/10)*dt end
if Starfield.elapsedTime>=17.88 then
local t=(Starfield.elapsedTime-17.88)/2.0
if t>1 then t=1 end
Starfield.hyperspaceFactor=t end
local currentCameraRadius=0.01+(400-0.01)*Starfield.transitionFactor
Starfield.currentCameraOffsetX=currentCameraRadius*math.cos(Starfield.cameraAngle)
Starfield.currentCameraOffsetY=currentCameraRadius*math.sin(Starfield.cameraAngle)
for i=1,Starfield.numStars do
Starfield.stars.z[i]=Starfield.stars.z[i]-Starfield.stars.speed[i]*Starfield.speedMultiplier*dt
if Starfield.stars.z[i]<1 then
Starfield.stars.z[i]=Starfield.width
Starfield.stars.x[i]=math.random(-Starfield.width,Starfield.width)
Starfield.stars.y[i]=math.random(-Starfield.height,Starfield.height)
Starfield.stars.speed[i]=math.random(20,150)
Starfield.stars.brightness[i]=math.random()
Starfield.stars.size[i]=math.random(2,5) end
Starfield.stars.brightness[i]=Starfield.stars.brightness[i]+(math.random()-0.5)*0.05
Starfield.stars.brightness[i]=math.min(math.max(Starfield.stars.brightness[i],0),1)
if Starfield.hyperspaceFactor>0 then
local x,y=Starfield.stars.x[i],Starfield.stars.y[i]
local magnitude=math.sqrt(x*x+y*y)
if magnitude<1e-6 then
x=0.0001
y=0
magnitude=0.0001 end
Starfield.stars.dx[i]=(x/magnitude)*Starfield.hyperspaceFactor*Starfield.width
Starfield.stars.dy[i]=(y/magnitude)*Starfield.hyperspaceFactor*Starfield.width
else
Starfield.stars.dx[i]=0
Starfield.stars.dy[i]=0 end end end
local function project(x,y,z)
if z<1e-6 then z=1e-6 end
local projection=Starfield.fov/z
local sx=x*projection+Starfield.width/2+(Starfield.currentCameraOffsetX or 0)
local sy=y*projection+Starfield.height/2+(Starfield.currentCameraOffsetY or 0)
return sx,sy end
function Starfield.draw()
love.graphics.setColor(0,0,0,0.2)
love.graphics.rectangle("fill",0,0,Starfield.width,Starfield.height)
love.graphics.setBlendMode("add")
for i=1,Starfield.numStars do
local sx,sy=project(Starfield.stars.x[i],Starfield.stars.y[i],Starfield.stars.z[i])
if sx>0 and sx<Starfield.width and sy>0 and sy<Starfield.height then
local brightness=1-(Starfield.stars.z[i]/Starfield.width)
brightness=math.min(math.max(brightness*Starfield.stars.brightness[i],0),1)
if Starfield.hyperspaceFactor>0 then
love.graphics.setColor(brightness,brightness,brightness,brightness)
love.graphics.line(sx,sy,sx+Starfield.stars.dx[i],sy+Starfield.stars.dy[i])
else
if love.graphics.setPointSize then
love.graphics.setPointSize(Starfield.stars.size[i]) end
love.graphics.setColor(brightness,brightness,brightness,brightness)
love.graphics.points(sx,sy) end end end
if love.graphics.setPointSize then
love.graphics.setPointSize(1) end
love.graphics.setBlendMode("alpha")
love.graphics.setColor(1,1,1,1) end
return Starfield
