worked on mp logic
This commit is contained in:
parent
1a5b5e92d4
commit
8c21cd11c7
24
package-lock.json
generated
24
package-lock.json
generated
@ -4222,9 +4222,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/json-parse-even-better-errors": {
|
"node_modules/json-parse-even-better-errors": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz",
|
||||||
"integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==",
|
"integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
@ -4456,9 +4456,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minipass": {
|
"node_modules/minipass": {
|
||||||
"version": "7.0.4",
|
"version": "7.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.0.tgz",
|
||||||
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
|
"integrity": "sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
@ -4583,9 +4583,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/nopt": {
|
"node_modules/nopt": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
|
||||||
"integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==",
|
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abbrev": "^2.0.0"
|
"abbrev": "^2.0.0"
|
||||||
@ -5918,9 +5918,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.0.14",
|
"version": "1.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.14.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz",
|
||||||
"integrity": "sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw==",
|
"integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -66,11 +66,11 @@
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
padding: 0.8rem 0;
|
padding: 0.6rem 0;
|
||||||
min-width: 6.25rem;
|
min-width: 6.25rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 0.80rem;
|
font-size: 0.65rem;
|
||||||
background-color: rgba(71, 65, 230, 0.75);
|
background-color: rgba(71, 65, 230, 0.75);
|
||||||
border: rgba(255, 255, 255, 0.35) 1px solid;
|
border: rgba(255, 255, 255, 0.35) 1px solid;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
@ -1,41 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<TilemapLayer ref="tilemapLayer" :tilemap="map" :layerIndex="0" :cull-padding-x="10" :cull-padding-y="10" :tileset="data" />
|
<TilemapLayer ref="tilemapLayer" :tilemap="map" :layerIndex="0" :cull-padding-x="10" :cull-padding-y="10" :tileset="mapTiles" />
|
||||||
<Controls :layer="layer" />
|
<!-- <Controls :layer="layer" />-->
|
||||||
<Player :layer="layer" />
|
|
||||||
<div v-for="player in playerList">
|
|
||||||
<Player :layer="layer"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { refObj, TilemapLayer, useScene } from 'phavuer'
|
import { refObj, TilemapLayer, useScene } from 'phavuer'
|
||||||
import Player from '@/components/sprites/player/Player.vue'
|
import Player from '@/components/sprites/player/Player.vue'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import { ref, type Ref } from 'vue'
|
import { reactive, ref, type Ref } from 'vue'
|
||||||
import Tileset = Phaser.Tilemaps.Tileset
|
import Tileset = Phaser.Tilemaps.Tileset
|
||||||
import Controls from '@/components/Controls.vue'
|
import Controls from '@/components/Controls.vue'
|
||||||
import { useSocketStore } from '@/stores/socket'
|
import { useSocketStore } from '@/stores/socket'
|
||||||
|
import Map from '@/engine/Map/Map'
|
||||||
|
|
||||||
let playerList = ref([]);
|
const isMapLoaded = ref(false);
|
||||||
|
|
||||||
const socket = useSocketStore();
|
const socket = useSocketStore();
|
||||||
|
const serverMapData = ref([]);
|
||||||
|
const mapTiles = ref([]);
|
||||||
|
|
||||||
socket.socket?.on('playerList', (players) => {
|
|
||||||
playerList.value = players;
|
|
||||||
console.log('players', players);
|
|
||||||
console.log('playerList', playerList.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.socket?.on('player_moved', (username, coords) => {
|
|
||||||
console.log('player_moved', username, coords);
|
|
||||||
const player = playerList.value.find((player: any) => player.username === username);
|
|
||||||
if (player) {
|
|
||||||
player.x = coords.x;
|
|
||||||
player.y = coords.y;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const scene = useScene()
|
|
||||||
const mapData = new Phaser.Tilemaps.MapData({
|
const mapData = new Phaser.Tilemaps.MapData({
|
||||||
width: 10,
|
width: 10,
|
||||||
height: 10,
|
height: 10,
|
||||||
@ -45,9 +27,27 @@ const mapData = new Phaser.Tilemaps.MapData({
|
|||||||
format: Phaser.Tilemaps.Formats.ARRAY_2D,
|
format: Phaser.Tilemaps.Formats.ARRAY_2D,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.socket?.emit('get_map');
|
||||||
|
socket.socket?.on('map', (map) => {
|
||||||
|
// Get map from server
|
||||||
|
mapTiles.value = map.data;
|
||||||
|
map.data.forEach((row, y) => {
|
||||||
|
row.forEach((tile, x) => {
|
||||||
|
layer.putTileAt(tile, x, y);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
isMapLoaded.value = true;
|
||||||
|
console.log('map', map);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const scene = useScene()
|
||||||
|
|
||||||
const { width: tileSizeWidth } = mapData;
|
const { width: tileSizeWidth } = mapData;
|
||||||
const { width, height } = scene.cameras.main;
|
const { width, height } = scene.cameras.main;
|
||||||
const map = new Phaser.Tilemaps.Tilemap(scene, mapData);
|
const map = new Phaser.Tilemaps.Tilemap(scene, mapData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1 tile is 64x32
|
* 1 tile is 64x32
|
||||||
* the map is 10x10
|
* the map is 10x10
|
||||||
@ -57,26 +57,11 @@ const tileset: (Tileset|null) = map.addTilesetImage('default', 'tiles');
|
|||||||
// const layer: (Layer|null) = map.createBlankLayer('layer', tileset);
|
// const layer: (Layer|null) = map.createBlankLayer('layer', tileset);
|
||||||
|
|
||||||
const layer:TilemapLayer = map.createBlankLayer('layer', tileset, 0, config.tile_size.y);
|
const layer:TilemapLayer = map.createBlankLayer('layer', tileset, 0, config.tile_size.y);
|
||||||
const tilemapLayer: Ref<(TilemapLayer|undefined)> = refObj();
|
const tilemapLayer= ref();
|
||||||
|
|
||||||
|
// const mapp = new Map('default', 10, 10, config.tile_size.x, config.tile_size.y, data, []);
|
||||||
|
|
||||||
const data: any = [
|
|
||||||
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
|
|
||||||
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
|
|
||||||
];
|
|
||||||
|
|
||||||
data.forEach((row, y) => {
|
|
||||||
row.forEach((tile, x) => {
|
|
||||||
layer.putTileAt(tile, x, y);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// center camera
|
// center camera
|
||||||
const centerY = (map.height * map.tileHeight) / 2
|
const centerY = (map.height * map.tileHeight) / 2
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<form method="post">
|
<form method="post">
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<input v-model="username" type="text" name="username" required>
|
<input v-model="username" type="text" name="username" required autofocus>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
|
@ -1,55 +1,60 @@
|
|||||||
<template>
|
<template>
|
||||||
<Sprite ref="sprite" texture="player" :x :y />
|
<Sprite ref="sprite" texture="IMap" :x="position.x" :y="position.y" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Sprite, useScene } from 'phavuer'
|
import { onPostUpdate, onPreUpdate, Sprite, useScene } from 'phavuer'
|
||||||
import { type Ref, ref } from 'vue'
|
import { reactive, type Ref, ref } from 'vue'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import { useSocketStore } from '@/stores/socket'
|
import { useSocketStore } from '@/stores/socket'
|
||||||
|
|
||||||
const socket = useSocketStore();
|
const socket = useSocketStore();
|
||||||
|
|
||||||
socket.socket?.emit('joinRoom', 'game');
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
layer: Phaser.Tilemaps.TilemapLayer,
|
layer: Phaser.Tilemaps.TilemapLayer,
|
||||||
player: Object
|
player: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const scene = useScene()
|
const scene = useScene()
|
||||||
const pointer_tile = ref(undefined);
|
|
||||||
const x: Ref<number> = ref(0);
|
|
||||||
const y: Ref<number> = ref(0);
|
|
||||||
|
|
||||||
if (props.player) {
|
// onPreUpdate((time, delta) => {
|
||||||
x.value = props.player.x;
|
// console.log(time, delta);
|
||||||
y.value = props.player.y;
|
// })
|
||||||
|
|
||||||
|
const pointer_tile = ref(undefined);
|
||||||
|
const position = reactive({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
if (props.player !== undefined) {
|
||||||
|
position.x = props.player?.coords.x;
|
||||||
|
position.y = props.player?.coords.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPointerClick(pointer: Phaser.Input.Pointer) {
|
function onPointerClick(pointer: Phaser.Input.Pointer) {
|
||||||
/**
|
|
||||||
* @TODO : Check if player was dragging, if so, don't move player
|
|
||||||
*/
|
|
||||||
const px = scene.cameras.main.worldView.x + pointer.x;
|
const px = scene.cameras.main.worldView.x + pointer.x;
|
||||||
const py = scene.cameras.main.worldView.y + pointer.y;
|
const py = scene.cameras.main.worldView.y + pointer.y;
|
||||||
|
|
||||||
pointer_tile.value = getTile(px, py, props.layer);
|
pointer_tile.value = getTile(px, py, props.layer);
|
||||||
if (pointer_tile.value) {
|
if (pointer_tile.value) {
|
||||||
// Convert tile coordinates to world coordinates
|
|
||||||
const worldPoint = props.layer.tileToWorldXY(pointer_tile.value.x, pointer_tile.value.y);
|
const worldPoint = props.layer.tileToWorldXY(pointer_tile.value.x, pointer_tile.value.y);
|
||||||
x.value = worldPoint.x + config.tile_size.y;
|
position.x = worldPoint.x + config.tile_size.y;
|
||||||
y.value = worldPoint.y;
|
position.y = worldPoint.y;
|
||||||
|
|
||||||
|
socket.socket?.emit('move', { x: position.x, y: position.y });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scene.input.on(Phaser.Input.Events.POINTER_DOWN, onPointerClick);
|
|
||||||
|
/**
|
||||||
|
* @BUG
|
||||||
|
* when this component is spawned multiple times, the event listener is also added multiple times
|
||||||
|
*/
|
||||||
|
scene.input.on(Phaser.Input.Events.POINTER_UP, onPointerClick);
|
||||||
|
|
||||||
function getTile (x: number, y: number, layer: Phaser.Tilemaps.TilemapLayer): Phaser.Tilemaps.Tile | undefined {
|
function getTile (x: number, y: number, layer: Phaser.Tilemaps.TilemapLayer): Phaser.Tilemaps.Tile | undefined {
|
||||||
const tile: Phaser.Tilemaps.Tile = layer.getTileAtWorldXY(x, y);
|
const tile: Phaser.Tilemaps.Tile = layer.getTileAtWorldXY(x, y);
|
||||||
|
|
||||||
console.log(x,y);
|
|
||||||
console.log('tile', tile);
|
|
||||||
|
|
||||||
if (!tile) {
|
if (!tile) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
10
src/engine/Map/IMap.ts
Normal file
10
src/engine/Map/IMap.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Player from '../Player/Player';
|
||||||
|
|
||||||
|
export default interface IMap {
|
||||||
|
readonly id: number;
|
||||||
|
name: string;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
data: any;
|
||||||
|
players: Array<Player>|[];
|
||||||
|
}
|
36
src/engine/Map/Map.ts
Normal file
36
src/engine/Map/Map.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import type IMap from '@/engine/Map/IMap';
|
||||||
|
import Player from '@/engine/Player/Player';
|
||||||
|
|
||||||
|
export default class Map implements IMap {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
data: any;
|
||||||
|
players: Array<Player>|[];
|
||||||
|
|
||||||
|
constructor(id: number, name: string, width: number, height: number, data: any, players: Array<Player>|[]) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.data = data;
|
||||||
|
this.players = players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addPlayer(player: Player) {
|
||||||
|
this.players.push(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removePlayer(player: Player) {
|
||||||
|
this.players = this.players.filter(p => p.id !== player.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public movePlayer(player: Player, x: number, y: number) {
|
||||||
|
const playerIndex = this.players.findIndex(p => p.id === player.id);
|
||||||
|
if (playerIndex !== -1) {
|
||||||
|
this.players[playerIndex].coords.x = x;
|
||||||
|
this.players[playerIndex].coords.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/engine/Player/IPlayer.ts
Normal file
8
src/engine/Player/IPlayer.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default interface IPlayer {
|
||||||
|
readonly id: number;
|
||||||
|
username: string;
|
||||||
|
coords: {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
}
|
13
src/engine/Player/Player.ts
Normal file
13
src/engine/Player/Player.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type IPlayer from '@/engine/Player/IPlayer';
|
||||||
|
|
||||||
|
export default class Player implements IPlayer {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
coords: { x: number; y: number; };
|
||||||
|
|
||||||
|
constructor(id: number, username: string, coords: { x: number; y: number; }) {
|
||||||
|
this.id = id;
|
||||||
|
this.username = username;
|
||||||
|
this.coords = coords;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import Map from '@/engine/Map/Map'
|
||||||
|
|
||||||
|
export const useMapStore = defineStore('map', {
|
||||||
|
state: () => ({
|
||||||
|
map: null as Map | null,
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
setMap(map: Map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
14
src/stores/player.ts
Normal file
14
src/stores/player.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import Player from '@/engine/Player/Player'
|
||||||
|
|
||||||
|
export const usePlayerStore = defineStore('player', {
|
||||||
|
state: () => ({
|
||||||
|
player: null as Player | null,
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
setPlayer(player: Player) {
|
||||||
|
this.player = player;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user