Jump to content

[PIXIJS] [Help] Resolution and Pivot [Solved]


Saqirm
 Share

Recommended Posts

Hello pixijs forum and devs.
I´m currently working on a multiplayer 2d Game.

Problem: I'm using pivot for main game scene to follow the Player (in center) everything works okay when i have resolution at 1.

 

-- Thanks for every reply, my english is not very well so ill try to explain throu the photos &code

I'll attach some photos to show u my problem

resol1.thumb.png.a7440c75633eb8641d4c3ab79d04a141.png

 

resol2.thumb.png.ea4c0baa8c04f01bb61b2a25f7c1c0e0.png

PIXIJS Inspector:
res3.thumb.jpg.ad4e437f4a8b9e0966a5eb0cb8a219a4.jpgres4.thumb.jpg.4f9a314264fed63144f3a5e0c176773c.jpg

- Pivot point does not scale properly with resolution.
My code for resize and App


I have my app declared here as static

export class Game
{
    //Create a Pixi Application
    public static app:any = new PIXI.Application({
        antialias: false,   // default: false
        transparent: false, // default: false
        autoDensity: true,
        autoResize: true,
        resolution: window.devicePixelRatio,
    });


    // Resolution & Camera
    public static WIDTH:number = 728;
    public static HEIGHT:number = 540;


I have own container which contain Game (everything expect UI) dynamic content Game.scene

 


    /** Game -> Dynamic container */
    public static scene:any = new PIXI.Container();
    
    public static init():void
    {
        // Initialize Display.Stage (Layers support)
        Game.app.stage = new PIXI.display.Stage();
        Game.app.stage.addChild(Game.scene);
        Game.resize(); // call resize funct.
        ....
        Game.app.renderer.render(Game.app.stage);
    }
     // i took those function from Pixi Forum
    /* Helper function to resize the game to fit the full screen */
    public static resize():void
    {
        const WIDTH:number = Game.WIDTH;
        const HEIGHT:number = Game.HEIGHT;
        const vpw:number = window.innerWidth;  // Width of the viewport
        const vph:number = window.innerHeight; // Height of the viewport
        let nvw:number; // New game width
        let nvh:number; // New game height

        // The aspect ratio is the ratio of the screen's sizes in different dimensions.
        // The height-to-width aspect ratio of the game is HEIGHT / WIDTH.

        if (vph / vpw < HEIGHT / WIDTH) {
          // If height-to-width ratio of the viewport is less than the height-to-width ratio
          // of the game, then the height will be equal to the height of the viewport, and
          // the width will be scaled.
          nvh = vph;
          nvw = (nvh * WIDTH) / HEIGHT;
        } else {
          // In the else case, the opposite is happening.
          nvw = vpw;
          nvh = (nvw * HEIGHT) / WIDTH;
        }
        
        // Set the game screen size to the new values.
        // This command only makes the screen bigger --- it does not scale the contents of the Game.
        // There will be a lot of extra room --- or missing room --- if we don't scale the scene.
        Game.app.renderer.resize(vpw, vph);
        
        // This command scales the scene to fit the new size of the Game.
        let zoom = Camera.activeCamera ? Camera.activeCamera.zoom : 1;

        Game.scene.scale.set(zoom * (nvw / WIDTH), zoom * (nvh / HEIGHT));

        Game.scene.filterArea = new PIXI.Rectangle(0,0, vpw, vph)
    }

export class Camera
{
....
    public static updateView()
    {
        if (Camera.activeCamera)
            Game.scene.pivot.set(Camera.activeCamera.position.x, Camera.activeCamera.position.y);
    }

    public setFocus(obj:any):void
    {
        this._cameraFocus = obj.position;
    }

    // On Update / GameLoop
    Camera.activeCamera.setPosition(Camera.activeCamera._cameraFocus.x, 
                                    Camera.activeCamera._cameraFocus.y);



...
}

    
        


Camera.activeCamera._cameraFocus.x is bounded to (referenced) container position 

- For some reason pivoting player position (container) is not centering container to the middle if resolution is higher.
in PlayerInit i have

