Python - Game questions

Hello,
I have some general BGE (2.49b) & Python (2.6) questions, hope someone can help.

  • Given a Python controller, cont, coming from object A, is there any way to set and activate actuators on other objects (B and C)?
    (I want to initiate a bunch of IPO actuator animations on B and C when A meets some condition.)
    I suspect the answer to this question is ‘no’. I have been getting the error “Cannot add an actuator from a non-active controller.”
  • Is there any way to add actuators on the fly? I mean, do actuators actually have to be bricks or can they be created and added to random objects via Python?
  • What is the difference between a message and a property in the context of events – i.e.:
    Scenario ONE: Object A has an always sensor and is running a function to check for a property in object C, C[‘p’]==True.
    Scenario TWO: Object A gets sent a message (by C) when C[‘p’]==True.
    Which is “faster/better”?
  • Is there any way to have object A send a message to many other objects in a Python function? I want A to send “blah” to B,C and X.
    (I don’t mean set a property which is checked on every pulse by B, C and X. This question relates to Q 3 above.

That’s it for now. I am really aiming for some kind of timeline + event control system. I want to be able to fire/trigger sequences of actions based on key frames. I understand that BGE is not geared towards this (it’s more of a game-loop kind of approach) but I have this perverse streak :smiley:

Thanks,
\d

  1. Yes you can. Even with logic brick you can connect controllers to actuators of other objects.
    I haven’t tried to activate an actuator of a different object with Python. In my eyes this bad style. It hides the activation of the actuator. If you look at the object you can’t see why the actuator is active or not. It is your choice.

  2. No it is not possible.

  • The property reflects the internal state of the object. So the property is related to the object it belongs to. The message has no relationship to the sending object anymore.
  • The property keeps it’s value. It will change when it is added, changed or removed explicitly. The message will live just for one logic tick. If it is not read it will get lost.
  • There should be no difference in term of performance between properties and messages.
  • When one script sets a new value to the property there is no guarantie which value is read by another script (old or new value). This completly depends on the execution order of the scripts. Messages will send by actuators and received by sensors within the next logic tick. The message content will not be changed in between.

What to use when strongly depends on the individual situation.

Your scenario One could be solved by adding a Property change sensor on object C which is connected to a controller in Object A. You even can copy the property with a script but better activate it with the property change sensor as it will execute the script only if the property changes and not always.
What ever is reading the property might get the new value or the previous value dependend on the execution order.

Your scenario Two would be good as well. As the message receives within the next frame you have to think about that the message is received at the next frame.

  1. Sure. You can send your message to all objecs.

You can trigger logic by keyframe as IPO and Action actuators provide you with the current frame if you set a frameProp. Just check this property when playing the actuators.

I hope it helps

Meister Monster! How ya doing?

If you try it you may get that error about non-active controllers that I did. Hard to reproduce it now but if I get one again, I will show you.

In my eyes this bad style. It hides the activation of the actuator. If you look at the object you can’t see why the actuator is active or not. It is your choice.
I far prefer handing the maximum control over to Python – it just makes more sense to me to see it all there in classes and modules than scattered all over the 3D space in bricks in objects. :wink:

  1. No it is not possible.
    Damn! Too much to hope for :smiley:

The property reflects the internal state of the object. So the property is related to the object it belongs to. The message has no relationship to the sending object anymore.
Okay I follow that already.

The property keeps it’s value. It will change when it is added, changed or removed explicitly. The message will live just for one logic tick. If it is not read it will get lost.
But can I use messages as a way to send ‘events’ to many other objects? In this context:
I have a list [A,W,X,Q] and I want to send a "StartPlay’ message to all of them – how would this look in Python? And would A,W,X,Q all have to have message-sensors attached?

here should be no difference in term of performance between properties and messages.
Even on an always pulse 0? Check prop, Check prop, Check Pro… tick tick tick every time? I was trying to ask if the message-send is more efficient or is it just doing the same polling in C++?

  1. Sure. You can send your message to all objecs.
    Could you give some Python code to show how you do this? I am sure I am missing something subtle.

You can trigger logic by keyframe as IPO and Action actuators provide you with the current frame if you set a frameProp. Just check this property when playing the actuators.
Yes, this is what I want to get right.

For example, the game starts.
A cartoon sun rises up. After a while a cloud floats by. After a while a bird flies across. Three cubes zip in and stop. They are buttons. When I click one they all zoom away, the sun goes down and the bird flies away.
Do you see this is a kind of timeline based stop/start play-on-keyframe thing.
Now I want to try and control as much of that timing in Python (in a single function perhaps, using a dict to hold all the players and their timing frames. So I need a “central control” where all my players are registered and then told to “go play!” as their turns come up.

Okay, thanks for your insight. I was looking for some code – so dont’ be shy!

\d

To activate another actuator on a different object you have to first get the controller that the actuator is connected to:

obl = GameLogic.getCurrentScene().objects
object = obl['OB<i>object_name</i>']

actuator = object.actuator['<i>actuator_name</i>']
cont = object.controllers[<i>controller_index</i>] # e.g 0,1,2...

cont.activate(actuator)

Getting controllers off an object is messy business because you can’t just use the controller name as a key, you have to use something like this:
controller_name#CONTR#controller_index

cont = object.controllers['python_controller#CONTR#1']

Thanks andrew-101, I will give those a go. I have seen those horrid controller keys on the console before and gave a little shudder. :slight_smile:

\d

Ah, a weakness here…
My setup - A sphere with one sensor, one cont and one IPO actuator. My camera does the ‘driving’ (it has a Python controller with a script) and gets the OBSphere as per your example post.

But, the method –


cont.<i><b>activate</b></i>(...)

– is only available when the controller is a type SCA_PythonController.So, I changed the Sphere’s controller from AND to Python. I left the script empty because I don’t want to run anything from the Sphere!

Now when I try I get the error mentioned in my OP:


"cont.activate(actuator)
SystemError: Cannot add an actuator from a non-active controller

So, it seems you cannot dictate to another actuator after all. Can you confirm this or set me on the right path?

\d

hmm, it is going to becaome a splatter thread. Lots of issues in one thread :).

Anyway here is the way to send messsages to all objects

  1. with GameLogic (see.http://www.blender.org/documentation/249PythonDoc/GE/GameLogic-module.html#sendMessage:

GameLogic.sendMessage("I'm a subject") #or
GameLogic.sendMessage("I'm a subject", I'm the body") #or
GameLogic.sendMessage("I'm a subject", I'm the body", "") #or
GameLogic.sendMessage("I'm a subject", I'm the body", "","OBCube")

  1. with KX_GameObject see http://www.blender.org/documentation/249PythonDoc/GE/GameTypes.KX_GameObject-class.html#sendMessage:

import GameLogic
own = GameLogic.getCurrentController().owner
own.sendMessage("I'm a subject") #or
own.sendMessage("I'm a subject", I'm the body") #or
own.sendMessage("I'm a subject", I'm the body","")

  1. With message actuator. Leave the To: parameter empty and activate the actuator.

I hope it helps

Back to controllers:
You need to activate the controller, so plug it into an always sensor -> pulse mode enabled.
Do that and it should work.

dotherwise,

you are right, only python controllers can activate its actuators. So I was incorrect with my answer to point 1. I haven’t recognised that.

For a central control, you could set up a “director” object that manages the timeline. This is a perfect situation for a FSM finite state mashine. I advice you to http://en.wikipedia.org/wiki/Finite-state_machine.

Monster,
Thanks for confirming my code. Glad I am not 100% off the path!

I should be able to do pretty much anything I need with Python, I have some experience, but it’s in the context of Blender GE that I am a newb.

Do you have any further advice (and code) in the subject of “controlling the timeline” ?

From what I can see there seems to be one main timeline and no concept of sub-timelines (that start from zero, relative to the main one) is this correct?

As to one ‘master director’ counting ticks and firing events on keyframes (manually set in some way) and telling other objects to do something, it looks like I will have to try message sending, or some kind of publish-subscribe trick.

\d

I’m not sure what you mean with subtimeline. The FSM is a state based system.
Every thing is state relative.

What you do is set a state of the FSM. The FSM will start the entry action and runs the state action (if any). When an event occurs the transition table will be traversed if the state should be changed.

Example:
Your FSM gets the “animation 1” state. When entering this state the animation “A” should start (entry action = play animation A).
When the animation ends the object sends an event to the FSM (message or property change or whatever).
The FSM checks the transition list what to do when state = “animation A” and event = “animation ended”. Lets assume it says: change state to “animation 2” state.

The FSM gets the “animation 2” state. When entering this state the animation “B” should start (entry action = play animation B).
When the animation ends the object sends an event “animation ended” to the FSM (message or property change or whatever).
The FSM checks the transition list what to do when state = “animation A” and event = “animation ended”. Lets assume it says: change state to “animation 1” state.

finally it will play animation A followed by animation B followed by animation A…

I’m working on an adventure game (since loooong time). Here I needed a similar concept for the characters. So each character has a FSM that synchronises animations between the character and other objects or between characters. It reacts on events like keypress, mouseclicks and animation ends etc…

I started a tutorial for FSMwithout python. With the states system implemented in blender it is obsolete now and you want to use python. But you still can catch the concept behind.

I hope it helps

I have since figured out my timeline problems. Sorry for the noise. :slight_smile:

It reacts on events like keypress, mouseclicks and animation ends etc…

What system do you use to send events like ‘animation ends’? I mean, how do you know when an animation ends? Is it a logic brick that sets a property/sends a message when a certain frame is reached? Or is there some other way?

My ideal system for BGE would be a way to send a message or call a function directly in/from the IPO – where the keyframes are made. So when you move a keyframe, its ‘actions’ go with it.

Right now I am trying to glue a second system onto the IPO such that it tracks the frame and then looks that up in a dict/list thing and then gets the ‘actions’ from there – and then fires them.

The problem is that if the keyframes change (say I move one to make an animation longer), then I have to manually go into my code and change the keyframe number there too.

It would be cool to say (in the IPO):
Frame 10: Call Python function foo( a,b,c )
Frame 20: Set property Foo=22
Frame 30: Stop playing
Frame 40: Loop to 20 if Foo==22
And so on…
And if I grabbed the first key (time 10) and moved it to 12, the action (call foo) would follow and fire at 12 instead of 10.

This is part of what my OP is aiming at – a way to control the timing/state of objects from Python with the minimum of ‘brick fuss.’

Anyway, thanks for the info about the FSM. I will take the time to look into it, but I won’t promise it will be soon :smiley:

\d

You can have both systems:
There is an Actuator sensor that should check if an actuator finishes. I haven’t used that as it is pretty new.
With that you can configure your animation sequences directly in the IPO actuators (e.g. one is playing from 1…50 another one from 61…100).
So you can set up a chain of IPO actuators one is triggering the other.

Here is an example:
ActuatorSensorTest.blend (151 KB)

You can do that with Python as well. Then you need just one actuator to play the IPO.

Unfortunatly the IPO or Action start and end must be setup manually in the actuator (or the processing the property if in property mode). If you change the IPO you have to change the logic.

Thanks for the sample file. Interesting to see NAND in use, I shall have to look into that.

Unfortunatly the IPO or Action start and end must be setup manually … If you change the IPO you have to change the logic.

Yeah, this is what I meant in my prev post – tying ‘actions’ more tightly to IPO keyframes. Perhaps 2.5x will surprise us one day.

Well, this thread has helped me and supplied several new lines to work along. Thanks all.

\d