Collision hitPosition?

Now when I try to access the Collision Sensor’s hitPosition I get this,

Python script error - object ‘Cube.001’, controller ‘Python’:
Traceback (most recent call last):
File “gamelogic_simple.py”, line 16, in <module>
File “gamelogic_simple.py”, line 14, in main
AttributeError: ‘KX_TouchSensor’ object has no attribute ‘hitPosition’

Now the Game Engine says that there is no hitPosition for the Collision sensor, and no hitPosition for a ‘KX_GameObject’. But when I turn on Physics visualization, and view two objects colliding in wireframe mode. What do I see?
/uploads/default/original/4X/6/9/a/69a95851f9e96b847ede1c95989226a187310f11.pngstc=1

The hitPositions of the two objects colliding… :confused:

So the attribute must be somewhere… is it accessible via python?

Attachments


yes you must use a collision callback, google will help you further :smiley:

Well now I have been searching on google, and I only found a thread from 2006 with a bunch of people discussing callbacks purpose and a bunch of complicated stuff I don’t understand. :no:

The python API didn’t help either, anytime I try to apply what it says the code does I just get errors saying there is no such attribute.

https://www.blender.org/api/blender_python_api_2_77_0/bge.types.KX_GameObject.html#bge.types.KX_GameObject.collisionCallbacks

… As I said, the blender API didn’t help me, I don’t know how to apply the information they give there, I know it represents 3 arguments, I just don’t know how to access them.

Like if I wanted a cube to go to the point of collision,

Cube.worldPosition = own.collisionCallbacks.collision1

Would it look something like the above? They don’t really tell you how to get the Hit Position. Not from what I can understand anyway from reading it, I really am a coding noob.

a callback is python that you build, and when a event happens it triggers the python

in this case it’s collision, but there are others like pre draw, and post draw.

you need a script to execute to feed the callbacks to the engine (1 time)

inside the callback you then set the property in the player you will need next frame,

I will make a example if I can get a minute,

but just understand

create thing-> each time event happens it calls thing -> thing sets property -> collision sensor fires same frame -> get data saved ln property and do stuff.

I still don’t know how to apply what you’ve said here though. :spin:

quote, quote

ok, after investigating, I got the callback to work however, I don’t know a method to get the owner of the callback, so I will have to hardcode it

so notice, the script runs one time, but the property HitPoint will update now forever.


import bge
def callback_three(object, point, normal):
    print('Hit by %r at %s with normal %s' % (object.name, point, normal))

    #Ugly hardcode because I don't know how to get the callback owner yet
    bge.logic.getCurrentScene().objects['Cube']['HitPoint']=str(point)
    


def main():
    
    cont = bge.logic.getCurrentController()
    own = cont.owner


    if 'init' not in own:
        cont.owner.collisionCallbacks.append(callback_three)
main()



Attachments

HitContact.blend (457 KB)

Thanks! :smiley: Works great!

Use functools.partial or a closure to bind the owner object to the function

Sent from my SM-G920F using Tapatalk

Agoose77, can you provide a example?

http://www.pydanny.com/python-partials-are-fun.html

Sent from my SM-G920F using Tapatalk


import bge
import random


def get_wrapper(owner):
    def wrap(x,y,z):
        owner.applyMovement((x,y,z),1)
    return wrap



def main():
    cont = bge.logic.getCurrentController()
    own = cont.owner
    
    if not "move_calls" in own:
        own["move_calls"] = []
        own["move_calls"].append(get_wrapper(own))
        own["move_calls"].append(get_wrapper(own.parent))
        own["move_calls"].append(get_wrapper(own.parent.parent))
        own.parent.removeParent()
        own.removeParent()
        
    for mc in own["move_calls"]:
        if 0.1 &gt; random.random():
            x = 0.2
            mc(x,0,0)
    
main()

this should be a closure (but i readed also wrapper somewhere)

to note that the reference owner still “traped” in the function nested (not the first)
the reference of wrap that return is a sort of instance unique

Can you make a example using the previous use case?

(Passing the object owning the callback into the callback?)
Otherwise it’s almost useless

(You can’t bind it to multiple objects)

That is already shown in Marcos and my example. Why not give it a try outside the bge

Sent from my SM-G920F using Tapatalk

Yeah, I need simple examples or they are not easily digested.

Adding the wrapper to pass the hitPosition back would also be something currently missing from the API right? Or did they add collision.hitPositionList yet?

As you can see I learn things that are useful to me, and then they stick. The stock callback seems to tell you who you hit, but not who you are.

Edit I see, it’s in the method mode, not the function mode

I got a class working , had to find the code to mutate the game object (sdfgeoff) and adjust it slightly,


import bge


class CustomGameObject(bge.types.KX_GameObject):
    RATE = 0.05


    # Method form
class YourGameEntity(bge.types.KX_GameObject):
    def __init__(self, old_owner):
        self.collisionCallbacks.append(self.on_collision_three)
        self.collisionCallbacks.append(self.on_collision_one)


    def on_collision_three(self, object, point, normal):
        print('Hit by %r at %s with normal %s' % (object.name, point, normal))


    def on_collision_one(self, object):
        print('Hit by %r' % object.name)
        
# Called first
def mutate(cont):
    old_object = cont.owner
    mutated_object = YourGameEntity(cont.owner)


    # After calling the constructor above, references to the old object
    # should not be used.
    assert(old_object is not mutated_object)
    assert(old_object.invalid)
    assert(mutated_object is cont.owner)



always(one time)-----------python.mutate

That will work. If you only want to keep things simple, just use functools.partial, a lambda or closure.

here is a neat example

Attachments

callbackdemo.blend (1.2 MB)