admin管理员组

文章数量:1401374

On a default Phaser project, I have a sprite positioned at 100, 100. I want to get its coordinates when zoomed in to place an absolute div on top of it in HTML.

On zoom 1 this works:

    const viewportX = (spriteX - this.cameras.main.scrollX);
    const viewportY = (spriteY - this.cameras.main.scrollY);

but as soon as I change the zoom it breaks, I've tried adding the cameras.main.zoom, multiplying it, dividing it, and the coordinates are not the correct one.

I understand the documentation for the zoom mentions Changing the zoom does not impact the Camera viewport in any way, it is only applied during rendering.

So I'm at a loss as to how I can zoom in everything but still obtain a zoomed in sprite's coordinates.


An MRE of this would be creating a project with npm create @phaserjs/game@latest with the following options:

√ Select Option: » Client Framework (React, Next.js, Vue, Angular, Svelte, SolidJS or Rapier)
√ Select Template: » solid
√ Minimal or Complete Project: » Minimal (Single Phaser Scene)

and only changing the create function to this:

    create() {
        this.cameras.main.centerOn(200, 200)
        this.cameras.main.setZoom(5)
        const logo = this.add.image(200, 200, 'logo');
        EventBus.emit('current-scene-ready', this);
    }

What I'm looking for in this case is the top left position of the sprite in viewport coordinates, in this case at default canvas width it'd be outside of the canvas, I'm looking for a way of getting where those coordinates are relative to my viewport, in this case if I fullscreen and set the canvas width to 1920 and height to 1080, then that top left position of the sprite would be somewhere in the negative x and positive y.


edit: A third example.

If I have this:

    this.cameras.main.centerOn(200, 200)
    this.cameras.main.setZoom(1)
    const line = this.add.line(150, 150, 0, 0, 1, 1, 0xffffff, 1).setOrigin(0, 0);
    console.log(line.x - this.cameras.main.scrollX, line.y - this.cameras.main.scrollY)

And i create an absolute positioned div with those logged coordinates, then it's on the bottom right of where the line ends, but if i set the zoom to 2 then it doesn't anymore. These new zoomed in coordinates are what I want.

Pic before the zoom in:

Pic of the div after zooming in:

On a default Phaser project, I have a sprite positioned at 100, 100. I want to get its coordinates when zoomed in to place an absolute div on top of it in HTML.

On zoom 1 this works:

    const viewportX = (spriteX - this.cameras.main.scrollX);
    const viewportY = (spriteY - this.cameras.main.scrollY);

but as soon as I change the zoom it breaks, I've tried adding the cameras.main.zoom, multiplying it, dividing it, and the coordinates are not the correct one.

I understand the documentation for the zoom mentions Changing the zoom does not impact the Camera viewport in any way, it is only applied during rendering.

So I'm at a loss as to how I can zoom in everything but still obtain a zoomed in sprite's coordinates.


An MRE of this would be creating a project with npm create @phaserjs/game@latest with the following options:

√ Select Option: » Client Framework (React, Next.js, Vue, Angular, Svelte, SolidJS or Rapier)
√ Select Template: » solid
√ Minimal or Complete Project: » Minimal (Single Phaser Scene)

and only changing the create function to this:

    create() {
        this.cameras.main.centerOn(200, 200)
        this.cameras.main.setZoom(5)
        const logo = this.add.image(200, 200, 'logo');
        EventBus.emit('current-scene-ready', this);
    }

What I'm looking for in this case is the top left position of the sprite in viewport coordinates, in this case at default canvas width it'd be outside of the canvas, I'm looking for a way of getting where those coordinates are relative to my viewport, in this case if I fullscreen and set the canvas width to 1920 and height to 1080, then that top left position of the sprite would be somewhere in the negative x and positive y.


edit: A third example.

If I have this:

    this.cameras.main.centerOn(200, 200)
    this.cameras.main.setZoom(1)
    const line = this.add.line(150, 150, 0, 0, 1, 1, 0xffffff, 1).setOrigin(0, 0);
    console.log(line.x - this.cameras.main.scrollX, line.y - this.cameras.main.scrollY)

And i create an absolute positioned div with those logged coordinates, then it's on the bottom right of where the line ends, but if i set the zoom to 2 then it doesn't anymore. These new zoomed in coordinates are what I want.

Pic before the zoom in:

Pic of the div after zooming in:

Share Improve this question edited Mar 26 at 0:45 L123 asked Mar 24 at 0:18 L123L123 492 silver badges6 bronze badges 2
  • How are you covering the whole browser screen? can you share your game config? If possible maybe even an MRE – winner_joiner Commented Mar 24 at 4:36
  • @winner_joiner HI, sorry about that, I added it at the bottom of the post. Also, the whole screen comment is irrelevant, sorry about that. I just care about the canvas size. Either way, in my game config I just have "100%" set as the height and width. – L123 Commented Mar 24 at 12:46
Add a comment  | 

2 Answers 2

Reset to default 0

If I understand your issue correct, you want to have the top-left position of the sprite in the visible camera zone.

The easy solution would be to set the the origin of the Image-GameObject to 0 => TopLeft. (By default it is in the middle of the sprite.

 this.add.image(200, 200, "logo").setOrigin(0);

Like this the TopLeft of the image is in the center of the camera.

If you don't want to move the origin of the image, you would have to calculate the new center of the zoom, subtracting the image dimensions width / 2 and height / 2 from the center-position (or some other specific offset).

If you need to know the relative size of the camera view-port, you can use the worldView property link to documentation

Update a working demo:

    class DemoScene extends Phaser.Scene {
        create () {
            this.add.text(10, 10, 'Wait for It...')
                .setScale(1.5)
                .setOrigin(0)
                .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
            
            let x = config.width/2;
            let y = config.height/2;
            
            // middle
            this.add.line( config.width/2, config.height/2, 0, 0, 0, config.height, 0xffffff )
            this.add.line( config.width/2, config.height/2, 0, 0, config.width, 0, 0xffffff )
            
            // set the center of the camera 
            this.cameras.main.centerOn(x, y);
            
            // GameObject
            this.rect = this.add.rectangle(x, y, 20, 20, 0xff0000)
              .setOrigin(0);
          
            // Timeout tow switch the zoom
            this.time.addEvent( { delay: 1000, callback: this.toogleZoom, callbackScope: this});
        }
        
        toogleZoom(){
            //set Zoom
            this.cameras.main.setZoom(3);

            // tween the Zoom back to 1
            this.rect.setFillStyle(0x0000ff);
                           this.tweens.add({
                  targets: this.cameras.main,
                  zoomX: {from: 3, to: 1},
                  zoomY: {from: 3, to: 1},
                  duration: 1500,
                  delay: 2000,
              });
        }

    }

    var config = {
        width: 540,
        height: 180,
        scene: DemoScene,
    }; 

    new Phaser.Game(config);

    console.clear();
    document.body.style = 'margin:0;';
 <script src="//cdn.jsdelivr/npm/phaser/dist/phaser.min.js"></script>

After the zoom the GameObject is still in the middle.

I haven't figured it out but for all intents and purposes what worked for me was using Phasers Dom Element with Solid.js and that places what I want in the sprite's x and y coordinates and moves along with the canvas when the camera moves.

本文标签: