Jump to content

Using a simple spritesheet animation without key


strivinglife
 Share

Recommended Posts

In Phaser 2 I was able to load a spritesheet and then define a simple animation that would loop through the spritesheet frames.

// Defined in the preloader state.
this.load.path = 'assets/avatar/';
for (let i = 1; i < 8; i++) {
	this.game.load.spritesheet('avatar_1_' + i, 'base/avatar_1_' + i +'.png', 16, 24);
}

// Use the spritesheet when adding the sprite.
this.hero = this.game.add.sprite(x, y, 'avatar_1_' + style);

// Define an animation and start playing it.
this.hero.animations.add('stand');
this.hero.animations.play('stand', 5, true);

With Phaser 3 I'm trying to understand how to convert this to the new animations model.

// Still loading the spritesheets in the preloader.
this.load.path = 'assets/avatar/';
for (let i = 1; i < 8; i++) {
	this.load.spritesheet('avatar_1_' + i, 'base/avatar_1_' + i +'.png', { frameWidth: 16, frameHeight: 24 });
}

// This doesn't appear to have changed much either.
this.body = this.scene.add.sprite(x, y, this.asset);

// Now I've tried just creating the animation:
this.anims.create({
	key: 'stand',
	frameRate: 5,
	repeat: -1
});

// And then using it on the sprite, but it's complaining about that it:
// Cannot read property 'frame' of undefined
this.body.anims.play('stand');

Is it still possible to define an animation that just loops through the sprite's spritesheet's frames?

If not, do I need to define an animation for every spritesheet I'm using? (Such as in the official Phaser 3 tutorial, https://phaser.io/tutorials/making-your-first-phaser-3-game/part5)

Thanks!

 

Link to comment
Share on other sites

That makes sense, but each actual Sprite may have a different spritesheet.

So I've got my monsters definition (Character doesn't add anything of importance, but extends Phaser.GameObjects.Group, in case it matters), where you can supply the style of monster asset to use.

// TypeScript
import Character from "./Character";

export default class Monster extends Character {
	constructor(scene: Phaser.Scene, x: number, y: number, style: string) {
		super(scene);

		// The base doesn't actually move at all.
		var characterBase = this.scene.add.sprite(x, y, 'avatar_1_1');

		this.asset = 'monsters_' + style;

		this.body = this.scene.add.sprite(x, y, this.asset);
	}
}

A preloader scene is adding these as:

// Load monsters.
this.load.path = 'assets/monsters/';
for (let i = 1; i <= 13; i++) {
	for (let j = 1; j <= 19; j++) {
		this.load.spritesheet('monsters_' + i + '_' + j, 'monsters_' + i + '_' + j + '.png', { frameWidth: 16, frameHeight: 24 });
	}
}

(Spritesheets are all just two frames.)

So I guess that means doing this (the 3.9.0 TS defs don't have a `generateFrameNumbers()` yet for what you've provided, hence the null)?

for (let i = 1; i <= 13; i++) {
	for (let j = 1; j <= 19; j++) {
		this.anims.create({
			key: 'stand',
			frames: this.anims.generateFrameNumbers('monsters_' + i + '_' + j, null),
			frameRate: 5,
			repeat: -1
		});
	}
}

That gets me the following, which is what I was expecting to see.

Quote

Invalid Animation Key, or Key already in use: stand

So now I'm thinking each sprite needs to have a 'stand' set (`key: 'stand_monsters_' + i + '_' + j`)? Or am I misunderstanding and there's an easier way to write the code?

Since you're on the thread, rich, here's more of what I'm trying to convert to Phaser 3, in case it helps with animation usage.

// TypeScript - Phaser 2
import { MonsterRarity } from "../Enums";
import Character from "./Character";

export default class Monster extends Character {
	private monsterBody: Phaser.Sprite;
	private asset: string;
	public experience: number;
	public rarity: MonsterRarity;

	constructor(game: Phaser.Game, x: number, y: number, style: string) {
		super(game);

		// The base doesn't actually move at all.
		var monsterBase = this.game.add.sprite(x, y, 'avatar_1_1');
		monsterBase.anchor.setTo(0.5);

		this.monsterBody = this.game.add.sprite(x, y, 'monsters_' + style);
		this.monsterBody.anchor.setTo(0.5);
		this.monsterBody.animations.add('stand');
		this.monsterBody.animations.play('stand', 5, true);

		this.monsterBody.inputEnabled = true;
		this.monsterBody.events.onInputDown.add(this.logInfo, this);

		this.add(monsterBase);
		this.add(this.monsterBody);

		// Add this to the game immediately.
		game.add.existing(this);
	}

	logInfo() {
		console.log(this.monsterBody.key);
	}
}

 

Link to comment
Share on other sites

For what it's worth, doing the following did work:

// TypeScript
// Creating the animations.
for (let i = 1; i <= 13; i++) {
	for (let j = 1; j <= 19; j++) {
		this.anims.create({
			key: 'stand_monsters_' + i + '_' + j,
			frames: this.anims.generateFrameNumbers('monsters_' + i + '_' + j, null),
			frameRate: 5,
			repeat: -1
		});
	}
}

// Calling this when creating the custom objects.
this.body.anims.play('stand_monsters_' + style);

Is there a recommended best practice on where to setup the animations? Since they're global, that would suggest creating them somewhere that might get called once. For my setup with multiple scenes (with the called order as below), I'm thinking in the Preloader.create() function, instead of where I have it now, instead MainGame.create().

this.scene.add(Boot.Name, Boot);
this.scene.add(Preloader.Name, Preloader);
this.scene.add(MainMenuScene.Name, MainMenuScene);
this.scene.add(MainGame.Name, MainGame);

 

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...