Mouse Look and Grab with just python (no actuators)

Apologies if this is a common question but I cannot find the answers in my searches.

I would like to control mouse look and grab objects with the mouse but with a pure python script (no actuators, just an always sensor hooked to a python controller)

So far I am able to sort of control both, but not in the kind of easy, fluid manner I’ve seen in some demo’s. Here’s a demo of the kind of ‘grab’ control I’m looking for,


see 11:43 - grabbing chain object in the game engine.

So I’m posting what I have in hopes that a bge guru will see what I’ve messed up and enlighten me. Thanks in advance.
Here’s what I’ve come up with so far.


import bge
from mathutils import Vector

co = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()

keyb = bge.logic.keyboard
mous = bge.logic.mouse
mous.visible = True

obCam = scene.objects['Camera']

sensi = [.001, .001]                #MOUSE LOOK SENSITIVITY
w = bge.render.getWindowWidth()
h = bge.render.getWindowHeight()
mx = int(mous.position[0] * w)      #MOUSE POS in PIXELS
my = int(mous.position[1] * h)
x = (w/2 - mx) * sensi[0]           #ADJUSTED LOOK dLOC
y = (h/2 - my) * sensi[1]


p0 = mous.position[0]-.5, -(mous.position[1]-.5)
######################
###---MOUSE GRAB---###
######################
if mous.events[bge.events.LEFTMOUSE]>0:
    msense = co.sensors['Mouse']
    if msense.positive:
        obH = msense.hitObject

        camZvec = obCam.localOrientation[2]
        mvec = Vector((0, p0[0], p0[1]))
        nloc = (camZvec + mvec)
        
        obH.worldPosition = nloc


######################
###---MOUSE LOOK---###
######################
if mous.events[bge.events.MIDDLEMOUSE]>0:

    obCam.applyRotation((0, 0, -x), False)
    obCam.applyRotation((-y, 0, 0), True)
    bge.render.setMousePosition(int(w/2), int(h/2))



@andrew101 - Thanks so much, that was an incredibly helpful and thorough explanation and answer. I’ll get on implementing this right away. You made my day!

Yes, andrew-101
that was a nice lesson!
Thank you!

that is what the mouse over any sensor already provides you ;).

Are you referring to the hit position? There is no hit position if the mouse is not over anything :wink:

I added a PD function to so the object would keep its velocity so you could ‘throw’ it.
here’s the code. Just needs an mouse over any sensor hooked up to this script.
Also doesn’t effect static objects.


import bge
from mathutils import Vector

co = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
msense = co.sensors['Mouse']

mous = bge.logic.mouse
mous.visible = True
keyb = bge.logic.keyboard

obCam = bge.logic.getCurrentScene().active_camera

######################
###---MOUSE GRAB---###
######################
def PDCLlin(cloc, tloc, lv, k, y):     ###---PD CONTROLLER
    #   cloc - current pos | tloc - target pos | lv - lin velocity
    #   k - stiffness     | y - damping
    dloc = tloc - cloc
    f = (k*(dloc)) - (y*(lv))
    return f

def mouseMove(obj): ### THANKS andrew-101
    p = msense.rayTarget
    c = obCam.worldPosition
    o = obj.worldPosition # point on the plane
    n = obCam.worldOrientation[0].cross(obCam.worldOrientation[1]) # normal to the plane
    npos = c + (n.dot(o-c) / n.dot(p-c)) * (p-c)
    linf = PDCLlin(o, npos, obj.worldLinearVelocity, 250, 25)
    obj.applyForce(linf, False)

if mous.events[bge.events.LEFTMOUSE]>0:
    if msense.positive:
        obH = msense.hitObject
        mouseMove(obH)

thanks again to andrew-101, you really helped me understand this better.