From e4b9bb4d61e3f7c5d440c92fbc69c9cac7cd487a Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Sat, 1 Feb 2025 15:10:52 +0100 Subject: [PATCH] Refactored Character.vue as preparation for attack anims. --- src/application/enums.ts | 5 + src/components/game/character/Character.vue | 152 +++--------------- .../partials/{Healthbar.vue => HealthBar.vue} | 0 .../useCharacterSpriteComposable.ts | 131 +++++++++++++++ 4 files changed, 157 insertions(+), 131 deletions(-) create mode 100644 src/application/enums.ts rename src/components/game/character/partials/{Healthbar.vue => HealthBar.vue} (100%) create mode 100644 src/composables/useCharacterSpriteComposable.ts diff --git a/src/application/enums.ts b/src/application/enums.ts new file mode 100644 index 0000000..8dd4620 --- /dev/null +++ b/src/application/enums.ts @@ -0,0 +1,5 @@ +export enum Direction { + POSITIVE, + NEGATIVE, + UNCHANGED +} diff --git a/src/components/game/character/Character.vue b/src/components/game/character/Character.vue index 29596bf..f1d2593 100644 --- a/src/components/game/character/Character.vue +++ b/src/components/game/character/Character.vue @@ -1,134 +1,43 @@ diff --git a/src/components/game/character/partials/Healthbar.vue b/src/components/game/character/partials/HealthBar.vue similarity index 100% rename from src/components/game/character/partials/Healthbar.vue rename to src/components/game/character/partials/HealthBar.vue diff --git a/src/composables/useCharacterSpriteComposable.ts b/src/composables/useCharacterSpriteComposable.ts new file mode 100644 index 0000000..500d768 --- /dev/null +++ b/src/composables/useCharacterSpriteComposable.ts @@ -0,0 +1,131 @@ +import { type MapCharacter } from '@/application/types' +import { loadSpriteTextures } from '@/composables/gameComposable' +import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/mapComposable' +import { CharacterTypeStorage } from '@/storage/storages' +import { refObj } from 'phavuer' +import { computed, ref } from 'vue' +import { Direction } from '@/application/enums' + +export function useCharacterSprite(scene: Phaser.Scene, tilemap: Phaser.Tilemaps.Tilemap, mapCharacter: MapCharacter) { + const charSprite = refObj() + const charSpriteId = ref('') + const currentPositionX = ref(0) + const currentPositionY = ref(0) + const isometricDepth = ref(1) + const isInitialPosition = ref(true) + const tween = ref(null) + + const updateIsometricDepth = (positionX: number, positionY: number) => { + isometricDepth.value = calculateIsometricDepth(positionX, positionY, 28, 94, true) + } + + const updatePosition = (positionX: number, positionY: number, direction: Direction) => { + const newPositionX = tileToWorldX(tilemap, positionX, positionY) + const newPositionY = tileToWorldY(tilemap, positionX, positionY) + + if (isInitialPosition.value) { + currentPositionX.value = newPositionX + currentPositionY.value = newPositionY + isInitialPosition.value = false + return + } + + if (tween.value?.isPlaying()) { + tween.value.stop() + } + + const distance = Math.sqrt(Math.pow(newPositionX - currentPositionX.value, 2) + Math.pow(newPositionY - currentPositionY.value, 2)) + const baseSpeed = 150 // pixels per second + const duration = (distance / baseSpeed) * 1000 // Convert to milliseconds + + tween.value = tilemap.scene.tweens.add({ + targets: charSprite.value, + x: newPositionX, + y: newPositionY, + duration, + ease: 'Linear', + onStart: () => { + if (direction === Direction.POSITIVE) { + updateIsometricDepth(positionX, positionY) + } + }, + onUpdate: () => { + currentPositionX.value = charSprite.value?.x ?? currentPositionX.value + currentPositionY.value = charSprite.value?.y ?? currentPositionY.value + }, + onComplete: () => { + if (direction === Direction.NEGATIVE) { + updateIsometricDepth(positionX, positionY) + } + } + }) + } + + const calcDirection = (oldPositionX: number, oldPositionY: number, newPositionX: number, newPositionY: number): Direction => { + if (newPositionY < oldPositionY || newPositionX < oldPositionX) return Direction.NEGATIVE + if (newPositionX > oldPositionX || newPositionY > oldPositionY) return Direction.POSITIVE + return Direction.UNCHANGED + } + + const isFlippedX = computed(() => [6, 4].includes(mapCharacter.character.rotation ?? 0)) + + const currentDirection = computed(() => { + return [0, 6].includes(mapCharacter.character.rotation ?? 0) ? 'left_up' : 'right_down' + }) + + const currentAction = computed(() => { + return mapCharacter.isMoving ? 'walk' : 'idle' + }) + + const charTexture = computed(() => { + const spriteId = charSpriteId.value ?? 'idle_right_down' + return `${spriteId}-${currentAction.value}_${currentDirection.value}` + }) + + const updateSprite = () => { + if (!charSprite.value) return + + if (mapCharacter.isMoving) { + charSprite.value.anims.play(charTexture.value, true) + } else { + charSprite.value.anims.stop() + charSprite.value.setFrame(0) + charSprite.value.setTexture(charTexture.value) + } + } + + const initializeSprite = async () => { + const characterTypeStorage = new CharacterTypeStorage() + const spriteId = await characterTypeStorage.getSpriteId(mapCharacter.character.characterType!) + if (!spriteId) return + + charSpriteId.value = spriteId + await loadSpriteTextures(scene, spriteId) + + if (charSprite.value) { + charSprite.value.setTexture(charTexture.value) + charSprite.value.setFlipX(isFlippedX.value) + charSprite.value.setName(mapCharacter.character.name) + } + + updatePosition(mapCharacter.character.positionX, mapCharacter.character.positionY, mapCharacter.character.rotation) + } + + const cleanup = () => { + tween.value?.stop() + } + + return { + charSprite, + charSpriteId, + currentPositionX, + currentPositionY, + isometricDepth, + isFlippedX, + updatePosition, + calcDirection, + updateSprite, + initializeSprite, + cleanup + } +} \ No newline at end of file