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.rotationSpeed=(2*math.pi)/10
Starfield.cameraRadiusTarget=400
Starfield.transitionDuration=45
Starfield.transitionTimer=0
Starfield.transitionFactor=0
Starfield.baseCameraRadius=0.01
Starfield.rotationStartTime=07.50
Starfield.hyperspaceStartTime=28.13
Starfield.hyperspaceDuration=3.5
Starfield.hyperspaceFactor=0
function Starfield.load(numStars,width,height)
Starfield.numStars=numStars or 108000
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<Starfield.rotationStartTime then
Starfield.speedMultiplier=0.0001+(Starfield.elapsedTime/Starfield.rotationStartTime)*(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/Starfield.transitionDuration
if t>1 then t=1 end
Starfield.transitionFactor=math.sin(t*(math.pi/2))
end
Starfield.cameraAngle=Starfield.cameraAngle+Starfield.rotationSpeed*dt
end
if Starfield.elapsedTime>=Starfield.hyperspaceStartTime then
local t=(Starfield.elapsedTime-Starfield.hyperspaceStartTime)/Starfield.hyperspaceDuration
if t>1 then t=1 end
Starfield.hyperspaceFactor=t
end
local currentCameraRadius=Starfield.baseCameraRadius+(Starfield.cameraRadiusTarget-Starfield.baseCameraRadius)*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 magnitude=math.sqrt(Starfield.stars.x[i]^2+Starfield.stars.y[i]^2)
Starfield.stars.dx[i]=(Starfield.stars.x[i]/magnitude)*Starfield.hyperspaceFactor*Starfield.width
Starfield.stars.dy[i]=(Starfield.stars.y[i]/magnitude)*Starfield.hyperspaceFactor*Starfield.width
end end end
local function project(x,y,z)
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
love.graphics.setPointSize(Starfield.stars.size[i])
love.graphics.setColor(brightness,brightness,brightness,brightness)
love.graphics.points(sx,sy)
end end end
love.graphics.setPointSize(1)
love.graphics.setBlendMode("alpha")
love.graphics.setColor(1,1,1,1)
end
return Starfield
