How to create sensors and actuators with Python

Here’s my refactored version of the noClutterEmpty.py code. This code encapsulates everything in an object to eliminate the global variables. It reflects my personal preferences on naming conventions. Also, I’ve eliminated the cascaded ‘if’ statements in favor of dict lookups.

import bge
import GameKeys as K

SCENE_OBJECTS = ["Cube", "Cube.001", "Cube.002", "Cube.003"]

class Master:
    def __init__(self):
        scene  = bge.logic.getCurrentScene()
        self.master = scene.objects["Empty"]
        self.camera = scene.cameras["Camera"]
        self.player = [scene.objects[x] for x in SCENE_OBJECTS]

        self.actuator     = self.master.actuators["Parent"]
        self.key_sensor   = self.master.sensors["senKeys"]
        self.mouse_sensor = self.master.sensors["senMouse"]

        scene.active_camera = scene.cameras[0]
        self.affected = self.player[0]
        self.master["playerNumber"] = 0
        self.master["cameraNumber"] = 0
    
    def looper(self):
        self.actuator.object = self.player[self.master["playerNumber"]]
        bge.logic.getCurrentController().activate(self.actuator)
        self.affected = self.player[self.master["cameraNumber"]]
  
    def keyboardHandler(self):
        SELECT_PLAYER = {K.F1KEY: 0, K.F2KEY: 1, K.F3KEY:   2, K.F4KEY:  3}
        SELECT_CAMERA = {K.ONEKEY:0, K.TWOKEY:1, K.THREEKEY:3, K.FOURKEY:3}
        MOVEMENT      = {K.WKEY: [-0.10,0.0,0.0],
                         K.SKEY: [0.10,0.0,0.0],
                         K.AKEY: [0.0,-0.10,0.0],
                         K.DKEY: [0.0,0.10,0.0]}
                         
        for key in self.key_sensor.events:
            if key[1] == 1:  # Key Down Event
                if key[0] in SELECT_PLAYER:
                    self.master["playerNumber"] = SELECT_PLAYER[key[0]]
                    print(SELECT_PLAYER[key[0]])
                    
                if key[0] in SELECT_CAMERA:
                    self.master["cameraNumber"] = SELECT_CAMERA[key[0]]
                    
            if key[1] == 2:  # Key Down Trigger
                if key[0] in MOVEMENT:
                    self.affected.applyMovement(MOVEMENT[key[0]])
   
    def mouseHandler(self):
        pass

def funcLoader():
    pass
    
master = Master()
funcKeyboard = master.keyboardHandler
funcMouse    = master.mouseHandler
funcLooper   = master.looper

Content has been removed. MayDev

This thread is one of those little nuggets that manages to get across some fairly fundamental concepts.

I gave some thought to your earlier suggestion that we make a list of what we would like to know, but the problem, (for me anyway,) is that I know so little that everything I try to do is a major struggle involving hours, if not days, of research.

An example problem from my current, (first,) noob project is firing my space ships guns:

I have two guns symmetrically placed at the front of the ship and a fixed targeting reticule in the pilots view-port. To launch the bullets I have two empties in front of each gun.

I have five different scripts that get the bullets to fire:0) Run_Start.py, basically it declares globalDict variables used by the other scripts, otherwise, (until all the scripts have been called,) there is warnings about missing variables

  1. Targeting.py, attached to the pilot-view: Calculates the bullet velocity vector so that it goes to where the reticule is pointing irrespective of the distance to the target.

  2. Bullets.py, attached to the empties: Checks all the conditions are met, collects basic data about the ship and creates the bullet.

  3. Bullet_orientation.py, attached to the bullet: Takes the data from the two previous scripts and, putting it all together, sends the bullet off with the correct velocity and orientation so that it hits the target at the position indicated by the targeting reticule at the time of launch.

  4. Bullet_explosion.py, attached to the bullet collision sensor: replaces the bullet with an IPO animation of an explosion.

Even at the time I put the scripts together, I was fairly certain that it was not the best way to do it, I searched for a long time looking for targeting examples that were applicable to what I was trying to do. Its only redeeming feature is that, once debugged, it works well. But… Shall we just say that debugging the scripts so that they talk nicely to each other was challenging.

