problem with a table and function

hi,

i have a problem with my enemy. When i use one enemy, (not a table) i have no problem with this code below. But when i use a table with my enemy the function enemy[i].attack move my character hyper faster and after a delay my enemy dissappears.

Could you tell me why ? Thanks

--parameters.lua local M={} M.W=display.contentWidth M.W2=display.contentWidth\*.5 M.H=display.contentHeight M.H2=display.contentHeight\*.5 M.number={} M.number.enemy=1 M.cnt={} M.position={} M.current={} M.multiplier=10000000000000000000 return M

-------------------------------------------------------------------------------- -- main.lua -------------------------------------------------------------------------------- local physics = require("physics") local P =require("parameters") local grid=require("grid") physics.start() physics.setScale(5) physics.setGravity(0,0) -------------------------------------------------------------------------------- --group -------------------------------------------------------------------------------- local backgroundGroup=display.newGroup() local enemyGroup=display.newGroup() local playerGroup=display.newGroup() local hudGroup=display.newGroup() -------------------------------------------------------------------------------- --variables -------------------------------------------------------------------------------- local borders={} local background local grid={} local bonus local weapon local obstacle={}--obstacles durs et picots local player local enemy={} local hud={}-- local viseur -------------------------------------------------------------------------------- -- draw Elements -------------------------------------------------------------------------------- local function drawPLayer()     player=display.newCircle(playerGroup,P.W2,P.H2,10)     player:setFillColor(1,0,0)     player.name="player"     player.alpha=1     player.isVisible=true     player.isHit=false     player.isMoving=false     player.float=function()         if player.isMoving==false then             choix={-19,19}             player:applyLinearImpulse(choix[math.round(math.random(1,2))],choix[math.round(math.random(1,2))])         end         end     timer.performWithDelay(1000,player.float,-1)     physics.addBody(player,{density=10,friction=0,bounce=0}) end local function drawEnemy()         enemyGroup.body=display.newCircle(enemyGroup,P.W2+30,P.H2,5)         enemyGroup.body:setFillColor(0,0,0)              for i=1,P.number.enemy do         enemy[i]=enemyGroup         physics.addBody(enemy[i],{density=1,friction=0,bounce=.50})         enemy[i].name="enemy"         enemy[i].alpha=1         enemy[i].isHit=false         enemy[i].isDead=false         enemy[i].isVisible=true         enemy[i].isMoving=false         enemy[i].attack=function()             if enemy[i].isDead == false then             local attack={}             attack.direct=function()                 enemy[i]:setLinearVelocity((player.x-enemy[i].x)\*P.multiplier,(player.y-enemy[i].y)\*P.multiplier)             end             attack.zigzag=function()                 enemy[i]:applyLinearImpulse((player.x-enemy[i].x),(player.y-enemy[i].y))                 timer.performWithDelay(100,function()                     enemy[i]:applyLinearImpulse((player.x-enemy[i].x),(player.y-enemy[i].y))                 end)                 timer.performWithDelay(200,function()                     enemy[i]:applyLinearImpulse((player.x-enemy[i].x),(player.y-enemy[i].y))                 end)             end             attack.feinte=function()                 enemy[i]:applyLinearImpulse((player.x-enemy[i].x+200)\*P.multiplier\*.5,(player.y-enemy[i].y-200)\*P.multiplier\*.5)                 timer.performWithDelay(500,function()                     enemy[i]:applyLinearImpulse((player.x-enemy[i].x)\*P.multiplier,(player.y-enemy[i].y)\*P.multiplier)                 end)             end             attack.repos=function()             end             attack.crazy=function()                 enemy[i]:applyLinearImpulse(math.random(100,P.W-100),math.random(100,P.H-100))             end             choix=math.round(math.random(1,5))             if choix==1 then                 print("direct")                 attack.direct()             elseif                 choix==2 then                 print("zigzag")                 attack.zigzag()             elseif                 choix==3 then                 print("feinte")                 attack.feinte()             elseif                 choix==4 then                 print("repos")                 attack.repos()             elseif                 choix==5 then                 print("crazy")                 attack.crazy()             end         end         end         timer.performWithDelay(3000,enemy[i].attack,-1)     timer.performWithDelay(500,function() enemy[i].isMoving=true end,-1)     timer.performWithDelay(1500,function() enemy[i].isMoving=false end, -1)         u=0             enemy[i].damping=function()                 u=u+.19                 print(u)                 if enemy[i].isMoving then                     enemy[i].linearDamping=u                 else                     enemy[i].linearDamping=0                     u=0                 end               end             timer.performWithDelay(100,enemy[i].damping,-1)     end end

drawPlayer() drawEnemy()

 

It’s very hard to read to code so I will throw out a guess and say that the variables are not unique to the enemy. Having said that try and clean up your code a little bit and use Modular Classes on the enemies:

https://coronalabs.com/blog/2011/09/29/tutorial-modular-classes-in-corona/

Try it out and if you still have problem after cleaning up the code and using Modular Classes I will gladly check out what the problem might be.

