Added player mouse cursors

This commit is contained in:
thepaperpilot 2022-09-07 22:40:32 -05:00
parent 6edf16515b
commit e79f6433ed
4 changed files with 718 additions and 612 deletions

1252
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -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 />
</> </>
)) ))

View file

@ -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 {

View file

@ -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>