Jump to content

Rotate bullets position in rotation of gun


alexandernst
 Share

Recommended Posts

I have done a demo code that creates a gun (blue box) and bullets (red boxes).

How can I set the initial position of the bullets depending of the rotation of the gun?

Said with other words, if I rotate the gun (left/right arrows) , the bullets keep coming from the top side of the gun (box) instead of rotating accordingly.

 

Code: http://plnkr.co/edit/3evg6J2cGo0nS7QKxiak?p=preview

Preview: http://run.plnkr.co/AodG3n4Ykb3osdh2/

Link to comment
Share on other sites

Hey, i couldnt actually get the gun to rotate, but looking at the code quickly, you could try putting the gun fire code in the update() loop too. If it is in create() it will not update as the gun changes, so always fires as per calculations in the called once only create()..... 

Link to comment
Share on other sites

Preview says internal server error...

If the gun is not moving at all fair enough, but remember that maybe it is because the sprite is transformed after its position. Ie what we see is not what the code will have as its position. But I am a phaser3 noob too, so can-t guarantee, but it appears that is its modus operandi.

To test it, start with the gun angled in create(), then see how it fires

EDIT 

HAD A LOOK and this isnt the problem, sorry

Link to comment
Share on other sites

Put this in your update() and fire repeatedly

update() {
      this.gun.setOrigin(0,0);
      this.gun.angle -= 1;
      this.gun.x -= 1;
      
  }

Notice that you are firing from the origin, its pivot point. I may well have been right after all on closer inspection. It fires from origin() irrespective of subsequent transforms.

Not sure what you can do now though? I am still tinkering.... try Groups??? or setOrigin dynamically as it rotates?

Link to comment
Share on other sites

I feel my entire approach is not optimal. There must be "something" that I can use, like "attach" that "something" to one of the sides of the box and make the bullets go out from that "something", no matter where it's located or how it's rotated.

Link to comment
Share on other sites

I've modified your code, now it should work as expected. There's still a problem with your bullet's move direction, you need to use a Point/Vector2 or an angle to control that.

class Bullet extends Phaser.GameObjects.Sprite {
  constructor(scene) {
    super(scene, 0, 0, 'bullet');
    this.speed = Phaser.Math.GetSpeed(400, 1);
  }
  
  fire(x, y) {
    this.setPosition(x, y);
      this.setActive(true);
      this.setVisible(true);
  }
  
  update(time, delta) {
    this.y -= this.speed * delta;
    this.x -= this.speed * delta;
    
    if (this.y < -50) {
      this.setActive(false);
      this.setVisible(false);
    }
  }
}

class Gun extends Phaser.Scene {
  constructor(config) {
    super({
      key: "Gun"
    })
  }
  
  preload() {
    this.load.html("gun", "gun.html", 50, 50);
    this.load.html("bullet", "bullet.html", 20, 20);    
  }
  
  create() {
    this.gun = this.add.image(400, 300, 'gun');
  
    this.key_left = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT);
    this.key_right = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT);
    
    this.bullets = this.add.group({
        classType: Bullet,
        maxSize: 10,
        runChildUpdate: true
    });
    
    this.input.on("pointerdown", (event) => {
  
        let bullet = this.bullets.get();

        if(bullet) {
          let offset = new Phaser.Geom.Point(0, -this.gun.height / 2);
          Phaser.Math.Rotate(offset, this.gun.rotation);
          bullet.fire(this.gun.x + offset.x, this.gun.y + offset.y);
        }
    });
  }
  
  update() {
    if(this.key_left.isDown) {
      this.gun.angle -= 1;
    } else if(this.key_right.isDown) {
      this.gun.angle += 1;
    }
  }
}

var config = {
    width: 800,
    height: 600,
    type: Phaser.CANVAS,
    parent: 'phaser-example',
    scene: [Gun],
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { z: 300 },
            debug: true
        }
    }
};

var game = new Phaser.Game(config);

 

Link to comment
Share on other sites

Yes, exactly! Thank you, @PixelPicoSean

Those 2 lines are exactly what I was looking for. 

let offset = new Phaser.Geom.Point(0, -this.gun.height / 2);
Phaser.Math.Rotate(offset, this.gun.rotation);

 

You probably know where I'm going with this, so I'll shoot my next question. How can I change the direction of the bullets depending of the angle of the gun? Currently, bullets will always go to the upper left corner, which is not a desirable thing.

 

Link to comment
Share on other sites

First in the bullet class:

