or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation.mdapplication.mdassets.mddisplay-objects.mdfilters.mdgraphics.mdindex.mdinteraction.mdmath.mdsprites-textures.mdtext.mdutilities.md

animation.mddocs/

0

# Animation & Sprites

1

2

Frame-based animation system and animated sprite functionality for creating sprite animations and sequences. PixiJS provides efficient systems for both texture-based animations and programmatic animations.

3

4

## Capabilities

5

6

### Animated Sprite

7

8

Frame-based animation using texture sequences.

9

10

```typescript { .api }

11

/**

12

* Animated sprite for frame-based animations

13

*/

14

class AnimatedSprite extends Sprite {

15

/** Array of textures for animation */

16

textures: Texture[];

17

/** Current frame index */

18

currentFrame: number;

19

/** Whether animation is playing */

20

playing: boolean;

21

/** Whether animation should loop */

22

loop: boolean;

23

/** Animation playback speed */

24

animationSpeed: number;

25

/** Update anchor to match texture anchor */

26

updateAnchor: boolean;

27

/** Called when animation completes */

28

onComplete?: () => void;

29

/** Called when animation loops */

30

onLoop?: () => void;

31

/** Called when frame changes */

32

onFrameChange?: (currentFrame: number) => void;

33

/** Total frames */

34

readonly totalFrames: number;

35

36

/**

37

* Create animated sprite

38

* @param textures - Animation frames

39

* @param autoUpdate - Auto-update from ticker

40

*/

41

constructor(textures: Texture[], autoUpdate?: boolean);

42

43

/** Start animation */

44

play(): void;

45

46

/** Stop animation */

47

stop(): void;

48

49

/**

50

* Go to frame and play from there

51

* @param frameNumber - Frame to start from

52

*/

53

gotoAndPlay(frameNumber: number): void;

54

55

/**

56

* Go to frame and stop

57

* @param frameNumber - Frame to go to

58

*/

59

gotoAndStop(frameNumber: number): void;

60

61

/**

62

* Update animation

63

* @param deltaTime - Time since last update

64

*/

65

update(deltaTime: number): void;

66

67

/** Destroy animated sprite */

68

destroy(options?: boolean | IDestroyOptions): void;

69

}

70

```

71

72

### Spritesheet Management

73

74

Loading and managing sprite sheet animations.

75

76

```typescript { .api }

77

/**

78

* Spritesheet for managing texture atlases and animations

79

*/

80

class Spritesheet {

81

/** Base texture */

82

baseTexture: BaseTexture;

83

/** Spritesheet data */

84

data: ISpritesheetData;

85

/** Generated textures */

86

textures: Record<string, Texture>;

87

/** Generated animations */

88

animations: Record<string, Texture[]>;

89

/** Resolution */

90

resolution: number;

91

92

/**

93

* Create spritesheet

94

* @param texture - Base texture or image

95

* @param data - Spritesheet data

96

* @param resolutionFilename - Resolution from filename

97

*/

98

constructor(texture: BaseTexture | Texture, data: ISpritesheetData, resolutionFilename?: string);

99

100

/**

101

* Parse spritesheet data

102

* @param onProgress - Progress callback

103

*/

104

parse(onProgress?: (progress: number) => void): Promise<Record<string, Texture>>;

105

106

/** Destroy spritesheet */

107

destroy(destroyBase?: boolean): void;

108

}

109

110

interface ISpritesheetData {

111

frames: Record<string, ISpritesheetFrameData>;

112

animations?: Record<string, string[]>;

113

meta: {

114

scale: string;

115

format: string;

116

size: { w: number; h: number };

117

image: string;

118

};

119

}

120

121

interface ISpritesheetFrameData {

122

frame: { x: number; y: number; w: number; h: number };

123

trimmed?: boolean;

124

rotated?: boolean;

125

sourceSize?: { w: number; h: number };

126

spriteSourceSize?: { x: number; y: number; w: number; h: number };

127

anchor?: { x: number; y: number };

128

}

129

```

130

131

### Ticker-Based Animation

132

133

Using the ticker system for custom animations.

134

135

