Quantcast
Channel: Pixi.js Latest Topics
Viewing all articles
Browse latest Browse all 3978

How to make camera view with abstract world units in pixi.js?

$
0
0

What I'm trying to accomplish is to basically write all my game logic in world units and use camera to see part of it rendered on the screen.

Let's say my world is an infinite plane and I want to add a sprite, which will have dimensions of one unit in x axis and one unit in y axis. Then, I define a camera with dimensions of 4 units on x axis and 2 units on y axis. Visualization below. example.png.6a3b8dcb68db3c910a369f34f4aba833.png

To get close to my desired result I followed the example in this blog post and used RenderTextureSystem to actually define source canvas dimensions equal to my world dimensions and target dimensions to the browser window size. Here is the code

class WorldContainer extends DisplayObject {
  sortDirty: boolean;

  public content: Container;

  public camWidth = 4;

  public camHeight = 2;

  public camOffsetX = 0;

  public camOffsetY = 0;

  constructor() {
    super();
    this.content = new Container();
  }

  calculateBounds(): void {
    return this.content._calculateCachedBounds();
  }

  removeChild(child: DisplayObject): void {
    this.content.removeChild(child);
  }

  removeChildren(): DisplayObject[] {
    return this.content.removeChildren();
  }

  addChild(child: DisplayObject): DisplayObject {
    return this.content.addChild(child);
  }

  render(renderer: Renderer) {
    const targetWidth = renderer.view.width;
    const targetHeight = renderer.view.height;
    const targetRatio = targetWidth / targetHeight;
    const sourceWidth = this.camWidth;
    const sourceHeight = this.camHeight;
    const sourceRatio = sourceWidth / sourceHeight;
    let requiredWidth = 0;
    let requiredHeight = 0;
    if (sourceRatio >= targetRatio) { // source is wider than target in proportion
      requiredWidth = targetWidth;
      requiredHeight = requiredWidth / sourceRatio;
    } else { // source is higher than target in proportion
      requiredHeight = targetHeight;
      requiredWidth = requiredHeight * sourceRatio;
    }
    renderer.renderTexture.bind(
      null,
      new Rectangle(this.camOffsetX - this.camWidth / 2, -this.camOffsetY + this.camHeight / 2, this.camWidth, this.camHeight),
      new Rectangle((targetWidth - requiredWidth) / 2, (targetHeight - requiredHeight) / 2, requiredWidth, requiredHeight),
    );

    this.content.render(renderer);

    renderer.batch.flush();
    renderer.renderTexture.bind(null);
  }

  updateTransform() {
    super.updateTransform();

    const { _tempDisplayObjectParent: tempDisplayObjectParent } = this.content;
    this.content.parent = tempDisplayObjectParent as Container;
    this.content.updateTransform();
    this.content.parent = null;
  }
}

I have done some extra work to preserve aspect ratio of camera, when drawing to canvas, so it won't get stretched and will just fit the screen.

However, real issue comes when I try to make sprites, because when I give it a texture and let's say dimensions of my texture are 64x64 pixels, then my sprite is huge filling the whole screen. That's when I thought just setting width and height of the sprite should be enough. For example to recreate the example in the picture above, I would make the sprite like this and add it to the content of world container.

const sprite: Sprite = Sprite.from('sadge.png');
sprite.anchor.set(0.5);
sprite.x = 1.5;
sprite.y = 1.5;
sprite.width = 1;
sprite.height = 1;
worldContainer.content.addChild(sprite);

Now, what I don't like about this solution is, that when I add child sprite to that previous sprite and give it's x to be equal to 1, y to be equal to 0, I expect it to appear on second row and third column.  However, not only the child sprite is not in my expected position, it's also not visible. After, hours of debugging I found out, that when setting width and height for parent sprite, under the hood pixi modifies scale and it ruins everything for child sprite. If, I set sprite's width height to be 1x1, it sets scale for sprite to be ( 4 / canvas_w, 2 / canvas_h), which is very tiny and because that scale is also applied to its children, they get so small that they are not visible. I know that I can manually multiply by inverse of the scale ratio for every child and cancel that effect, but to be frank it is very ugly solution.

I was wondering if you could help me to fix this issue, or give me a directing advice on how to approach it. If feels like I am solving this whole world unit issue in a very wrong way and there is far simpler and neater solution. I've been struggling with this thing for weeks now and would really appreciate any help.


Viewing all articles
Browse latest Browse all 3978

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>