156 lines
4.3 KiB
Vue
156 lines
4.3 KiB
Vue
<template>
|
|
<div class="flex justify-center items-center h-dvh relative">
|
|
<GmTools v-if="gameStore.character?.role === 'gm'" />
|
|
<GmPanel v-if="gameStore.character?.role === 'gm'" />
|
|
|
|
<Game :config="gameConfig" @create="createGame">
|
|
<Scene name="main" @preload="preloadScene" @create="createScene">
|
|
<div v-if="isLoaded">
|
|
<Menu />
|
|
<Hud />
|
|
<Keybindings />
|
|
<Minimap />
|
|
<Zone />
|
|
<Chat />
|
|
<ExpBar />
|
|
|
|
<Inventory />
|
|
<Effects />
|
|
</div>
|
|
</Scene>
|
|
</Game>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import 'phaser'
|
|
import { ref, onBeforeUnmount } from 'vue'
|
|
import { Game, Scene } from 'phavuer'
|
|
import { useGameStore } from '@/stores/gameStore'
|
|
import { useZoneEditorStore } from '@/stores/zoneEditorStore'
|
|
import Menu from '@/components/gui/Menu.vue'
|
|
import ExpBar from '@/components/gui/ExpBar.vue'
|
|
import Hud from '@/components/gui/Hud.vue'
|
|
import Zone from '@/components/zone/Zone.vue'
|
|
import Keybindings from '@/components/gui/Keybindings.vue'
|
|
import Chat from '@/components/gui/Chat.vue'
|
|
import GmTools from '@/components/gameMaster/GmTools.vue'
|
|
import ZoneEditor from '@/components/gameMaster/zoneEditor/ZoneEditor.vue'
|
|
import GmPanel from '@/components/gameMaster/GmPanel.vue'
|
|
import Inventory from '@/components/gui/UserPanel.vue'
|
|
import Effects from '@/components/Effects.vue'
|
|
import { loadAssets } from '@/composables/zoneComposable'
|
|
import Minimap from '@/components/gui/Minimap.vue'
|
|
|
|
const gameStore = useGameStore()
|
|
const isLoaded = ref(false)
|
|
|
|
const gameConfig = {
|
|
name: 'Sylvan Quest',
|
|
width: window.innerWidth,
|
|
height: window.innerHeight,
|
|
type: Phaser.AUTO, // AUTO, CANVAS, WEBGL, HEADLESS
|
|
resolution: 5
|
|
}
|
|
|
|
const createGame = (game: Phaser.Game) => {
|
|
/**
|
|
* Resize the game when the window is resized
|
|
*/
|
|
addEventListener('resize', () => {
|
|
game.scale.resize(window.innerWidth, window.innerHeight)
|
|
})
|
|
|
|
// We don't support canvas mode, only WebGL
|
|
if (game.renderer.type === Phaser.CANVAS) {
|
|
gameStore.addNotification({
|
|
title: 'Warning',
|
|
message: 'Your browser does not support WebGL. Please use a modern browser like Chrome, Firefox, or Edge.'
|
|
})
|
|
gameStore.disconnectSocket()
|
|
}
|
|
}
|
|
|
|
const preloadScene = async (scene: Phaser.Scene) => {
|
|
isLoaded.value = false
|
|
|
|
/**
|
|
* Create loading bar
|
|
*/
|
|
const width = scene.cameras.main.width
|
|
const height = scene.cameras.main.height
|
|
|
|
const progressBox = scene.add.graphics()
|
|
const progressBar = scene.add.graphics()
|
|
progressBox.fillStyle(0x222222, 0.8)
|
|
progressBox.fillRect(width / 2 - 180, height / 2, 320, 50)
|
|
|
|
const loadingText = scene.make.text({
|
|
x: width / 2,
|
|
y: height / 2 - 50,
|
|
text: 'Loading...',
|
|
style: {
|
|
font: '20px monospace',
|
|
fill: '#ffffff'
|
|
}
|
|
})
|
|
loadingText.setOrigin(0.5, 0.5)
|
|
|
|
scene.load.on(Phaser.Loader.Events.PROGRESS, function (value: any) {
|
|
progressBar.clear()
|
|
progressBar.fillStyle(0x368f8b, 1)
|
|
progressBar.fillRect(width / 2 - 180 + 10, height / 2 + 10, 300 * value, 30)
|
|
})
|
|
|
|
scene.load.on(Phaser.Loader.Events.COMPLETE, function () {
|
|
progressBar.destroy()
|
|
progressBox.destroy()
|
|
loadingText.destroy()
|
|
isLoaded.value = true
|
|
})
|
|
|
|
/**
|
|
* Load the base assets into the Phaser scene
|
|
*/
|
|
scene.load.image('BLOCK', '/assets/zone/bt_tile.png')
|
|
scene.load.image('TELEPORT', '/assets/zone/tp_tile.png')
|
|
scene.load.image('blank_tile', '/assets/zone/blank_tile.png')
|
|
scene.load.image('blank_object', '/assets/zone/blank_tile.png')
|
|
scene.load.image('waypoint', '/assets/waypoint.png')
|
|
|
|
/**
|
|
* Load the assets into the Phaser scene
|
|
*/
|
|
await loadAssets(scene)
|
|
}
|
|
|
|
const createScene = async (scene: Phaser.Scene) => {
|
|
/**
|
|
* Create sprite animations
|
|
* This is done here because phaser forces us to
|
|
*/
|
|
gameStore.assets.forEach((asset) => {
|
|
if (asset.group !== 'sprite_animations') return
|
|
|
|
scene.anims.create({
|
|
key: asset.key,
|
|
frameRate: 7,
|
|
frames: scene.anims.generateFrameNumbers(asset.key, { start: 0, end: asset.frameCount! - 1 }),
|
|
repeat: -1
|
|
})
|
|
})
|
|
}
|
|
|
|
onBeforeUnmount(() => {
|
|
isLoaded.value = false
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
canvas {
|
|
image-rendering: -moz-crisp-edges;
|
|
image-rendering: -webkit-crisp-edges;
|
|
image-rendering: pixelated;
|
|
}
|
|
</style>
|