import { gameFrame } from '../constants/Prototype.js'; import { catAnimation, imageAssets } from '../sketch.js'; import { grid, cheeses, activeCats, activeMice, calculateCell, mouseGroup, throwableGroup, gameSprites } from '../GameScene.js'; import { Yarn, Snowball } from './Throwable.js'; export const throwables = []; export const sleepyCats = []; const catAniDesc = { chefCat: { idle: { row: 0, frames: 4, frameSize: [200, 200], frameDelay: 10 }, action: { row: 0, frames: 4, frameSize: [200, 200], frameDelay: 10 } }, singleYarnCat: { idle: { row: 0, frameSize: [200, 200] }, action: {row: 1, frames: 8, frameSize: [200, 200], frameDelay: 22 } }, doubleYarnCat: { idle: { row: 0, frameSize: [200, 200] }, action: {row: 1, frames: 8, frameSize: [200, 200], frameDelay: 22 } }, sleepyCat: { idle: {row: 0, frames: 6, frameSize: [200, 200], frameDelay: 20 }, action: {row: 1, frames: 9, frameSize: [200, 200], frameDelay: 10 } }, explosion: { action: {row: 0, frames: 9, frameSize: [200, 200], frameDelay: 10 } }, iceCat: { idle: { row: 0, frameSize: [200, 200] }, action: {row: 1, frames: 8, frameSize: [200, 200], frameDelay: 22 } } } class Cat { constructor(x, y, cost, spriteSheet, ani) { // (x, y) is the center of the grid this.width = 1.2 * gameFrame.tileWidth; this.sprite = createSprite(x, y, this.width, this.width); this.sprite.spriteSheet = spriteSheet; this.sprite.scale = gameFrame.catRatio; this.sprite.addAnis(ani); this.sprite.collider = 'static'; this.sprite.overlaps(throwableGroup); this.sprite.layer = 1; this.sprite.changeAni('idle'); this.active = false; this.explosion = undefined; this.x = x; this.y = y; this.cost = cost; this.ani = ani; this.HP = 100; const { row, col } = calculateCell(x, y); this.row = row; this.col = col; } switchToIdle() { this.sprite.changeAni('idle'); this.active = false; } switchToAction() { this.sprite.changeAni('action'); this.active = true; } attacked(mouse) { this.addExplosion(imageAssets.grayExplosion); this.explosion = undefined; this.HP -= mouse.AP; setTimeout(() => { if (this.HP <= 0) { this.remove(); mouse.targetCat = undefined; } else { this.sprite.opacity = (this.HP / 100) * 0.7 + 0.3; } }, 1500); } changeAni(name) { this.sprite.changeAni(name); } remove() { this.sprite.remove(); grid[this.row][this.col] = null; const index = activeCats.indexOf(this); if (index !== -1) { activeCats.splice(index, 1); } } addExplosion(spriteSheet) { this.explosion = createSprite(this.x, this.y, this.width, this.width); gameSprites.push(this.explosion); this.explosion.spriteSheet = spriteSheet; this.explosion.scale = gameFrame.catRatio; this.explosion.life = 90; this.explosion.collider = 'none'; this.explosion.addAnis(catAniDesc.explosion); this.explosion.changeAni('action'); // this.explosion.overlaps(mouseGroup); // this.explosion.overlaps(catGroup); } } class ChefCat extends Cat { constructor(x, y) { super(x, y, 50, catAnimation.chefCat, catAniDesc.chefCat); this.lastProduced = millis(); this.offset = 0; } action() { // Produces 25 cheese every 10 seconds, cheese.png pop in front of the chefCat if (millis() - this.lastProduced > 10000) { const cheese = createSprite(this.x + this.width / 4 + this.offset * this.width / 20, this.y + this.width / 3 + this.offset * this.width / 20); cheese.scale = this.width / 216; cheese.image = imageAssets.cheese; cheese.collider = 'static'; cheese.overlaps(mouseGroup); cheeses.push(cheese); gameSprites.push(cheese); this.lastProduced = millis(); this.offset = (this.offset + 1) % 3; } } } class SingleYarnCat extends Cat { constructor(x, y) { super(x, y, 100, catAnimation.singleYarnCat, catAniDesc.singleYarnCat); this.lastShot = millis(); } action() { // Throw yarn every 3 seconds -> yarn has velocity x of 1 (to the right) if (activeMice[this.row].length > 0) this.switchToAction(); else this.switchToIdle(); if (this.active && (millis() - this.lastShot > 3000)) { let yarnX = this.x + gameFrame.tileWidth / 2; let yarnY = this.y; const yarn = new Yarn(yarnX, yarnY); if (yarn) { throwables.push(yarn); throwableGroup.add(yarn.sprite); } this.lastShot = millis(); } } } class DoubleYarnCat extends Cat { constructor(x, y) { super(x, y, 200, catAnimation.doubleYarnCat, catAniDesc.doubleYarnCat); this.lastShot = millis(); } action() { // Throw 2 yarns every 3 seconds -> yarn has velocity x of 1 (to the right) if (activeMice[this.row].length > 0) this.switchToAction(); else this.switchToIdle(); if (this.active && (millis() - this.lastShot > 3000)) { // TODO: check on the offset again for (let offset of [0, 20]) { let yarnX = this.x + gameFrame.tileWidth / 2 + offset; let yarnY = this.y; const yarn = new Yarn(yarnX, yarnY); if (yarn) { throwables.push(yarn); throwableGroup.add(yarn.sprite); } } this.lastShot = millis(); } } } export class SleepyCat extends Cat { constructor(x, y) { super(x, y, 150, catAnimation.sleepyCat, catAniDesc.sleepyCat); this.awake = false; this.hasAttacked = false; this.wakeStart = undefined; this.targetMouse = undefined; } action(targetMouse) { if (this.awake) { this.changeAni('action'); this.addExplosion(imageAssets.redExplosion); this.wakeStart = millis(); this.targetMouse = targetMouse; this.targetMouse.sprite.vel.x = 0; this.targetMouse.sprite.changeAni('idle'); this.awake = false; } if (this.wakeStart != undefined) { if (!this.hasAttacked && this.targetMouse && millis() - this.wakeStart > 900) { this.targetMouse.attacked(150); if (this.targetMouse && this.targetMouse.HP > 0) this.targetMouse.sprite.changeAni('walk'); this.hasAttacked = true; } if (millis() - this.wakeStart > 1480) { this.remove(); this.explosion.remove(); this.explosion = undefined; } } } } class IceCat extends Cat { constructor(x, y) { super(x, y, 150, catAnimation.iceCat, catAniDesc.iceCat); this.lastShot = millis(); } action() { // Throw snowball every 3 seconds -> snowball has velocity x of 1 (to the right) if (activeMice[this.row].length > 0) this.switchToAction(); else this.switchToIdle(); if (this.active && (millis() - this.lastShot > 3000)) { const snowballX = this.x + gameFrame.tileWidth / 2; const snowballY = this.y; const snowball = new Snowball(snowballX, snowballY) if (snowball) { throwables.push(snowball); throwableGroup.add(snowball.sprite); } this.lastShot = millis(); } } } export function createCat(type, x, y) { switch (type) { case 'chefCat': const chefCat = new ChefCat(x, y); chefCat.action(); return chefCat; case 'singleYarnCat': return new SingleYarnCat(x, y); case 'doubleYarnCat': return new DoubleYarnCat(x, y); case 'sleepyCat': const sleepyCat = new SleepyCat(x, y); if (sleepyCat) sleepyCats.push(sleepyCat); return sleepyCat; case 'iceCat': return new IceCat(x, y); default: return undefined; } }