Posted: 12th May 2023 4:22
So I need when my player comes up to other objects for there heads to point to them.

I have this and it works but there heads turn all the way around. So I need to figure out a way to limit there head bone rotation to 90 deg.

Here is the code I am fighting with and I used a lot of different ways and nothing works.

Right now i figured to have the bone look at the player with getting the bone ang z but well, that is pointless.

+ Code Snippet
	if ( GetObjectIsAnimating(Taurus) = 0 ) 
		SetObjectAnimationSpeed(Taurus,60)
		SetObjectBoneCanAnimate( Taurus, headBone, 0 )
		PlayObjectAnimation( Taurus, "", 1, 60, 0, 0.5 )
	endif
    bonex# = 2*GetObjectBoneWorldX( Taurus, headBone ) - GetObjectX(Player)
    boney# = 2*GetObjectBoneWorldY( Taurus, headBone ) - GetObjectY(Player)
    bonez# = 2*GetObjectBoneWorldZ( Taurus, headBone ) - GetObjectZ(Player)
    
Headang#=GetObjectBoneWorldAngleZ(Taurus, headBone)
if Headang#>2 and Headang#<3  then setObjectBoneLookAt( Taurus, headBone, bonex#, boney#, bonez#, 0 )
Posted: 12th May 2023 14:14
I'd recommend using the angle between your player object as a whole and the item to determine if the head should be pointed at it or not. This can be done using the dot product of two heading vectors on the XZ plane, one for the player's forward direction and one for a dummy object that is set to always look at the item.

+ Code Snippet
SetWindowSize(1280,720,0)
SetVirtualResolution(1280, 720)

oPlayer = CreateObjectBox(0.4, 2, 0.25)
oItem = CreateObjectBox(0.5, 0.5, 0.5)
SetObjectPosition(oItem, 0, 0, 5)

// dummy object to look at item object
oDummy = CreateObjectBox(0.1, 0.1, 2)

// vectors to store headings
hvDummy = CreateVector3()
hvPlayer = CreateVector3()


MoveCameraLocalZ(1,18)