```typescript { .api }

136

/**

137

* Ticker for driving animations and updates

138

*/

139

class Ticker {

140

/** Shared ticker instance */

141

static shared: Ticker;

142

/** Current delta time */

143

deltaTime: number;

144

/** Elapsed time in milliseconds */

145

elapsedMS: number;

146

/** Current FPS */

147

FPS: number;

148

/** Animation speed multiplier */

149

speed: number;

150

/** Whether ticker is started */

151

started: boolean;

152

153

/**

154

* Add update function

155

* @param fn - Update function

156

* @param context - Function context

157

* @param priority - Update priority

158

*/

159

add<T = any>(fn: TickerCallback<T>, context?: T, priority?: number): this;

160

161

/**

162

* Remove update function

163

* @param fn - Function to remove

164

* @param context - Function context

165

*/

166

remove<T = any>(fn: TickerCallback<T>, context?: T): this;

167

168

/** Start ticker */

169

start(): void;

170

171

/** Stop ticker */

172

stop(): void;

173

174

/** Update manually */

175

update(currentTime?: number): void;

176

}

177

178

type TickerCallback<T = any> = (this: T, deltaTime: number) => void;

179

```

180

181

**Usage Examples:**

182

183

```typescript

184

import { AnimatedSprite, Spritesheet, Assets, Ticker } from "pixi.js";

185

186

// Load spritesheet and create animation

187

const sheet = await Assets.load('character-spritesheet.json');

188

const walkTextures = sheet.animations['walk'];

189

190

const animatedCharacter = new AnimatedSprite(walkTextures);

191

animatedCharacter.animationSpeed = 0.167; // 10 FPS (1/60 * 10)

192

animatedCharacter.loop = true;

193

animatedCharacter.play();

194

195

// Animation callbacks

196

animatedCharacter.onComplete = () => {

197

console.log('Animation completed');

198

};

199

200

animatedCharacter.onFrameChange = (frame) => {

201

console.log(`Frame changed to: ${frame}`);

202

};

203

204

// Manual animation control

205

animatedCharacter.gotoAndStop(0); // Go to first frame

206

animatedCharacter.gotoAndPlay(5); // Start from frame 5

207

208

// Custom ticker-based animation (requires TickerPlugin)

209

const sprite = Sprite.from('player.png');

210

let elapsed = 0;

211

212

// app.ticker.add((delta) => {

213

// elapsed += delta;

214

// sprite.x = Math.cos(elapsed * 0.1) * 100 + 200;

215

// sprite.y = Math.sin(elapsed * 0.1) * 50 + 150;

216

// sprite.rotation = elapsed * 0.05;

217

// });

218

219

// Programmatic spritesheet creation

220

const textures = [];

221

for (let i = 0; i < 8; i++) {

222

textures.push(Texture.from(`frame${i}.png`));

223

}

224

225

const programmaticAnimation = new AnimatedSprite(textures);

226

programmaticAnimation.animationSpeed = 0.5;

227

programmaticAnimation.play();

228

```

229

230

### Animation States

231

232

Managing complex animation states and transitions.

233

234

```typescript

235

// Animation state manager example

236

class AnimationStateMachine {

237

private currentState: string = 'idle';

238

private animations: Record<string, AnimatedSprite> = {};

239

private sprite: Container;

240

241

constructor() {

242

this.sprite = new Container();

243

}

244

245

addAnimation(name: string, textures: Texture[]) {

246

const animatedSprite = new AnimatedSprite(textures);

247

animatedSprite.visible = false;

248

this.animations[name] = animatedSprite;

249

this.sprite.addChild(animatedSprite);

250

}

251

252

setState(newState: string) {

253

if (this.animations[this.currentState]) {

254

this.animations[this.currentState].stop();

255

this.animations[this.currentState].visible = false;

256

}

257

258

this.currentState = newState;

259

260

if (this.animations[newState]) {

261

this.animations[newState].visible = true;

262

this.animations[newState].gotoAndPlay(0);

263

}

264

}

265

266

getSprite() {

267

return this.sprite;

268

}

269

}

270

271

// Usage

272

const character = new AnimationStateMachine();

273

character.addAnimation('idle', idleTextures);

274

character.addAnimation('walk', walkTextures);

275

character.addAnimation('jump', jumpTextures);

276

277

app.stage.addChild(character.getSprite());

278

character.setState('idle');

279

280

// State transitions based on input

281

document.addEventListener('keydown', (e) => {

282

switch(e.key) {

283

case 'ArrowLeft':

284

case 'ArrowRight':

285

character.setState('walk');

286

break;

287

case ' ':

288

character.setState('jump');

289

break;

290

default:

291

character.setState('idle');

292

}

293

});

294

```

