Cleanly removing everything?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
OmarShehata
Party member
Posts: 259
Joined: Tue May 29, 2012 6:46 pm
Location: Egypt
Contact:

Cleanly removing everything?

Post by OmarShehata »

I wanted to double check if my methods to clean memory were correct.

Basically I just have a couple of arrays that hold everything in the game, from fonts to images to objects. And all I do to clean memory it set them all to nil.

But some objects have properties or possibly other objects inside of them. For example:

Code: Select all

--Creating a game object
local ob = GameObject:init(0,0,"Images/Test.png")
print(ob.x) -- outputs the x
print(ob.sprite) -- outputs the image used to draw this object
And ob is automatically added to my "RenderArray" when it is created. So when I set RenderArray to nil, I don't have to worry about any of that?

--------------------------------------------------
While we're on the topic of memory, I'm trying to make my game as lag free as possible while at the same time having huge levels.

I noticed I had some lag with about ~2000 or so tiles in my game, not all displayed at once. After some testing I discovered I could get about 50k moving tiles in a separate file at 60 fps by simply not rendering those offscreen.

Going back to my game however, with 2k tiles it seems like the entire process of rendering is negligible to performance. On my laptop the game currently works at 50 fps, and removing the rendering, it's still at 50 fps. Removing the function that loops through the rendering array brings the fps up to 55. Why would a simple loop do that? This is all the code of the loop below:

Code: Select all

for  i=1,max,1 do  
    local obj = renderArray[i]
    if (obj.b2Object ~= nil) then
      obj.b2Object.body:applyForce(0,obj.b2Object.gravityPull * gravity * 10)
      obj.x = obj.b2Object.body:getX()
      obj.y = obj.b2Object.body:getY() 
      obj.angle = obj.b2Object.body:getAngle() ;
    end

    local x,y = cam:worldCoords(obj.x,obj.y,scrW,scrH)
    
    if(math.abs(camx - x) < 10000 and math.abs(camy - y) < 10000) then 
      obj:render() 
    end
    
  end
Any general optimization tips would also be welcome!
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Cleanly removing everything?

Post by Robin »

So you asked several different things here, I'm going to answer this one:
OmarShehata wrote:And ob is automatically added to my "RenderArray" when it is created. So when I set RenderArray to nil, I don't have to worry about any of that?
You don't ever have to worry about garbage collection. OK, that's not true, but it won't hurt you to think about it like that.

Lua's garbage collection works like it should work: as long as you can access something, it's there. When you can no longer access an object in any way, Lua will clean it up automatically at an appropriate time.

I think this is all you need to know about garbage collection for now.
Help us help you: attach a .love.
Rad3k
Citizen
Posts: 69
Joined: Mon Aug 08, 2011 12:28 pm

Re: Cleanly removing everything?

Post by Rad3k »

OmarShehata wrote:Removing the function that loops through the rendering array brings the fps up to 55. Why would a simple loop do that? This is all the code of the loop below:

CODE: SELECT ALL
for  i=1,max,1 do 
    local obj = renderArray
    if (obj.b2Object ~= nil) then
      obj.b2Object.body:applyForce(0,obj.b2Object.gravityPull * gravity * 10)
      obj.x = obj.b2Object.body:getX()
      obj.y = obj.b2Object.body:getY()
      obj.angle = obj.b2Object.body:getAngle() ;
    end

    local x,y = cam:worldCoords(obj.x,obj.y,scrW,scrH)
   
    if(math.abs(camx - x) < 10000 and math.abs(camy - y) < 10000) then
      obj:render()
    end
   
  end


I presume you're using box2d, right? It seems like rendering is not the only thing you're doing in this loop - e.g. Body:applyForce - it's not a good idea to modify game objects inside love.draw, I'm not even sure what this call is supposed to do. And of course, if you iterate over a huge array on each frame, it's going to take some time. If you want to know what objects are inside your viewport, you can use World:queryBoundingBox.

