So I have power ups that I spawn to different empties randomly, I’m pretty new to python but I got it to work just the way I want. I want to know if there is a better way of scripting this without changing the way it works in game.
That is a lot of work, better grab everything at the start of the engine.
if not 'init' in own:
own['powerUpsList'] = [obj for obj in scene.objectsInactive if 'powerUps' in obj]
own['locationList'] = [obj for obj in scene.objects if 'PU_locations' in obj]
own['init'] = True
scene.addObject(random.choice(own['powerUpsList']), random.choice(own['locationList']), 120)
# now just give the power_ups a property called: powerUps
# and give the empties a property called: PU_locations
This way you dont grab every single object every single frame but just the first time the script runs, and then it stores it in the owner, so you can use it anytime of the day.
Thanks cotax, I defiantly want it to be optimized. Could you break down that script a bit? I am new to python and I want to understand the script, I pretty much just copy and pasted it and I don’t completely understand what is happening.
Ah, cotax is definitely right - it is better to optimize it that way. This is because creating a list with referencing only once will be more efficient than constantly creating a list with referencing every other frame regardless of if your scene has 1 or 200000 objects in it.
But if the scene or the inactive layers in concern contain (or might/are going to contain) a ton of objects, and only several powerups are needed, it is actually better to reference individual objects in the list by name rather than:
obj for obj in scene.objectsInactive if 'powerUps' in obj
obj for obj in scene.objects if 'PU_locations' in obj
because those operations will basically take O(n) time (basically meaning you have to process n elements, where n is the amount of objects you are processing, which can be huge) to enumerate through all objects in a given scene in the respective layers. List reference is only O(1) (basically meaning a constant amount of items to process, regardless of how much objects you have).
Cotax’s code (and the code I wrote actually) will suffice for the current scene you have now, because there are not a lot of objects in your current scene, and the python controller is not evaluated very frequently.
Basically what cotax just wrote for you goes as follows:
if not 'init' in own:
This is a check to see whether or not the property “init” exists in own. So far it doesn’t, unless you’ve explicitly created the property already.
own['powerUpsList'] = [obj for obj in scene.objectsInactive if 'powerUps' in obj]
A list in python is defined by the open and close square brackets: . This code is obtaining a list of all the objects that are on different layers from the currently selected layer(s) when those objects have the property ‘powerUps’. This is enumeration.
own['init'] = True
This creates the property ‘init’ and assigns it to own.
Basically, the code above so far grabs your objects once in list format (hence the square brackets), then does not grab them anymore because of the assignment own[‘init’] = True (own now has a property called ‘init’ and therefore,
if not 'init' in own:
evaluates to False).
random.choice() is a function which chooses a random element of a non-empty sequence type you specify inside the parameters.
I appreciate your desire to learn the code you just obtained.
@cotax:
I used to do things like pre-allocating lists at game start for performance, as you have done there. I still do in some situations.
BUT
I now know the difference it makes is so small as to be insignificant unless you have very very many objects (in which case you will have other issues - namely the rasterizer). Even in a fairly huge/complex system I am developing, I use [o for o in scene.objects if …] several hundred times per frame. without issues, and with several hundred objects in the scene. You’re better off designing a more efficient system than optimising small things like this.
Premature optimisation makes complex systems with huge issues later on.
The property names can be anything you want, like init can be abcd, aslong as the property is not already in the owner object.
own['powerUpsList'] = [obj for obj in scene.objectsInactive if 'powerUps' in obj]
this creates a property in the owner object.
this property will be filled with a list containing all objects with a property in this case powerUps.
it is grabbing all object from the scene, checks if it has the property you are looking for, and if it has the property it will be put into the list.
a long version of the code:
own['property_name'] = []
for obj in scene.objects:
if 'property_name' in obj:
own['property_name'].append(obj)
@ sdfgeof
I agree, but this is easier to setup, then assigning every single object by hand (in this case).
Assigning by hand if you have only a hand full of items will be better, but the more objects you have the easier and faster it will be if you do it at the start. And i always like it to do it this way, due to you only go through all objects once, then you have your use able lists, and be able to use it whenever you like (even in other scripts just by grabbing that object containing the list).
That is way i suggested this over manually filling in the lists or going trough all scene objects every frame. (it’s just easier to re use)