Log In  

I have enemies in my game that have behaviours - 1 behaviour function per enemy. Instead of defining the behaviour within the enemy class definition (waste of memory as the function will be created for each enemy of the same type) I want to define each behaviour once (outside the enemy class) and have each enemy instance hold a reference to its single behaviour. The enemy object needs to be able to send a reference of itself to the single behaviour function. I tried this:

function setup()
 enemy_group1={}
 for i=1,max_group_enemies do
  enemy={
   e.alive=false,
   behav=en_visit(self)
  }
  add(enemy_group1,enemy)
 end
 add(enemies,enemy_group1)
end

function en_visit(e)
 e.x+=1
end

function spawn(x,y,etype,edir,vel)
 for _,e in pairs(enemies[etype]) do
  if not e.alive then
   e.alive=true
   return
  end
 end
end

function update()
 for _,egroup in pairs(enemies) do
  for _,e in pairs(egroup) do
   if e.alive then
    e:behav()
   end
  end
 end
end

The en_visit function is correctly being called, but it isn't receiving a value for its parameter (e). The error reported is: attempt to index local 'e' (a nil value). Can anyone spot where I'm going wrong?

P#77862 2020-06-09 22:42 ( Edited 2020-06-11 04:51)

1

You need to pass the function object, not call the function:

   behav=en_visit,
P#77870 2020-06-10 02:12

Thanks, that's fixed that particular problem.

P#77871 2020-06-10 02:28

https://www.lua.org/pil/16.html

Short answer: "self" doesn't have any particular meaning except as a variable name (which is currently nil), unless you're naming functions like "function enemy:behav(...)" (which get an implied "self" variable passed, as if you wrote "function behav(enemy,...)" instead). You also can't put {a=self} or enemy={a=enemy} inside a table declaration and expect Lua to know you're referring to a table that hasn't been created yet, because both "self" and "enemy" would just be nil variables here.

In Pico-8, I'd probably recommend not using these self functions, since it's messy and can cost tokens. Instead, just do this:

local enemy={alive=false, --e doesn't exist! the false value is now at enemy.alive / enemy["alive"]
 behav=en_visit}    --assigns a function normally, even if it needs enemy as a parameter
enemy.gun = new_gun(enemy) --tables can be updated dynamically, for anything that *needs* self
enemy:behav()       --the function is defined the same, but its 1st argument when called is enemy
P#77912 2020-06-10 21:34 ( Edited 2020-06-10 21:40)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-04-18 18:45:29 | 0.007s | Q:16