0
\$\begingroup\$

I'm having some trouble putting together a method that will constantly move a "bullet" in the same direction accurately. Here is what I have so far

public Vector3f moveFromPosition(Vector3f location, float pitch, float yaw, Game game) {
        Vector3f loc = location;
       loc.z += 0 * Math.cos(Math.toRadians(yaw - 90)) - 1 * Math.cos(Math.toRadians(yaw));
       loc.x -= 0 * Math.sin(Math.toRadians(yaw - 90)) - 1 * Math.sin(Math.toRadians(yaw));
       loc.y += 0 * Math.sin(Math.toRadians(pitch - 90)) - 1 * Math.sin(Math.toRadians(pitch));
       return loc;
    }

This method is being called in the render method, so every frame it will move the bullet 1 space depending on the pitch, yaw, and location the bullet was fired from. The pitch and yaw values stay the same each frame, and the vector3f "location" stands for the location the bullet is currently at. The bullet is then translated accordingly depending on the return location from this method.

The x and z values are calculated correctly, but the y value seems to be a little off and I can't figure out why

Here is where the method is being called from

package Entitys;

import Main.Game;
import Model.Model;
import Tools.TrigCalculator;
import org.lwjgl.util.vector.Vector3f;

public class Projectile {

    Model model;
    Game game;
    Entity entity;
    Vector3f startLocation;
    float startPitch;
    float startYaw;
    TrigCalculator trigCalculator;

    public Projectile(Vector3f startLocation, float startPitch, float startYaw, Entity entity, Game game){
        //The location the camera is at, or where the bullet will be fired from
        this.startLocation = startLocation;
        //Camera's pitch when shot
        this.startPitch = startPitch;
        //Camera's yaw when shot
        this.startYaw = startYaw;
        //The entity representing the bullet
        this.entity = entity;
        //The class the calculation moveFromPosition is at
        this.trigCalculator = game.getToolHandler().getToolTrigCalculator();
    }
    /* This move method is being called in the render method */
    public void move(){
        //Translating the entity according the the calculation below.
        entity.setTranslation(startLocation);
        //Here is where the method is called
        startLocation = trigCalculator.moveFromPosition(startLocation, startPitch, startYaw, game);
    }
}

This is when I'm facing down

Requested Edit: This is how I create a new projectile

projectiles.add(new Projectile(new Vector3f(loc.x, loc.y, loc.z), game.getCamera().getPitch(), game.getCamera().getYaw(),entity, game));

After debugging the return of game.getCamera().getYaw() and getPitch() both return the correct value. Then it's passed into the startPitch value, which is passed into the moveFromPosition method each frame. Other than that it doesn't change.

\$\endgroup\$
6
  • \$\begingroup\$ What is exactly happening with the pitch of the bullet vs what you are expecting? To high/low or wrong trajectory? \$\endgroup\$
    – Shroeder
    Oct 24, 2014 at 16:44
  • \$\begingroup\$ @Shroeder The bullet, as seen in the picture, should be lined up with the cross. When the pitch is 0, it works, but as I move up or down, the bullet starts to move off the target. So something is wrong with the y calculation in the method \$\endgroup\$
    – jthort
    Oct 24, 2014 at 16:51
  • \$\begingroup\$ Yes it looks like your pitch is slightly off, can you show the code you use to get and set the pitch for each logic cycle. \$\endgroup\$
    – Shroeder
    Oct 24, 2014 at 18:33
  • \$\begingroup\$ @Shroeder Edited post \$\endgroup\$
    – jthort
    Oct 24, 2014 at 18:51
  • \$\begingroup\$ Why exactly do you multiply by 0 in moveFromPosition? \$\endgroup\$
    – JFBM
    Oct 25, 2014 at 17:37

3 Answers 3

0
\$\begingroup\$

Well for one, your x,y,and z would stay zero based on moveFromPosition. If you want the bullet to follow a certain path, you need to get rid of the zeros, math calculates anything multiplied by 0 is equal to 0

Your next problem is you are over-complicating the math in moveFromPosition. All you need to do during an update is

float horizontal = Math.cos(Math.toRadians(pitch)) * wantedSpeedForward;
float vertical = Math.sin(Math.toRadians(pitch)) * wantedSpeedForward;

