const {GRAVITY} = require('./constants.js'); const {SpriteSheet} = require('./sprite-sheet'); export type NPCOptions = { bubbleOffset?: [number, number]; noBounds?: boolean; noGravity?: boolean; scale?: number; } export class NPC { private readonly emojis = [ 0x1F600, 0x1F601, 0x1F603, 0x1F603, 0x1F604, 0x1F605, 0x1F606, 0x1F607, 0x1F609, 0x1F60A, 0x1F642, 0x1F643, 0x1F355, 0x1F354, ]; private readonly texturePack: any; private random: number = 0; private sprite!: any; private text: string; public pos = [0, 0]; public vel = [0, 0]; constructor(private readonly ctx: CanvasRenderingContext2D, public readonly spriteSheetPath: string, public readonly spriteDefPath: string, public readonly options: NPCOptions = {}, ) { this.texturePack = new SpriteSheet(this.ctx, './assets/sprites/texture-pack/spritesheet.png', '../assets/sprites/texture-pack/spritesheet.json'); if(this.options.bubbleOffset == null) this.options.bubbleOffset = [0, 0]; if(this.options.scale == null) this.options.scale = 1; this.sprite = new SpriteSheet(ctx, spriteSheetPath, spriteDefPath); setInterval(() => { this.message(String.fromCodePoint(this.emojis[~~(Math.random() * this.emojis.length)])); }, 10000); } animate(name: string, reverse = false) { if(this.text) { const bubble = this.texturePack.definitions.sprites['bubble']; const x = this.pos[0] + this.options.bubbleOffset[0] * (reverse ? -1 : 1); const y = this.pos[1] + this.options.bubbleOffset[1]; this.texturePack.drawSprite(x, y, 'bubble', reverse); this.ctx.save(); this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.font = '24px serif'; this.ctx.fillText(this.text, x + (bubble.width / 2 * (reverse ? -1 : 1)), y + (bubble.height / 2)); this.ctx.restore(); } this.sprite.animate(this.pos[0], this.pos[1], name, reverse, this.options.scale); } tick() { if(this.random <= 0) { const move = Math.random(); if(move < 0.333) this.vel = [0, 0]; else if(move < 0.666) this.vel = [-10, 0]; else this.vel = [10, 0]; this.random = Math.random() * 50; } this.random--; this.pos = [this.pos[0] + this.vel[0], this.pos[1] + this.vel[1]]; if(!this.options.noGravity) this.vel[1] -= GRAVITY; if(this.pos[1] < 0) this.pos[1] = 0; if(!this.options.noBounds) { if(this.pos[0] < 0) this.pos[0] = 0; if(this.pos[0] > this.ctx.canvas.width) this.pos[0] = this.ctx.canvas.width; } this.animate(this.vel[0] == 0 ? 'idle' : 'walk', this.vel[0] < 0); } message(text: string, ms = 5000) { setTimeout(() => this.text = null, ms); this.text = text; } }