        Game.camera.setFocus(this.container)
 
      -- My HTML Viewport is:
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" />
Edited by Saqirm
Link to comment
Share on other sites

 For some reason pivoting player position (container) is not centering container to the middle if resolution is higher.

It looks like despite all the CSS-ing canvas is actually 2 times bigger in CSS size.  Code looks fine and `autoDensity` i there,  but can you please check that canvas css is correct?

Link to comment
Share on other sites

@ivan.popelyshev

Oh i'm sorry to disturb you, i already find the problem

 

I used Game.app.renderer.width instead of screen 
I'm abit confused with Game.app.screen/view/renderer widths/heights
Renderer and View returns twice more than screen ... 

view is returning width/height based on <canvas> element i guess

screen seems to be updatable with resolution while view and renderer are fixed for resolution 1.
by changing it to screen it works well 

 

        Game.scene.position.x = Game.app.screen.width / 2 + Game.offsetX;
        Game.scene.position.y = Game.app.screen.height / 2 + Game.offsetY;
Edited by Saqirm
Link to comment
Share on other sites

Ye, that's why i recommend people to use "screen" (i added that property). Handling resolution is always trouble. Btw, I recommend to look in "pivot" prop too, usually its how i do it:

camera.position.set(screen.width/2, screen.height/2);
camera.pivot.set(lookAt.x, lookAt.y);
camera.scale.set(...);

basicaly, you are pinning "lookAt" local coords to position on screen, which is half of screen. It works regardless of scale or rotation, you have guarantee that position in global is pinned to local pivot.

Edited by ivan.popelyshev
Link to comment
Share on other sites



export class Camera
{
    public static cameras:Camera[] = [];
    private _cameraFocus:any;

    public static activeCamera:Camera;

    private id:number = 0;
    private _pos:any = 
    {
        x: 0,
        y: 0
    }
    public zoom:number = 1;
    public canZoom:boolean = true;
    public zoomSpeed:number = 0;

    /**
     * Create a new camera for game
     * @param id - ID of Camera (Unique ID)
     * @param x - Position of camera
     * @param y - Position of Camera
     * @param scale - Scale of FOV (Zoom)
     * @param active - If camera is Active
     * @param follow - If camera should follow spirite/Obj
     */
    constructor(id:number, x:number, y:number, scale:number, active?:boolean, follow?:any)
    {
        this.id = id;

        if (active)
            Camera.setActiveCamera(this);

        this.setZoom(scale, true);

        this.setPosition(x,y);

        if (follow)
            this.setFocus(follow);

        Camera.cameras[this.id] = this;
        return this;
    }

    /**
     * 
     * @param camera - Camera Object (Optional)
     * @param id - ID param
     */
    public static setActiveCamera(camera?:Camera, id?:number):any
    {
        if (camera)
            Camera.activeCamera = camera;
        
        if (id)
            Camera.activeCamera = Camera.cameras[id];

        if (!Camera.activeCamera)
        {
            console.warn("Warining: Camera.setActiveCamrea - Cannot find active camera...");
            return;
        }

        // Set View for camera
        Camera.updateZoom();
        Camera.updateView();

        return Camera.activeCamera;
    }

    public static updateView()
    {
        // change view only for active camera
        if (Camera.activeCamera)
            Game.scene.pivot.set(Camera.activeCamera.position.x, Camera.activeCamera.position.y);
    }

    /**** Camera */
    /**
     * SetCameraView (Position X/Y)
     * @param x - X coords / global
     * @param y - Y coords / global
     */
    public setPosition(x:number, y:number):void
    {
        this.position = {x: x, y: y};

        if (Camera.activeCamera && this.id == Camera.activeCamera.id)
            Camera.updateView();
    }

    /** Set position of camera
     * @param val -> Object with properities (x, y)
     */
    public set position(val:any)
    {
        this._pos.x = val.x;
        this._pos.y = val.y;
    }

