Can't display animated sprite / gif on a PIXI Tile map

50 views Asked by At

I have this map where I can add different Tiles. Till now all textures are normal Spritesheets. You can select on the editor one Tile Type and add it per click to the map, so that the selected tile displays the chosen tile type. Map with diffrent addable tile types

So far so good. Now I want to animate the small wind turbine so it's constantly turning. I made the following sprite sheet with texture packer: (There are four frames but I deleted them here so this question doesn't get too long)

{"frames": {

"wt1.png":
{
    "frame": {"x":0,"y":0,"w":72,"h":72},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":72,"h":72},
    "sourceSize": {"w":72,"h":72}
},
...
},
"animations": {
    "wt": ["wt1.png","wt2.png","wt3.png","wt4.png"]
},
"meta": {
    "app": "https://www.codeandweb.com/texturepacker",
    "version": "1.1",
    "image": "animatedWT.png",
    "format": "RGBA8888",
    "size": {"w":144,"h":144},
    "scale": "1",
    "smartupdate": "$TexturePacker:SmartUpdate:11679a5566d7f64fe2a648dcd7ee9107:cd3569348d06082e95cf14df37fe1bf3:d807192215a8ab88d955d69e2dbe949c$"
}
}

Then I call this function textureLoader.addGIF("animatedWT", app); in my main.js. The other textures get called like this textureLoader.addSpritesheet("windturbines_big");

The definition of the function looks like this:

addGIF(animatedWT, app) {
    this.app.loader.add(`./textures/${animatedWT}.json`, (resource) => {
      this.textures[animatedWT] = new PIXI.AnimatedSprite(
        resource.spritesheet.animations.wt
      );
      // console.log(this.textures.animatedWT);
// Here I add some deeper laying attributes to the front of the object because i had some issues with //n // later calls on the object
      this.textures.animatedWT["baseTexture"] =
        this.textures.animatedWT._texture.baseTexture;
      this.textures.animatedWT["orig"] = this.textures.animatedWT._texture.orig;
      this.textures.animatedWT["_uvs"] = this.textures.animatedWT._texture._uvs;
// I don't really know what I do here but it's done in this tutorial
// https://youtu.be/FjiQSwohBVs?si=tyc_2JG7jNWziNxq
      app.stage.addChild(this.textures.animatedWT);
      app.ticker.add(this.animate(this.textures.animatedWT, app));
    });
  }
  animate(animatedWT, app) {
    animatedWT.x = app.renderer.screen.width / 2;
    animatedWT.y = app.renderer.screen.height / 2;
  }

the animatedWT object after added to app.stage or how the animatedSprite looks like:

children: (1) […]
​​​0: {…}
​​​​_anchor: {…}
​​​​_autoUpdate: true
​​​​_bounds: {…}
​​​​_boundsID: 0
​​​​_boundsRect: null
​​​​_cachedTint: 16777215
​​​​_currentTime: 0
​​​​_destroyed: false
​​​​_durations: null
​​​​_enabledFilters: null
​​​​_events: {}
​​​​_eventsCount: 0
​​​​_height: 0
​​​​_isConnectedToTicker: false
​​​​_lastSortedIndex: 0
​​​​_localBounds: null
​​​​_localBoundsRect: null
​​​​_mask: null
​​​​_playing: false
​​​​_previousFrame: 0
​​​​_roundPixels: false
​​​​_texture: {…}
​​​​_textureID: -1
​​​​_textureTrimmedID: -1
​​​​_textures: (4) […]
​​​​_tint: 16777215
​​​​_tintRGB: 16777215
​​​​_transformID: -1
​​​​_transformTrimmedID: -1
​​​​_uvs: {…}
​​​​_width: 0
​​​​_zIndex: 0
​​​​alpha: 1
​​​​animationSpeed: 1
​​​​baseTexture: {…}
​​​​blendMode: 0
​​​​children: []
​​​​filterArea: null
​​​​filters: null
​​​​indices: Uint16Array(6)
​​​​isMask: false
​​​​isSprite: true
​​​​loop: true
​​​​onComplete: null
​​​​onFrameChange: null
​​​​onLoop: null
​​​​orig: {…}
​​​​parent: {…}
​​​​pluginName: "batch"
​​​​renderable: true
​​​​sortDirty: false
​​​​sortableChildren: false
​​​​tempDisplayObjectParent: null
​​​​transform: {…}
​​​​updateAnchor: false
​​​​uvs: Float32Array(8)
​​​​vertexData: Float32Array(8)
​​​​vertexTrimmedData: null
​​​​visible: true
worldAlpha: 1
<prototype>: {…}
//to add a normal Sprite the function looks like this
  addSpritesheet(name) {
    this.app.loader.add(`./textures/${name}.json`, (resource) => {
      this.textures[name] = resource.textures;
    });
  }

In the next step the Tiles are rendered

