Analog Movement Based On Camera Orientation

Hey guys,

Last night while dogsitting, I finally decided to suck it up and attempt to program analog joystick movement and view controls in the BGE. To my surprise, I’ve mostly succeeded! Just one problem remains though- I have the player moving in the direction of the left stick, and at a speed relative to how far the player has pressed the stick, but in order to complete my 3rd person game setup, the ‘forward left stick’ direction needs to point in the direction opposite the camera. (If you need an example of this kind of setup, I think it’s used in just about every modern 3rd person game, but the Uncharted series comes readily to mind.)

The camera is parented to the object ‘PEmpty’ which the right stick rotates. I tried creating another empty ‘EmptyDir’ which is also parented to ‘PEmpty’ and grabing its position to obtain the vector of the camera direction. However, as you might expect (lol), it doesn’t work, and I’m stumped.

If you uncomment line 34 in ‘analog.py’ (and comment lines 30 and 31), you will obtain the behavior that does not take the camera angle into account - this is a little hackish, I think, but it’s how I was able to get it working ;). In its current broken state, in lines 30 and 31 I’m attempting to use a similar method, but taking the camera into account.

What’s going wrong here? : /
P.S. Apologies for use of magic numbers, and a messy, unoptimized script- I was so excited I wanted to get it to work first, with the intention of cleaning it up later.

AnalogTestPack.blend (480 KB)

I haven’t looked at your blend file, but an easy way would be to, when you want to move forward, set the Player’s orientation on the Z-axis to be the Camera’s Z-axis orientation, and then move locally. For example,


obj = cont.owner
sce = logic.getCurrentScene()
cam = sce.active_camera

ori = obj.orientation.to_euler()
ori.z = cam.orientation.to_euler().z # Copy only the Camera's Z-axis rotation to the Player's orientation
obj.orientation = ori

xspd = 0.0
yspd = 0.1
zspd = 0.0

obj.applyMovement([xspd, yspd, zspd], 1) # Move locally forward on the Y-axis


That should work pretty much bug-free.

The problem is that I don’t want the player to rotate to match the camera- the camera and player’s orientation are independent. It’ll probably make more sense if you look at the blend.

Easy don’t worry

Use vertex parent
(have the camera parented to 1 vertex on your player)

This make it so that the camera follows you, but doesn’t inherit the rotations.

@ Anubis

I’m already employing vertex parent- PEmpty is vertex parented to the player. I might have misspoke when I said that the player didn’t rotate to match the camera - in the case that the player pushes exactly forward on the analog stick, the player will rotate to the same orientation as the camera.

And therefore, when the player pushes right on the stick, the player will move to face:
(pseudo-code)

camera.orientation - 90 degrees

and in the case of pushing the stick down, he will move to face:

camera.orientation +/- 180 degrees

My problem isn’t with the scene setup (at least I don’t think it is)- the problem is in the script- it seems to me like my script should find these values, but it doesn’t.

Here is my joystick script.

Attachments

Xbox 3D Platforming Controls 2.blend (487 KB)

Thanks very much- I see you’re using a couple trig functions in that script, as opposed to my hackish implementation. I’ll study this one closely.

EDIT: Is this script using any deprecated functionality? It works fine in 2.5, but iirc, the “2.5 way” to import is:

from bge import logic
not
import GameLogic

correct?

I haven’t scripted in 2.4x, so I’m not 100% sure about that.

@HG1- I know you, SolarLune and Linkxgl helped me greatly with the script, but I did start it in the first place. Don’t get me wrong, I don’t mind sharing it at all with the community, but I really don’t appreciate you calling it ‘your’ script. Technically it’s ‘our’ script.

@Starclopsofish: Yeah, I have 2.5, but Blender only recognizes that I have Python 2.7 (I think) on my computer. I do have the latest version of Python (3.something), but Blender refuses to recognize it, so ‘import bge.logic’ doesn’t work on my computer. Even with the latest version of Blender, I find that I still have glitches from previous versions which are still somewhere on my computer. I’m going to delete all versions of Blender and then re-install only the latest one, which will hopefully solve it.

Import GameLogic working with Blender 2.49b and Blender 2.5x. From bge import logic is newer but only works with Blender 2.5x.

@ MCStudios. The most scripts are not from one person. Linkxgl helped you but did not write any code he gave you Joeman16 (Joeman16 = SolarLune) script. I gave you the from me changed analogJoystick2_5x.blend (origanl blendenzo). Then you make you new file with the codes of them. And I explained you how it works, rewrite and fixed your changes several times and at least I finished it. The Camera rotate script is 100% only from me. But to avoid such discussions in the future, I will write blendenzo, Linkxgl, SolarLune, MCStudio and my Script. And I make an new file where I rewrite the last script lines that are not from me.

Double post deleted

Sorry I can’t help, but shouldn’t you provide your script along with the blend file?

@ 2ck

Weird, I thought i packed it, sorry about that- here it is for anyone who’s interested:

from bge import logic
from bge import types
import mathutils
from math import radians
import math

def Analog():
	
	scene = logic.getCurrentScene()
	
	PEmpty = scene.objects['PEmpty']
	EmptyDir = scene.objects['EmptyDir']
	

	cont = logic.getCurrentController()
	obj = cont.owner
	
	motion = cont.actuators['Motion']
	motion.dLoc = [0,0,0]
	speedFactor = .4
	
	nub = cont.sensors['Joystick']
	#print(nub.axisValues)	
	
	#get left analog stick direction and magnitude
	leftStickVector = mathutils.Vector((nub.axisValues[0], nub.axisValues[1], 0))
	leftStickMag = leftStickVector.magnitude
	
	#get 'forward' vector
	forward = EmptyDir.worldPosition
	forward = ((forward[0], forward[1], 0))
	
	# Set 'forward' vector for analog movement - static version - works without camera
	#forward = mathutils.Vector((0, -1, 0))
	
	differ = leftStickVector.angle((forward))
	#differ = forward.angle((leftStickVector))
	
	if nub.axisValues[0] < 0:
		obj.localOrientation = (0, 0, differ)
	else:
		obj.localOrientation = (0, 0, -differ)

	#normalize magnitude
	leftStickMag /= 32767
	if leftStickMag > 1:
		leftStickMag = 1
	print(leftStickMag)
	if leftStickMag >= .25:
		motion.dLoc = [0.0, speedFactor * leftStickMag, 0.0]
		cont.activate(motion)

def Cam():
	cont = logic.getCurrentController()
	obj = cont.owner
	
	motion = cont.actuators['Motion']
	motion.dRot = [0,0,0]
	rotFactor = .1
	nub = cont.sensors['Joystick']
	rightStickHozValue = -nub.axisValues[3]
	
	if rightStickHozValue > 6400 or rightStickHozValue < -6400:
		motion.dRot = [0,0,rightStickHozValue * rotFactor / 32767]
		cont.activate(motion)
	

But, after taking a look at HG1’s blend, I’ve trashed this version and I’m using a new script which implements the method in that .blend for moving the player based on the camera position.

I’ve also added vertical camera movement (look up and down) which is currently functional, but buggy until I can squash the last remnants of gimball lock. (ugh) I will also add zooming in/out as I did in an earlier effort (the easiest part) once I have the vertical movement squared away.

So… who should I credit when this script is eventually released with a project? (Even though I “clean-room” reverse engineered it, some parts look nearly identical, and I’d just like to credit whoever was responsible anyway out of courtesy).

SolarLune, HG1, Linkxgl, MCStudios, blendenzo, any others?

Thanks again for the help!

EDIT: Yes, I know it’s really ugly and redundant, but I was really excited while writing it- don’t make fun of me!