    /**
     * Get method for position
     */
    public get position():any
    {
        return this._pos;
    }

    /** setFocus (focusing spirite/object)
     * @param obj - Object which are focused in camera FOV
     */
    public setFocus(obj:any):void
    {
        this._cameraFocus = obj.position;
    }

    /** Remove focus */
    public clearFocus():void
    {
        this._cameraFocus = null;

        this.setPosition(this.position.x, this.position.y);
    }

    /**
     * Update zoom of camera (FOV)
     * @param value - Value (Scale value)
     * @param update - force update screen
     */
    public setZoom(value:number, update?:boolean):void
    {
        this.zoom = value;
        if (update)
            Camera.updateZoom();
    }

    /**
     * call to Game.resize to correct values
     */
    public static updateZoom():void
    {
        if (Camera.activeCamera)
            Game.resize()
        else
            throw new Error("ERROR: Can't update zoom because active camera does not exists!");
    }

    public static update(delta:number, deltaTime:number):void
    {
        if (Camera.activeCamera._cameraFocus && Camera.activeCamera)
        {
            // Update camera position
            //this.activeCamera.position = {x: this.scene.pivot.x, y: this.scene.pivot.y};
        }

        // Smooth zoom test
        if (Camera.activeCamera.zoomSpeed != 0)
        {
            let zoomSpeed = Camera.activeCamera.zoomSpeed > 1 ? 1 : Camera.activeCamera.zoomSpeed;

            Camera.activeCamera.zoomSpeed += zoomSpeed > 0 ? -(zoomSpeed * 0.15) : Math.abs(zoomSpeed* 0.15);

            if (Math.abs(Camera.activeCamera.zoomSpeed) < 0.2)
                Camera.activeCamera.zoomSpeed = 0;

            if (Camera.activeCamera.zoomSpeed > 0)
            {
                if (Camera.activeCamera.zoom < 2.5)
                    Camera.activeCamera.setZoom(Camera.activeCamera.zoom + Math.abs(Camera.activeCamera.zoom * 0.01 * zoomSpeed), true);
            }
            else
                if (Camera.activeCamera.zoom > 1)
                    Camera.activeCamera.setZoom(Camera.activeCamera.zoom - Math.abs(Camera.activeCamera.zoom * 0.01 * zoomSpeed), true);
        }
    }
}

 

 

This is my whole Camera class im using (it is only very basis) ill expand it later, maybe someone will use it.

Thanks for the answer. 
Have a nice day.

 

PS> Should be re-named to Viewport (camera does not exists in 2d i know :-D)

Edited by Saqirm
Link to comment
Share on other sites

Well it exist in 2d we just dont have it on low-level in pixi :( I made camera several times but i dont know how to make a good plugin. Technically its separation of projection and world transforms, and in pixi projection is just thing that converts pixels to webgl coords, it can be moved only with "renderer.render(... matrix as fourth param)" but the support is limited.

That's the best we've got: https://github.com/davidfig/pixi-viewport

more plugins: https://github.com/pixijs/pixi.js/wiki/v5-Resources

Edited by ivan.popelyshev
Link to comment
Share on other sites

@ivan.popelyshev

Well,  I found plugin Tiled for pixijs, when i already did it by myself ?
I also checked viewport plugin but id like to build my own, actually for my game i do not need anything complex. 

Viewport in 2D is just about pivoting and positioning of the main scene which is actually view. For 3D projection or 2.5d it is much harder.

It is not very hard to make own viewport for 2d projection with full support. 

 

But there is lot of super cool plugins that i will definitely use like Pixi-Tilemap which is superfast and cool. I'm using it with tiled editor

Edited by Saqirm
Link to comment
Share on other sites

Well,  I found plugin Tiled for pixijs, when i already did it by myself ?

> i will definitely use like Pixi-Tilemap which is superfast and cool

Yes, usually people do that, its better if you know how that importer works, writing it yourself is the best way to ensure that ;) Yes, pixi-tilemap helps with it, it doesnt care of particular format, you can use whatever you want with it. Btw, people asked and I added tile rotations/flips there some time ago.

Link to comment
Share on other sites

@ivan.popelyshev

This is my code for rotation, it might not be the best way to do it but it works.