class Bullet extends Phaser.GameObjects.Sprite {
  constructor(scene) {
    super(scene, 0, 0, 'bullet');
    this.speed = Phaser.Math.GetSpeed(400, 1);
    // Use velocity for movement
    // Note that `velocity` is a built-in property
    //   if you are using any of the physics engines
    //   of Phaser
    this.velocity = new Phaser.Geom.Point(0, 0);
  }
  
  // Pass direction to bullet as 3rd param
  fire(x, y, direction) {
    this.setPosition(x, y)
      .setActive(true)
      .setVisible(true)
      
    this.velocity.setTo(0, -this.speed)
    Phaser.Math.Rotate(this.velocity, direction)
  }
  
  update(time, delta) {
    // Update position based on velocity
    this.x += this.velocity.x * delta;
    this.y += this.velocity.y * delta;
    
    if (this.y < -50) {
      this.setActive(false);
      this.setVisible(false);
    }
  }
}

And fire the bullet:

bullet.fire(this.gun.x + offset.x, this.gun.y + offset.y, this.gun.rotation);

But I suggest look at physics engines of Phaser that have all these features built-in, there're tons of physics examples available that you take as a reference.

Link to comment
Share on other sites

Great! Just to keep the post up to date, this is the final result now: http://plnkr.co/edit/qvCmo6hXjkKsRtemx2GF?p=preview

I have a few more questions. @PixelPicoSean

As you suggested, I'm going to switch to physics engine. This example looks exactly as what I want to do http://labs.phaser.io/view.html?src=src\physics\arcade\space.js , but it's broken. I already opened an issue: https://github.com/photonstorm/phaser/issues/3341

Currently I have this http://plnkr.co/edit/s3CFDNzhvnMTrtPam3Ld?p=preview but, for some reason, `body` (in the bullet context) is null. Why is that?

Link to comment
Share on other sites

All right, this is looking nice! 

Update with the latest code: http://plnkr.co/edit/FI3odryYIolonM8KwyPz?p=preview 

What would be the way to instantiate a single `Phaser.Physics.Arcade.Image` class?

I mean, if I do

this.scene.physics.add.group({ classType: Bullet,...

 I'm creating a group of instances of the class `Bullet`. But how would I create a single instance (not a group)?

Link to comment
Share on other sites

// image
this.physics.add.image(0, 0, 'bullet');
// sprite
this.physics.add.sprite(0, 0, 'bullet');

Take a look at this example, and you will know how to create `Bullet` instances.

BTW. you don't need to call `Phaser.Physics.Arcade.Image.call(this, scene, ...)` when `super(scene, ...)` is already called, they do the same thing.

Link to comment
Share on other sites

But if I do that, I'm not instantiating a class of my own. I'll be literally creating a new object directly from a loaded image.

I want to instantiate my "Gun" class from the scene, and then call some of the methods that class has.

Something like `this.physics.add.class(Gun)`

Link to comment
Share on other sites

@PixelPicoSean I have another problem with the position of the bullets. http://plnkr.co/edit/wEsq9eFKaQKAL0wyPQTB?p=preview

Note that I have set the initial position to be `x + 40`. If I fire the gun right after launching the game, the position of the bullets is correct, but when I rotate the gun, the bullets don't rotate using the gun's "orbit".

 

JS_Bin.png.927588d5c6616f368590a6c762ebe016.png <-- this is correct

 

JS_Bin.png.7958fdac995f00fdd220a264c697556c.png <--- this is incorrect

 

How can I "orbit" rotate the bullets?

Link to comment
Share on other sites

Change your fire method to:

fire(gun) {
    this.lifespan = 2000;

    this.setActive(true);
    this.setVisible(true);
    this.setRotation(gun.rotation); // angle is in degree, rotation is in radian
    var offset = new Phaser.Geom.Point(40, 0);
    Phaser.Math.Rotate(offset, gun.rotation); // you can only rotate with radian
    this.setPosition(gun.x + offset.x, gun.y + offset.y);
    // this.body.reset(gun.x + offset.y, gun.y + offset.y);
    
    // var angle = Phaser.Math.DegToRad(gun.body.rotation);
    this.body.world.scene.physics.velocityFromRotation(gun.rotation, this.speed, this.body.velocity);
    this.body.velocity.x *= 2;
    this.body.velocity.y *= 2;
}

 

Link to comment
Share on other sites

Great! Everything looks like it would have been very easy to figure out, only if there were some books/docs on Phaser 3...

Anyway, my next question: how can I make my gun always face the pointer?

I saw this demo ( http://labs.phaser.io/edit.html?src=src\input\mouse\pointer lock 3d rotate.js ), so I already know how to detect when the pointer is moving, and I know how to get the (x,y) vector of the pointer, but I don't know how to translate that position to the required angle.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...