Anyway, I think that example illustrates my noob problems quite nicely, I would be quite interested to hear your views on how you would have went about this and any other guidance you may care to offer.
.

Content has been removed. MayDev

Content has been removed. MayDev

@Irvine,
if you want to have everything in one script, it is time to switch to module mode.
Rather than having 5 scripts you can have one script (e.g. Weapon.py)with 4 functions:


def run_scripts(cont):
  ...
def targeting(cont):
  ...
etc.

Then switch your Python controllers from script to module mode and use these parameter:
“Weapon.run_scripts”
“Weapon.targeting”

Keep in mind cont is the current controller.

I hope it helps

Monster:

Sorry, I am a noob and did not even know it was possible to have the scripts as modules… However, that has now changed and in furure I will be using a modular technique.

MayhemOfHell:

Yes, your description more or less sums it up. The term “bullets” is used loosely… basically it is a glowing special effects object that traces a nice visually pleasing path, like a “photon torpedo” perhaps?

As I pointed out, I did not know about modules, so yes it is standard basic noob scripting.

I suppose that the best way to describe the structure is to consider each script as a procedure or function, (though they are not specifically declared as such.) A complication to this is that in the case of “Targeting.py”, the script serves double duty for setting the “target aquired overlay”

Taking the main components:1) There is a “ray sensor” attached to the pilot camera. If there is no target then the velocity vectors are a constant at extreme range, the vectors are calculated by taking the range value from the sensor and combining this with the offsets for each gun. The velocities are then stored in the globalDict.
2) With a target detected by the “ray sensor”, the vectors are updated every half second by calculating the displacement vector from the “pilot camera” to the “target.hitPosition”, converting this into a length, combining it with the gun offsets and then converting to velocities. Again, it is stored in the globalDict

  1. The firing sequence, (bullet.py,) is initiated by a “keyboard sensor” on each “gun empty” with a python controller and an “edit object actuator” to create the bullet and give it a life time.

  2. Bullet_orientation.py is called by an “always sensor” on each bullet at creation, it is connect to a “motion actuator” to which it sends the retrieved velocity vectors. The script determines which velocity vector to use by having “left” and “right” bullets and then reading the controller name.

  3. “Bullet_explosion.py” is called by a collision sensor and is connected to two “edit object actuators” the first creates the bullet explosion overlay and the second ends the life of the bullet.
    I hope that is reasonably clear, I do not really want to clutter up the post with lots of code segments and there is no easy way of attaching zip files or, (since it is dynamic,) making nice understandable diagrams.

This thread evolves very nicely, it makes BGE more than a game engine rather than an authoring environment. While BGE does it both very well programmers prefer mostly code for integrity.

I have started implementing a couple of mini-games with this technique, I hope that it will make the transition to BGE 2.5 better and more convinient.

The positive results of using this technique are:

  1. Separate content from code (content can be also separated and be handled better with linked objects).
  2. Code can be edited externally
  3. Use your favourite IDE (a.k.a Netbeans) :stuck_out_tongue:
  4. Track your project as a solution rather than single scripts
  5. Most important, it’s SVN friendly

The quest to enlightment continues… :smiley:

Content has been removed. MayDev

I actually have been using Komodo Edit, which is free, but this will be spectacularly useful with autocomplete.

This got me thinking about Linux where, [at the moment,] I am using Gedit with “snippets” for python… Anyway, has anyone tried “SPE”?

It is a Python IDE with Blender support and the ability to be integrated directly into Blender, (I think that means Blender 2.4xx) I am going to give it a go, but due to my slow connection, it is going to take me a few hours to finish all the recent upgrades I have missed over the weekend and download “Spe” from the Ubuntu repos, I may get back to you on this.

Update:
At the moment, “Spe” does not work with Blender 2.5, I did a bit of research and the problem is some of the utilities that are used by"Spe", in particular “wxPython” which has not been updated to Python 3 and does not appear to have even a road-map for when we can expect an update.

The author of “Spe” has been making inquiries that specifically mention Blender, [for over two years and as recently as this year,] about when he can expect updates, so he is on the ball… But for the foreseeable future it is going to be “Gedit” and “snippets”, which I suppose works quit well providing you remember to add any Blender code segments to “snippets” when first used.