Using texture set to create animation in phaser3

Time:2020-5-30

I started to learn phaser a few days ago. The first thing I want to do after reading the tutorial is to make an animation effect. But I just stepped on the first step and stepped on the pit. Record it.

Create a texture set

Here, I use texturepacker to generate the texture set supported by phaser3 from the prepared materials. Texturepacker is very easy to use. There are tutorials on the official website. I won’t go into details here
Using texture set to create animation in phaser3
The texture set of flame and a JSON file are obtained through texturepacker
Using texture set to create animation in phaser3
All the information recorded in the JSON file is about the position and size of each frame in the texture set. It doesn’t matter if you don’t understand it. Fortunately, phaser will help us analyze it

Paint flame

Load the resource in the preload method first

//Read assets / sprites/ fire.json The third parameter is the path of the picture
this.load.multiatlas('fire', 'assets/sprites/fire.json', 'assets/sprites')

Then add the loaded texture to the scene in the Create method

//The three parameters are sprite's X coordinate, y coordinate and texture's key value, corresponding to the first parameter of the above multiatlas()
const fire = this.add.sprite(400, 100, 'fire')

Using texture set to create animation in phaser3
In this way, the first frame of the texture set is drawn to the screen, which is very easy. But a fire doesn’t burn. Next, let it burn.

Create animation

It’s also very easy to create an animation. Add the following code to the Create method

const frames = this.anims.generateFrameNames('fire', {
  start: 0,
  end: 14
})
console.log(frames)
this.anims.create({
  key: 'burn',
  frames,
  repeat: -1
})

Go back to the browser and find out whether the flame is still motionless. Don’t worry. Let’s see what these parameters are first

  • Key: as the name of this animation
  • Frames: data for generating animation frames
  • Repeat: animation playback times, – 1 is infinite loop

Here you can see that the frames parameter is very special. It uses the this.anims That’s the point I stepped on.
According to the API document, the two parameters of this method are texture key and animation frame name configuration, so click open to continue to view the configuration attributes of the second parameter, and you can see that there are seven attributes.

  • Start: start
  • End: end
  • Prefix: prefix
  • Suffix: suffix
  • Zeropad: fill 0
  • Outputarray: output array. You can push the generated animation frame data into this array
  • Frames: frame number array

This is the understanding I just saw. According to the document, start, end and frames are mutually exclusive. If you pass in frames, start and end will fail.
Due to the vague description in the document(English slag), and all of them are optional parameters. I only wrote the start and end parameters, and wrote them from 0 to 14, so the browser mercilessly reported an error to me
Using texture set to create animation in phaser3
There is no reference to frame property in my code. It seems that the runtime error of phase is not handled well, and the print frame is an empty array at this time. Due to the lack of phaser resources in China, no relevant solutions have been found after a good search. What should we do? Look at the source code.
I’m in phaser / SRC / animations/ AnimationManager.js Generateframenames method found under path

generateFrameNames: function (key, config)
{
    var prefix = GetValue(config, 'prefix', '');
    var start = GetValue(config, 'start', 0);
    var end = GetValue(config, 'end', 0);
    var suffix = GetValue(config, 'suffix', '');
    var zeroPad = GetValue(config, 'zeroPad', 0);
    var out = GetValue(config, 'outputArray', []);
    var frames = GetValue(config, 'frames', false);

    var texture = this.textureManager.get(key);

    if (!texture)
    {
        return out;
    }

    var diff = (start < end) ? 1 : -1;

    //  Adjust because we use i !== end in the for loop
    end += diff;

    var i;
    var frame;

    if (!config)
    {
        //  Use every frame in the atlas?
        frames = texture.getFrameNames();

        for (i = 0; i < frames.length; i++)
        {
            out.push({ key: key, frame: frames[i] });
        }
    }
    else if (Array.isArray(frames))
    {
        //  Have they provided their own custom frame sequence array?
        for (i = 0; i < frames.length; i++)
        {
            frame = prefix + Pad(frames[i], zeroPad, '0', 1) + suffix;

            if (texture.has(frame))
            {
                out.push({ key: key, frame: frame });
            }
        }
    }
    else
    {
        for (i = start; i !== end; i += diff)
        {
            frame = prefix + Pad(i, zeroPad, '0', 1) + suffix;

            if (texture.has(frame))
            {
                out.push({ key: key, frame: frame });
            }
        }
    }

    return out;
}

This code is not difficult to understand. You can understand it after careful speculation. The return value out is an array, which is the “data for generating animation frame” mentioned above. After a series of judgments, you can see that the frame attribute of the object in out is alwaysprefix + xxx + suffixThe original parameters start, end, prefix, suffix, frames, and zeropad are used to generate concatenated strings. We need to use these parameters to generate frame names in texture set data
Using texture set to create animation in phaser3
The code is then modified

const frames = this.anims.generateFrameNames('fire', {
  start: 1,
  end: 15,
  prefix: 'fire',
  suffix: '.png'
})

In this way, the generated frame is fire1.png ~ fire15.png, and the printed frames will be an array of 15 items
Using texture set to create animation in phaser3
Then add a line of code at the end of the code to make the flame burnfire.play('burn')
Using texture set to create animation in phaser3

Full code

new Phaser.Game({
  type: Phaser.AUTO,
  width: 750,
  height: window.innerHeight,
  scene: [
    {
      preload() {
        this.load.multiatlas('fire', 'assets/sprites/fire.json', 'assets/sprites')
      },
      create() {
        const fire = this.add.sprite(400, 100, 'fire')
        const frames = this.anims.generateFrameNames('fire', {
          start: 1,
          end: 15,
          prefix: 'fire',
          suffix: '.png'
        })
        console.log(frames)
        this.anims.create({
          key: 'burn',
          frames,
          repeat: -1
        })
        fire.play('burn')
      }
    }
  ]
})

Summary

This simultaneous interpreting is due to the misconfiguration of the generateFrameNames () method. It was originally thought that start and end were the corresponding index of each frame, so they would be written in 0 and 14, but this is actually corresponding to the filename of each frame, and the prefix, suffix and complement 0 generated by combining the configuration parameters are generated. Therefore, the different configuration is the positive solution according to the different filename.

Recommended Today

Analysis of super comprehensive MySQL statement locking (Part 1)

A series of articles: Analysis of super comprehensive MySQL statement locking (Part 1) Analysis of super comprehensive MySQL statement locking (Part 2) Analysis of super comprehensive MySQL statement locking (Part 2) Preparation in advance Build a system to store heroes of the Three KingdomsheroTable: CREATE TABLE hero ( number INT, name VARCHAR(100), country varchar(100), PRIMARY […]