    /**
     * rotate single tile
     * @param data - Tile Data Id ((Taken from JSON)
     */
    private checkTileRotation(data:number):number
    {
        let rotation = 0;
        if (data & Env.FLIPPED_DIAGONALLY_FLAG) 
            rotation += 4;
        if (data & Env.FLIPPED_VERTICALLY_FLAG && data & Env.FLIPPED_HORIZONTALLY_FLAG)
            rotation += 4;
        else 
        {
            if (data & Env.FLIPPED_VERTICALLY_FLAG)
                rotation -= 2;
            if (data & Env.FLIPPED_HORIZONTALLY_FLAG)
                rotation += 2;
        }

        return rotation;
    }

// In LOOP (drawing)
                    // now remove last 3 bits
data &= ~(Env.FLIPPED_HORIZONTALLY_FLAG | Env.FLIPPED_VERTICALLY_FLAG | Env.FLIPPED_DIAGONALLY_FLAG);

export enum Environments
{
    // Flags for map -> Tiles (Rotation)
    FLIPPED_HORIZONTALLY_FLAG = 0x80000000,
    FLIPPED_VERTICALLY_FLAG   = 0x40000000,
    FLIPPED_DIAGONALLY_FLAG   = 0x20000000,

 

Edited by Saqirm
Link to comment
Share on other sites

https://pixijs.io/examples/#/textures/texture-rotate.js

0,2,4,6 rotations

8,10,12,14 flip-y then rotate

you flips are below 8, that isn't correc

on its own, vertical is 8, diagonal is 10, horizontal is 12. just make three IF's for flags and set rotation to one of those . There shouldn't be two flags active at the same time, right?

Edited by ivan.popelyshev
Link to comment
Share on other sites

@ivan.popelyshev

Last 4 bites are: 
1.-> Once right 1010 -> 6
2 -> Twice right  1100 -> 4
3 -> 3 times Right 0110 -> 2
4 -> Flipped Y 1000 -> 12
5 -> Flipped Y & Once right 1110 -> 14
6 -> Flipped Y & twice right 0100 -> 8
7 -> Flipped Y & 3times right 0010 -> 10
8 -> Flipped X 0100 -> 8
9 -> Flipped X & once Right 0010 -> 10
10 -> Flipped X & twice right 1000 -> 12
11 -> Flipped X & 3times right 1110 -> 14

32th bit => Flipped Y
31th bit => Flipped X
30th bit => Flipped Diagonaly
There can be set up 3 flags at once.
 
My final code for it. (Data) parm is Data taken from JSON. This is JSON Tiled export
 

    private checkTileRotation(data:number):number
    {
        if (data & Env.FLIPPED_VERTICALLY_FLAG && data & Env.FLIPPED_HORIZONTALLY_FLAG && data & Env.FLIPPED_DIAGONALLY_FLAG)
            return 14;
        else if (data & Env.FLIPPED_VERTICALLY_FLAG && data & Env.FLIPPED_HORIZONTALLY_FLAG)
            return 4;
        else if (data & Env.FLIPPED_VERTICALLY_FLAG && data & Env.FLIPPED_DIAGONALLY_FLAG)
            return 2;
        else if (data & Env.FLIPPED_HORIZONTALLY_FLAG && data & Env.FLIPPED_DIAGONALLY_FLAG)
            return 6;
        else if (data & Env.FLIPPED_HORIZONTALLY_FLAG)
            return 12;
        else if (data & Env.FLIPPED_VERTICALLY_FLAG)
            return 8;
        else if (data & Env.FLIPPED_DIAGONALLY_FLAG)
            return 10;
        return 0;
    }

I tested it with all possible rotations and it works

333246324_Nepojmenovan2.jpg.aa5ca7e6e3c5b59af3eb728ce2d77d29.jpg
 

Edited by Saqirm
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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