Player- Object interaction => Your opinion!

Greetings fellow BGE users!
For COS I plan to use a general player- objects module.
So all interactive objects (NPC, ships, food, tools, consoles, you name it…) have 3 main properties:
Active, selection, execute
Then 10 options. In the options properties, as a string I put an action the object can perform, the action is performed when the 3 main properties are True.
So far I think that this system is efficient enough to be used for all objects in the game.

I’ll try to illustrate it with an examples:
Ship: it has many objects(airlock, consoles, seats, parts). To have access to the ship, one needs the access code(optional). The airlock has 2 options: Open and close. The player approaches the ship, placing all it’s components in a list of active objects. The player points to the airlock and the 2 options appear(almost Sims like), the selected option is executed and the player moves in. The seat has 2 options (use, unuse), the have a shortcut (e.i. “F”). The console has it’s options (start engines, steer, take off, land, dock, etc) by selecting steer, the mouse look of the ship is coupled with the players, or replaced. And so on and so forth.

The same applies to other objects, the action can be performed by the player or by the object. The code will check if the 3 options are True. Also how do I turn a string value into a command. In this case, the “selection” property will have the action value selected, as a string. I’ll use that value as a parameter in the module…

Thank you for reading!

For my last question:
could it be eval(object[‘prop’])?

The main question is:
Is there a case scenario I’ve not foreseen for this system?

Warning:
lots of text!

This is a typical OOP approach. You have Objects which can do something.

How you trigger this “do” depends on the interface the object provides. The interface can be for example your three properties.

The “user” of the object needs to know this interface. E.g. it needs to know it has to set “active” to True. The user does not care how the object acts on that. It only cares it does something.

BTW. There is no need to limit anything to three properties. I’m sure you thought about them really much and you discovered that it fits to nearly each object.

But I think you mix different tasks here.

A) Selection
Selecting a objects is necessary for a user (usually the player) to determine what object to interact with. There can be multiple users at the same time with independent selections at the same time. E.g. The player opens a door while an NPC drives a car. Which means the player selects the door to be opened, the NPC selects the car to be driven.

If you go further down you see you need a selector which can select one or more things (without actually touching it). The selector provides the user (player) with the currently selected objects. It also offers options to select other objects.

All of the that does not involve any other function as active objects or so.

The basic is:

Selector — selected objects —> User

B) Running Actions
This is what the Object exist. It does something. Usually it is simply visible. You do not need to do anything for that the 3D engine does it for you. If objects should collide or fall - The Physics engine does that for you.
The object should perform tasks (motion, reactions etc.) you use the Logic system to establish a behavior.

This is a typical programming task: The object acts on input (=events).
Example: On Open Requests a door plays it’s open animation.
If necessary the object triggers other objects an expects them to do something.

C) Using Objects
Using objects means one or more objects interact with each other.
Example: When touching a switch -> the door should open

The door does not care what touches the switch not that it is a switch. The door only cares the Open Request it receives from the switch.
This means the switch generates an OpenRequest at the door.

User – Request --> Object

This request is an
D) interface
For interaction with other objects an object (user) needs to know how to interact with the other objects. E.g. A door accepts a OpenRequest. That can be a message, a property, a call to a Python module or whatever.

Both involved objects know this interface (the OpenRequest). The switch knows how to send it, the door knows how to receive it and what to do with it.

An object can have multiple interfaces. For example the door can have these interfaces:

  • open
  • close
  • lock
  • unlock

The switch knows of:

  • open
  • close
    A key knows of:
  • lock
  • unlock

User — Interface — Object

Where is the selection?
The selection is what the user has chosen to interact with.
E.g The opener’s selection is the door.

The simplest case: it is hardcoded and will never change.
Complex situation (like a remote control) the switcher opens all doors within a specific range.
More complex situation (like a remote control) the switcher opens all doors within a specific range with a specific code.

The key unlocks doors within a specific range and with a specific code. This means a key does not unlock all doors even if all doors have the same “unlock” interface.

Anyway, this principles are already present in the BGE. You can simply use the logic bricks (but you are not restricted to it).

Object = Game object (or group instance)
Interface = properties, messages, code (your choice)
Behavior = the logic bricks

