Create a table for turrets and have all of them perform a function at once

I am having trouble creating a table for an object and having them all perform the same function. I have two files, turretM.lua and main.lua. On turretM.lua, I have the code for firing a turret, on main.lua, I create my table of turrets, I am having trouble trying to get all of the turrets to fire at once. Right now, I am getting this error: 

Attempt to index field '?' (a nil value) File: ssk2/math2d.lua Line: 110

This is from a result of the function trying to make this work with the table. So, how could I get this to work? 

turretM.lua: 

local lifetime = 5000 local projectileCount = 3 local spread = 7 local bulletSpeed = 300 local turretM = {} local function onCollision2( self, event ) if( event.other.myType == "bullet" ) then return false end display.remove(self) return false end function turretM.fire() local vec = ssk.math2d.diff( turret, target ) --Most likely the line causing the error local angle0 = ssk.math2d.vector2Angle(vec) local angle = angle0 - spread \* (projectileCount-1)/2 for i = 1, projectileCount do local vec2 = ssk.math2d.angle2Vector( angle, true ) vec2 = ssk.math2d.normalize(vec2) vec2 = ssk.math2d.scale( vec2, bulletSpeed ) local bullet = ssk.display.newImageRect( target.group, turret.x, turret.y, "arrow.png", { size = 20, rotation = angle, collision = onCollision2, myType = "bullet", fill = \_Y\_ }, { isSensor = true, radius = 10} ) bullet:toBack() bullet:setLinearVelocity( vec2.x, vec2.y ) bullet.timer = display.remove timer.performWithDelay( lifetime, bullet ) angle = angle + spread end end return turretM

main.lua:

