I’m having a weird issue with .alignAxisToVect. The pivot points of the guns turn correctly as long as my ship is pointing at what appears to be X 0 on the global plane, but if I rotate the ship, they seem to continue pointing in that direction (they will eventually seperate from the main base of the gun … making it look like a wheel without hubcaps lol) … and for the life of me, I cannot figure out why. This has been happening for several days now but I didn’t really think much of it until I noticed it again today, and it bugs me. Any help would be appreciated.
the python script (attached to the pivoting point of the guns, note that this is not the barrel. gun has 3 parts … think of this as the middle part):
import GameLogic
from mathutils import Vector
controller = GameLogic.getCurrentController()
obj = controller.owner
ship = GameLogic.ship_data[obj.parent.parent['tag']]
if not ship.target == None:
tracking_speed = obj.parent['tracking']
target = ship.target.position - obj.position
turret = Vector([0, 0, 0])
turret.rotate(obj.orientation)
# align the turret, local Y axis should be locked :/
if obj.parent['sense'] == True:
obj.alignAxisToVect([turret[0], target[1], target[2]], 2, tracking_speed)
showing that they remain normal, and correctly rotate towards the target without seperating if the ship does not rotate:
(0,0,0) is a null-vector that points nowhere. Avoid this value.
I do not know if that is the source of your problem. The images are pretty hard to interpret as it is to dark and the details are to small.
According to the other code target is already a vector no need to convert it to a list. Especially as this function expects a vector as first argument.
if obj.parent['sense'] == True:
this is doing the same thing twice. If the value is already boolean you can check it directly. If it is not boolean it is a bad check ;).
(Btw. what means “sense”? how about “isSensing”?)
tracking_speed = obj.parent['tracking']
property “tracking” describes a speed? Better call it “tracking_speed” too. Otherwise it is not clear that you mean a speed rather than True/False value or the name of a tracking object ;).
target = ship.target.position - obj.position
target is a vector. I would assume it is a game object. Please give it a better name
E.g. vectorToTarget
thanks for the tips, though I have to disagree on a few of them (renaming) :p. also, if you look at the first spot in the list in
([turret[0], target[1], target[2]], 2, tracking_speed)
the first arg was an attempt to fix the problem by copying the turret’s rotation. however, it still happens even if I set the first value to 0.
it gets converted to a Vector by the method anyways (or so it seems, I didn’t notice any change between passing Vector() or just .
here’s a better picture of the (bug?). notice how it appears seperated from the base of the gun. I want it to track the target by rotating up/down, but keep the left/right rotation locked so it stays “attached” to the ship.
You shouldn’t have to involve the physics engine in this at all BluePrint (in my opinion)
There are two ways to do this.
Vector maths. Translate/rotate the vectors to the target to get the proper align vectors for the turret and the barrel. I can’t be bothered doing it this way…
Make sure that the rotation is always zero except in the right planes.
The code I gave you in the other thread used #1, but wasn’t flexible enough to handle turrets at any rotation.
This code here can, but may be perceived by some as the ‘wrong’ way to do it. I don’t mind though, it works.
import bge
def turretAI(cont):
target = bge.logic.getCurrentScene().objects['target']
aimPos = lead(target)
turret = cont.owner
barrel = [chi for chi in turret.children if 'barrel' in chi][0]
aimAt(aimPos, turret, barrel)
def lead(target):
#Will contain the necessary logic to lead ahead of a target
return target.worldPosition
def aimAt(aimPos, turret, barrel):
maxTurn = turret['maxTurn']
#Z axis stuff
turVec = turret.getAxisVect([0,1,0])
aimVec = aimPos - turret.worldPosition
angle = turVec.angle(aimVec)
if angle > 0:
if maxTurn > 1:
factor = 1/maxTurn
else:
factor = maxTurn/turVec.angle(aimVec)
turret.alignAxisToVect(aimVec, 1, factor)
localOr = turret.localOrientation.to_euler()
localOr.x = 0
localOr.y = 0
turret.localOrientation = localOr
#X Axis Stuff
barVec = barrel.getAxisVect([0,1,0])
aimVec = barrel.getVectTo(aimPos)[1]
angle = barVec.angle(aimVec)
if angle > 0:
if maxTurn > 1:
factor = 1/maxTurn
else:
factor = maxTurn/turVec.angle(aimVec)
barrel.alignAxisToVect(aimVec, 1, factor)
localOr = barrel.localOrientation.to_euler()
localOr.z = 0
barrel.localOrientation = localOr
The change between this code and the previous version is that I removed the vector maths, and instead constrained the axis. All the inputs are the same, and I’m sure you can decode/integrate it into your code easily enough.
Thanks but all of the ideas are inspired by CCP’s EvE online. I wanted to make my own version of their game because there were a few aspects of theirs that I don’t like. Also, thanks for the code; I will try it out again, but the first time I used it, it still had the same issue that the screenshots above were having
Edit: I’m so dumb! haha. A few simple changes (I wasn’t fully sure how some of the methods worked back then) and it works like a charm! thanks! now to move on to bigger things
And since when is localOrientation a method? If I knew that a week ago… sigh :L
Yeah I know… for the first few days of learning the api I had that page open nearly 6 hours a day I just don’t know how I missed such an important method.