Interaction = one game object requests another via your defined interface.

Coming back to your idea:
Active, selection, execute are more states rather than interfaces.
Active
If an object is active or not should be the decision of the object. Other object can request a state change (activation/deactivation) if the object does that is up to the object.
Example: the actuators.
They can be active and inactive.
They activate on activation signal (True Pulse) but they might run for one frame only (Property actuator) or
run until they receive a deactivation signal (Motion actuator) or
they continue until finish ignoring the deactivation signal (ActionActautor).

You can do the same with your logic.

Selection
see above. I do not think that one selection property is enough as it restricts the selection to one user. But it is an option.

Execute
I think this is the same as Active.

Nevertheless, it is a good idea to create similar interfaces. This makes development much easier. It is important to document the interfaces (e.g. “expects property ‘active’ to be true to play open animation”). The BGE is not really good in documentation support.

In logic bricks:
property sensors checking each property

or
expression controller (triggered by a request e.g. message sensor).

in Python code:


if obj["active"] and obj["selection"] and obj["execute"]:

I suggest not to re-invent the wheel and simply use Logic bricks.

Addition:

To make all of that more complex, you can provide a context sensitive menu to the player. I think that is what you meant with your 10 options.

You could implement an “interface finder” which checks all available interfaces and presents them to the user via a menu or whatever. The user can request this interface by selecting the menu item.

The “interface finder” uses an “interface descriptor” interface. E.g. it expects the property “player options” with a list of property names: “open”, “close”, “take”, “lock” etc.

The “interface finder” could check the “selected” object and get this list of option = interfaces. The user can select one of them.

Thank you very much Monster, I’m still trying to see what your opinion is, we seem to be on the same page.
To put thins in your terms:

There are 3 states that control an action: Active, selection and execute.

Action
Definitely object dependent, but there is a small common ground for most of them:
Hold: The object is parented to another; Keep: The object is ended and added to an inventory; Open: The object plays it’s open animation; etc. The action might change a set of properties, like ship controls.

Before an action can be performed, it must be chosen, but the object needs to be selected, this is where active and selection come in.

Active
the selected object turns active(True/False), then the interface appears (10 options).
To determine if an object is active, it needs to be in range and a selection action needs to discriminate it. In the case of NPC, the selection process might be included in the interface. Like order bot B to destroy target D. The destroy option requires a target, to be defined by the player or AI.

Interface
It can easily be managed by logic bricks, only I’ll have to design the logic system for every object type in the game. A python approach can centralize this task. I though of OOP but I can’t have an action class, with a set of conditions per object. I can have object’s classes, each with it’s action conditions, but well the amount of work is the same. The problem is the usage after. I’m checking the available objects from a list of interactive objects, then one is selected. From there I determine the object type and fill up the options slots and make the option available.

Execution

The selected task is executed according to the object type. Having the 3 properties on True, will trigger the action. This means that we know what object and we know what action the object will perform, and now we have the order to do it. It pretty much applies to most objects.

The idea of action- Reaction is pretty basic. There are cases where interaction is direct and in others aren’t(switch), the 3 states can be used in a generic way for all objects. In any case one action can cause a chain of reactions, so the use of logic bricks is a bit out of question.

In logic bricks:
property sensors checking each property

or
expression controller (triggered by a request e.g. message sensor).

in Python code:
Code:
if obj[“active”] and obj[“selection”] and obj[“execute”]:

I suggest not to re-invent the wheel and simply use Logic bricks.

Actually the question was, how do I use the string as a function.
for instance:


act= ob["select"]
for ob in Control["inter_Objs"]:
    if ob["execute"]== True:
        action(ob, act, None)# In this case act is a string("act1"), so will raise an error, I need it to be a global name to use it as function, therefore need to convert it : action(ob, eval(act), None) maybe?

def action(object, action, target):
     ob executes atc1 on target
def act1():
    action1
def act2():
    action2

Hi Torakunsama,

I suggest to keep objects within the game and objects within the inventory separate. They seam to be the same but logically they are different. The inventory objects are “just” representations to for the player.