Some code to get you started:

enemy.lua

local enemy = {} local enemy\_mt = { \_\_index = enemy } -- metatable ------------------------------------------------- -- PUBLIC FUNCTIONS ------------------------------------------------- function enemy.new( params ) -- constructor local newEnemy = {} newEnemy.name = "enemy" newEnemy.isDead = false return setmetatable( newEnemy, enemy\_mt ) end ------------------------------------------------- function enemy:attack() print( self.name .. " attacked." ) end return dog

main.lua

local enemy = require( "enemy" ) local enemies = {} for i = 1, 10, 1 do local e = enemy.new() table.insert( enemies, e ) end

Best regards,

Tomas

Hi Tomas,

Very interresting your documentation. thanks a lot i don’t know this.

But i can’t have a physics body, it’s below …could you look a this if you have time.

Have a nice day.

--enemy.lua local enemy={} local enemy\_mt = { \_\_index = enemy } --set metatable -------------------------------------------------------------------------------- -- public function -------------------------------------------------------------------------------- function enemy.draw( group,posx,posy,radius ) local e={} --e for enemy e.body=display.newCircle(group,posx,posy,radius) e.body:setFillColor(0,0,0) --black e.name="enemy" e.isHit=false e.isDead=false e.isVisible=true e.isMoving=false return setmetatable ( e,enemy\_mt ) end function enemy:attack()     if self.isDead == false then print("enemy attack")     end end return enemy

--main.lua -------------------------------------------------------------------------------- -- require -------------------------------------------------------------------------------- local physics = require("physics") local enemy= require("enemy") physics.start() physics.setScale(5) physics.setGravity(0,0) -------------------------------------------------------------------------------- --group -------------------------------------------------------------------------------- local enemyGroup=display.newGroup() -------------------------------------------------------------------------------- --variables -------------------------------------------------------------------------------- local enemies = {} for i=1,10,1 do     local e = enemy.draw(enemyGroup,100,100,50)     table.insert (enemies, e) end for i=1,10,1 do enemies[i]:attack() --physics.addBody(enemies[i],{density=1,friction=0,bounce=.50})--this don't work , why ? end

solved :wink:

i have one question…how do you do remove properly for example the enemies[2] from the main.lua ?

--enemy.lua local enemy={} local enemy\_mt = { \_\_index = enemy } --set metatable -------------------------------------------------------------------------------- -- public function -------------------------------------------------------------------------------- function enemy.draw( group,posx,posy,radius ) local e={} --e for enemy e.body=display.newCircle(group,posx,posy,radius) e.body:setFillColor(0,0,0) --black e.name="enemy" e.isHit=false e.isDead=false e.isVisible=true physics.addBody(e.body,{density=1,friction=0,bounce=.50}) return setmetatable ( e,enemy\_mt ) end function enemy:attack()     if self.isDead == false then print("enemy attack")     end end return enemy -------------------------------------------------------------------------------- --main.lua -------------------------------------------------------------------------------- -- require -------------------------------------------------------------------------------- local physics = require("physics") local enemy= require("enemy") physics.start() physics.setScale(5) physics.setGravity(0,0) -------------------------------------------------------------------------------- --group -------------------------------------------------------------------------------- local enemyGroup=display.newGroup() -------------------------------------------------------------------------------- --variables -------------------------------------------------------------------------------- local enemies = {} for i=1,10,1 do     local e = enemy.draw(enemyGroup,100,100,50)     table.insert (enemies, e) end for i=1,10,1 do enemies[i]:attack() end

I would probably create a method called “enemy:remove()” and do something like this:

-- enemy.lua function enemy:remove() physics.removeBody( self.body ) self.body:removeSelf() self = nil end -- main.lua table.remove( enemies, enemies[2] ) enemies[2]:remove() enemies[2] = nil

Best regards,

Tomas

Hi Tomas,

Thanks for your response :slight_smile:

Sorry… but i have this error when i attempt to remove the enemies[2] :

bad argument #2 to 'remove' (number expected, got table)

It should be the position that you remove so table.remove( enemies, 2 ). This will bring down all the posts above that (i.e. enemies[3] becomes enemies[2], enemies[4] becomes enemies[3] and so on). 

Best regards,

Tomas

so we cannot remove an item from a metatable ?

Skip the enemies table and use create a new displayGroup called enemiesDisplayGroup where you add all the enemies.

Now when the enemy gets hit and needs to die (i.e. be removed) call the remove function. If all enemies needs to be removed (when game over or whatever) just remove the enemiesDisplayGroup.

The enemies table is not necessary in this case as I see it.

Best regards,

Tomas

just a last question is it better in a game to :

remove a item ?

or simply adjust the alpha channel or put isVisible to false and then reuse this item when needed ?

Probably it’s better to hide the item instead of removing and recreating it each time but require more code to make it work well.

Best regards,

Tomas

hi Tomas,

I wanted to thank you for everything you taught me. :slight_smile:

It’s now really easy to split my code …

