python class object disappears from list, where did it go?

Hi

So im making a small game in blender for a project in one of my classes. Im working on getting some object(currently a sphere) to move around from square to square on periodic table of elements.

I have 2 classes, one Tile class(squares on the periodic table). This class adds a plane from the second layer at intervals and eventually ill stick some sciency info in the class.

The other class(the one im having trouble with) is the Selector class. This is the object that moves around and selects different tiles.
So i have the constructor which adds an object named Select from layer 2.
The Selector class update method gets an input telling it how to move in the grid, than it goes and changes the position of the game object Select based on that.

My problem is that after i create an instance of this class and append it to the list select, it seems to disappear because when i try to call its update() method in the next if statement it says index is out of range. even though in the first if statement in the main function it clearly says that there IS an object in the list, however when i print the size of the list in the second it says there its size is 0 and that’s where i get the index out of range error.

from bge import logic







cont = bge.logic.getCurrentController()


own = cont.owner
init = own['init']
scene = logic.getCurrentScene()
Space = cont.sensors['Space']
Right = cont.sensors['Right']
Down = cont.sensors['Down']
AddObject = cont.actuators['AddObject']




elementsize = 0
elements = [[],[],[],[],[],[],[],[],[],[]]


select= []


NC = 0
null = 0








row1 = ('H',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'He')
row2 = ('Li','Be',0,0,0,0,0,0,0,0,0,0,'B','C','N','O','F','Ne')
row3 = ('Na','Mg',0,0,0,0,0,0,0,0,0,0,'Al','Si','P','S','Cl','Ar')
row4 = ('K','Ca','Sc','Ti','V','Cr','Mn','Fe','Co','Ni','Cu','Zn','Ga','Ge','As','Se','Br','Kr')
row5 = ('Rb','Sr','Y','Zr','Nb','Mo','Tc','Ru','Rh','Pd','Ag','Cd','In','Sn','Sb','Te','I','Xe')
row6 = ('Cs','Ba','La','Hf','Ta','W','Re','Os','Ir','Pt','Au','Hg','Tl','Pb','Bi','Po','At','Rn')
row7 = ('Fr','Ra','Ac','Rf','Db','Sg','Bh','Hs','Mt','Uun','Uuu','Uub','Uut','Uuq','Uup','Uuh','Uus','Uuo')
row8 = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
row9 = (0,0,0,'Ce','Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er','Tm','Yb','Lu',0)
row10 = (0,0,0,'Th','Pa','U','Np','Pu','Am','Cm','Bk','Cf','Es','Fm','Md','No','Lr',0)
eNames = (row1,row2,row3,row4,row5,row6,row7,row8,row9,row10)




def exec_AO():
    AddObject.instantAddObject()
    




def getName():
    global NC
    NC+=1
    return eNames[NC-1]


class Element(object):
    x = null 
    y = null
    z = null
    row = 0
    col = 0;
    name = 'element'
    gameObject = null
    def __init__(self,R,C,Name):
        global elements
        global elementsize
        global bgeElements
        
        
        self.gameObject = scene.addObject("Tile",scene.objects['Empty'])
        
        elementsize+=1
        
        self.name = Name
        
        x = C*3
        y = R*-3
        z = 0 
        self.gameObject.localPosition = [x,y,z]
        


class Selector(object):
   
    x = 3
    y=3
    z=null
    myObject=0
    e_r = 0
    e_c = 0
    def update(self,r,c):
        global elements
        self.e_c+=c
        self.e_r=+r
        
        self.myObject.localPosition = [elements[self.e_r][self.e_c].x,elements[self.e_r][self.e_c].y,elements[self.e_r][self.e_c].z]
        print(self.myObject.worldPosition)
    def __init__(self):
       self.myObject=scene.addObject("Select",scene.objects['Empty'])
       print("select created")
       #self.update()
            
            
            
      


        


def createTable():
    print("table created")
    for i in range(len(eNames)):
        for j in range(len(eNames[i])):
            if eNames[i][j] != 0:
                elements[i].append(Element(i,j,eNames[i][j]))
                
    own['init'] = 1
            
            
    


             




def main():
    global select
    if(Space.positive):
        if (own['init'] == 0):
            createTable()
            select.append(Selector())
            print(len(select))
            print("select created")
    
    if Down.positive:
        print(len(select))
        if own['init']==1:
            print(len(select))
            select[0].update(-1,0)
            print(len(select))
            




main()



Could someone please help me find why i cant reference my Selector class after i first create it. Is it some kind of weird scope issue? does it have something to do with the way blender calls the script.

Im pretty fluent in java and C++ but its been a while since ive used python in this is really really frustrating me.

Ive attached the blend file

Attachments

Game.blend (577 KB)

Your python controller uses “Script” execution mode, which means that the entire script is executed from beginning to end, on each and every pulse. Therefore, select is redefined as an empty list, and this leads to the aforementioned error.

You could use “Module” execution mode, and specify gamelogic_simple.main as the running function. This will make global scope variables persistent, as they would be part of a module, which is only evaluated once (upon initialization).

hmmm i was wondering if that might be the issue.

Is there any way of writing a script where the variables and arrays and whatnot do not get reset? i want to be able to have a class that keeps some information inside it. I suppose i could use game properties, however i using a class would be a very clean way of doing things if possible.

A module would work for setting up the periodic table, however it would not work for the actual selecting of stuff in the game(the purpose of the selector class)

As I said, “Module” execution mode will ensure that the global scope variables are defined once, and that they persist.

So, that should give you what you want.

A module would work for setting up the periodic table, however it would not work for the actual selecting of stuff in the game(the purpose of the selector class)

I don’t see why not.

I mean, if your problem is a lack of persistence, and “Module” execution mode provides that … where’s the trouble exactly?

hmmm perhaps i am misunderstanding what a module is than. I briefly read something about it the other day and what i got from it is that a module only runs once at the beginning of when you start the game.

Last time i used BGE python very extensively was when Blender 2.49b was the most recent version so im a little behind on some of the newer features.

That’s what I mean by “running once” - the code in the module is evaluated, so the terminology is proper.

I’m not talking about the function specified for the controller, which is executed on every pulse.

PS: Your “Module vs. Script” link leads to a post on matrices.

I will look at all those resources thanks guys!

one quick question though, does this mean that in a module, i could have a while loop running concurrently with the game engine without the engine freezing up and waiting for the code to finish executing?

UPDATE
i got it working! Thanks guys. Modules are pretty darn awesome.

Thanks, I just updated the link with the right URL.

No. The integration as Logic Brick is still the same. It is just another way to connect the Python interpreter with your custom Python code.