For normal sprites it's done like this:

  renderWaterTile(x, y) {
// a random texture is chosen from the spritesheet
    const textureNumber = 1 + Math.round(this.randomizedTerrain[y][x] * 8);
// the texture from the TextureTile[][] is set to the new texture
    this.getTextureTile(x, y).texture =
      this.textures.water[`water-0${textureNumber}`];
    this.getTextureTile(x, y).visible = true;
  }

a this.TextureTile[][] normally loks like this:

_anchor: {…}
​​​_bounds: {…}
​​​_boundsID: 159
​​​_boundsRect: null
​​​_cachedTint: 16777215
​​​_destroyed: false
​​​_enabledFilters: null
​​​_events: {}
​​​_eventsCount: 0
​​​_height: 72
​​​_lastSortedIndex: 0
​​​_localBounds: null
​​​_localBoundsRect: null
​​​_mask: null
​​​_roundPixels: true
​​​_texture: {…}
​​​_textureID: 1
​​​_textureTrimmedID: -1
​​​_tint: 16777215
​​​_tintRGB: 16777215
​​​_transformID: 2
​​​_transformTrimmedID: -1
​​​_width: 72
​​​_zIndex: 0
​​​alpha: 1
​​​blendMode: 0
​​​children: []
​​​filterArea: null
​​​filters: null
​​​indices: Uint16Array(6)
​​​isMask: false
​​​isSprite: true
​​​parent: {…}
​​​pluginName: "batch"
​​​renderable: true
​​​sortDirty: false
​​​sortableChildren: false
​​​tempDisplayObjectParent: null
​​​transform: {…}
​​​uvs: Float32Array(8)
​​​vertexData: Float32Array(8)
​​​vertexTrimmedData: null
​​​visible: true
​​​worldAlpha: 1

TextureTile[][] is a matrix and is previously defined like this in the constructor:

this.textureTiles = Array2D.create(
      this.city.map.width,
      this.city.map.height,
      null
    );

this.city.map.allCells().forEach(([x, y]) => {
      const bgTile = new PIXI.Graphics();
      bgTile.x = x * MapView.TILE_SIZE;
      bgTile.y = y * MapView.TILE_SIZE;
      this.bgTiles[y][x] = bgTile;

// here it's predefined as new PIXI.Sprite maybe that's part of the problem
      const textureTile = new PIXI.Sprite();
      textureTile.x = x * MapView.TILE_SIZE;
      textureTile.y = y * MapView.TILE_SIZE;
      textureTile.width = MapView.TILE_SIZE;
      textureTile.height = MapView.TILE_SIZE;
      textureTile.roundPixels = true;
      this.textureTiles[y][x] = textureTile;
      this.renderTile(x, y);
    });

For my animated tile I tried several things:

Normally only the texture attribute of the object is updated but the PIXI.sprite object and the PIXI.animatedSprite Object are different from each other. So I tried it like this: this.textureTiles[y][x] = this.textures.animatedWT; instead of this: this.getTextureTile(x, y).texture = this.textures.water[water-0${textureNumber}];

here is the whole function:

  renderWindTurbineSmallTile(x, y) {
    let animatedWT = this.textures.animatedWT;
    // app.stage.addChild(img);

    animatedWT.animationSpeed = 1;
    animatedWT.play();

    animatedWT.onLoop = () => {
      console.log("loop");
    };
    animatedWT.onFrameChange = () => {
      console.log("currentFrame", animatedWT.currentFrame);
    };
    animatedWT.onComplete = () => {
      console.log("done");
    };
    // here is the important bit I think
    this.textureTiles[y][x] = this.textures.animatedWT;
    this.getTextureTile(x, y).visible = true;

with this I get no errors in the console and it prints the loops and frame changes etc. but I don't see the animated sprite just the grey tile

I also tried this: `this.getTextureTile(x, y).texture = this.textures.animatedWT.texture; It displays one frame of the animated sprite and if I add another windturbine it changes the frame but on all windturbines I set. I also have the feeling that the animation speed influences the change of the frames. enter image description here enter image description here

the texture object of the animatedWt looks like this:

_events: {}
​_eventsCount: 0
​_frame: {…}
​_rotate: 0
​_updateID: 1
​_uvs: {…}
​baseTexture: {…}
​defaultAnchor: {…}
​noFrame: false
​orig: {…}
​textureCacheIds: (1) […]
​trim: null
​uvMatrix: null
​valid: true
​<prototype>: {…}

I also tried this cause I thought maybe it doesn't work because in the constructor TextureTiles[][] is only defined as Sprite: this.textureTiles[y][x] = new PIXI.AnimatedSprite( this.textures.animatedWT.textures ); but again only a grey tile and no animatedSprite.

The Frame changes are constantly printed in all tries.

If anyone has an idea what I might be doing wrong, it would be nice to hear or if you have an example for a similar problem so I could have look :) also if anyone can tell me what app.ticker does, that would be great too.

0

There are 0 answers