Help Needed: How to reference a Radar.hitObjectList to Constraint ID

Hello, I have a small predicament. My goal is to have my Player object jump and swing onto a pole, and swing back and forth with the option to jump off when desired. I have successfully achieved this through a Point to Point add/remove constraint script (http://tinyurl.com/TFB3D-PtoP), an Edit Object actuator(to change player from dynamic to rigid body and vice versa), and a “teleport” script(player.localPosition = object.localPosition) to set the player beneath the pole.

My issue is this:
I need to set obj1 in the Point to Point script to the hit object (pole) of a rader (obj2 is the player). This is so that whichever pole with the property “pole” is detected by the radar becomes obj1.

This seems simple enough, but I am not completely sure how to do it. I thought about making a script that detects the radar hit object, then stores it to be referenced by the PtoP script. I tried the globalDict, but that was unsuccessful (plus I read that globalDict is not suitable to store game objects), and I am not sure how to do it otherwise. Help would be much appreciated. I have decent python knowledge, so don’t be afraid to scare me with some code.

Thanks

Jo

I can’t follow your link from here.

what I read from your post is that you might mean KX_GameObject.getPhysicsId().

Btw. I would not call variables obj1 and obj2.

If you have multiple objects for the same purpose, place them in a list (objects[0], objects[1]).
If you have multiple objects with different purposes give them a name that describes that purpose (e.g. target, hook, player).

GlobalDict’s purpose is to be used by the save/load actuators. “mis-using” it for other purposes is not a good design decision. You can create your own dictionary/lists/containers at any module/game object you want.

GlobalDict is a plain dictionary. It can contain KX_GameObjects. But it makes no sense in an save/load system, as you can’t marshal/unmarshal a KX_GameObject.

Ok, ya I figured GlobalDict wasn’t an option. Sorry about the link here is another: http://www.tutorialsforblender3d.com/BGE_Python/Physics_Constraints/PointToPoint/PointToPoint_removeConstraint.html

KX_GameObject.getPhysicsId(). is part of it; the PtoP constraint script uses this to get the PhysicsId of obj1:

# get object listobjList = scene.objects


# get Obj_1
obj1 = objList["Pole1"]#this is the value I want to be Radar.hitObjectList or Near.hitObject


# get Obj_2
obj2 = player


# want to use a point constraint
constraintType = 4


# get obj1 physics ID
obj1_ID = obj1.getPhysicsId()


# get obj2 physics ID
obj2_ID = obj2.getPhysicsId()

If you have multiple objects for the same purpose, place them in a list (objects[0], objects[1]).

Making a list of every pole would work, except that if I want a large scale map with many different poles, naming and listing each one would seem inefficient. If each pole had the property “pole”, a radar or near sensor should be able to get the object’s name in order to be referenced as obj1. (see this Track to Nearest for some clarity: https://www.youtube.com/watch?v=hzgFS5M7SCo)

So just to clarify so it’s not confusing: obj1 is a pole. obj2 is the player. The constraint connects the player to the pole’s origin (x=0.0, y=0.0, z=0.0) using the Point to Point constraint (constraint type = 1). If there is more than 1 pole in the scene, I want whatever pole the player is nearest to or that the player “looks at” to become obj1 (obj1 = Near/Radar.hitObject). The script then takes the hit.Object (which is obj1) and gets it’s PhysicsID. I hope that makes sense.

Like I said in my first post, it seems simple enough, I just can’t quite figure out how to do it. :frowning:

Btw. I would not call variables obj1 and obj2.

Haha ya I was too lazy to make them something better like “pole” and “player”.

It seems this is what you want (on an higher abstraction layer):

A) the player is already known
B) a way to select a pole (or “climbable” [I guess your English is better than mine])
C) a way to create a p2p with A) and B)

All these operations can be implemented separately in any complexity you like.
example on C)


def createPointToPoint():
  player = getPlayer()
  pole = getSelectedPole()
  constraint = createPointToPointConstraint(player, pole)

Obviously you need to detail the implementation further (getPlayer, getSelectedPole, createPointToPointConstraint). It is also missing the sensor handling.

Btw. getSelectedPole does not need to do any complex processing. These can be done somewhere else beforehand (e.g. by a selector = game object that performs selection). getSelectedPole just needs to know how to get the result of the previous selection operation. The constraint can’t be started before this isn’t known anyway.

I hope you get what I mean.

In 2.49 you could store references to objects like this:


cont = GameLogic.getCurrentController()
own = cont.owner

reference_to_me = id(own)

Then to get the object to play with:


objectReference = GameLogic.getCurrentScene().objects.from_id(reference_to_me)

# Then you can do things like...
objectReference["Property"] = "woo"
objectReference.position = [1,2,3]

Perhaps someone who is familiar with recent Blender builds can update that into relevant code.

