Help with game lag
Help with game lag
First of all a couple of things, it's my first post so i dont know if it's in the right place, and second english isn't my native language so sorry if i write bad or some sentences don't have coherence xD.
I'm making my first game with Löve (and my first game in general) , and the problem probably is that i'm doing wrong a lot of things, anyway. Today i woke up and started coding, but when i ran the game, it was soooooooooooooooooo laggy, laggy as hell. And yesterday the game ran perfect, no lag, no screeen shakes, so i dont know what the f*** i changed. The last files i wrote was enemyNormal, enemyWave and the game. I attach the .love file so you can check the game and the code.
Well, i'll be glad if someone can help me, and of course, tell me what i'm doing wrong coding and if something is right , see ya!
I'm making my first game with Löve (and my first game in general) , and the problem probably is that i'm doing wrong a lot of things, anyway. Today i woke up and started coding, but when i ran the game, it was soooooooooooooooooo laggy, laggy as hell. And yesterday the game ran perfect, no lag, no screeen shakes, so i dont know what the f*** i changed. The last files i wrote was enemyNormal, enemyWave and the game. I attach the .love file so you can check the game and the code.
Well, i'll be glad if someone can help me, and of course, tell me what i'm doing wrong coding and if something is right , see ya!
- Attachments
-
- 2042.love
- The game in question.
- (178.58 KiB) Downloaded 247 times
- SpotlightKid
- Prole
- Posts: 6
- Joined: Mon Nov 10, 2014 7:57 am
- Location: Cologne, Germany
Re: Help with game lag
I don't have any advice on your code but rather on coding practice. Maybe you already do, but if you don't, get in the habit of putting your code into a version control system (e.g. git, mercurial, subversion) right away when you start a project and commit your changes often. Especially when you finish a coding session, e.g. when you go to bed, make sure, you have a clean working space and have commited your latest changes with meaningful commit log messages. Don't leave committing your changes until the next day / coding session, because by then you might not remember all the details of what you changed and, more importantly, why.
This way, the next day, when you're wondering why your code isn't working as before, you have a way of finding out what you changed exactly and, more importantly of going back to a known working state.
Update: I had a quck look at your main.lua. One thing that caught my attention immediately is that you are not handling modules correctly.
In love.load() you do:
which assigns the return value from splash.lua to a local variable, which is only in scope within that function. But you then use
in your love.update() function. But splash here isn't the local variable you assigned with require in love.load(). It's a global variable that is assigned when require loads the splash.lua file, because in splash.lua you don't make splash local. So it works, but only accidentally and you may experience strange behaviour if you aren't aware which variables are global and which local and what your modules are doing to the global variable namespace.
I suggest reading the section on modules in the book "Programming in Lua" to get this straight.
This way, the next day, when you're wondering why your code isn't working as before, you have a way of finding out what you changed exactly and, more importantly of going back to a known working state.
Update: I had a quck look at your main.lua. One thing that caught my attention immediately is that you are not handling modules correctly.
In love.load() you do:
Code: Select all
local splash = require"splash"
Code: Select all
splash.update(dt)
I suggest reading the section on modules in the book "Programming in Lua" to get this straight.
Re: Help with game lag
Disclaimer: I haven't looked at your code I just have some general tips
tip 1: Only draw what's visible
tip 2: Do as little love.graphics.setColor() as possible
tip 3: read this: http://www.love2d.org/wiki/Optimising
tip 4: use locals and remove any unused globals
tip 1: Only draw what's visible
tip 2: Do as little love.graphics.setColor() as possible
tip 3: read this: http://www.love2d.org/wiki/Optimising
tip 4: use locals and remove any unused globals
- Positive07
- Party member
- Posts: 1014
- Joined: Sun Aug 12, 2012 4:34 pm
- Location: Argentina
Re: Help with game lag
Why?? I use it like a thousand times and NOTHING, I dont think this is a bottleneckjjmafiae wrote: tip 2: Do as little love.graphics.setColor() as possible
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Re: Help with game lag
Well, it is a bottleneck. Replace it with pre-"compiled" meshes where possible (but don't build new ones in draw!) or use shades to both lose triangles and color change calls.Positive07 wrote:Why?? I use it like a thousand times and NOTHING, I dont think this is a bottleneckjjmafiae wrote: tip 2: Do as little love.graphics.setColor() as possible
Re: Help with game lag
I agree with SpotlightKid.
Also upon quick glance I noticed that you use a lot of if-statements without the use of else or elseif.
That causes your code to check every statement, even though some of them are always false if others are true.
For example:
Edit:
Just checked, and I can call love.graphics.setColor 42000 times per second before dropping in framerate on my old laptop.
Also upon quick glance I noticed that you use a lot of if-statements without the use of else or elseif.
That causes your code to check every statement, even though some of them are always false if others are true.
For example:
Code: Select all
if gameState == 0 then -- Splash screen, mango and dat stuff
splash.update(dt)
end
if gameState == 1 then --Menu screen, simple animation, buttons and show the highscore
menu.update(dt)
end
I don't believe this is a bottleneck either...Positive07 wrote:Why?? I use it like a thousand times and NOTHING, I dont think this is a bottleneckjjmafiae wrote: tip 2: Do as little love.graphics.setColor() as possible
Edit:
Just checked, and I can call love.graphics.setColor 42000 times per second before dropping in framerate on my old laptop.
Re: Help with game lag
It's context dependent though, of course it runs rather fast like that.undef wrote:I agree with SpotlightKid.
Also upon quick glance I noticed that you use a lot of if-statements without the use of else or elseif.
That causes your code to check every statement, even though some of them are always false if others are true.
For example:Code: Select all
if gameState == 0 then -- Splash screen, mango and dat stuff splash.update(dt) end if gameState == 1 then --Menu screen, simple animation, buttons and show the highscore menu.update(dt) end
I don't believe this is a bottleneck either...Positive07 wrote:Why?? I use it like a thousand times and NOTHING, I dont think this is a bottleneckjjmafiae wrote: tip 2: Do as little love.graphics.setColor() as possible
Edit:
Just checked, and I can call love.graphics.setColor 42000 times per second before dropping in framerate on my old laptop.
Re: Help with game lag
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:
gameState is now a global variable. If you know java, this would essentially be same as static int gameState = 1;
And local variable scope:
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:
How I would fix these problems:
Then move the
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:
Changing this into:
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
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
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"
Code: Select all
{
int size = 300;
}
size += 100; // <-- error, size does not exist outside the scope. This is what local does for variable.
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
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
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
Re: Help with game lag
From what I've read there is actually little impact using globals over locals. Only in certain cases (intense physics simulations perhaps, something like that) do you start to encounter situations where globals significantly affect performance. They're mostly recommended because it helps to 'keep the scope clean' and makes your code somewhat easier to maintain. You should really read someone's source before offering advice.jjmafiae wrote: tip 4: use locals and remove any unused globals
Do you recognise when the world won't stop for you? Or when the days don't care what you've got to do? When the weight's too tough to lift up, what do you? Don't let them choose for you, that's on you.
Re: Help with game lag
Globals and easier to maintain code doesn't really sound like something I would put together in most cases, unless you are 100% sure that you know exactly what you are doing. I honestly think the worst thing about LUA is the fact that instead of crashing, it actually makes global variables by default unless especially told not to aka local.Lafolie wrote:makes your code somewhat easier to maintain.jjmafiae wrote: tip 4: use locals and remove any unused globals
The reason why I decided to go with libgdx on my project is mostly because I have a gut feeling that if the project size grows, the probability of me not being able to track bugs that comes from having accidentally created globals, and not being able to find a bug in my program. The other reason is that I feel that debugging in java is easier, but there could be good tools for lua too.
Still I honestly think that Love2D is probably the best 2d engine I have seen so far, and most productive thing I've found.
Who is online
Users browsing this forum: Semrush [Bot] and 4 guests