while not GetRawKeyPressed(27)

    delta# = GetFrameTime()
    
    // handle rotation
    turn# = (GetRawKeyState(68) - GetRawKeyState(65))
    RotateObjectGlobalY(oPlayer, turn# * 90 * delta#)

    // handle movement
    move# = (GetRawKeyState(87) - GetRawKeyState(83))
    MoveObjectLocalZ(oPlayer, move# * 4.0 * delta#)

    // set dummy object position to player position on XZ plane only
    SetObjectPosition(oDummy, GetObjectX(oPlayer), 0, GetObjectZ(oPlayer))

    // set dummy object to look at item position on the XZ plane only
    SetObjectLookAt(oDummy, GetObjectX(oItem), 0, GetObjectZ(oItem), 0)

    // set heading vectors for dummy and player on XZ plane
    SetVector3(hvDummy, cos(GetObjectAngleY(oDummy)), 0, sin(GetObjectAngleY(oDummy)))
    SetVector3(hvPlayer, cos(GetObjectAngleY(oPlayer)), 0, sin(GetObjectAngleY(oPlayer)))

    // get the dot product of the two heading vectors
    hvDot# = GetVector3Dot(hvDummy, hvPlayer)

    // if dot product < 0, then the angle from player to item is > 90 degrees
    if hvDot# >= 0
        print("In range!")
    else
        print("NOT in range!")
    endif


    print(hvDot#)
    print("")
    print("Move with WASD")

    sync()

endwhile
Posted: 12th May 2023 15:53
And here's a method that doesn't use a dummy object, as I know some people don't like using them. Not sure which method would be more performant, though.

+ Code Snippet
type tVector3
    x as float
    y as float
    z as float
endtype

SetWindowSize(1280, 720, 0)
SetVirtualResolution(1280, 720)

oPlayer = CreateObjectBox(0.4,2,0.25)
oItem = CreateObjectBox(0.5,0.5,0.5)

SetObjectPosition(oItem, 0, 0, 5)

MoveCameraLocalZ(1,15)

while not GetRawKeyPressed(27)

    delta# = GetFrameTime()

    // handle rotation
    turn# = (GetRawKeyState(68) - GetRawKeyState(65))
    RotateObjectGlobalY(oPlayer, turn# * 90 * delta#)

    // handle movement
    move# = (GetRawKeyState(87) - GetRawKeyState(83))
    MoveObjectLocalZ(oPlayer, move# * 4.0 * delta#)

    // get player and item positions on XZ plane as vector3
    pPos as tVector3
    iPos as tVector3
    pPos = ObjectPositionToVector3(oPlayer)
    iPos = ObjectPositionToVector3(oItem)
    pPos.y = 0
    iPos.y = 0 

    // get vector pointing from player to item on XZ plane
    dVec as tVector3
    dVec = Vector3Subtract(iPos, pPos)
    
    // normalize it
    dVec = Vector3Normalized(dVec)

    // get player direction on XZ plane (heading vector)
    hVec as tVector3
    hVec = YAngleToHeadingVector3(GetObjectAngleY(oPlayer))

    // get dot product of player heading and heading toward item
    hvDot# = Vector3DotProduct(dVec, hVec)

    // if dot product < 0, then angle from player to item > 90 degrees
    if hvDot# >= 0.0
        print("In range!")
    else
        print("Not in range!")
    endif

    print(hvDot#)
    print("")
    print("Move with WASD")

    sync()
endwhile

function YAngleToHeadingVector3(angle as float)
    v as tVector3
    v.x = sin(angle)
    v.y = 0
    v.z = cos(angle)
endfunction v

function Vector3DotProduct(v1 ref as tVector3, v2 ref as tVector3)
    dot# = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
endfunction dot#

function Vector3Magnitude(v ref as tVector3)
    mag# = sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
endfunction mag#

function Vector3Normalized(v ref as tVector3)
    nv as tVector3
    mag# = Vector3Magnitude(v)
    nv.x = v.x / mag#
    nv.y = v.y / mag#
    nv.z = v.z / mag#
endfunction nv

function ObjectPositionToVector3(obj)
    ov as tVector3
    ov.x = GetObjectX(obj)
    ov.y = GetObjectY(obj)
    ov.z = GetObjectZ(obj)
endfunction ov

function Vector3Subtract(v1 ref as tVector3, v2 ref as tVector3)
    sv as tVector3
    sv.x = v1.x - v2.x
    sv.y = v1.y - v2.y
    sv.z = v1.z - v2.z
endfunction sv
Posted: 12th May 2023 21:48
hendron thank you, I will check it out today and let you know. This is such a big help.
Posted: 13th May 2023 3:20
Ok this kind of works but only when I am looking at the other object, If I am behind him and still looking at him his head still turn's all the way around as it is not set to pos but angles.
Posted: 13th May 2023 13:06
Not sure I follow. Can you post a video of what's happening? The example I posted is meant to show how you can determine if an object is within 90 degrees of the player avatar's forward direction (as a whole, not the head bone). The logic being that you would only set the head bone to look at the object if it falls into this range. If it falls outside, set the head bone back to its normal orientation.
Posted: 13th May 2023 13:41
Ok picture one shows a normal head rotation when I am in front of him.

picture 2 shows head turned into body when I'm behind him or even beside him.

No matter how far away I am I still get a in range=1 when I am turned to him.









code I'm using and thanks for looking.

+ Code Snippet
	if ( GetObjectIsAnimating(Taurus) = 0 ) 
		SetObjectAnimationSpeed(Taurus,60)
		SetObjectBoneCanAnimate( Taurus, headBone, 0 )
		PlayObjectAnimation( Taurus, "", 61, 90, 0, 0.5 )
	endif
    bonex# = 2*GetObjectBoneWorldX( Taurus, headBone ) - GetObjectX(Player)
    boney# = 2*GetObjectBoneWorldY( Taurus, headBone ) - GetObjectY(Player)
    bonez# = 2*GetObjectBoneWorldZ( Taurus, headBone ) - GetObjectZ(Player)
   
    // get player and item positions on XZ plane as vector3
    pPos as tVector3
    iPos as tVector3
    pPos = ObjectPositionToVector3(Player)
    iPos = ObjectPositionToVector3(Taurus)
    pPos.y = 0
    iPos.y = 0 
 
    // get vector pointing from player to item on XZ plane
    dVec as tVector3
    dVec = Vector3Subtract(iPos, pPos)
     
    // normalize it
    dVec = Vector3Normalized(dVec)
 
    // get player direction on XZ plane (heading vector)
    hVec as tVector3
    hVec = YAngleToHeadingVector3(GetObjectAngleY(Player))
 
    // get dot product of player heading and heading toward item
    hvDot# = Vector3DotProduct(dVec, hVec)
 
   // if dot product < 0, then angle from player to item > 90 degrees
    if hvDot# >= 0.0
        print("In range!")
        setObjectBoneLookAt( Taurus, headBone, bonex#, boney#, bonez#, 0 )
    else
        print("Not in range!")
    endif
Posted: 13th May 2023 14:00
Ah, so you're talking about the NPC looking at the Player? In that case, you need to run the code from the perspective of the NPC. I've turned the code into a function that should be able to be used on any character.

+ Code Snippet
function CharLookAt(charObj, charHeadBone, targetVector ref as tVector3)
    // get character and target on XZ plane
    charPos as tVector3
    targetPos as tVector3
    charPos = ObjectPositionToVector3(charObj)
    targetPos = targetVector
    charPos.y = 0
    targetPos.y = 0 

    // get vector pointing from character to target on XZ plane
    dVec as tVector3
    dVec = Vector3Subtract(targetPos, charPos)
    
    // normalize it
    dVec = Vector3Normalized(dVec)

    // get character direction on XZ plane (heading vector)
    hVec as tVector3
    hVec = YAngleToHeadingVector3(GetObjectAngleY(charObj))

    // get dot product of character heading and heading toward target
    hvDot# = Vector3DotProduct(dVec, hVec)

    // if dot product < 0, then angle from character to target > 90 degrees
    if hvDot# >= 0.0
        setObjectBoneLookAt( charObj, charHeadBone, targetVector.x, targetVector.y, targetVector.z, 0 )
    else
    // I'm not sure about this code here, but the idea is to just set the head back to normal if it's out of range
        setObjectBoneRotation( charObj, charHeadBone, 0, 0, 0)
    endif
endfunction


you can call it like this:

+ Code Snippet
lookTarget as tVector3
lookTarget.x = bonex#
lookTarget.y = boney#
lookTarget.z = bonez#
CharLookAt(Taurus, headBone, lookTarget)


Let me know if it works. I haven't tested it myself because I'd need to setup a character for it to do so.

[edit] updated some of the variable names to make more sense in the context of the function
Posted: 13th May 2023 14:12
GameControls.agc:614: error: Cannot convert type "Integer" to "Type"

It is trying to convert my player integer into a type and does not like this.

lookTarget as tVector3
lookTarget.x = bonex#
lookTarget.y = boney#
lookTarget.z = bonez#
CharLookAt(Taurus, headBone, Player)
Posted: 13th May 2023 14:15
use lookTarget instead of Player (I'm assuming from your previous code snippet that bonex#, boney# and bonez# are the target coordinates you want the NPC to look at?)
Posted: 13th May 2023 14:18
Oh lol, my mistake, it works, it works good, But his head snaps back to to the rest head pos real fast like he was hit by something lol.

It looks funny. But it works.

One problem at a time I always say.
Posted: 13th May 2023 14:23
Cool, glad it worked. Look into object tweens to fix the head snapping.
Posted: 13th May 2023 14:24
Ok sure thing.

Thank you very much for the help
Posted: 13th May 2023 14:25
double post i guess