Hey guys! So I’ve been working on a simple fake 3D asteroid shooting game, but there are a few bugs I’ve run into. First of all is performance. Maybe I just did it wrong, but deleting objects from tables didn’t speed it up. I also tried reusing the asteroids and lasers that were no longer active, but that kinda slowed it down more. I commented out the tests for right now.
Another problem is that when it loops through the asteroid table, it draws the newer ones last, so the small asteroids are in front of the bigger ones. Is there a way to loop through the table backwards? Thanks for the help!
--# Main
-- Space Shooter
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
lasers = {}
asteroids = {}
explosions = {}
rock1 = readImage("Space Art:Asteroid Large",1400,1160)
rock2 = readImage("Space Art:Asteroid Small",1000,1000)
bang = readImage("Space Art:Red Explosion",232,232)
points = 0
space = image(WIDTH*2,HEIGHT*2)
setContext(space)
for i = 1, math.random(1000,2000) do
local colr = math.random(180,220)
fill(colr,colr+20,colr+35,math.random(255))
ellipse(math.random(WIDTH*2),math.random(HEIGHT*2),math.random(3,8))
end
setContext()
parameter.watch("1/DeltaTime")
left = {}
right = {}
left.angle = -30
right.angle = 30
left.size = 400
right.size = 400
left.y = 0
right.y = 0
cannon = readImage("Space Art:Part Gray Wing 2",260,840)
hull = readImage("Space Art:Part Gray Hull 4",WIDTH-200,300)
counter = 1
hit = {}
hit.alpha = 0
end
function draw()
background(20,20,30)
if counter%10 == 0 then
--[[
local test = false
for i,a in pairs(asteroids) do
if a.dist == 101 then
test = true
a:init()
end
end
if test == false then table.insert(asteroids,Asteroid()) end
]] -- Test for reusing asteroids
table.insert(asteroids,Asteroid())
end
counter = counter + 1
pushMatrix()
translate(WIDTH/2,HEIGHT/2)
translate(math.random(-1,1),math.random(-1,1))
rotate(ElapsedTime*5)
sprite(space,0,0)
popMatrix()
for i,l in pairs(lasers) do if l.dist ~= 0 and l ~= nil then l:draw() end end
for i,a in pairs(asteroids) do if a.dist < 100 and a ~= nil then a:draw()
elseif a.dist == 100 then a:draw();a.dist = 101 end end
for i,e in pairs(explosions) do if e.size ~= 0 then e:draw() end end
translate(0,5*math.sin(ElapsedTime))
pushMatrix()
rotate(left.angle+5)
sprite(cannon,0,left.y,70,left.size)
popMatrix()
pushMatrix()
translate(WIDTH,0)
rotate(right.angle-5)
scale(-1,1)
sprite(cannon,0,right.y,70,right.size)
popMatrix()
sprite(hull,WIDTH/2,-50)
fill(255, 255, 255, 255)
textMode(CENTER)
font("Futura-Medium")
fontSize(40)
text(points,WIDTH/2,24)
fill(255,0,0,hit.alpha)
rect(0,0,WIDTH,HEIGHT)
end
function touched(touch)
if touch.state == BEGAN and touch.x < WIDTH/2 then
left.angle = vec2(0,1):angleBetween(vec2(touch.x,touch.y))
left.angle = math.deg(left.angle)
left.size = vec2(0,0):dist(vec2(touch.x,touch.y))
left.y = -50
tween(0.1,left,{y=0})
table.insert(lasers,Laser(touch.x,touch.y,"left",left.angle))
--[[
local test = false
for i,l in pairs(lasers) do
if l.dist == 0 and l.side == "left" then
test = true
l:init(touch.x,touch.y,"left",left.angle)
end
end
if test == false then table.insert(lasers,Laser(touch.x,touch.y,"left",left.angle)) end
]] -- Test for reusing lasers
elseif touch.state == BEGAN and touch.x >= WIDTH/2 then
right.angle = vec2(0,1):angleBetween(vec2(WIDTH-touch.x,touch.y))
right.angle = math.deg(-right.angle)
right.size = vec2(WIDTH,0):dist(vec2(touch.x,touch.y))
right.y = -50
tween(0.1,right,{y=0})
table.insert(lasers,Laser(touch.x,touch.y,"right",right.angle))
--[[
local test = false
for i,l in pairs(lasers) do
if l.dist == 0 and l.side == "right" then
test = true
l:init(touch.x,touch.y,"right",right.angle)
end
end
if test == false then table.insert(lasers,Laser(touch.x,touch.y,"right",right.angle)) end
]] -- Test for reusing lasers
end
if touch.state == BEGAN then
sound(SOUND_SHOOT, 46566)
end
end
--# Laser
Laser = class()
function Laser:init(touchX,touchY,side,angle)
self.side = side
self.dist = 100
self.angle = angle
self.beam = readImage("Space Art:Red Bullet",self.dist/1.5,self.dist*3)
if self.side == "left" then
self.x = 0
self.y = 0
self.move = tween(0.7,self,{x=touchX*1.5,y=touchY*1.5,dist=0},tween.easing.quartOut,self:destroy())
elseif self.side == "right" then
self.x = WIDTH
self.y = 0
self.move = tween(0.7,self,{x=touchX*1.5-WIDTH/2,y=touchY*1.5,dist=0},tween.easing.quartOut,self:destroy())
end
end
function Laser:draw()
pushMatrix()
translate(self.x,self.y)
rotate(self.angle)
sprite(self.beam,0,0,self.dist/1.5+5,self.dist*3)
popMatrix()
for i,a in pairs(asteroids) do
if self.dist > 0 and a.dist < 100 then
local distance = vec2(self.x,self.y):dist(vec2(a.x,a.y))
if distance < a.dist * 2 and math.abs(self.dist-a.dist) < 20 then
if a.rock == rock2 then
self.points = (100-self.dist)*2
self.points = math.ceil(self.points)
else
self.points = 100-self.dist
self.points = math.ceil(self.points)
end
points = points + self.points
table.insert(explosions,Explosion(self.x,self.y,self.dist,self.points))
lasers[self] = nil
tween.stop(self.move)
self.dist = 0
asteroids[a] = nil
tween.stop(a.move)
a.dist = 100
-- a = nil
table.remove(asteroids,i)
sound(SOUND_EXPLODE, 16856)
end
end
end
end
function Laser:destroy()
lasers[self] = nil
self = nil
end
--# Asteroid
Asteroid = class()
function Asteroid:init(x,y)
self.x = math.random(200,WIDTH-200)
self.y = math.random(300,HEIGHT-200)
self.dist = 0
self.pos = vec2(WIDTH/2,HEIGHT/2)+vec2(self.x-WIDTH/2,self.y-HEIGHT/2)*5
self.move = tween(5,self,{x=self.pos.x,y=self.pos.y,dist=100},tween.easing.quintIn,self:testHit())
self.random = math.random(1,2)
if self.random == 1 then
self.rock = rock1
else
self.rock = rock2
end
self.spin = math.random(-50,50)/10
self.angle = 0
end
function Asteroid:draw()
pushMatrix()
translate(self.x,self.y)
rotate(self.angle)
sprite(self.rock,0,0,self.dist*5)
popMatrix()
self.angle = self.angle + self.spin
self:testHit()
end
function Asteroid:testHit()
if self.x > 0 and self.x < WIDTH and self.y > 0 and self.y < HEIGHT and self.dist == 100 then
hit.alpha = 255
tween(0.7,hit,{alpha=0})
sound(SOUND_EXPLODE, 16856)
end
end
--# Explosion
Explosion = class()
function Explosion:init(x,y,size,points)
self.x = x
self.y = y
self.size = size * 3
self.bang = tween(0.5,self,{size=0},tween.easing.backIn)
self.textAlpha = 255
self.fade = tween(0.5,self,{textAlpha=0},tween.easing.quadIn)
self.points = points
end
function Explosion:draw()
sprite(bang,self.x,self.y,self.size)
fill(255, 255, 255, self.textAlpha)
textMode(CENTER)
font("Futura-Medium")
fontSize(40)
text("+"..self.points,self.x,self.y+50)
end