I've got a fairly intricate issue. Essentially, I've got an object that tracks a players position, using a LOS algorithm to always fly towards the players current position.
I'm having an issue however, as I'm trying to get the object to shoot bullets in the direction of the player. The object uses pure vector mathematics to move towards the player, but considering how my functions operate, the bullets need to use quaternions.
So, if an object moves towards a player, how can I make a Quaternion rotation that can be used by the bullet function to create bullets that also move towards the player with their source being the object?
My function to draw the object that follows the player:
private void drawEnemy(GameTime gameTime)
{
angle += 0.1f;
velocity = Vector3.Normalize(xwingPosition - enemyPos) * 0.02f;
enemyPos = enemyPos + velocity;
enemyWorldMatrix = Matrix.CreateRotationY(angle) * Matrix.CreateTranslation(enemyPos);
DrawObject(enemy, enemyWorldMatrix, viewMatrix, projectionMatrix);
//enemyRotation = GetRotation(xwingPosition, enemyPos);
//Quaternion additionalRot = Quaternion.CreateFromAxisAngle(new Vector3(0, -1, 0), -0.1f) * Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), -0.1f);
//enemyRotation *= additionalRot;
double currentTime = gameTime.TotalGameTime.TotalMilliseconds;
if (currentTime - enemyLastBulletTime > 1000)
{
EnemyBullet newBullet = new EnemyBullet();
newBullet.position = new Vector3(enemyPos.X + 0.2f, 71, enemyPos.Z + 0.2f);
newBullet.t = 0.01f;
newBullet.proportion = newBullet.t / 120;
newBullet.playerPosition = xwingPosition;
newBullet.enemyPosition = enemyPos;
newBullet.currentAccel = 0.025f;
enemyBulletList.Add(newBullet);
enemyLastBulletTime = currentTime;
}
}
As you can see, it uses vector maths to track and move towards the player.
As you can see, I'm trying to create bullets. The bullets use a Quaternion rotation that I'm hoping I created correctly.
My function to update the positions of the bullets once they are created from the first function I wrote.
private void UpdateEnemyBulletPositions()
{
for (int i = 0; i < enemyBulletList.Count; i++)
{
EnemyBullet currentBullet = enemyBulletList[i];
currentBullet.t += 0.01f;
currentBullet.position = enemyPos + (Vector3.Normalize(currentBullet.playerPosition - currentBullet.enemyPosition) * currentBullet.proportion);
MoveForward(ref currentBullet.position, currentBullet.rotation, 0.04f + (currentBullet.currentAccel));
enemyBulletList[i] = currentBullet;
BoundingSphere bulletSphere = new BoundingSphere(currentBullet.position, 0.05f);
CollisionType colType = CheckCollision(bulletSphere);
if (colType != CollisionType.None)
{
enemyBulletList.RemoveAt(i);
i--;
if (colType == CollisionType.Target)
gameSpeed *= 1.05f;
}
}
}
xwingPosition is the players current position.
enemyPos is the current position of the object that follows the player
The issue is shown in this youtube clip which Im just preparing...
http://www.youtube.com/watch?v=PnkCVKdfN9Y
I think the problem lies with setting t to the total elapsed milliseconds rather than a counter starting from 0. Thing is, I don't know how to start a counter from 0 each time a bullet is made.
The linear trajectory between two points E and P (3d vectors representing the enemy and the player) can be calculated with the following formula:
T(t) = E + t*(P-E)
where t is a coefficient that varies from 0 to 1 (for the bullet to animate).
This is a base you can build from. However, you might want your bullets to have a limited reach. If that was the case, you could do the following:
D = P-E
len = sqrt(Dx^2 + Dy^2 + Dz^2)
. Where Dx is the x coordinate of D, etc., and ^2 means squaredND = (1/len)*D
. (Just divide each coordinate by len
)Now, in ND
, you will have a vector of length one, in the direction of the enemy to the player. Every time you fire a bullet, you should allocate a structure where you store:
ND
E
, the current position of the enemy)In every cycle of your game, for each bullet that is "alive" (the following is pseudocode):
bullet.t += 1
if(bullet.t < maxNumberOfCyclesABulletLives){
bPos = bullet.E + bullet.t * coefficient * bullet.ND // coefficient is the distance the bullet should move in each cycle
if(bPos touches P){
damageToPlayer()
releaseTheStructureForThisBullet()
}
else drawBulletInPosition(bPos) // depending on your gaming library, you may have to erase it from the previous position
}
else{
makeTheBulletExplode()
releaseTheStructureForThisBullet() //or rather return it to a pool, where it can be reused
}
By the way, you game looks quite cool. I expect a free copy once you publish it ;-)