Have a nice day ;

It’s very hard to read to code so I will throw out a guess and say that the variables are not unique to the enemy. Having said that try and clean up your code a little bit and use Modular Classes on the enemies:

https://coronalabs.com/blog/2011/09/29/tutorial-modular-classes-in-corona/

Try it out and if you still have problem after cleaning up the code and using Modular Classes I will gladly check out what the problem might be.

Some code to get you started:

enemy.lua

local enemy = {} local enemy\_mt = { \_\_index = enemy } -- metatable ------------------------------------------------- -- PUBLIC FUNCTIONS ------------------------------------------------- function enemy.new( params ) -- constructor local newEnemy = {} newEnemy.name = "enemy" newEnemy.isDead = false return setmetatable( newEnemy, enemy\_mt ) end ------------------------------------------------- function enemy:attack() print( self.name .. " attacked." ) end return dog

main.lua

local enemy = require( "enemy" ) local enemies = {} for i = 1, 10, 1 do local e = enemy.new() table.insert( enemies, e ) end

Best regards,

Tomas

Hi Tomas,

Very interresting your documentation. thanks a lot i don’t know this.

But i can’t have a physics body, it’s below …could you look a this if you have time.

Have a nice day.

--enemy.lua local enemy={} local enemy\_mt = { \_\_index = enemy } --set metatable -------------------------------------------------------------------------------- -- public function -------------------------------------------------------------------------------- function enemy.draw( group,posx,posy,radius ) local e={} --e for enemy e.body=display.newCircle(group,posx,posy,radius) e.body:setFillColor(0,0,0) --black e.name="enemy" e.isHit=false e.isDead=false e.isVisible=true e.isMoving=false return setmetatable ( e,enemy\_mt ) end function enemy:attack()     if self.isDead == false then print("enemy attack")     end end return enemy

--main.lua -------------------------------------------------------------------------------- -- require -------------------------------------------------------------------------------- local physics = require("physics") local enemy= require("enemy") physics.start() physics.setScale(5) physics.setGravity(0,0) -------------------------------------------------------------------------------- --group -------------------------------------------------------------------------------- local enemyGroup=display.newGroup() -------------------------------------------------------------------------------- --variables -------------------------------------------------------------------------------- local enemies = {} for i=1,10,1 do     local e = enemy.draw(enemyGroup,100,100,50)     table.insert (enemies, e) end for i=1,10,1 do enemies[i]:attack() --physics.addBody(enemies[i],{density=1,friction=0,bounce=.50})--this don't work , why ? end

solved :wink:

i have one question…how do you do remove properly for example the enemies[2] from the main.lua ?

--enemy.lua local enemy={} local enemy\_mt = { \_\_index = enemy } --set metatable -------------------------------------------------------------------------------- -- public function -------------------------------------------------------------------------------- function enemy.draw( group,posx,posy,radius ) local e={} --e for enemy e.body=display.newCircle(group,posx,posy,radius) e.body:setFillColor(0,0,0) --black e.name="enemy" e.isHit=false e.isDead=false e.isVisible=true physics.addBody(e.body,{density=1,friction=0,bounce=.50}) return setmetatable ( e,enemy\_mt ) end function enemy:attack()     if self.isDead == false then print("enemy attack")     end end return enemy -------------------------------------------------------------------------------- --main.lua -------------------------------------------------------------------------------- -- require -------------------------------------------------------------------------------- local physics = require("physics") local enemy= require("enemy") physics.start() physics.setScale(5) physics.setGravity(0,0) -------------------------------------------------------------------------------- --group -------------------------------------------------------------------------------- local enemyGroup=display.newGroup() -------------------------------------------------------------------------------- --variables -------------------------------------------------------------------------------- local enemies = {} for i=1,10,1 do     local e = enemy.draw(enemyGroup,100,100,50)     table.insert (enemies, e) end for i=1,10,1 do enemies[i]:attack() end

I would probably create a method called “enemy:remove()” and do something like this:

-- enemy.lua function enemy:remove() physics.removeBody( self.body ) self.body:removeSelf() self = nil end -- main.lua table.remove( enemies, enemies[2] ) enemies[2]:remove() enemies[2] = nil

Best regards,

Tomas

Hi Tomas,

Thanks for your response :slight_smile:

Sorry… but i have this error when i attempt to remove the enemies[2] :

bad argument #2 to 'remove' (number expected, got table)

It should be the position that you remove so table.remove( enemies, 2 ). This will bring down all the posts above that (i.e. enemies[3] becomes enemies[2], enemies[4] becomes enemies[3] and so on). 

Best regards,

Tomas

so we cannot remove an item from a metatable ?

Skip the enemies table and use create a new displayGroup called enemiesDisplayGroup where you add all the enemies.

Now when the enemy gets hit and needs to die (i.e. be removed) call the remove function. If all enemies needs to be removed (when game over or whatever) just remove the enemiesDisplayGroup.

The enemies table is not necessary in this case as I see it.

Best regards,

Tomas