295

296

### Tween Animation

297

298

While PixiJS doesn't include built-in tweening, it integrates well with external libraries:

299

300

```typescript

301

// Using external tween library (conceptual)

302

import { Sprite, Ticker } from "pixi.js";

303

304

// Custom simple tween implementation

305

class SimpleTween {

306

private object: any;

307

private property: string;

308

private startValue: number;

309

private endValue: number;

310

private duration: number;

311

private elapsed: number = 0;

312

private onComplete?: () => void;

313

private easing: (t: number) => number;

314

315

constructor(object: any, property: string, endValue: number, duration: number, easing?: (t: number) => number) {

316

this.object = object;

317

this.property = property;

318

this.startValue = object[property];

319

this.endValue = endValue;

320

this.duration = duration;

321

this.easing = easing || ((t) => t); // Linear by default

322

323

Ticker.shared.add(this.update, this);

324

}

325

326

private update(delta: number) {

327

this.elapsed += delta * (1000 / 60); // Convert to milliseconds

328

const progress = Math.min(this.elapsed / this.duration, 1);

329

const easedProgress = this.easing(progress);

330

331

this.object[this.property] = this.startValue + (this.endValue - this.startValue) * easedProgress;

332

333

if (progress >= 1) {

334

Ticker.shared.remove(this.update, this);

335

if (this.onComplete) {

336

this.onComplete();

337

}

338

}

339

}

340

341

onCompleteCallback(callback: () => void) {

342

this.onComplete = callback;

343

return this;

344

}

345

}

346

347

// Usage

348

const sprite = Sprite.from('player.png');

349

app.stage.addChild(sprite);

350

351

// Animate position

352

new SimpleTween(sprite, 'x', 400, 1000, (t) => t * t) // Quadratic easing

353

.onCompleteCallback(() => {

354

console.log('Movement complete');

355

// Chain another animation

356

new SimpleTween(sprite, 'rotation', Math.PI * 2, 2000);

357

});

358

359

// Animate alpha

360

new SimpleTween(sprite, 'alpha', 0.5, 500);

361

362

// Animate scale

363

new SimpleTween(sprite.scale, 'x', 2, 800);

364

new SimpleTween(sprite.scale, 'y', 2, 800);

365

```

366

367

### Performance Optimization

368

369

```typescript

370

// Efficient animation techniques

371

372

// 1. Object pooling for temporary animated sprites

373

class AnimatedSpritePool {

374

private pool: AnimatedSprite[] = [];

375

376

get(textures: Texture[]): AnimatedSprite {

377

let sprite = this.pool.pop();

378

if (!sprite) {

379

sprite = new AnimatedSprite(textures);

380

} else {

381

sprite.textures = textures;

382

sprite.gotoAndStop(0);

383

}

384

return sprite;

385

}

386

387

release(sprite: AnimatedSprite) {

388

sprite.stop();

389

sprite.visible = false;

390

sprite.parent?.removeChild(sprite);

391

this.pool.push(sprite);

392

}

393

}

394

395

// 2. Batch animation updates (requires TickerPlugin)

396

const animations: AnimatedSprite[] = [];

397

// app.ticker.add((delta) => {

398

// for (const animation of animations) {

399

// animation.update(delta);

400

// }

401

// });

402

403

// 3. Use appropriate animation speeds

404

// Too fast: Wastes GPU cycles

405

// Too slow: Appears choppy

406

const optimalSpeed = 0.167; // ~10 FPS for most game animations

407

408

// 4. Limit concurrent animations

409

const MAX_CONCURRENT_ANIMATIONS = 50;

410

let activeAnimations = 0;

411

412

function startAnimation(sprite: AnimatedSprite) {

413

if (activeAnimations < MAX_CONCURRENT_ANIMATIONS) {

414

sprite.play();

415

activeAnimations++;

416

417

sprite.onComplete = () => {

418

activeAnimations--;

419

};

420

}

421

}

422

```