Wow thanks guys! BluePrintRandom thats pretty much exactly what I’m looking for (change ray to radar/near of course), however is it possible to work between states? Let me explain: In state 1 the player can move around. When space is pressed to jump, the state switches to 2 (jump state). In state 2, if the radar/near sensor senses the pole object with the property pole, the pole object is referenced to state 3 where the player switches to rigid body, and the constraint is added (then space to jump off). here is a blend file of exactly that (without the near/radar):pole swing.blend (533 KB)

TheDave I tried the 2.49 method and as may have been expected, it did not work. :’(

Working with ids is pretty strange and does not look like a good design. Even in 2.49 you were able to keep game object references in properties. In pre-2.49 the properties where limited to primitive data types.

The only place it might be useful are messages as they support string values only. But still I do not recommend to use them.

Typically you store such information somewhere in your object. This can be a property or even a logic brick. In your case a property seems to be sufficient.

I strongly suggest you give our states names. Numbers are hard to handle. What I do is I name the according state change actuators. This way it is easy to read, what the next state is supposed to do.

If you want you can add a dummy controller at the top of each state with a name of the state. This was the 2.49 way of state naming. Unfortunately state naming was removed in 2.50.

Scanning
Back to your problem:
state 2 is your “jumping” state. As you already explained it should sense for a pole too(it does not matter how). The result of the scan is either there is one (next state 3) or there is none (continue jumping).

As you need the found pole you can store it in a property:


def storeNearestHitObject():
   hitObjects = retrieveHitObjects()
   hitObject = getNearestObject(hitObjects)
   owner = getOwner()
   owner["pole"] = hitObject
   
def retrieveHitObjects():
   ...

def getNearestObject(objects):
   ...

def getOwner():
   return bge.logic.getCurrentController().owner


Again pretty abstract, but I guess you are able to implement them.
You activate this Python controller with a radar, near, ray or whatever sensor.
Btw.: I prefer Module mode “yourModule.storeNearestHitObject”.

In your situation it is easy to determine if a pole was found or not. We know that if a pole was in sensor range one will be picked. So you can decide with “AND” that it was successful.
[This does not work if the code filters the hitObjects even further. In this case, you either check the property or activate the actuator from the Python controller).

Hanging

After you know what pole to use [point B) in the above list]. You have all information you need to create the constraint.


def createPointToPoint():
  player = getPlayer()
  pole = getSelectedPole()
  constraint = createPointToPointConstraint(player, pole)

looks familiar? Now look into more details:


def createPointToPointConstraint(player, pole):
    return bge.constraints.createConstraint(
        pole.getPhysicsId(), 
        player.getPhysicsId(),
        bge.constraints.POINTTOPOINT_CONSTRAINT,
        0.0, 0.0, 0.0)

This is pretty much the same what you had. Just skipped this (incorrect) comments and used the constant with its name.

But it is not enough you need to store the constraint to allow removing it at a later stage:


ROPERTY_CONSTRAINT = "constraint"

def createPointToPoint():
   ...
   player[PROPERTY_CONSTRAINT] = constraint

Not really much more, isn’t it?

Releasing
ok, now lets look at the “release” state (4).


def release():
    player = getPlayer()
    constraint = player.get(PROPERTY_CONSTRAINT)
    if not constraint:
        return
    
    bge.constraints.removeConstraint(constraint.constraint_id)
    del player[PROPERTY_CONSTRAINT]

Basically we grab the stored constraint. Remove it from physics and remove it from store, that we do not try it again. Btw. this should be done once only.

States
A word to your states. Mixing set and add is not really a good idea. This is pretty confusing, especially as you set a state from an added one. I suggest to stay clean and use set only.

The re-positioning can be performed while creating the constraint, or shortly before. This saves a state.

There are quite a few always sensors that do the same thing. Most of them can be replaced by a single one.

If that does not really help. I can post you a demo tomorrow.

you need


if own['Constraint']!="Empty":
    state = swinging

if own['Contstraint']=="Empty":
    if feet on ground:
        state=walking

etc?

Wow that does help! However, I have had little experience coding with module types as opposed to script types, so I’m not completely sure how to compile all this goodness into module compatible code. Would you be willing to creating a code and/or example file?

The coding style between module and script mode is minimal. See the BGE Guide to Python Coding (follow the Guide link in my signature) on the details.

As promised here is an demo. There are just a few changes to your original design. I hope you see the idea.

Remark: It seems the used radar sensor senses at the incorrect location after deactivation. I fixed that by connecting it to a controller in state 4 - release. This re-positioned it to the object. There is no other purpose of that sensor - controller combination.

Attachments

pole swing revised.blend (412 KB)

Wow, that did it! It works perfectly, I just went ahead and added another detector module brick the the release state (4) and a state switch actuator to the hanging state (3) so the player can jump from pole to pole. I’ll definitely look at that Python Guide; modules seem like very useful assets to one’s coding knowledge bank. Thank you all for the help everyone, the forum is a great place to meet very talented and intelligent people willing to help others in need! :smiley: