Skip to content

Commit

Permalink
feat(graphics): animated sprite component
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaisthorpe committed Aug 25, 2024
1 parent 03f7c7b commit dde8044
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 0 deletions.
Binary file added apps/docs/assets/person.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions apps/docs/docs/examples/2d/animated-sprite-component.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Animated Sprite Component

import useBrowserOnly from '@docusaurus/useIsBrowser';
import { TGame } from '@tedengine/ted';

export const Game = () => {
const onBrowser = useBrowserOnly();
if (!onBrowser) {
return null;
}
return (
<TGame
config={{
renderWidth: 200,
renderHeight: 150,
imageRendering: 'pixelated',
}}
game={
new Worker(
new URL('@examples/2d/animated-sprite-component.ts', import.meta.url),
)
}
/>
);
};

<Game />
66 changes: 66 additions & 0 deletions apps/docs/src/examples/2d/animated-sprite-component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import asteroidTexture from '@assets/person.png';
import { vec3 } from 'gl-matrix';
import type { TResourcePackConfig } from '@tedengine/ted';
import {
TGameState,
TActor,
TOriginPoint,
TResourcePack,
TEngine,
TAnimatedSpriteComponent,
TSpriteLayer,
TOrthographicCamera,
} from '@tedengine/ted';

class Sprite extends TActor {
public static resources: TResourcePackConfig = {
textures: [asteroidTexture],
};

constructor(engine: TEngine) {
super();

const box = new TAnimatedSpriteComponent(
engine,
this,
12,
24,
TOriginPoint.Center,
TSpriteLayer.Foreground_0,
{
frameCount: 9,
frameRate: 10,
},
);
box.applyTexture(engine, asteroidTexture);

this.rootComponent.transform.translation = vec3.fromValues(0, 0, -3);
}
}

class SpriteState extends TGameState {
public async onCreate(engine: TEngine) {
const rp = new TResourcePack(engine, Sprite.resources);

await rp.load();

this.onReady(engine);
}

public onReady(engine: TEngine) {
const asteroid = new Sprite(engine);
this.addActor(asteroid);

const camera = new TOrthographicCamera(engine);
this.activeCamera = camera;
}
}

const config = {
states: {
game: SpriteState,
},
defaultState: 'game',
};

new TEngine(config, self as DedicatedWorkerGlobalScope);
68 changes: 68 additions & 0 deletions packages/ted/src/actor-components/animated-sprite-component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type TActor from '../core/actor';
import type TEngine from '../engine/engine';
import type { TPhysicsBodyOptions } from '../physics/physics-world';
import type { TSerializedSpriteInstance } from '../renderer/frame-params';
import type { TActorComponentWithOnUpdate } from './actor-component';
import TSpriteComponent, {
TOriginPoint,
TSpriteLayer,
} from './sprite-component';

export interface TSpriteSheetOptions {
frameCount: number;
frameRate: number;
}

export default class TAnimatedSpriteComponent
extends TSpriteComponent
implements TActorComponentWithOnUpdate
{
public frame = 0;

private time = 0;

constructor(
engine: TEngine,
actor: TActor,
width: number,
height: number,
origin = TOriginPoint.Center,
layer = TSpriteLayer.Foreground_0,
private spriteSheetOptions: TSpriteSheetOptions,
bodyOptions?: TPhysicsBodyOptions,
) {
super(engine, actor, width, height, origin, layer, bodyOptions);
}

public async onUpdate(_: TEngine, delta: number): Promise<void> {
this.time += delta;
if (this.time > 1 / this.spriteSheetOptions.frameRate) {
this.time = 0;
this.frame = (this.frame + 1) % this.spriteSheetOptions.frameCount;
}
}

public getRenderTask(): TSerializedSpriteInstance | undefined {
const task = super.getRenderTask();
if (!task) {
return undefined;
}

// @todo modify the instance UVs based on the frame
const startX = this.frame * (1 / this.spriteSheetOptions.frameCount);
const endX = startX + 1 / this.spriteSheetOptions.frameCount;

task.material.options.instanceUVs = [
startX,
0,
startX,
1,
endX,
0,
endX,
1,
];

return task;
}
}
2 changes: 2 additions & 0 deletions packages/ted/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export * from './actor-components/sprite-component';
export { default as TTexturedMeshComponent } from './actor-components/textured-mesh-component';
export { default as TTilemapComponent } from './actor-components/tilemap-component';
export * from './actor-components/tilemap-component';
export { default as TAnimatedSpriteComponent } from './actor-components/animated-sprite-component';
export * from './actor-components/animated-sprite-component';

export { default as TAudio } from './audio/audio';
export { default as TSound } from './audio/sound';
Expand Down

0 comments on commit dde8044

Please sign in to comment.