Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Two ways to move a bunch of sprites (benchmarked) — Gideros Forum

Two ways to move a bunch of sprites (benchmarked)

eezingeezing Member
edited February 2014 in Code snippets
(Note: This does not pertain to Box2d)

After comparing methods found around the forums, I've decided to clear out the previous content (sorry for that) and simply post two ways to move sprites and how they compare.

There are two basic approaches:

Inclusive method:

--[[ Linear move function ]]--

local function move(sprite, vx, vy)

local x, y = sprite:getPosition()
local dx = (vx or 0) * (1 / 60)
local dy = (vy or 0) * (1 / 60)

local function action()

x = x + dx
y = y + dy
sprite:setPosition(x, y)
end

sprite:addEventListener(Event.ENTER_FRAME, action)
return action
end


--[[ Start move action ]]--

-- Make a sprite

local theSprite = Sprite.new()


-- Make varaible and set it's value to the move function. The move
-- function will return the reference to the listener function so
-- we can stop the action when needed.

-- Supply a sprite along with velocity x and y (pixels per second)

local theAction = move(theSprite, 100, 0)


--[[ End move action ]]--

-- Remove the event listener

theSprite:removeEventListener(Event.ENTER_FRAME, theAction)

Pretty simple approach. We call the move function that contains an enter frame listener that executes the move chunk. The move function returns the reference to the listener so we can then destroy it when desired.


Mono listener method:

--[[ The Enter Frame listener ]]--

local actions = {}

local function onEnterFrame(event)

for someAction in pairs(actions) do

someAction()
end
end

stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)


--[[ Linear move function ]]--

local function move(sprite, vx, vy)

local x, y = sprite:getPosition()
local dx = (vx or 0) * (1 / 60)
local dy = (vy or 0) * (1 / 60)

local function action()

x = x + dx
y = y + dy
sprite:setPosition(x, y)
end

actions[action] = true
return action
end


--[[ Start move action (same as before) ]]--

local theSprite = Sprite.new()
local theAction = move(theSprite, 100, 0)


--[[ End move action ]]--

-- Remove action from actions table

actions[theAction] = nil

The move part is the same, but now we have an external table to store actions, along with a listener function to execute those actions. So we call the move function like before, then the move function ads the action as a key to the actions table and returns the reference back to you. The single listener calls every key in the actions table as a function. We can then destroy the action with a nil at the key equal to the reference.


So, which is better?

First off, it may seem as though the Mono method is faster, and it is… but not as much as you think (at least not in this case).

My tests included a for loop that would create x-amount of sprites based on a one class that contained:

- bitmap with a 36x36 PNG set to a random color
- random y position (within screen bounds)
- random x velocity between 10-50 pixels per second
- y velocity set to 0
- added self to scene


Results on iPhone 5:

1. < = 1200 moving sprites on screen: 60fps for both

2. 1500: Inclusive = 57fps, Mono = 60fps

3. 2000: Inclusive = 43, Mono = 54fps

4. 2500: Inclusive = 34, Mono = 43fps

5. 5000: Inclusive = 17, Mono = 22fps

6. 10000: Inclusive = 8, Mono = 11fps

So in this case, there’s no visually noticeable difference until we hit 2000 sprites moving on screen, beyond that mono listener method pulls ahead.


To conclude, yes grouping into one listener is faster, but real world results will probably depend on the design and needs of your game.
+1 -1 (+4 / -0 )Share on Facebook

Comments

Sign In or Register to comment.