diff options
Diffstat (limited to 'static/src/engine/render.ts')
| -rw-r--r-- | static/src/engine/render.ts | 84 |
1 files changed, 79 insertions, 5 deletions
diff --git a/static/src/engine/render.ts b/static/src/engine/render.ts index 8f0343a..4ff1ec0 100644 --- a/static/src/engine/render.ts +++ b/static/src/engine/render.ts @@ -2,6 +2,8 @@ import { ComponentType, PositionComponent, TrailingPositionComponent, + SpriteSheetComponent, + SpriteSpec, } from "./component"; import { Game } from "./game"; import { System, SystemType } from "./system"; @@ -17,7 +19,7 @@ export class RenderSystem extends System { this.canvas.height = height; } - public update(_dt: number, game: Game) { + public update(dt: number, game: Game) { const ctx = this.canvas.getContext("2d"); if (ctx === null) return; ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); @@ -32,15 +34,87 @@ export class RenderSystem extends System { return; } - if (ComponentType.POSITION in entity.components) { + if ( + ComponentType.POSITION in entity.components && + ComponentType.SPRITESHEET in entity.components + ) { const position = entity.components[ ComponentType.POSITION ] as PositionComponent; - ctx.beginPath(); - ctx.arc(position.x, position.y, 50, 0, 2 * Math.PI); - ctx.stroke(); + const spritesheet = entity.components[ + ComponentType.SPRITESHEET + ] as SpriteSheetComponent; + + if (typeof spritesheet.sheet === "undefined") { + const img = new Image(); + img.src = spritesheet.source; + spritesheet.sheet = img; + } + const spritespec = + spritesheet.state_to_spritespec[spritesheet.current_state]; + + this.blit_sprite(ctx, spritesheet, position); + + spritesheet.last_update += dt; + if (spritesheet.last_update > spritespec.ms_per_frame) { + spritesheet.current_frame++; + spritesheet.current_frame %= spritespec.frames; + spritesheet.last_update = 0; + } + return; } }); } + + private blit_sprite( + ctx: CanvasRenderingContext2D, + spritesheet: SpriteSheetComponent, + position: { x: number; y: number }, + ) { + ctx.save(); + ctx.translate(position.x, position.y); + ctx.translate(-position.x, -position.y); + + if (typeof spritesheet.sheet === "undefined") return; + + const spritespec = + spritesheet.state_to_spritespec[spritesheet.current_state]; + + ctx.drawImage( + spritesheet.sheet, + ...this.get_sprite_args(spritesheet.current_frame, spritespec), + ...this.get_draw_args(spritespec, position), + ); + + ctx.restore(); + } + + private get_sprite_args( + current_frame: number, + sprite_spec: SpriteSpec, + ): [sx: number, sy: number, sw: number, sh: number] { + const [width, height] = this.get_dimensions(sprite_spec); + return [ + sprite_spec.top_x, + sprite_spec.top_y + current_frame * height, + width, + height, + ]; + } + + private get_draw_args( + sprite_spec: SpriteSpec, + position: { x: number; y: number }, + ): [dx: number, dy: number, dw: number, dh: number] { + const [width, height] = this.get_dimensions(sprite_spec); + return [position.x - width / 2, position.y - height / 2, width, height]; + } + + private get_dimensions(sprite_spec: SpriteSpec): [number, number] { + return [ + sprite_spec.end_x - sprite_spec.top_x, + (sprite_spec.end_y - sprite_spec.top_y) / sprite_spec.frames, + ]; + } } |