I tried such code as you do long time ago. It was hard work and took me a while, but that what this code is processing is exactly what the logic bricks already do.
That is the reason why I went away from pure Python. It is like replacing a porsche 911 with a wood carved bike (If I’m allowed to use such a bad comparison;)) .

… oups I hove to go now. See you later …

Yes Monster, I know that!
The moment the object is ended, it should not be used since it’s a zombie now…
The inventory is a storage place, more like a database, only reference and status ob the objects are kept there!
The logic brick system cannot respond to dynamic messages! I can send a property as message, but can’t receive it.
Th logic bricks will be very costly if the objects have it even to run just once! As an example, I have 1 star to represent all stars in the galaxy. The logic brick setup is to play an action according to a property and then go to state 2 where there are no logic bricks. By doing so, I get a very big logic usage, since the bge seems to remember that those objects ran logic at a given moment and might do it again(I really don’t know…). So having all interactive objects have logic bricks is out of question, when hundreds of objects might appear on screen! This is the case of a space station when there will be places like restaurants, with a few noc and players. If all of them(chairs, food, npc, players, etc) are running a logic brick, the game will crash. Better control it via a module that determines what objects can run logic and which can’t!
I’ll test it out!

You will see if you have the game objects already it is the same if not worse performance when running this in python only.

What you can do is an off screen simulation. This can and shout be done via internal (invisible models). But I think you do not need this much details then (opening doors etc.) A simplified simulation would do the trick as well. The player will not see it anyway.
For example this is done with X by egosoft. The high details run only in the sector the player is in. All other sectors are running a simulation with much lower details as they are not visible. The player can watch (a single) sector on a map (mini-map without the player’s “real sight”). This runs with a bit more details but still far less then at the player’s sector. With that method they can simulate a complete “universe” with hundreds of npcs and a trading simulation.

In that case you are right a single game object acting as “simulator” (proxy) would do the trick. In this case you do not have a game objects nor properties. You need to implement everything (really everything) within Python.

Btw. you can receive properties as message. Just use the S2A. What I meant was not to restrict you to logic bricks only. I meant better use use the logic bricks rather than replace them. If you do not have a game object you are right the simulation must run in Python at the above mentioned proxy.

With that you still have to simulate an event system. There are multiple approaches to do that.
Example: You can create lists or dicts of events.
Virtual objects (listeners) can register on events.
When running run over the events and execute the listeners if the event gets true.

You can loop through all virtual objects and see if any event is dealt by them.

There are much more methods to do that.

You are right!
I use logic bricks where they apply. The case I mentioned before is that there is a drop in frame rate just to have the logic bricks in the objects. The space station example, where I sampled a restaurant can have many levels and active things going on.
An example of multiple objects are client generated content, like other player npc, tools, ship, or any other objects that their existence is not controlled by the player. These objects might be in range or not of the player, but if they are in sight and have multiple logic bricks, this will crash the game. Logic bricks are fast and efficient. However the problem here is not always using a logic, but when to use it. The whole purpose of going mostly python way is to have as less as possible object run logic or complex physics, in order to leave room for other things, like AI, Mission and task managements, database updates and so on! Object interaction, should stay in check!
Since you mentioned other mean of achieving this, I’m very interested now!

I suggest to heavily use states for your objects. With them you can dynamically disable/enable temporarily unnecessary sensors (e.g. the heavy Near or Radar sensors). You can use light weight sensors such as Property sensors to switch into a “heavier” state. I guess this is what you want to achieve with your code (checking properties). I’m pretty sure you get a pretty efficient logic with this method.

The problem with the “one” python code method is it creates a dependency between all involved objects. This means with any change you influence all objects. This quite easy leads to unwanted side effects. If the objects and their logic is separate you can even replace them without touching the other objects.

E.g. You can replace a door with another one without effecting the opener (as it does not care what door it is).

There is more work if you change the interface. Then you need to modify all objects using this interface (but only them) to adapt to this changed interface.
E.g. a doors react on “OpenRequest” property. You decide to rename the property to “Request:Open”. Then you have to modify all doors and all openers. Therefore it is very important to design the interface as early as possible as you currently do.

