From aa2642c1e4119d89c9feb1fdff52f3942f2c85cd Mon Sep 17 00:00:00 2001 From: Paolo Brasolin <paolo.brasolin@eurac.edu> Date: Mon, 14 Mar 2022 23:44:56 +0100 Subject: [PATCH] feat: split foe into clue+critter --- frontend/src/js/clue.ts | 48 +++++++++++++++++++ frontend/src/js/critter.ts | 62 ++++++++++++++++++++++++ frontend/src/js/fight_scene.ts | 21 ++++---- frontend/src/js/foe.ts | 87 ---------------------------------- frontend/src/js/spear.ts | 2 +- 5 files changed, 123 insertions(+), 97 deletions(-) create mode 100644 frontend/src/js/clue.ts create mode 100644 frontend/src/js/critter.ts delete mode 100644 frontend/src/js/foe.ts diff --git a/frontend/src/js/clue.ts b/frontend/src/js/clue.ts new file mode 100644 index 0000000..d13ab82 --- /dev/null +++ b/frontend/src/js/clue.ts @@ -0,0 +1,48 @@ +import "phaser"; +import FightScene from "./fight_scene"; + +interface WordObject { + id: string; + image: string; + ocr_confidence: number; + ocr_transcript: string; +} + +class Clue extends Phaser.GameObjects.Sprite { + word: WordObject; + + constructor(scene: FightScene, word: WordObject) { + // TODO: set positions + super(scene, 400, 300, word.id); + + this.setAlpha(0); + this.scene.add.existing(this); + + this.scene = scene; + this.word = word; + + this.loadTexture(); + } + + loadTexture() { + this.scene.textures.addBase64(this.word.id, this.word.image); + this.scene.textures.once( + "addtexture", + this.showTexture.bind(this), + this.scene, + ); + } + + showTexture() { + this.setTexture(this.word.id); + this.scene.tweens.add({ + targets: this, + alpha: 1, + ease: "Linear", + delay: 0, + duration: 100, + }); + } +} + +export default Clue; diff --git a/frontend/src/js/critter.ts b/frontend/src/js/critter.ts new file mode 100644 index 0000000..435150b --- /dev/null +++ b/frontend/src/js/critter.ts @@ -0,0 +1,62 @@ +import "phaser"; +import Clue from "./clue"; +import FightScene from "./fight_scene"; + +const SPECIES = ["bear", "wolf", "deer", "boar"]; + +class Critter extends Phaser.Physics.Arcade.Sprite { + clue: Clue; + scene: FightScene; + species: string; + body: Phaser.Physics.Arcade.Body; + + constructor(scene: FightScene, clue: Clue) { + const species = SPECIES[Math.floor(Math.random() * SPECIES.length)]; + super(scene, -100, scene.cameras.main.height - 100, species); + scene.add.existing(this); + + this.scene = scene; + this.species = species; + this.clue = clue; + + let scale = 2; + if (this.species === "deer") { + scale = 2.5; + } else if (this.species === "bear") { + scale = 3; + } + + this.body = new Phaser.Physics.Arcade.Body(this.scene.physics.world, this); + this.scene.physics.world.add(this.body); + this.scene.physics.add.collider(this, this.scene.ground); + + this.setScale(scale); + // this.setInteractive(true); + this.flipX = true; + + this.play({ key: this.species + "_walk", repeat: -1 }); + // TODO: bring animal below grass + + this.body.setVelocity(100, 0); + + // here to implement health + this.scene.physics.add.overlap( + this.scene.player, + this, + (_player, _enemy) => { + this.play(this.species + "_run"); + this.body.setVelocity(300, 0); + setTimeout(() => this.destroy(), 2000); + }, + ); + } + + flee() { + this.play(this.species + "_run"); + this.flipX = false; + this.body.setVelocity(-200, 0); + setTimeout(() => this.destroy(), 2000); // TODO: disappear offscreen + } +} + +export default Critter; diff --git a/frontend/src/js/fight_scene.ts b/frontend/src/js/fight_scene.ts index 137303f..ec046f6 100644 --- a/frontend/src/js/fight_scene.ts +++ b/frontend/src/js/fight_scene.ts @@ -1,14 +1,15 @@ import "phaser"; -import Foe from "./foe"; +import Critter from "./critter"; import Spear from "./spear"; import backend from "./backend"; // TODO: write interfaces import levenshtein from "damerau-levenshtein"; +import Clue from "./clue"; export default class FightScene extends Phaser.Scene { - foes: Array<Foe>; + foes: Array<Critter>; ground: Phaser.Types.Physics.Arcade.ImageWithStaticBody; player: Phaser.Types.Physics.Arcade.SpriteWithDynamicBody; @@ -282,25 +283,25 @@ function submitTranscription(transcription: string, scene: FightScene) { let similarity = 0; let match = null; - scene.foes.forEach((foe) => { + scene.foes.forEach((critter) => { const s = levenshtein( transcription.toLowerCase(), - foe.word.ocr_transcript.toLowerCase(), + critter.clue.word.ocr_transcript.toLowerCase(), ).similarity; if (s < similarity) return; similarity = s; - match = foe; + match = critter; }); match ??= scene.foes[0]; // TODO: remove this - console.log(similarity, match.word.ocr_transcript); + console.log(similarity, match.clue.word.ocr_transcript); // TODO: we can have near misses depending on similarity! const hit = similarity >= 0.9; const enemy = match; - scene.shootSpear(enemy.animalSprite, hit); + scene.shootSpear(enemy, hit); } function gameStart(scene: any) { @@ -309,7 +310,9 @@ function gameStart(scene: any) { function dispatchEnemy(scene: any) { backend.post("GetImage", {}).then(function (response) { - const foe = new Foe(scene, response.data); - scene.foes.push(foe); + const clue = new Clue(scene, response.data); + const critter = new Critter(scene, clue); + // TODO: clue + scene.foes.push(critter); }); } diff --git a/frontend/src/js/foe.ts b/frontend/src/js/foe.ts deleted file mode 100644 index ccf208c..0000000 --- a/frontend/src/js/foe.ts +++ /dev/null @@ -1,87 +0,0 @@ -import "phaser"; - -const SPECIES = ["bear", "wolf", "deer", "boar"]; - -interface wordObject { - id: string; - image: string; - ocr_confidence: number; - ocr_transcript: string; -} - -class Foe { - scene: Phaser.Scene; - clueSprite: Phaser.GameObjects.Sprite; - animalSprite: Phaser.GameObjects.Sprite; - word: wordObject; - species: string; - - constructor(scene: Phaser.Scene, word: wordObject) { - this.scene = scene; - this.word = word; - this.addClue(); - this.addAnimal(); - } - - addClue() { - this.scene.textures.addBase64(this.word.id, this.word.image); - this.scene.textures.once( - "addtexture", - this.addClueSprite.bind(this), - this.scene, - ); - } - - addClueSprite() { - // TODO: position - this.clueSprite = this.scene.add.sprite(400, 300, this.word.id); - } - - addAnimal() { - this.species = SPECIES[Math.floor(Math.random() * SPECIES.length)]; - - let scale = 2; - if (this.species === "deer") { - scale = 2.5; - } else if (this.species === "bear") { - scale = 3; - } - - this.animalSprite = this.scene.physics.add - .sprite(-100, this.scene.cameras.main.height - 100, this.species) - .setScale(scale) - .setInteractive(); - this.animalSprite.flipX = true; - - this.animalSprite.flee = function () { - this.play(this.species + "_run"); - this.flipX = false; - this.body.setVelocity(-200, 0); - setTimeout(() => this.destroy(), 2000); // TODO: disappear offscreen - }; - - this.scene.physics.add.collider(this.animalSprite, this.scene.ground); - - setAnimation(this.animalSprite, this.species + "_walk"); - // TODO: bring animal below grass - - this.animalSprite.body.setVelocity(100, 0); - - // here to implement health - this.scene.physics.add.overlap( - this.scene.player, - this.animalSprite, - (player, nemico) => { - nemico.play(this.species + "_run"); - this.animalSprite.body.setVelocity(300, 0); - setTimeout(() => nemico.destroy(), 2000); - }, - ); - } -} - -function setAnimation(obj, idleKey) { - obj.play({ key: idleKey, repeat: -1 }); -} - -export default Foe; diff --git a/frontend/src/js/spear.ts b/frontend/src/js/spear.ts index 74ca7ac..784e868 100644 --- a/frontend/src/js/spear.ts +++ b/frontend/src/js/spear.ts @@ -48,7 +48,7 @@ class Spear extends Phaser.Physics.Arcade.Sprite { this.hitTarget.bind(this), ); } else { - console.error("Cannot hit foe. :("); + console.error("Cannot hit critter. :("); } } -- GitLab