From 9b592d6c7c2528273021f116e525b5f83f67d374 Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Sun, 22 Sep 2024 02:14:32 +0200 Subject: [PATCH] npm run format, started working on follow player logic, refactor some camera logic --- src/components/gameMaster/GmTools.vue | 13 +++--- .../gameMaster/zoneEditor/ZoneEditor.vue | 12 +---- .../zoneEditor/partials/Toolbar.vue | 24 +++++----- src/components/sprites/Character.vue | 24 +++++----- src/components/utilities/Modal.vue | 6 +-- src/components/zone/Zone.vue | 8 ---- .../pointerHandlers/useGamePointerHandlers.ts | 44 +++++++++++-------- .../useZoneEditorPointerHandlers.ts | 28 +++++++----- src/composables/useCameraControls.ts | 21 ++------- src/composables/zoneComposable.ts | 6 +-- src/config.ts | 2 +- src/screens/Game.vue | 4 +- src/stores/gameStore.ts | 19 +++++--- src/types.ts | 1 - 14 files changed, 101 insertions(+), 111 deletions(-) diff --git a/src/components/gameMaster/GmTools.vue b/src/components/gameMaster/GmTools.vue index 01f62d8..923f3c5 100644 --- a/src/components/gameMaster/GmTools.vue +++ b/src/components/gameMaster/GmTools.vue @@ -19,29 +19,26 @@ import { onMounted, ref } from 'vue' const zoneEditorStore = useZoneEditorStore() const gameStore = useGameStore() -const modalWidth = ref(200); -const modalHeight = ref(160); +const modalWidth = ref(200) +const modalHeight = ref(160) -let posXY = ref({x: 0, y: 0}); +let posXY = ref({ x: 0, y: 0 }) onMounted(() => { - window.addEventListener('resize', () => { - posXY.value = customPositionGmPanel(modalWidth.value); + posXY.value = customPositionGmPanel(modalWidth.value) }) - }) const customPositionGmPanel = (modalWidth: number) => { const padding = 25 const width = window.innerWidth - const x = width - (modalWidth+4) - 25 + const x = width - (modalWidth + 4) - 25 const y = padding return { x, y } } posXY.value = customPositionGmPanel(modalWidth.value) - diff --git a/src/components/gameMaster/zoneEditor/ZoneEditor.vue b/src/components/gameMaster/zoneEditor/ZoneEditor.vue index d1d24f5..ce2d45f 100644 --- a/src/components/gameMaster/zoneEditor/ZoneEditor.vue +++ b/src/components/gameMaster/zoneEditor/ZoneEditor.vue @@ -29,15 +29,7 @@ import { Container, Image, useScene } from 'phavuer' import { storeToRefs } from 'pinia' import { useGameStore } from '@/stores/gameStore' import { useZoneEditorStore } from '@/stores/zoneEditorStore' -import { - calculateIsometricDepth, - loadAssets, - placeTile, - setAllTiles, - sortByIsometricDepth, - tileToWorldX, - tileToWorldY -} from '@/composables/zoneComposable' +import { calculateIsometricDepth, loadAssets, placeTile, setAllTiles, sortByIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable' import { ZoneEventTileType, type ZoneObject, type ZoneEventTile, type Zone } from '@/types' import { uuidv4 } from '@/utilities' import config from '@/config' @@ -323,5 +315,5 @@ const setSelectedZoneObject = (zoneObject: ZoneObject | null) => { onBeforeMount(async () => { await gameStore.fetchAllZoneAssets() await loadAssets(scene) -}); +}) diff --git a/src/components/gameMaster/zoneEditor/partials/Toolbar.vue b/src/components/gameMaster/zoneEditor/partials/Toolbar.vue index e1e90d1..aebe5a4 100644 --- a/src/components/gameMaster/zoneEditor/partials/Toolbar.vue +++ b/src/components/gameMaster/zoneEditor/partials/Toolbar.vue @@ -68,9 +68,7 @@
- +
@@ -163,14 +161,14 @@ onBeforeUnmount(() => { }) function handleClick(tool: string) { - if(tool === 'settings') { + if (tool === 'settings') { zoneEditorStore.toggleSettingsModal() } else { zoneEditorStore.setTool(tool) } - selectPencilOpen.value = tool === 'pencil' ? !selectPencilOpen.value : false; - selectEraserOpen.value = tool === 'eraser' ? !selectEraserOpen.value : false; + selectPencilOpen.value = tool === 'pencil' ? !selectPencilOpen.value : false + selectEraserOpen.value = tool === 'eraser' ? !selectEraserOpen.value : false } // Key bindings @@ -180,15 +178,15 @@ function initKeyShortcuts(event: KeyboardEvent) { if (document.activeElement?.tagName === 'INPUT') return const keyActions: any = { - 'm': 'move', - 'p': 'pencil', - 'e': 'eraser', - 'b': 'paint', - 'z': 'settings' - }; + m: 'move', + p: 'pencil', + e: 'eraser', + b: 'paint', + z: 'settings' + } if (keyActions.hasOwnProperty(event.key)) { - handleClick(keyActions[event.key]); + handleClick(keyActions[event.key]) } } diff --git a/src/components/sprites/Character.vue b/src/components/sprites/Character.vue index aeb0533..a6de646 100644 --- a/src/components/sprites/Character.vue +++ b/src/components/sprites/Character.vue @@ -8,8 +8,7 @@ - - + @@ -29,6 +28,8 @@ enum Direction { NOCHANGE } +const charContainer = ref(null) + interface Props { layer: Phaser.Tilemaps.TilemapLayer character?: CharacterT @@ -38,14 +39,15 @@ const props = withDefaults(defineProps(), { character: undefined }) -const isometricDepth = ref(calculateIsometricDepth(props.character.positionX, props.character.positionY, 28, 94, true)) +const gameStore = useGameStore() +const scene = useScene() + +const isometricDepth = ref(calculateIsometricDepth(props.character!.positionX, props.character!.positionY, 28, 94, true)) const currentX = ref(0) const currentY = ref(0) -const gameStore = useGameStore(); const tween = ref(null) const isInitialPosition = ref(true) - const calculateLocalDepth = (x: number, y: number, width: number, height: number, isCharacter: boolean) => { isometricDepth.value = calculateIsometricDepth(x, y, width, height, isCharacter) } @@ -54,11 +56,6 @@ const updatePosition = (x: number, y: number, direction: Direction) => { const targetX = tileToWorldX(props.layer, x, y) const targetY = tileToWorldY(props.layer, x, y) - // Used for camera resize calculation to center on Character. - if(gameStore.character) { - gameStore.character.relativePosition = { x: targetX, y: targetY }; - } - if (isInitialPosition.value) { currentX.value = targetX currentY.value = targetY @@ -165,6 +162,13 @@ const createText = (text: Phaser.GameObjects.Text) => { } onMounted(() => { + /** + * @TODO: Put this at an appropriate place not in this component + */ + // Check if player is this character, then lock with camera + if (props.character && props.character.id === gameStore.character?.id) { + scene.cameras.main.startFollow(charContainer.value as Phaser.GameObjects.Container) + } if (props.character) { updatePosition(props.character.positionX, props.character.positionY, Direction.POSITIVE) } diff --git a/src/components/utilities/Modal.vue b/src/components/utilities/Modal.vue index ce46bee..850fef9 100644 --- a/src/components/utilities/Modal.vue +++ b/src/components/utilities/Modal.vue @@ -157,7 +157,7 @@ function handleResize() { function initializePosition() { width.value = Math.min(props.modalWidth, window.innerWidth) height.value = Math.min(props.modalHeight, window.innerHeight) - if(props.modalPositionX !== 0 && props.modalPositionY !== 0) { + if (props.modalPositionX !== 0 && props.modalPositionY !== 0) { console.log(props.modalPositionX) console.log(props.modalPositionY) x.value = props.modalPositionX @@ -226,7 +226,7 @@ onMounted(() => { window.addEventListener('mouseup', stopDrag) window.addEventListener('mousemove', resizeModal) window.addEventListener('mouseup', stopResize) - if(props.modalPositionX !== 0 && props.modalPositionY !== 0) { + if (props.modalPositionX !== 0 && props.modalPositionY !== 0) { window.addEventListener('resize', handleResize) } initializePosition() @@ -237,7 +237,7 @@ onUnmounted(() => { window.removeEventListener('mouseup', stopDrag) window.removeEventListener('mousemove', resizeModal) window.removeEventListener('mouseup', stopResize) - if(props.modalPositionX !== 0 && props.modalPositionY !== 0) { + if (props.modalPositionX !== 0 && props.modalPositionY !== 0) { window.removeEventListener('resize', handleResize) } }) diff --git a/src/components/zone/Zone.vue b/src/components/zone/Zone.vue index d633b86..8955bb1 100644 --- a/src/components/zone/Zone.vue +++ b/src/components/zone/Zone.vue @@ -26,7 +26,6 @@ type zoneLoadData = { characters: CharacterT[] } - gameStore.connection!.emit('zone:character:join', async (response: zoneLoadData) => { // Fetch assets for new zone await gameStore.fetchZoneAssets(response.zone.id) @@ -35,7 +34,6 @@ gameStore.connection!.emit('zone:character:join', async (response: zoneLoadData) // Set zone and characters zoneStore.setZone(response.zone) zoneStore.setCharacters(response.characters) - scene.cameras.main.setScroll(-(scene.cameras.main.worldView.width/2) - gameStore.character.relativePosition.x, -(scene.cameras.main.worldView.height/2) + gameStore.character.relativePosition.y) }) // Event listeners @@ -57,12 +55,6 @@ gameStore.connection!.on('zone:character:teleport', async (data: zoneLoadData) = zoneStore.setZone(data.zone) zoneStore.setCharacters(data.characters) - - const character = gameStore.character; - // Position character centered on zone change or teleport - const posX = tileToWorldX(tileMap.value, character.positionX, character.positionY) - const posY = tileToWorldY(tileMap.value, character.positionX, character.positionY) - scene.cameras.main.setScroll(-(scene.cameras.main.worldView.width/2) + posX, -(scene.cameras.main.worldView.height/2) + posY) }) gameStore.connection!.on('zone:character:join', async (data: ExtendedCharacterT) => { diff --git a/src/composables/pointerHandlers/useGamePointerHandlers.ts b/src/composables/pointerHandlers/useGamePointerHandlers.ts index 508d161..aac16d5 100644 --- a/src/composables/pointerHandlers/useGamePointerHandlers.ts +++ b/src/composables/pointerHandlers/useGamePointerHandlers.ts @@ -3,27 +3,31 @@ import { getTile, tileToWorldXY } from '@/composables/zoneComposable' import { useGameStore } from '@/stores/gameStore' import config from '@/config' -export function useGamePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Ref, isDragging: Ref) { +export function useGamePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { const gameStore = useGameStore() function updateWaypoint(pointer: Phaser.Input.Pointer) { - const { x: px, y: py } = camera.value.getWorldPoint(pointer.x, pointer.y) + const { x: px, y: py } = camera.getWorldPoint(pointer.x, pointer.y) const pointerTile = getTile(px, py, layer) waypoint.value.visible = !!pointerTile - if (pointerTile) { - const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) - waypoint.value.x = worldPoint.positionX - waypoint.value.y = worldPoint.positionY + config.tile_size.y + 15 + if (!pointerTile) { + return } + + const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) + waypoint.value.x = worldPoint.positionX + waypoint.value.y = worldPoint.positionY + config.tile_size.y + 15 } function dragZone(pointer: Phaser.Input.Pointer) { - if (isDragging.value) { - const { x, y, prevPosition } = pointer - const { scrollX, scrollY, zoom } = camera.value - camera.value.setScroll(scrollX - (x - prevPosition.x) / zoom, scrollY - (y - prevPosition.y) / zoom) + if (!gameStore.isPlayerDraggingCamera) { + return } + + const { x, y, prevPosition } = pointer + const { scrollX, scrollY, zoom } = camera + camera.setScroll(scrollX - (x - prevPosition.x) / zoom, scrollY - (y - prevPosition.y) / zoom) } function handlePointerMove(pointer: Phaser.Input.Pointer) { @@ -32,22 +36,26 @@ export function useGamePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilema } function clickTile(pointer: Phaser.Input.Pointer) { - const { x: px, y: py } = camera.value.getWorldPoint(pointer.x, pointer.y) + const { x: px, y: py } = camera.getWorldPoint(pointer.x, pointer.y) const pointerTile = getTile(px, py, layer) - if (pointerTile) { - gameStore.connection?.emit('character:initMove', { - positionX: pointerTile.x, - positionY: pointerTile.y - }) + if (!pointerTile) { + return } + + gameStore.connection?.emit('character:initMove', { + positionX: pointerTile.x, + positionY: pointerTile.y + }) } function handleZoom({ event, deltaY }: Phaser.Input.Pointer) { if (event instanceof WheelEvent && event.shiftKey) { - scene.scale.setZoom(scene.scale.zoom - deltaY * 0.01) - camera.value = scene.cameras.main + return } + + scene.scale.setZoom(scene.scale.zoom - deltaY * 0.01) + camera = scene.cameras.main } const setupPointerHandlers = () => { diff --git a/src/composables/pointerHandlers/useZoneEditorPointerHandlers.ts b/src/composables/pointerHandlers/useZoneEditorPointerHandlers.ts index 305120a..923dce7 100644 --- a/src/composables/pointerHandlers/useZoneEditorPointerHandlers.ts +++ b/src/composables/pointerHandlers/useZoneEditorPointerHandlers.ts @@ -2,28 +2,32 @@ import { computed, type Ref, ref } from 'vue' import { getTile, tileToWorldXY } from '@/composables/zoneComposable' import { useZoneEditorStore } from '@/stores/zoneEditorStore' import config from '@/config' +import { useGameStore } from '@/stores/gameStore' -export function useZoneEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Ref, isDragging: Ref) { +export function useZoneEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { + const gameStore = useGameStore() const zoneEditorStore = useZoneEditorStore() const isMoveTool = computed(() => zoneEditorStore.tool === 'move') function updateWaypoint(pointer: Phaser.Input.Pointer) { - const { x: px, y: py } = camera.value.getWorldPoint(pointer.x, pointer.y) + const { x: px, y: py } = camera.getWorldPoint(pointer.x, pointer.y) const pointerTile = getTile(px, py, layer) waypoint.value.visible = !!pointerTile if (pointerTile) { - const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) - waypoint.value.x = worldPoint.positionX - waypoint.value.y = worldPoint.positionY + config.tile_size.y + 15 + return } + + const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) + waypoint.value.x = worldPoint.positionX + waypoint.value.y = worldPoint.positionY + config.tile_size.y + 15 } function dragZone(pointer: Phaser.Input.Pointer) { - if (isDragging.value) { + if (gameStore.isPlayerDraggingCamera) { const { x, y, prevPosition } = pointer - const { scrollX, scrollY, zoom } = camera.value - camera.value.setScroll(scrollX - (x - prevPosition.x) / zoom, scrollY - (y - prevPosition.y) / zoom) + const { scrollX, scrollY, zoom } = camera + camera.setScroll(scrollX - (x - prevPosition.x) / zoom, scrollY - (y - prevPosition.y) / zoom) } } @@ -35,10 +39,12 @@ export function useZoneEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser. } function handleZoom({ event, deltaY }: Phaser.Input.Pointer) { - if (event instanceof WheelEvent && event.shiftKey) { - scene.scale.setZoom(scene.scale.zoom - deltaY * 0.01) - camera.value = scene.cameras.main + if (event! instanceof WheelEvent && !event.shiftKey) { + return } + + scene.scale.setZoom(scene.scale.zoom - deltaY * 0.01) + camera = scene.cameras.main } const setupPointerHandlers = () => { diff --git a/src/composables/useCameraControls.ts b/src/composables/useCameraControls.ts index be94cfb..05f26e9 100644 --- a/src/composables/useCameraControls.ts +++ b/src/composables/useCameraControls.ts @@ -3,35 +3,22 @@ import { useGameStore } from '@/stores/gameStore' export function useCameraControls(scene: Phaser.Scene): any { const gameStore = useGameStore() - const camera = ref(scene.cameras.main) - const isDragging = ref(false) - - // Resize center camera on character. - window.addEventListener('resize', () => { - console.log('woep') - // Need to change camera position next frame - setTimeout(() => { - scene.cameras.main.setScroll(-(scene.cameras.main.worldView.width/2) + gameStore.character.relativePosition.x, -(scene.cameras.main.worldView.height/2) + gameStore.character.relativePosition.y) - }, 0) - }) + const camera = scene.cameras.main function onPointerDown(pointer: Phaser.Input.Pointer) { if (pointer.event instanceof MouseEvent || pointer.event.shiftKey) { - isDragging.value = true - gameStore.setMovingCamera(true) + gameStore.setPlayerDraggingCamera(true) } } function onPointerUp() { - isDragging.value = false - gameStore.setMovingCamera(false) + gameStore.setPlayerDraggingCamera(false) } scene.input.on(Phaser.Input.Events.POINTER_DOWN, onPointerDown) scene.input.on(Phaser.Input.Events.POINTER_UP, onPointerUp) return { - camera, - isDragging + camera } } diff --git a/src/composables/zoneComposable.ts b/src/composables/zoneComposable.ts index 9f12b66..5846105 100644 --- a/src/composables/zoneComposable.ts +++ b/src/composables/zoneComposable.ts @@ -61,11 +61,11 @@ export const sortByIsometricDepth = => { return new Promise((resolve) => { const gameStore = useGameStore() - let addedLoad = false; + let addedLoad = false gameStore.assets.forEach((asset) => { if (scene.load.textureManager.exists(asset.key)) return - addedLoad = true; + addedLoad = true if (asset.group === 'sprite_animations') { scene.load.spritesheet(asset.key, config.server_endpoint + asset.url, { frameWidth: asset.frameWidth ?? 0, frameHeight: asset.frameHeight ?? 0 }) } else { @@ -73,7 +73,7 @@ export const loadAssets = (scene: Phaser.Scene): Promise => { } }) - if(addedLoad) { + if (addedLoad) { scene.load.start() scene.load.on(Phaser.Loader.Events.COMPLETE, () => { resolve() diff --git a/src/config.ts b/src/config.ts index 011e758..a663e30 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,4 @@ -const dev: boolean = false +const dev: boolean = true export default { name: 'New Quest', diff --git a/src/screens/Game.vue b/src/screens/Game.vue index f4e3028..bcae740 100644 --- a/src/screens/Game.vue +++ b/src/screens/Game.vue @@ -106,7 +106,7 @@ const preloadScene = async (scene: Phaser.Scene) => { progressBar.fillRect(width / 2 - 180 + 10, height / 2 + 10, 300 * value, 30) }) - scene.load.on(Phaser.Loader.Events.COMPLETE, function() { + scene.load.on(Phaser.Loader.Events.COMPLETE, function () { progressBar.destroy() progressBox.destroy() loadingText.destroy() @@ -145,7 +145,7 @@ const createScene = async (scene: Phaser.Scene) => { frames: scene.anims.generateFrameNumbers(asset.key, { start: 0, end: 4 }), repeat: -1 }) - }); + }) } onBeforeUnmount(() => { diff --git a/src/stores/gameStore.ts b/src/stores/gameStore.ts index f91cf8a..6af343e 100644 --- a/src/stores/gameStore.ts +++ b/src/stores/gameStore.ts @@ -13,7 +13,8 @@ export const useGameStore = defineStore('game', { user: null as User | null, character: null as Character | null, isGmPanelOpen: false, - isMovingCamera: false, + isPlayerDraggingCamera: false, + isCameraFollowingCharacter: false, isChatOpen: false, isUserPanelOpen: false }), @@ -93,11 +94,17 @@ export const useGameStore = defineStore('game', { toggleGmPanel() { this.isGmPanelOpen = !this.isGmPanelOpen }, - toggleMovingCamera() { - this.isMovingCamera = !this.isMovingCamera + togglePlayerDraggingCamera() { + this.isPlayerDraggingCamera = !this.isPlayerDraggingCamera }, - setMovingCamera(moving: boolean) { - this.isMovingCamera = moving + setPlayerDraggingCamera(moving: boolean) { + this.isPlayerDraggingCamera = moving + }, + toggleCameraFollowingCharacter() { + this.isCameraFollowingCharacter = !this.isCameraFollowingCharacter + }, + setCameraFollowingCharacter(following: boolean) { + this.isCameraFollowingCharacter = following }, toggleChat() { this.isChatOpen = !this.isChatOpen @@ -145,7 +152,7 @@ export const useGameStore = defineStore('game', { this.user = null this.character = null this.isGmPanelOpen = false - this.isMovingCamera = false + this.isPlayerDraggingCamera = false this.isChatOpen = false this.isUserPanelOpen = false } diff --git a/src/types.ts b/src/types.ts index 763553c..55fafe7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -142,7 +142,6 @@ export type Character = { role: string positionX: number positionY: number - relativePosition: {x: number, y: number} rotation: number zoneId: number zone: Zone