I suggest to heavily use states for your objects. With them you can dynamically disable/enable temporarily unnecessary sensors (e.g. the heavy Near or Radar sensors). You can use light weight sensors such as Property sensors to switch into a “heavier” state. I guess this is what you want to achieve with your code (checking properties). I’m pretty sure you get a pretty efficient logic with this method.

Indeed, that’s the idea. If I use some logic bricks, it must be that way. In many cases, I’m trying to avoid having too many objects animated, since the frames take up space in memory. I need that memory for lists and dictionaries. For the door example, if I add a width property for the door size, I can in the open action set the object to move to one direction, that length(width). But as I said, I’ll run some tests and see how it goes.

Designing the interface this early is crucial, the number of objects can increase considerably if a standard protocol is not used! So for objects like doors, switches, container, etc, I think there should be only a hand full of them applicable to most facilities!

Example:


This scheme shows three different interfaces. Each of them has a different independent purpose. Be aware this are examples. It is not written in stone ;).

With the Opening-interface an object can open and close another object (e.g. a door). It can also retrieve the current open-state of the other object.

The Locking-interface provides the option to lock and unlock another object. It does not need to be a door. It can be anything. Important is the user has to provide a specific key.

Wait! when I look a door I can’t open it. Isn’t that a dependency between Opening-Interface and Locking-Interface?
No it isn’t. If the user request “open” at the door. The door decides if it opens or not. This means the dependency is at the implementation of the door. The user does not need to know that another interface exist.
The next thing is the user of the Opening-interface is the opener while the user of the Locking-interface is a key.
How you implement the interface is up to you.

The third example is a UserAction-interface as mentioned at post#5 (interface finder).
An object can ask another one what actions it currently allows. The user can request this action by setting a property with the name of the action. Please keep in mind this is just an example. You can define whatever interface you like.

But this interface has a dependency :evilgrin:! Yes, but it is the purpose of this interface to provide information about the other interfaces. This creates a dependency of the UserAction-interface to all implemented interfaces (but not vice versa).

Now an working example:



This shows the declaration of the Opening-Interface,
partly the implementation of this interface and
a usage of the interface.

I hope you see, it does not matter how the interface is implemented at the door. The User is not effected as long as the interface remains unchanged.
The User can change (this is a quick and dirty example) without effecting the door itself. It is up to you how you identify the door and how you use the interface. You can even have multiple users at the same time.

I hope it is somehow understandable what I mean.
Here is the blend:

Attachments

DoorDemo.blend (72.5 KB)

Yes, that is the idea! And that’s the first option I have in mind!
While trying to implement a OOP approach, I’m seeking a way to add property values as part of the code. The type property will be used to call upon a class, and the selected action would be the method. That would make the code very short and simple:


if Obj["Active"]==True:
			n= eval(Obj["Selected"])
			if Obj["Execute"]==True:
				ob= eval(obj["type"])
				ob.n(target)	

http://dl.dropbox.com/u/6162142/COS_Alpha%20V0.1.2/Object%20interaction.jpg

Unfortunately, as far as I know that is not possible. I can however use conditions related to the property, depending on it’s values and the same for the method.

Using logic bricks can be simple and straight to the point. I’ll give that option a second chance.

Hint:


if Obj["Active"]==True:

is redundant
better use


if Obj["Active"]:

I think I know now what you mean with eval(object[‘selection’]). The property value needs to contain Python code. Better avoid. If there is an error it is hard to discover.

I guess you mean the “selected choice of actions”. I think this is what I described as UserAction-interface. You can do that with a string value. Then you can to evaluate the string again via Python or Property. This methods restricts the “action” to one action. This can be fine especially if used as menu item.

Another option is described above (UserAction-interface). It sets one or more properties according to the available options. This would allow to trigger multiple actions (of multiple interfaces) at the same time. But this might not needed in our situation. But it might be easier to implement as you just need to set the property. If you want I can prepare you an example.

BTW:
You can use classes, but you still need one or more modules to call the according methods.
E.g.:


def requestOpen(cont):
  obj = objectFromGameObject(obj) # however you do this
  obj.open() # it calls the specific implementation of this object instance regardless of door or container