Added player mouse cursors
This commit is contained in:
parent
6edf16515b
commit
e79f6433ed
4 changed files with 718 additions and 612 deletions
1252
package-lock.json
generated
1252
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,11 +1,13 @@
|
||||||
|
import { createBoard, Shape } from "features/boards/board";
|
||||||
import { jsx } from "features/feature";
|
import { jsx } from "features/feature";
|
||||||
import type { BaseLayer, GenericLayer } from "game/layers";
|
import type { BaseLayer, GenericLayer } from "game/layers";
|
||||||
import { createLayer } from "game/layers";
|
import { createLayer } from "game/layers";
|
||||||
import { persistent } from "game/persistence";
|
import { persistent } from "game/persistence";
|
||||||
import type { PlayerData } from "game/player";
|
import type { PlayerData } from "game/player";
|
||||||
import { computed } from "vue";
|
import { render } from "util/vue";
|
||||||
|
import { computed, ref } from "vue";
|
||||||
import Chat from "./Chat.vue";
|
import Chat from "./Chat.vue";
|
||||||
import { room } from "./socket";
|
import { emit } from "./socket";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
@ -13,13 +15,42 @@ import { room } from "./socket";
|
||||||
export const main = createLayer("main", function (this: BaseLayer) {
|
export const main = createLayer("main", function (this: BaseLayer) {
|
||||||
const contentPacks = persistent<(ContentPack | string)[]>(["core"]);
|
const contentPacks = persistent<(ContentPack | string)[]>(["core"]);
|
||||||
|
|
||||||
|
const board = createBoard(() => ({
|
||||||
|
startNodes: () => [
|
||||||
|
{
|
||||||
|
type: "placeholder",
|
||||||
|
position: { x: 0, y: 0 }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
types: {
|
||||||
|
placeholder: {
|
||||||
|
shape: Shape.Diamond,
|
||||||
|
size: 10,
|
||||||
|
title: "placeholder"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
width: "calc(100% + 20px)",
|
||||||
|
height: "calc(100% + 100px)",
|
||||||
|
style: "margin-top: -50px; margin-left: -10px; overflow: hidden"
|
||||||
|
}));
|
||||||
|
|
||||||
|
const position = ref<{ x: number; y: number }>({ x: 0, y: 0 });
|
||||||
|
setInterval(() => {
|
||||||
|
const pos = board.mousePosition.value;
|
||||||
|
if (pos && (pos.x !== position.value.x || pos.y !== position.value.y)) {
|
||||||
|
position.value = pos;
|
||||||
|
emit("set cursor position", pos);
|
||||||
|
}
|
||||||
|
}, 50)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "Main",
|
name: "Main",
|
||||||
minimizable: false,
|
minimizable: false,
|
||||||
contentPacks,
|
contentPacks,
|
||||||
|
board,
|
||||||
display: jsx(() => (
|
display: jsx(() => (
|
||||||
<>
|
<>
|
||||||
<div>placeholder</div>
|
{render(board)}
|
||||||
<Chat />
|
<Chat />
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
|
|
|
@ -16,6 +16,7 @@ export const connected = ref<boolean>(false);
|
||||||
export const room = ref<string | null>(null);
|
export const room = ref<string | null>(null);
|
||||||
export const isHosting = ref<boolean>(false);
|
export const isHosting = ref<boolean>(false);
|
||||||
export const nicknames = ref<Record<string, string>>({});
|
export const nicknames = ref<Record<string, string>>({});
|
||||||
|
export const cursorPositions = ref<Record<string, { x: number; y: number }>>({});
|
||||||
|
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
|
@ -153,6 +154,11 @@ function setupSocket(socket: Socket<ServerToClientEvents, ClientToServerEvents>)
|
||||||
socket.on("set nicknames", n => {
|
socket.on("set nicknames", n => {
|
||||||
nicknames.value = n;
|
nicknames.value = n;
|
||||||
});
|
});
|
||||||
|
socket.on("set cursor position", (id, pos) => {
|
||||||
|
if (id !== socket.id) {
|
||||||
|
cursorPositions.value[id] = pos;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomName(): string {
|
function randomName(): string {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
@mouseup="() => endDragging(dragging)"
|
@mouseup="() => endDragging(dragging)"
|
||||||
@touchend.passive="() => endDragging(dragging)"
|
@touchend.passive="() => endDragging(dragging)"
|
||||||
@mouseleave="() => endDragging(dragging)"
|
@mouseleave="() => endDragging(dragging)"
|
||||||
|
@zoom="zoom"
|
||||||
>
|
>
|
||||||
<svg class="stage" width="100%" height="100%">
|
<svg class="stage" width="100%" height="100%">
|
||||||
<g class="g1">
|
<g class="g1">
|
||||||
|
@ -45,12 +46,19 @@
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
|
<template v-for="[id, { x, y }] in cursors" :key="id">
|
||||||
|
<text class="player-mouse" :style="`transform: scale(${1 / currentZoom}) translate(${x}px, ${y}px)`">
|
||||||
|
🢄
|
||||||
|
</text>
|
||||||
|
<text class="player-name" :style="`transform: scale(${1 / currentZoom}) translate(${x + 20}px, ${y + 8}px)`">{{ nicknames[id] }}</text>
|
||||||
|
</template>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</panZoom>
|
</panZoom>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { cursorPositions, nicknames } from "data/socket";
|
||||||
import type {
|
import type {
|
||||||
BoardData,
|
BoardData,
|
||||||
BoardNode,
|
BoardNode,
|
||||||
|
@ -88,6 +96,7 @@ const dragging = ref<number | null>(null);
|
||||||
const hasDragged = ref(false);
|
const hasDragged = ref(false);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const stage = ref<any>(null);
|
const stage = ref<any>(null);
|
||||||
|
const currentZoom = ref<number>(1);
|
||||||
|
|
||||||
const draggingNode = computed(() =>
|
const draggingNode = computed(() =>
|
||||||
dragging.value == null ? undefined : props.nodes.value.find(node => node.id === dragging.value)
|
dragging.value == null ? undefined : props.nodes.value.find(node => node.id === dragging.value)
|
||||||
|
@ -135,6 +144,8 @@ const receivingNode = computed(() => {
|
||||||
}, null);
|
}, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cursors = computed(() => Object.entries(cursorPositions.value).filter(([id]) => id in nicknames.value));
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function onInit(panzoomInstance: any) {
|
function onInit(panzoomInstance: any) {
|
||||||
panzoomInstance.setTransformOrigin(null);
|
panzoomInstance.setTransformOrigin(null);
|
||||||
|
@ -193,8 +204,8 @@ function drag(e: MouseEvent | TouchEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
props.mousePosition.value = {
|
props.mousePosition.value = {
|
||||||
x: (clientX - x) / scale,
|
x: (clientX - x - 10),
|
||||||
y: (clientY - y) / scale
|
y: (clientY - y - 50)
|
||||||
};
|
};
|
||||||
|
|
||||||
dragged.value = {
|
dragged.value = {
|
||||||
|
@ -238,6 +249,17 @@ function endDragging(nodeID: number | null) {
|
||||||
props.state.value.selectedAction = null;
|
props.state.value.selectedAction = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function zoom() {
|
||||||
|
const { x, y, scale } = stage.value.panZoomInstance.getTransform();
|
||||||
|
const { x: clientX, y: clientY } = lastMousePosition.value;
|
||||||
|
|
||||||
|
props.mousePosition.value = {
|
||||||
|
x: (clientX - x - 10),
|
||||||
|
y: (clientY - y - 50)
|
||||||
|
};
|
||||||
|
currentZoom.value = scale;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -259,4 +281,13 @@ function endDragging(nodeID: number | null) {
|
||||||
.link-leave-to {
|
.link-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.player-mouse,
|
||||||
|
.player-name {
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
transition-timing-function: ease;
|
||||||
|
fill: var(--foreground);
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue