Fire propagation script errors

I’m trying to develop a method for spreading fire along a ground plane, like so:

  • A “fireball” is launched
  • When it hits the ground, it spawns a piece of “firewood”
  • After a pause, the firewood spreads in a grid fashion, to adjacent squares
  • These new pieces of firewood will again spread in similar fashion

However, the python script for my blocks of firewood creates errors after spawning the second generation of firewood.

I wrote a finite state machine within a class called Firewood, with this basic structure:

class Firewood(types.KX_GameObject):

	def __init__(self, own):
		self.main = self.state_idle
		
	def state_idle(self):
		foo

...

def main(cont):
	own = cont.owner

	if not "init" in own:
		own["init"] = True
		own = Firewood(own)

	own.main()

However, the second generation of firewood spawns and gives this attribute error:

Python script error - object 'firewood', controller 'Python':
Traceback (most recent call last):
  File "C:\...\fire_propogation\firewood.py", line 94, in main
    own.main()
AttributeError: 'KX_GameObject' object has no attribute 'main'

Does the game engine not play nicely when objects use the same code? Am I making a logic error in how I control the firewood’s state changes?

Attachments

fire_prop.zip (90.8 KB)

Don’t use the instantAddObject actuator method (actually, you can get rid of the actuator completely) - It seems to do some really bizarre property copy tricks, so when you create a new instance, it already carries the “init” property, meaning that the Firewood re-instance doesn’t happen, and that’s why main doesn’t exist.

It might be a bug, but I’m not sure.

Use scene.addObject instead:


# Add a firewood
scene = logic.getCurrentScene()
fire_obj = scene.addObject("firewood", self)

That should work properly.

*Edit

Try to avoid posting .zip files in the future. Make your scripts internal, and just post the .blend.

Make it as easy as possible for us.

Thanks for the help and advice! Problem solved.

I suggest to improve your Python code:


class Firewood(types.KX_GameObject):

	def __init__(self, own):
		self.main = self.state_idle
		
	def state_idle(self):
		foo
...
def init(cont):
  Firewood(own)

def performSomething(cont):
  ...
def performSomethingElse(cont):
  ...

Simply trigger the init-EntryPoint first.
This is much better than fiddling around with needless init-properties.