diff --git a/src/constants/animations.ts b/src/constants/animations.ts index cef52a2..19cd711 100644 --- a/src/constants/animations.ts +++ b/src/constants/animations.ts @@ -2,5 +2,6 @@ export enum Animation { Attack = 'Attack', Cooldown = 'Cooldown', Idle = 'Idle', + Move = 'Move', Stunned = 'Stunned', } diff --git a/src/constants/index.ts b/src/constants/index.ts index 8ca92c2..eb505d7 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -3,4 +3,5 @@ export * from './music' export * from './scenes' export * from './sounds' export * from './sprites' +export * from './states' export * from './tags' diff --git a/src/constants/states.ts b/src/constants/states.ts new file mode 100644 index 0000000..9ed3f49 --- /dev/null +++ b/src/constants/states.ts @@ -0,0 +1 @@ +export { Animation as State } from './animations' diff --git a/src/events/index.ts b/src/events/index.ts index 3bd631e..9350ed3 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,2 +1,3 @@ export * from './attack' export * from './cursors' +export * from './states' diff --git a/src/events/states.ts b/src/events/states.ts new file mode 100644 index 0000000..5be64a2 --- /dev/null +++ b/src/events/states.ts @@ -0,0 +1,59 @@ +import { Animation, Sprite, State } from '../constants' +import { addProjectile, getPlayer } from '../gameobjects' +import type { Enemy } from '../types' + +export function addEnemyState(enemy: Enemy) { + enemy.onStateEnter(State.Idle, async () => { + enemy.play(Animation.Idle) + await wait(rand(0.3, 1)) + enemy.enterState(State.Move) + }) + + enemy.onStateEnter(State.Move, () => { + enemy.play(Animation.Move) + }) + + enemy.onStateEnter(State.Attack, async () => { + const player = getPlayer() + + if (!player?.exists()) { + return + } + + enemy.play(Animation.Attack) + + if (enemy.sprite === Sprite.Pokey) { + addProjectile(enemy, player) + } + + await wait(0.2) + enemy.enterState(State.Cooldown) + }) + + enemy.onStateEnter(State.Cooldown, async () => { + enemy.play(Animation.Cooldown) + await wait(rand(1, 3)) + enemy.enterState(State.Move) + }) + + enemy.onStateEnter(State.Stunned, async () => { + enemy.play(Animation.Stunned) + await wait(rand(0.3, 1)) + enemy.enterState(State.Move) + }) + + enemy.onStateUpdate(State.Move, async () => { + const player = getPlayer() + + if (!player?.exists()) { + return + } + + if (enemy.sprite === Sprite.Pokey && Number(rand()) < 0.005) { + return enemy.enterState(State.Attack) + } + + const direction = player.pos.sub(enemy.pos).unit() + enemy.move(direction.scale(enemy.speed)) + }) +} diff --git a/src/gameobjects/enemy.ts b/src/gameobjects/enemy.ts index f210dab..2de36d3 100644 --- a/src/gameobjects/enemy.ts +++ b/src/gameobjects/enemy.ts @@ -1,6 +1,6 @@ -import { Animation, Sound, Sprite, Tag } from '../constants' -import type { Player } from '../types' -import { addProjectile } from './projectile' +import { Sound, Sprite, State, Tag } from '../constants' +import { addEnemyState } from '../events' +import { getPlayer } from './player' import { incrementScore } from './score' enum Health { @@ -8,9 +8,7 @@ enum Health { Max = 100, } -const State = Animation - -export function addEnemy(x: number, y: number, player: Player) { +export function addEnemy(x: number, y: number) { const sprites = [ Sprite.Bubbie, Sprite.Gooba, @@ -31,57 +29,20 @@ export function addEnemy(x: number, y: number, player: Player) { area(), body(), scale(0.75), - state(State.Attack, Object.values(State)), + state(State.Move, Object.values(State)), Tag.Enemy, { damage, speed }, ]) - enemy.onStateEnter(State.Idle, async () => { - enemy.play(State.Idle) - await wait(rand(0, 1)) - enemy.enterState(State.Attack) - }) - - enemy.onStateEnter(State.Stunned, async () => { - enemy.play(State.Stunned) - await wait(rand(0, 1)) - enemy.enterState(State.Attack) - }) - - enemy.onStateEnter(State.Cooldown, async () => { - enemy.play(State.Cooldown) - await wait(rand(1, 3)) - enemy.enterState(State.Attack) - }) - - enemy.onStateEnter(State.Attack, async () => { - enemy.play(State.Attack) - if (enemy.sprite === Sprite.Pokey) { - addProjectile(enemy, player) - } - }) - - enemy.onStateUpdate(State.Attack, async () => { - if (!player.exists()) { - return - } - - if (enemy.sprite === Sprite.Pokey && Number(rand()) < 0.005) { - return enemy.enterState(State.Idle) - } - - const direction = player.pos.sub(enemy.pos).unit() - enemy.move(direction.scale(enemy.speed)) - }) + addEnemyState(enemy) enemy.onCollide(Tag.Player, async () => { - enemy.enterState(State.Cooldown) - player.hurt(enemy.damage) + enemy.enterState(State.Attack) + getPlayer()?.hurt(enemy.damage) }) enemy.onHurt(() => { enemy.enterState(State.Stunned) - enemy.play(State.Stunned) }) enemy.onDeath(() => { diff --git a/src/gameobjects/player.ts b/src/gameobjects/player.ts index f16fa79..85dc3bb 100644 --- a/src/gameobjects/player.ts +++ b/src/gameobjects/player.ts @@ -1,6 +1,7 @@ import { Scene, Sound, Sprite, Tag } from '../constants' import { addAttack, addCursorKeys } from '../events' import { stopMusic } from '../gameobjects' +import type { Player } from '../types' const HEALTH = 100 @@ -35,3 +36,7 @@ export function addPlayer(x = center().x, y = center().y) { return player } + +export function getPlayer() { + return get(Tag.Player)[0] as Player | undefined +} diff --git a/src/scenes/game.ts b/src/scenes/game.ts index 263edd8..16c0596 100644 --- a/src/scenes/game.ts +++ b/src/scenes/game.ts @@ -30,6 +30,6 @@ scene(Scene.Game, () => { loop(5, () => { const { x, y } = outsideCoordinates(player.pos.x, player.pos.y) - addEnemy(x, y, player) + addEnemy(x, y) }) }) diff --git a/src/scenes/preload.ts b/src/scenes/preload.ts index 33dcd52..d7d3b3a 100644 --- a/src/scenes/preload.ts +++ b/src/scenes/preload.ts @@ -11,6 +11,7 @@ scene(Scene.Preload, () => { sliceX: 4, anims: { [Animation.Idle]: 0, + [Animation.Move]: 0, [Animation.Attack]: 1, [Animation.Cooldown]: 2, [Animation.Stunned]: 3, @@ -21,14 +22,13 @@ scene(Scene.Preload, () => { loadSprite(Sprite.Pokey, 'sprites/pokey.png', { sliceX: 5, anims: { + [Animation.Idle]: 3, + [Animation.Move]: 0, [Animation.Attack]: { from: 1, to: 2, - loop: true, - speed: 1, }, [Animation.Cooldown]: 0, - [Animation.Idle]: 3, [Animation.Stunned]: 4, }, }) @@ -43,9 +43,10 @@ scene(Scene.Preload, () => { sprites.forEach(([name, src]) => { loadSprite(name, src, { anims: { + [Animation.Idle]: 0, + [Animation.Move]: 0, [Animation.Attack]: 0, [Animation.Cooldown]: 0, - [Animation.Idle]: 0, [Animation.Stunned]: 0, }, })