I did quickly glance the code, and what I see is that what you are trying to do is OOP approach to the programming. The bad thing is though, nothing is encapsulated and everything is flooding global variables, which you can essentially think as static members in other languages. In other words they are visible from any other file and accessible from those.
I have some suggestions of possible points where there could be some performance issues, but I am not master of LUA, so don't take everything for granted for being the best solution.
I am not the best person to answer, but here are couple of things that I noticed:
Use of globals:
Code: Select all
-- In main.lua
function love.load()
love.mouse.setVisible (false) -- disable the mouse
gameState = 1 -- 0 splash screen, 1 menu, 2 game, 3 scores
gameState is now a global variable. If you know java, this would essentially be same as static int gameState = 1;
And local variable scope:
Code: Select all
-- inside love.load()
local splash = require"splash"
local game = require"game"
local menu = require"menu"
local over = require"gameover"
-- Enemies
local enemyWave = require"enemyWave"
--local enemyBall = require"enemyBall"
local enemyNormal = require"enemyNormal"
These variables are local meaning they are only visible inside love.load, essentially compared to other languages you can think it working same way as:
Code: Select all
{
int size = 300;
}
size += 100; // <-- error, size does not exist outside the scope. This is what local does for variable.
How I would fix these problems:
Code: Select all
local splash = require"splash" -- now these splash, game etc are
local game = require"game"
local menu = require"menu"
local over = require"gameover"
local gameState = game -- now this variable is only visible inside main.lua, and not accessible from any other file.
-- Enemies
local enemyWave = require"enemyWave"
--local enemyBall = require"enemyBall"
local enemyNormal = require"enemyNormal"
function love.load()
love.mouse.setVisible (false) -- disable the mouse
...
function love.update(dt)
-- setting gameState value splash, game, menu or over essentially makes it possible to just call update through it
gameState.update(dt)
end
function setState( stateName )
if( stateName == "game" ) gameState = game
elseif( stateName == "splash" ) gameState = splash
elseif( stateName == "menu" ) gameState = menu
elseif( stateName == "gameover" ) gameState = over
end
end
Then move the
Code: Select all
enemyWave.update(dt)
--enemyBall.update(dt)
enemyNormal.update(dt)
into game.update(dt)
Now the OOP. The thing with lua is that it doesn't exactly have classes, but you can mimic this feature, and I think there are some lua-files for even greater way of providing classes than what the lua documentation suggests. I myself havent used those so probably someone else can give a better explanation on those. Here is the lua reference:
http://lua-users.org/wiki/SimpleLuaClasses
What you basically do is create an array, then splash the methods into the object with the setmetatable. Something to notice tho, obj:func(a) is not the same as obj.func(a). The one with the semicolon uses the obj as reference, and one without it is kind of like just normal static function. As a matter of fact obj:func(a) is essentially same as obj.func(a, obj).
Then some other speed up suggestions:
Throughout the code there are lots of loops that iterate objects through. It would be better to try to reduce the amount of iterations and do as much as possible inside one loop. Also ipairs in general is something that isn't as recommended as simply indexing table,
So for example:
Code: Select all
-- enemyNormal.lua : update
for i, enemy in ipairs(normalEnemies) do --movement of the ships
enemy.x = enemy.x - (normalEnemy.speed * dt)
end
for i, enemy in ipairs(normalEnemies) do
if enemy.x <= -80 then
table.remove(normalEnemies, i) -- delete enemies when left screen
end
if enemy.health < 1 then
table.remove(normalEnemies, i)-- delete enemies when hp is 0
end
end
for i, bull in ipairs(bullets) do -- collisions with bullets and normal enemies
for j, enemy in ipairs(normalEnemies) do
Changing this into:
Code: Select all
-- enemyNormal.lua : update
local enemy
local enemies = normalEnemie -- localising normalEnemy, to make it faster to look up
for i = 1, #enemies do -- now using local enemies. #enemies = enemies.size() in java for example.
enemy = enemies[ i ]
enemy.x = enemy.x - (normalEnemy.speed * dt)
if enemy.x <= -80 or enemy.health < 1 then -- combining the check...
-- some magic so that we dont need to call table.remove
-- Although instead of throwing things into bit universe, it would be better to recycle this
-- such as recycledEnemies[ #recycledEnemies + 1 ] = enemies[ i ], then pull the new enemy data
-- from recycledEnemies when needing new ones.
enemies[ i ] = enemies[ #enemies ]
enemies[ #enemies ] = nil
else -- check collisions
local bullets = bullets -- localising
local bull
for j = 1, #bullets do
bull = bullets[j]
if overlap(bull.x, bull.y, bull.width, bull.height, enemy.x, enemy.y, enemy.width, enemy.height) then
enemy.health = enemy.health - 1
-- some magic so that we dont need to call table.remove
bullets[ i ] = bullets[ #bullets ]
bullets[ #bullets ] = nil
j = j - 1 -- since we remove one, we should move backwards one
explosionSound:play() -- hit sound
score = score + 10 --add score
end
end
end
end
Then last but not least, I would suggest checking out spritebatches for drawing stuffs. Since you are making tile-based game, spritebatches can give ernomous boost in drawing stuffs on the screen.
https://love2d.org/wiki/Tutorial:Effici ... _Scrolling