4
votes

I'm working on a top down shooter HTML5 game. I'm currently trying to get bullets to fire from my characters facing angle.

My character always faces the mouse position (rotates). So, when I fire a bullet, I need to take the rotation into account.

I'm almost there, the only problem is that the bullets initiate where my actual mouse position is, although - it moves in the correct facing direction.

I believe my math is off within my velocity variable:

var b = new Rectangle( this.x + (this.width / 2) - 4, this.y + (this.height / 2) - 4, 8, 8);

var velocityInstance = new Vector2(0, 0);
velocityInstance.x = input.mouseX - (this.localX + this.width/2);
velocityInstance.y = input.mouseY - (this.localY + this.height/2);

var bulletInstance = new Bullet(velocityInstance, b, this.bullets.length + 1);

this.bullets.push(bulletInstance);
this.shotBullet = true;

'this' refers to my Player. localX/Y is the centre position of my character (he's always in the center of the screen, and the scene moves around him).

Would appreciate if someone could check this for me. Thanks!

------ EDIT ------

Here is my Bullet function:

Bullet = function(vel, rectangle, index){

    this.velocity = vel;
    this.rect = rectangle;
    this.index = index;

    this.Update = function(){
        this.rect.x += this.velocity.x;
        this.rect.y += this.velocity.y;

        //Collisions
        for(var c = 0; c < GameObjects.length; c++){
            if(this.rect.Intersects(GameObjects[c])){
                console.debug("Bullet Hit: " + GameObjects[c].tag);

                //Player.bullets.splice(index, 1);
            }
        }
    };

    this.Draw = function(ctx){

        this.rect.Draw(ctxMap);
    };

};
2
If the bullet is always supposed to originate from the character, why is there any mention of input.mouseX or input.mouseY in the calculation? Those values determine the direction of the bullet, not it's position.jbabey
If the bullets are moving in the correct direction, it's not your velocity that's off - it's your bullet's initial position. I would think you're setting it to (input.mouseX, input.mouseY) instead of (this.localX + this.width/2, this.localY + this.height/2), but you haven't shown us the code for position.Scott Mermelstein
I updated my question. My initial seems to be okay? I'm using the players position.Oliver Jones
Is there a difference between this.x and this.localX? If there's not, then yes, the initial position looks ok, and I'd have to blame the code higher up - maybe the part that's rendering the bullets.Scott Mermelstein
localX/Y is the position of the centre of my screen (screen = 300x300, localX/Y = 150x150), this.x is the position of my player (even though the player is always central, it still takes into account its movement around the map).Oliver Jones

2 Answers

3
votes

Actually, I would recommend not using trig functions, simply for efficiency. Math.atan2, Math.cos, and Math.sin can get expensive.

You already have (slightly renamed)

var deltaX = input.mouseX - (this.localX + this.width/2);
var deltaY = input.mouseY - (this.localY + this.height/2);

Why not simply jump this way?

var magnitude = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var velocityScale = bulletSpeed / magnitude;
velocityInstance.x = deltaX * velocityScale;
velocityInstance.y = deltaY * velocityScale;

Its functionally the same, but uses only one Taylor series instead of 3, so should be much more efficient. Faster is better, right?

1
votes

Figured it out. I needed to use Math.cos and Math.sin:

var targetX = input.mouseX - (this.localX + this.width/2);
var targetY = input.mouseY - (this.localY + this.height/2);

this.rotation = Math.atan2(targetY, targetX);

velocityInstance.x = Math.cos(this.rotation) * bulletSpeed;
velocityInstance.y = Math.sin(this.rotation) * bulletSpeed;

Thanks anyway community! Helped me get my head around it!