loc.x += Math.cos(Math.toRadians(yaw)) * horizontal;
loc.z -= Math.sin(Math.toRadians(yaw)) * horizontal;
loc.y += vertical;
//if you wanted strafing, or non-forward motion add this
loc.x -= Math.sin(Math.toRadians(yaw)) * wantedStrafingSpeed;
loc.z += Math.cos(Math.toRadians(yaw)) * wantedStrafingSpeed;

This insures the bullet travels at the speed you want based on pitch and yaw (just set the rotations properly and it will work) but you may not want to create a physical bullet projectile like this because if you calculate physics, it will slow down the program a lot so the preferred way is a directional spray, probably through raycasting, and spawning particles after its fired upon the raycasted path. This severely decreases the actual physics and makes bullets simplified and more realistic in the end. Now if you were aiming for a bow, you would want this, but I think I have answered your problem and suggested a better solution if need be so I will hold my peace.

EDIT: wouldn't a separate object for the bullet itself be better (you know, where it holds its position, rotation and anything else significant) All you would need to do is bullet_object.update()

\$\endgroup\$
2
  • \$\begingroup\$ The formula you've given here will move the bullet faster than wantedForwardSpeed if pitch is nonzero. To correct for this, you'd want to multiply the x & z increments by the cosine of pitch. (And as Peethor describes in the other answer, it's beneficial to do this trig only once and cache the increments on the three axes to a velocity vector) \$\endgroup\$
    – DMGregory
    Feb 20, 2015 at 20:29
  • \$\begingroup\$ Yea, I forgot exactly how to use the trig properly at the time and then remembered shortly afterward. I was just making sure understanding was shared here also. \$\endgroup\$
    – Spartan322
    Feb 22, 2015 at 4:36
1
\$\begingroup\$

You're doing something strange: Every frame, you calculate the x,y,z values of the bullet's movement, based on a yaw and pitch that will never change. Why not create a vector3 that stores the direction and speed of the bullet in the bullet constructor? This way, you can do the calculations once per bullet, and then just add its speed vector to its current position every frame. This saves resources.

Also, wouldn't it be easier to store the camera's rotation as a matrix or quaternion? You might already be doing this, I can't tell. If you do that, you could simply say that the bullet's direction is equal to the forward member of the quaternion or matrix.

I've personally had a LOT of issues with rotations when trying to calculate them by yaw pitch and roll (especially when you add the third, it can be a nightmare), but simply copying over a rotation matrix (or quaternion) that already works is quite simple.

\$\endgroup\$
0
\$\begingroup\$

As a rule of thumb: never use Euler angles unless you have to. For velocities, it's probably just better to use vectors, and don't worry about the orientation. You can use the matrix representation of the camera to find which direction the player is facing.

public Vector3f moveFromPosition(Vector3f location, Vector3f velocity, float dt) {
   return location + velocity * dt;   
}

Or, since it seems you're using java, you'll probably need some boiler plate for copying and such.

public Vector3f moveFromPosition(Vector3f location, Vector3f velocity, float dt) {
   Vetor3f loc = new Vector3f(location);
   Vector3f vel = new Vector3f(velocity);
   vel.multiply(dt);
   loc.add(vel);
   return loc; 
}

Then, calculate the velocity like this:

public Vector3f getBulletDirection(Camera camera) {
  return new Vector3f(camera.getForward());
}
\$\endgroup\$
3
  • \$\begingroup\$ "Okay, rule of thumb never use Euler angles unless you have to." If we're working in only two axis (or 2.5D if you will), wouldn't it be ok to use Euler angles as it won't suffer from Gimbal locking? \$\endgroup\$
    – fryBender
    Feb 22, 2015 at 17:48
  • \$\begingroup\$ Gimbal locking is just one of the reasons you wouldn't want to use Euler angles. For one thing, it makes you do trigonometry and do an awkward conversion to matrices or quaternions whenever you want to represent it as a rotation. Euler angles are also difficult to compose without an intermediate representation like a rotation matrix. For 2D it doesn't matter (just one angle). For 2.5D (player orientation on a plane in 3D), it might be okay, but you still suffer from all the above problems. \$\endgroup\$
    – mklingen
    Feb 22, 2015 at 17:57
  • \$\begingroup\$ Thank you, I'm still a beginner with game dev but I think this helped clarify my concerns. \$\endgroup\$
    – fryBender
    Feb 22, 2015 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .