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 type { BaseLayer, GenericLayer } from "game/layers";
|
||||
import { createLayer } from "game/layers";
|
||||
import { persistent } from "game/persistence";
|
||||
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 { room } from "./socket";
|
||||
import { emit } from "./socket";
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
|
@ -13,13 +15,42 @@ import { room } from "./socket";
|
|||
export const main = createLayer("main", function (this: BaseLayer) {
|
||||
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 {
|
||||
name: "Main",
|
||||
minimizable: false,
|
||||
contentPacks,
|
||||
board,
|
||||
display: jsx(() => (
|
||||
<>
|
||||
<div>placeholder</div>
|
||||
{render(board)}
|
||||
<Chat />
|
||||
</>
|
||||
))
|
||||
|
|
|
@ -16,6 +16,7 @@ export const connected = ref<boolean>(false);
|
|||
export const room = ref<string | null>(null);
|
||||
export const isHosting = ref<boolean>(false);
|
||||
export const nicknames = ref<Record<string, string>>({});
|
||||
export const cursorPositions = ref<Record<string, { x: number; y: number }>>({});
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
|
@ -153,6 +154,11 @@ function setupSocket(socket: Socket<ServerToClientEvents, ClientToServerEvents>)
|
|||
socket.on("set nicknames", n => {
|
||||
nicknames.value = n;
|
||||
});
|
||||
socket.on("set cursor position", (id, pos) => {
|
||||
if (id !== socket.id) {
|
||||
cursorPositions.value[id] = pos;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function randomName(): string {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
@mouseup="() => endDragging(dragging)"
|
||||
@touchend.passive="() => endDragging(dragging)"
|
||||
@mouseleave="() => endDragging(dragging)"
|
||||
@zoom="zoom"
|
||||
>
|
||||
<svg class="stage" width="100%" height="100%">
|
||||
<g class="g1">
|
||||
|
@ -45,12 +46,19 @@
|
|||
/>
|
||||
</g>
|
||||
</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>
|
||||
</svg>
|
||||
</panZoom>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { cursorPositions, nicknames } from "data/socket";
|
||||
import type {
|
||||
BoardData,
|
||||
BoardNode,
|
||||
|
@ -88,6 +96,7 @@ const dragging = ref<number | null>(null);
|
|||
const hasDragged = ref(false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const stage = ref<any>(null);
|
||||
const currentZoom = ref<number>(1);
|
||||
|
||||
const draggingNode = computed(() =>
|
||||
dragging.value == null ? undefined : props.nodes.value.find(node => node.id === dragging.value)
|
||||
|
@ -135,6 +144,8 @@ const receivingNode = computed(() => {
|
|||
}, null);
|
||||
});
|
||||
|
||||
const cursors = computed(() => Object.entries(cursorPositions.value).filter(([id]) => id in nicknames.value));
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function onInit(panzoomInstance: any) {
|
||||
panzoomInstance.setTransformOrigin(null);
|
||||
|
@ -193,8 +204,8 @@ function drag(e: MouseEvent | TouchEvent) {
|
|||
}
|
||||
|
||||
props.mousePosition.value = {
|
||||
x: (clientX - x) / scale,
|
||||
y: (clientY - y) / scale
|
||||
x: (clientX - x - 10),
|
||||
y: (clientY - y - 50)
|
||||
};
|
||||
|
||||
dragged.value = {
|
||||
|
@ -238,6 +249,17 @@ function endDragging(nodeID: number | 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>
|
||||
|
||||
<style>
|
||||
|
@ -259,4 +281,13 @@ function endDragging(nodeID: number | null) {
|
|||
.link-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.player-mouse,
|
||||
.player-name {
|
||||
transition-duration: 0.1s;
|
||||
transition-timing-function: ease;
|
||||
fill: var(--foreground);
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue