List of states

why not have

own.state[1]=0

own.state[5]=1

right now it’s just silly, the whole masking thing.
a list of

[True,False,True…etc]

would be easier no?
?

that way you could do,


active=[]
x=0
for items in states:
    if items=1:
        active=active+[x]
    x=x+1
z=0
for items in active:

    OutString="State "+(str(active[z]))+" is active"
    print(OutString)
    z=z+1




What is your question? What are you trying to do with this code? What do you need these states for? Why a boolean? It’s just not clear enough for me in order to help you.

You can, using bitwise operations. You can even create a bit field class to manage this (as I have done) or just use setter and getter functions

Sent from my Nexus 5 using Tapatalk

I just want to be able so do

own.state[0]=False

own.state[1]=True

etc.

the bit mask thing seems WAY over complicated

You can write a wrapper that translates from bitmap form to list/dictionary form.

You can even translate the numbers to strings. This will increase readability a lot.


class StateList(list):
    def __init__(self, obj):
        self.obj = obj
        super().__init__([obj.state >> i & 1 for i in range(30)])
        
    def __getitem__(self, i):
        self.__init__(self.obj)
        return super().__getitem__(i)
        
    def __setitem__(self, i, val):
        self.__init__(self.obj)
        super().__setitem__(i, val)
        self.obj.state = sum([2 ** i * v for i, v in enumerate(self)])

Bitwise operations are fast, simple means of setting multiple flags at the same time. You can avoid writing multiple assignment statements. The BGE expects a certain caliber / capability of programmer who uses it, and it is not too much to learn a fundamental aspect of computer programming.

@Goran
Are there 30 states? (IIRC there are only 20 :S)

The BGE build-in state machine supports up-to 30 States.

When using single-state activation the bit-mask seams a bit overhead, but does not disturb at all.

Finally the numbering of states does not matter that much as you need to translate them to the semantic meaning to avoid feeling like an accountant. So it does not matter if the “inital” state’s index is 1 or 2048 as long as it is unique.

I need state 0 to always be on

I was going to use

state 0-
message subject state--------------python set state[message.bodies[0]] to on and all else but 0 off.

Yo BPR!

Why don’t you use state actuator?

Simple, Easy and Fast!

I kinda wanted to be able to have 1 sensor---------python--------state actuator

Check this if it can do you any good http://www.tutorialsforblender3d.com/LogicBricks/Actuators/State/State_Actuator_Add_State.html

Then use 2**index (or the equivalent shift operation )

http://www.zoo-logique.org/3D.Blender/scripts_python/BPY/bge.logic.html#state-actuator-operation

is better, I can use add bit,

@ BPR: Sorry. I totally missed that you were talking about the built-in states.
@ Goran: Thanks, this is very helpful. I got it working like this:

from bge import logic

class StateList(list):
    def __init__(self, obj):
        self.obj = obj
        super().__init__([obj.state >> i & 1 for i in range(30)])
        
    def __getitem__(self, i):
        self.__init__(self.obj)
        return super().__getitem__(i)
        
    def __setitem__(self, i, val):
        self.__init__(self.obj)
        super().__setitem__(i, val)
        self.obj.state = sum([2 ** i * v for i, v in enumerate(self)])

statelist = StateList(logic.getCurrentController().owner)

def main():
    statelist[3] = True #enables state 4

Edit: To use it with a mutated object:

from bge import logic
from bge.types import KX_GameObject

class StateList(list):
    def __init__(self, obj):
        self.obj = obj
        super().__init__([obj.state >> i & 1 for i in range(30)])
        
    def __getitem__(self, i):
        self.__init__(self.obj)
        return super().__getitem__(i)
        
    def __setitem__(self, i, val):
        self.__init__(self.obj)
        super().__setitem__(i, val)
        self.obj.state = sum([2 ** i * v for i, v in enumerate(self)])

class CustomObject(KX_GameObject):
    
    def __init__(self, obj):
        self.states = StateList(self)
        
    def main(self):
        pass

CustomObject(logic.getCurrentController().owner)

def main(cont):
    own = cont.owner
    own.states[3] = True

Thank you so much, Goran and Raco,
this looks perfect,

Be aware that the previous code only works for one object. With multiple objects using the same code, the object has to be mutated locally:

from bge import logic
from bge.types import KX_GameObject

class StateList(list):
    def __init__(self, obj):
        self.obj = obj
        super().__init__([obj.state >> i & 1 for i in range(30)])
        
    def __getitem__(self, i):
        self.__init__(self.obj)
        return super().__getitem__(i)
        
    def __setitem__(self, i, val):
        self.__init__(self.obj)
        super().__setitem__(i, val)
        self.obj.state = sum([2 ** i * v for i, v in enumerate(self)])

class CustomObject(KX_GameObject):
    
    def __init__(self, obj):
        self.states = StateList(self)
        
    def main(self):
        pass

def main(cont):
    own = cont.owner
    if not hasattr(own, 'states'):
        own = CustomObject(own)
    own.states[3] = True

What is “main” supposed to do? You could give it a real name.

I purposely named it ‘main’ because it describes a main function on some object. It’s not specific, it could be anything. The same goes for naming the class which mutates the object. If the object would be the player, I wouldn’t be calling it ‘CustomObject’, but ‘Player’ instead. The same goes for the name of the object. I call it ‘own’ because it could be a player, but it could also be an enemy…

My point is that I don’t think it’s wrong to name a module ‘main’. As long as you don’t use it in your actual code. These were just examples.

It might also be sensible to use is instance rather than look for a states attribute

Sent from my Nexus 5 using Tapatalk