How should I be using collectionfactories?

Hi!

So, I want to make guards that have attached lights. I also want the light to have different collision properties than the guard. My solution involves making a collection with the guards having subordinate lights.

Now I want to continually spawn these “lightguards” as entities in the game, but am having trouble implementing the factories. I’m using them as I use normal factories, and the following code (please point out anything stupid, even unrelated):

local frequency = 0.5
local min_y = -40
local max_y = 680
local min_x = -60
local max_x = 1020
local temp = 0

function init(self)
self.timer = 1/frequency
local props = {}
– make the game deterministic
math.randomseed(0)
end

function update(self, dt)
self.timer = self.timer - dt
if self.timer <= 0 then
self.timer = 1/frequency
local p = go.get_position()
temp = math.random(4)
if temp == 1 then
p.y = -20
p.x = vmath.lerp(math.random(), min_x, max_x)
elseif temp == 2 then
p.y = 660
p.x = vmath.lerp(math.random(), min_x, max_x)
elseif temp == 3 then
p.x = -20
p.y = vmath.lerp(math.random(), min_y, max_y)
elseif temp == 4 then
p.x = 1020
p.y = vmath.lerp(math.random(), min_y, max_y)
end
local rot = vmath.quat_rotation_z(math.pi / temp)
local self.enemy_id = collectionfactory.create(“#lightguard_spawn”, p, rot, nil, 1)
end
end

The error I get is for

local self.enemy_id = collectionfactory.create(“#lightguard_spawn”, p, rot, nil, 1)

saying

unexpected symbol near ‘.’

I’m sure I’m just doing something obviously stupid, but I don’t get the engine well enough yet to say what.

Thanks in advance!

is just a syntax error, and should be:

self.enemy_id = collectionfactory.create("#lightguard_spawn", p, rot, nil, 1)

That is, just remove the local keyword in this case (more info: Programming in Lua : 4.2) :slight_smile:

Also, a quick note on collectionfactory.create. you will get a table mapping the id:s from the collection to the new instance id:s as return value. Good to know if you want to, for example, delete all the objects from the spawned collection later on.

Looking forward to seeing your game, happy jamming!

1 Like

I really appreciate the help

Now I’m getting the error:

ERROR:SCRIPT: guard/guard_spawn.script:37: expected table at argument #4 to collectionfactory.create
stack traceback:
[C]: in function ‘create’
guard/guard_spawn.script:37: in function <guard/guard_spawn.script:17>

I tried putting an actual table in place by making props actually used

local props = {}
  props[hash("#guard")] = { }
  props[hash("#flashlight")] = { }

[…]

 self.enemy_id = collectionfactory.create("#lightguard_spawn", p, rot, props, 1)

I’d love to fiddle with this on my own, but, alas, we are quickly running short on time

Try replacing the ‘#’ with ‘/’:
props[hash("/guard")] = {}

1 Like

This still gives me the same error :confused:

Does anything happen to props between you declared it and the call to collectionfactory.create? Try printing it right before collectionfactory.create to make sure it’s still a table.

1 Like

Regarding using slash / or pound #, there is more info on how game objects and components are assigned addresses (URLs) here: http://www.defold.com/doc/message-passing

1 Like

It was considered to be a nil value in the update(), so I defined the table in there instead of init() .

Seems more ineffecient, but the spawning works, at least. Thanks for the help!

Ah I see. That’s what you use the ‘self’ for. That is supposed to carry the ‘state’ of your script, and you use it just like a table. Local variables only live inside the scope they are declared in, in this case your init-function. I agree that your fix works fine (creating the table at the point of spawning), but for documentation-purposes this would work:

self.props = {...}

In update:

collectionfactory.create(..., self.props, ...)

Appropriate that you mention delting, since that’s exactly what I wanted it for :smile:

unfortunately, problems arise :confused:

I’m putting this code in the script for the collection:

function on_message(self, message_id, message, sender)
if message_id == hash(“collision_response”) then
go.delete_all(self.enemy_ids)
end
end

but whenever collisions happen, it just tells me

WARNING:GAMEOBJECT: go.delete_all() needs a table as its first argument

Which it seems to me that I’ve provided

print(self.enemy_ids)

is the only way to really know! :slight_smile: You might have forgotten to assign it to that variable before. There is also a debugger called zerobrane that lets you inspect the code, but printing is usually the fastest way.

2 Likes

More on this here: http://www.defold.com/doc/debugging

1 Like

Well, the print tells me that the table is a nil value before I try to destroy it, and not when I spawn it. I still don’t know why

In the spawn script:

    self.enemy_id = collectionfactory.create("#lightguard_spawn", p, rot, props, 1)

In the guard script:

    go.delete_all(self.enemy_id)

Is the problem related to the guard object not knowing about the spawner’s table? Is there another way for guards to destroy their flashlight, themselves and nothing else?

Ah I see, yes, the self value is bound to the specific script in question. They could directly adress the game objects they want to delete. In the guard script:
go.delete() – implicitly deletes “this” game object
go.delete(“light”) – assuming the light sprite is attached to a game object called “light” in the spawned collection

1 Like

All right, project done!

Thank you so much for the help, everyone :wink:

I would have given up for Game Maker by Saturday morning without you!

2 Likes

Awesome! You’re more than welcome to share screens or captures of your game.

Well, here’s a basic screenshot:

It ended up as more of a proof of concept than a full game, but we are happy with the results :slight_smile:

2 Likes

Nicely done! Not bad for a two day game jam with a new engine.

Great. Looks cool. Good work!