require "ssk2.loadSSK" \_G.ssk.init( {} ) require "physics" physics.start( ) physics.setGravity(0,0) local turretM = require "turretM" local turrets = {} local turret local currentTurret local background = display.newGroup() local content = display.newGroup() local function onCollision( self, event ) display.remove(self) return false end local function onTouch( self, event ) if( event.phase ~= "began" ) then return end local target = ssk.display.newImageRect( content, event.x, event.y, "corona256.png", { size = 40, collision = onCollision }, { radius = 20 } ) turretM.fire() end ssk.display.newRect( background, centerX, centerY, { w = fullw, h = fullh, fill = \_G\_, alpha = 0.2, touch = onTouch } ) --[[local function onDropped( self ) for k,v in pairs( turrets ) do v:setFillColor( unpack(\_P\_) ) end self:setFillColor( unpack(\_G\_) ) currentTurret = self end]] for a = 1, 2 do turret = ssk.display.newImageRect( content, (centerX - 100) + (a \* 200), bottom - 75, "rg256.png", { size = 100 } ) ssk.misc.addSmartDrag( turret, { retval = true } ) turrets[#turrets + 1] = turret end

Note: This will not work if you do not have SSK2 Lite or Pro, and I will not provide SSK2, as it is a payed module.

Why did you modify the turret module I gave you?  You broke it. 

local lifetime = 5000 local projectileCount = 3 local spread = 7 local bulletSpeed = 300 local turretM = {} local function onCollision2( self, event ) if( event.other.myType == "bullet" ) then return false end display.remove(self) return false end function turretM.fire( turret, target ) local vec = ssk.math2d.diff( turret, target ) local angle0 = ssk.math2d.vector2Angle(vec) local angle = angle0 - spread \* (projectileCount-1)/2 for i = 1, projectileCount do local vec2 = ssk.math2d.angle2Vector( angle, true ) vec2 = ssk.math2d.normalize(vec2) vec2 = ssk.math2d.scale( vec2, bulletSpeed ) local bullet = ssk.display.newImageRect( target.group, turret.x, turret.y, "arrow.png", { size = 20, rotation = angle, collision = onCollision2, myType = "bullet", fill = \_Y\_ }, { isSensor = true, radius = 10} ) bullet:toBack() bullet:setLinearVelocity( vec2.x, vec2.y ) bullet.timer = display.remove timer.performWithDelay( lifetime, bullet ) angle = angle + spread end end return turretM

My turret fire() method:

function turretM.fire( turret, target )

yours:

function turretM.fire()

See the difference?

How I called it:

turretM.fire( currentTurret, target )

How you called it:

 turretM.fire()

I did notice that, I had just changed it to see if it would make a difference, but now only one turret fires. Also, do you happen to know how I could edit the function turretM.fire to make it work with more than two values? (One turret, one target)

I just want the function set up so that it performs the same calculations it does now, but with all the members of a table.

I know I’m coming off angry here, but I’m just frustrated.

  1. I want new folks to be excited about programming and game making.

  2. I want to help them.

  3. However, I want them to slow down and learn fundamentals first and I feel like this is partly on me.

That is, I answer questions folks ask and give working solutions, videos, complete examples, but… I think this encourages them not to question and not to puzzle things out for themselves.

I guess my real question here is, What can I do to help point folks in the right direction and to encourage the right kind of learning?

Hmmm… I see what you mean, I practically asking for the answers instead of deciding to research. you are doing a great job of helping people out in the forums, so far, as well as providing with different resources. So instead, I am going to try to brainstorm ideas myself, and I hope I can refer to you if I ever need to ask if a certain idea would work. Starting with this one:

If I placed a for loop around the function turretM.fire() code, could it work? For example:

function turretM.fire(turret, target) for a = 1, ??? do -- For all members of a table local vec = ssk.math2d.diff( turret, target ) local angle0 = ssk.math2d.vector2Angle(vec) local angle = angle0 - spread \* (projectileCount-1)/2 for i = 1, projectileCount do local vec2 = ssk.math2d.angle2Vector( angle, true ) vec2 = ssk.math2d.normalize(vec2) vec2 = ssk.math2d.scale( vec2, bulletSpeed ) local bullet = ssk.display.newImageRect( target.group, turret.x, turret.y, "arrow.png", { size = 20, rotation = angle, collision = onCollision2, myType = "bullet", fill = \_Y\_ }, { isSensor = true, radius = 10} ) bullet:toBack() bullet:setLinearVelocity( vec2.x, vec2.y ) bullet.timer = display.remove timer.performWithDelay( lifetime, bullet ) angle = angle + spread end end end

@sdktester15,

Please know.  This is not about you specifically, so don’t let me bum you out.

I shouldn’t have responded while upset, but now that I have… I have.

I am just burned out recently.

I’m looking at your code once more and will try to answer once more, but then I’m taking some time off.

Please clarify for me.  Do you want the turretM.fire() method to operate on a table of objects turrets and targets?

i.e. you don’t want to call it in a loop, but you want it to loop internally?

Thank you.

Yes, I would just like all of them to fire at one target. So, would creating a table of targets mean that there would be multiple display objects. Also, yes I would like it to loop internally.

A - Are all the turrets supposed to fire at one target?

  • or -

B - do all turrets have their own targets?

All the turrets would fire at one target.

https://www.youtube.com/watch?v=jYKGodeuVGc&feature=youtu.be

The code: https://github.com/roaminggamer/RG_FreeStuff/raw/master/SSK2/forums_help/projectiles_module_multi_fire.zip

main.lua

require "ssk2.loadSSK" \_G.ssk.init( {} ) require "physics" physics.start( ) physics.setGravity(0,0) local turretM = require "turretM" local turrets = {} local background = display.newGroup() local content = display.newGroup() local function onTouch( self, event ) if( event.phase ~= "began" ) then return end local target = ssk.display.newImageRect( content, event.x, event.y, "corona256.png", { size = 40, collision = display.remove }, { radius = 20 } ) turretM.fire( turrets, target ) end ssk.display.newRect( background, centerX, centerY, { w = fullw, h = fullh, fill = \_G\_, alpha = 0.2, touch = onTouch } ) -- line of 5 turrets across the bottom of the example local ox = fullw/5 for i = 1, 5 do local turret = ssk.display.newImageRect( content, left + (i-1) \* ox + ox/2, bottom - 75, "rg256.png", { size = 100, fill = \_W\_ } ) turrets[#turrets+1] = turret end

turretM.lua

local lifetime = 5000 local projectileCount = 3 local spread = 7 local bulletSpeed = 300 local turretM = {} local function onCollision( self, event ) if( event.other.myType == "bullet" ) then return false end display.remove(self) return false end function turretM.fire( turrets, target ) for i = 1, #turrets do local turret = turrets[i] local vec = ssk.math2d.diff( turret, target ) local angle0 = ssk.math2d.vector2Angle(vec) local angle = angle0 - spread \* (projectileCount-1)/2 for j = 1, projectileCount do local vec2 = ssk.math2d.angle2Vector( angle, true ) vec2 = ssk.math2d.normalize(vec2) vec2 = ssk.math2d.scale( vec2, bulletSpeed ) local bullet = ssk.display.newImageRect( target.group, turret.x, turret.y, "arrow.png", { size = 20, rotation = angle, collision = onCollision, myType = "bullet", fill = \_Y\_ }, { isSensor = true, radius = 10} ) bullet:toBack() bullet:setLinearVelocity( vec2.x, vec2.y ) bullet.timer = display.remove timer.performWithDelay( lifetime, bullet ) angle = angle + spread end end end return turretM

Thank you very, very much!

And… the angry old man has left the building… 

http://giphy.com/gifs/old-man-uOkPb7ZyhcEpy

I apologize for all the trouble.

Please don’t.  You don’t need to.

Just keep making stuff and enjoy the experience. 

Dev On!

@Ed, I know this topic is answered (exceedingly well I might add), but while you did convey remorse, you are actually right.

Providing complex answers to questions that is great from the perspective that the question is answered, but to your point, how much is learned.

I don’t class myself as a Corona beginner, but once I see some code such as this, I realize how much I still have to learn. This is why I like  your ‘freestuff’ and full games, they are great for learning and reference.

It may be an iterative process, but I think you’re right to have the questioner work through some of it. It will allow them to learn. If they don’t, then it will lead to a 1:1 tutorial that you just can’t do for everybody. While many posters are very polite and thankful, it still means your resources are drained. 

As a bad example, even as a seasoned coder I still am having trouble with tables. I have read every tutorial (both Corona and LUA), and while I get the fundamentals, I start to get lost when using same tables in different modules and indexing them. (Scope and structure). Just one of those things. However I don’t post the question as I NEED to understand the answer.  I just write numerous examples until it’s clear :slight_smile:

So, I didn’t think you were out of line, these folks are grateful for your help. You’re right to pretty much demand that people know the basics before you dedicate a lot of time to an answer.

(This is in no way any criticism of sdktester so please don’t take it as such).

_ I guess my real question here is, What can I do to help point folks in the right direction and to encourage the right kind of learning? _

Keeping code as modular as possible makes it easier for people to follow. Comments (yes I said it), will help narrow down complex points. 

Kindly requesting people to search, or linking them helps too.  I use search extensively to answer questions, newbies should too :slight_smile:

A rather long 2c worth, but since you’re helping many people out, at no cost, I think you have the right to have some conditions.