## How to draw all objects on screen?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
LeNitrous
Prole
Posts: 27
Joined: Tue Sep 08, 2015 3:25 am

### How to draw all objects on screen?

I'm currently making a prototype Visual Novel Engine.
What I'm looking for is to draw all objects on screen without having to call their draw function one by one. I'm using hump.class to handle my classes and this is what I got so far.

Code: Select all

function love.draw()
actor1:draw()
actor2:draw()
actor3:draw()
end

Any help is appreciated. Thanks!

Lafolie
Inner party member
Posts: 803
Joined: Tue Apr 05, 2011 2:59 pm
Location: SR388
Contact:

### Re: How to draw all objects on screen?

Pop all your actors (or drawable actors) in a table and iterate over it, calling the relevant function. You can use this technique in many places and for many things. For example, updating all your actors could use the exact same table.

Code: Select all

actors = {} --this is our list of actors
table.insert(actors, player:new("Player 1", 16, 16)) --add a "player" actor to the table named 'Player 1, at x16:y16
end

love.update = function(dt)
for n, actor in ipairs(actors) do
actor:update(dt)
end
end

love.draw = function()
for n, actor in ipairs(actors) do
actor:draw()
end
end

This is a pretty basic example, obviously you need to consider how to 'skip' objects that don't get draw but how you do that is up to you. You could keep a separate table for drawing, a boolean property, check whether a draw function exists, or even something like only storing the functions themselves in the table (although this method has some caveats). Read up on polymorphism for really cool stuff you can do with tables of objects with common functionality.
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.

LeNitrous
Prole
Posts: 27
Joined: Tue Sep 08, 2015 3:25 am

### Re: How to draw all objects on screen?

Given above works well. Can it be more efficient by calling table.insert inside the object's init function instead of calling table.insert for every actor object?
Some psuedocode as it doesn't actually work but you'll get the gist of what I mean:

Code: Select all

-- inside actor.lua
actor = class{
init = function(self, name, image)
self.name	= name
self.image	= image
end

table.insert(actors, self)
}

function actor:draw()
-- some draw code here
end


Smoggert
Prole
Posts: 29
Joined: Thu Nov 10, 2016 11:23 pm

### Re: How to draw all objects on screen?

^ in order for this to work you would have to send the table reference (actors) with each actor you create.
Running the insert manually feels less convoluted, unless you would make a "actorhandler" class and run it with that.

LeNitrous
Prole
Posts: 27
Joined: Tue Sep 08, 2015 3:25 am

### Re: How to draw all objects on screen?

I'll try to make an actor handler. For now I'll use this solution for prototyping.

Sir_Silver
Party member
Posts: 282
Joined: Mon Aug 22, 2016 2:25 pm

### Re: How to draw all objects on screen?

Can it be more efficient by calling table.insert inside the object's init function instead of calling table.insert for every actor object?
Yes, but it probably won't matter too much how efficient your actor initialization and insertion is unless your going to be creating an absurd amount of them, or if you're creating many of them while the game is being played. I really like writing code examples so here's one showing how you can optimize table insertion.

Code: Select all

local test_table_1 = {}

local start = os.clock()

for i = 1, 1000000 do
table.insert(test_table_1, i)  --Using table.insert 1,000,000 times.
end

print("Default use of table.insert time taken: ", os.clock() - start, "\n")

local test_table_2 = {}
local insert = table.insert

local start = os.clock()

for i = 1, 1000000 do
insert(test_table_2, i)  --Using our localized version of table.insert 1,000,000 times.
end

print("Localized table.insert function time taken: ", os.clock() - start, "\n")

local test_table_3 = {}

local start = os.clock()

for i = 1, 1000000 do
test_table_3[#test_table_3 + 1] = i  --Directly placing our values at the end of the table 1,000,000 times.
end

print("Direct insertion without function overhead time taken :", os.clock() - start, "\n")

--[[Default use of table.insert time taken: 	0.2400000000000002

Localized table.insert function time taken: 	0.20999999999999996

Direct insertion without function overhead time taken :	0.17999999999999972]]

This example shows that even with a million values to be inserted into a table, the difference between the normal way and the fastest way of inserting into a table yields only about 1/20th of a second gain. Pretty negligible for most application, but I think it's good practice to use this method when storing values in a table in love.update or love.draw

ivan
Party member
Posts: 1313
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: How to draw all objects on screen?

Code: Select all

local test_table_4 = {}

local start = os.clock()

local n = #test_table_4
for i = 1, 1000000 do
test_table_4[n + i] = i  --Directly placing our values at the end of the table 1,000,000 times.
end
With multiple inserts, you don't need to get the table length (#) each time.
Note that n + i could be removed too with just:

Code: Select all

local n = #test_table_4
for i = n + 1, n + 1000000 do
test_table_4[i] = i  --Directly placing our values at the end of the table 1,000,000 times.
end

Sir_Silver
Party member
Posts: 282
Joined: Mon Aug 22, 2016 2:25 pm

### Re: How to draw all objects on screen?

Wow I'm surprised I've never tried to do it that way - nice work

Just came in here to edit it and say WOW massive optimization XD

Direct insertion without function overhead time taken : 0.2300000000000002 --This is how long my method took.
Ivan's way : 0.040000000000000036 --This is how long Ivan's method took.

Uh yeah wow... I feel embarrassed for even calling my method an optimization now.

ivan
Party member
Posts: 1313
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: How to draw all objects on screen?

Yep, "table.insert" is good when you want to put something in the front or middle of the table (incrementing all following indexes).
If you just want to append values to the end of the table then "#" is probably faster.

LeNitrous
Prole
Posts: 27
Joined: Tue Sep 08, 2015 3:25 am

### Re: How to draw all objects on screen?

Thanks for the ideas but I forgot to mention that each object should have a unique name. This is what my main.lua looks like:

Code: Select all

actors = {}

-- actor(name, position, isVisible)
Chris = actor(Chris, "center", true)
Tristan = actor(Tristan, "left", false)

table.insert(actors, Chris)
table.insert(actors, Tristan)
Chris:speak("Hello there!")
Tristan:show()
Tristan:speak("Hi there!")
end

function love.draw()
for n, actor in ipairs(actors) do
actor:draw()
end
end

Unless there's a roundabout way, it would be nice.

### Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Kemo_III and 10 guests