Game Property questions

I’m working on a game that, during startup, generates a random board made up of a grid of tiles (using scene.addObject()), and have come across several oddities that I was hoping someone could clarify for me.

  • I was under the impression that game properties could be called via tile.fred, tile.wilma etc, as attributes in an object. This provides an error: “AttributeError: ‘KX_GameObject’ object has no attribute ‘fred’” even when said attribute is listed when getPropertyNames() is called. The temporary solution I’ve found is to call them instead as an associative array (Dictionary?) tile[‘fred’]. Is there something I’m missing here?
  • Even with the afore mentioned solution, when objects are added inside a function, and then returned, the returned object pointers refuse access to their properties/attrubutes via the same error message as above.
def newTile(type, x, y):
    cursor.worldPosition = (x, y, 0);
    tile = scene.addObject(type, cursor, 0);
    tile.type = type; #error
    #or:
    tile['type'] = type; #works

    return tile;

tile = newTile('grass', 0, 0);
print(tile.type); #error
#or:
print(tile['type']); #Still error

  • When calling the list of objects in the scene, I was surprised to see that all of the objects I had added had the exact same name, no .001 on the end or anything. Is this usual/an indication that objects added inside the game are treated differently than objects that exist before the game starts?
  • Is there a way to change the name of an object? tile.name and tile.setName() are the two answers to this question that I’ve seen previously, however they both fail, possibly due to the questions above.
  • Failing renaming the tiles (and calling ‘tile3-2’, ‘tile5-7’ etc), what would be the best way of calling a specific tile by x/y coord on the grid? Is there a way to return a list of objects whose centers are currently at global(x,y,z)? Should I give each tile an x/y property, and assign it it’s location on the board, and then loop through all the tiles until I find the right one? (seems like the awkwardly long way 'round.)

I am using Blender 2.57b
I am fairly new to Python, but do have some coding experience with other languages.

Thanks in advance! =)

I have no idea what you are talking about, but I just wanted to post because I thought it was funny that you chose the two names “Fred” and “Wilma”. Those are my grandparents names… er… I think wilma is my grandma’s name. lol.

Lol. Several older O’reilly books (Learning Perl 3rd Edition comes to mind) used Flintstone names as variable examples. I’ve kinda continued the example. =)

Also to clarify a point, the error shows up whether copied object had that property or not. As I understand things, calling an unassigned property should allow you to assign it, but even if that is not the case, I’m still getting the error.

Very quickly, (I haven’t got time to experiment) check out the function (?method) lastAddedObject. It belongs to the actuator ie actAdd.lastAddedObject. I haven’t figured it out yet but you might. It might return an index or something that allows you to reference the object even if you can’t actually give it the name of your choice.

  1. No, in Blender 2.57b, you call variables using the dictionary usage that you talked about - tile[‘fred’] is equivalent to tile.fred. You can assign variables in the same way - tile[‘fred’] = 1, for example.

2. That function should return the correct pointer to the newly created tile object. Make sure that it’s not because your tile variable is spilling outside of the function declaration - try renaming it to something else in the function (like t).

  1. Yes, that is usual. All objects added are just instances / duplicates of their original objects, meaning that you can’t get a particular object just via the scene.objects array (you can, but there’s no way to know which one you will get - it will probably be the one that was created the earliest). However, each object can tell itself apart, meaning that obj = sce.objects[obj] will return true, while obj = sce.objects[obj.name] may not return true, as there are can be multiple objects that have the same name as the ‘calling’ object. See? I’m not sure if I explained it right, heh.

  2. You can’t set the name of the object directly, but you can put a custom variable that you can use. If you put it in all the tile objects, then it’s as good as a name.

  3. The best way of calling a specific tile would probably be one of two ways:

  4. Use a dictionary - use the position values to indicate which tile object to find on that position. I’m not sure if you can use a list, but you can use a string to correspond to a specific tile object - i.e.
    tiles = dict({
    ‘-1, -1,’: tile object pointer
    ‘1, 0’: tile object pointer,
    etc.})
    That’s a dictionary initialization, though - you can easily just append values to the dictionary by setting it - tiles[’-1, -1’] = tile object pointer

  5. The old-school method of using array values to indicate where you want objects to be. Loop through, create an array consisting of two dimensions, and then use those indices to indicate where to find the tile object pointers.

I think SolarLune write everything you need. Just some remarks:

  1. properties are dictionary keys on KX_GameObjects since 2.49 (before that they were attributes) {arrays in Python are lists ;)}
  2. better call it reference rather than pointer.
  3. you can get KX_GameObject with the same name via:
  • addObject (as you do)
  • group Instanciation
    They are all copies
    4/5 already answered :smiley:

Thanks Monster - I suppose reference is the correct term for an object… Well, reference, heh. Do you know what could be causing his addObject function reference returning error? I don’t see anything in the code myself…

Wowie! Thanks everyone for the help.

Equip: I will have to take a look at that lastAddedObject() function. That sounds like the right way to solve several problems.

SolarLune:

  • That would explain the confusion!
  • Changing the variable names appears to have solved the problem. I don’t see why doing so should change much of anything, as when the function is called, the variable created inside of it should be a local variable, and cease to exist as soon as the function is done running. Even if this were not the case, the second time the function get’s called the error still shouldn’t show up because it would be calling the variable from the last time around, which DID have the attribute requested. Weird. Solved, but weird. (Then again, I keep thinking that I’ve figured out things like variable scope and my attempts keep not working, so it’s probably my big goof on that one.)
  • I think so… Again, thanks for the clarification.

4/5 Some good ideas there. I’ll mess around and see which one fit’s best. :eyebrowlift:

Monster: Thanks for the tips! I’m still trying to get used to the way Python is different in many ways. Code blocks set apart by indentation, Lists vs. Arrays, words (and, or, not) instead of operators (&&, ||, !) etc. Not that I’m not enjoying it, but it’s taking time to form new habits. =p

Thanks again for the thorough replies! =)

you can use
!= instead of not ==
and im not sure about the others.