In general, it's difficult to understand what your loop is really doing when it's presented out of context. You could help us helping you best by attaching a love file (possibly stripped down to what's necessary to show the problem).
User avatar
juno
Citizen
Posts: 85
Joined: Thu May 10, 2012 4:32 pm
Location: London

Re: Cleanly removing everything?

Post by juno »

OmarShehata wrote: And all I do to clean memory it set them all to nil.
If you have fixtures which have user data, be sure to first manually dereference each of them by passing nil... setUserData(nil)
see https://love2d.org/wiki/Fixture:setUserData

Then you can set the object render table to nil.
wat ya mean she's in another castle!?
User avatar
OmarShehata
Party member
Posts: 259
Joined: Tue May 29, 2012 6:46 pm
Location: Egypt
Contact:

Re: Cleanly removing everything?

Post by OmarShehata »

Rad3k wrote: I presume you're using box2d, right? It seems like rendering is not the only thing you're doing in this loop - e.g. Body:applyForce - it's not a good idea to modify game objects inside love.draw, I'm not even sure what this call is supposed to do. And of course, if you iterate over a huge array on each frame, it's going to take some time. If you want to know what objects are inside your viewport, you can use World:queryBoundingBox.

In general, it's difficult to understand what your loop is really doing when it's presented out of context. You could help us helping you best by attaching a love file (possibly stripped down to what's necessary to show the problem).

Ah, that's a good catch. I guess I should move that applyForce to my update function instead.

The reason that's there is to make my own "air resistance" system of sort. Since in a physics simulation, any two objects of different masses would fall at the same speed, I have an added "gravityPull" that gets created depending on the object's mass so heavier objects fall down faster.

And the problem is that when I stripped it down to another love file, which just had a ton of tiles moving around, it worked perfectly. So it turns out my lag is coming from random bits around. Like for example something which was bringing the fps down by 10 was that the camera class function "worldCoords" which calls love.graphics.getWidth() in every iteration of the loop. I assumed there's no use to recalculate that every iteration so I calculated that prior and passed it to the function, and that seemed to help a lot. \
juno wrote:
If you have fixtures which have user data, be sure to first manually dereference each of them by passing nil... setUserData(nil)
see https://love2d.org/wiki/Fixture:setUserData

Then you can set the object render table to nil.
Ah, these are the obscure tips I'm afraid of losing track of. Thanks for pointing that out!
User avatar
juno
Citizen
Posts: 85
Joined: Thu May 10, 2012 4:32 pm
Location: London

Re: Cleanly removing everything?

Post by juno »

OmarShehata wrote:
Rad3k wrote: The reason that's there is to make my own "air resistance" system of sort. Since in a physics simulation, any two objects of different masses would fall at the same speed, I have an added "gravityPull" that gets created depending on the object's mass so heavier objects fall down faster.
Instead of using the applyForce() function to "fool gravity" why not use setGravityScale() for each body instead. It's only required at the body initialization and you need not call applyForce() at every iteration. This is what I use for simulating a floating effect in water. Very useful :)

body:setGravityScale(0.5) - Bodies will fall half as fast
body:setGravityScale(2) - Bodies will fall twice as fast

All you have to do is calculate a value depending on bodies mass.
wat ya mean she's in another castle!?
User avatar
OmarShehata
Party member
Posts: 259
Joined: Tue May 29, 2012 6:46 pm
Location: Egypt
Contact:

Re: Cleanly removing everything?

Post by OmarShehata »

juno wrote: Instead of using the applyForce() function to "fool gravity" why not use setGravityScale() for each body instead. It's only required at the body initialization and you need not call applyForce() at every iteration. This is what I use for simulating a floating effect in water. Very useful :)

body:setGravityScale(0.5) - Bodies will fall half as fast
body:setGravityScale(2) - Bodies will fall twice as fast

All you have to do is calculate a value depending on bodies mass.
Maaan, I've been using box2d for over a year or so and I'm discovering so much stuff in it now! Much better idea.
Post Reply

Who is online

Users browsing this forum: Bobble68 and 84 guests