Feat : various fixes, sounds and multiplayer additions
This commit is contained in:
@@ -15,17 +15,15 @@ const canvas = ref<HTMLCanvasElement | null>(null);
|
|||||||
const canvas_resize_temp = ref<HTMLCanvasElement | null>(null);
|
const canvas_resize_temp = ref<HTMLCanvasElement | null>(null);
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
colorStart?: [number, number, number];
|
isTurn?: boolean;
|
||||||
colorEnd?: [number, number, number];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
colorStart: () => [0, 0.3, 0],
|
isTurn: () => false,
|
||||||
colorEnd: () => [0, 1, 0],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const _colorStart = reactive(props.colorStart);
|
const _colorStart = reactive([0, 0.3, 0]);
|
||||||
const _colorEnd = reactive(props.colorEnd);
|
const _colorEnd = reactive([0, 1, 0]);
|
||||||
|
|
||||||
function initShader() {
|
function initShader() {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
@@ -119,15 +117,19 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// watch(() => [props.game.currentTurn], () => {
|
watch(
|
||||||
// if (props.game.teams.find() != goStore.self?.team) {
|
() => [props.isTurn],
|
||||||
// gsap.to(_colorStart, { duration: 0.5, 0: 0, 1: .2, 2: .3 })
|
() => {
|
||||||
// gsap.to(_colorEnd, { duration: 0.5, 0: 0, 1: 1, 2: 1 })
|
if (props.isTurn) {
|
||||||
// } else {
|
gsap.to(_colorStart, { duration: 0.5, 0: 0, 1: 0.3, 2: 0 });
|
||||||
// gsap.to(_colorStart, { duration: 0.5, 0: 0, 1: .3, 2: 0 })
|
gsap.to(_colorEnd, { duration: 0.5, 0: 0, 1: 1, 2: 0 });
|
||||||
// gsap.to(_colorEnd, { duration: 0.5, 0: 0, 1: 1, 2: 0 })
|
} else {
|
||||||
// }
|
gsap.to(_colorStart, { duration: 0.5, 0: 0, 1: 0.2, 2: 0.3 });
|
||||||
// }, { immediate: true })
|
gsap.to(_colorEnd, { duration: 0.5, 0: 0, 1: 1, 2: 1 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
watch([_colorEnd, _colorStart], () => {
|
watch([_colorEnd, _colorStart], () => {
|
||||||
recolorShader();
|
recolorShader();
|
||||||
@@ -153,8 +155,7 @@ onUnmounted(() => {
|
|||||||
:class="{ pixelated: settingsStore.shaderPixelated }"
|
:class="{ pixelated: settingsStore.shaderPixelated }"
|
||||||
width="480"
|
width="480"
|
||||||
height="270"
|
height="270"
|
||||||
>test</canvas
|
></canvas>
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
+152
-115
@@ -1,200 +1,237 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
uuid?: string
|
uuid?: string;
|
||||||
card_id?: number
|
card_id?: number;
|
||||||
locked?: boolean
|
locked?: boolean;
|
||||||
wrapped?: boolean
|
wrapped?: boolean;
|
||||||
tilted?: boolean
|
tilted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
wrapped: () => false,
|
wrapped: () => false,
|
||||||
tilted: () => true,
|
tilted: () => true,
|
||||||
locked: () => true
|
locked: () => true,
|
||||||
})
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["click"])
|
const emit = defineEmits(["click"]);
|
||||||
|
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
const childCount = ref<number>(0)
|
const childCount = ref<number>(0);
|
||||||
|
|
||||||
const card = ref<HTMLElement>()
|
const card = ref<HTMLElement>();
|
||||||
|
|
||||||
const extension = computed(() => {
|
const extension = computed(() => {
|
||||||
if (settingsStore.cardStyle == CardStyles.SVG) {
|
if (settingsStore.cardStyle == CardStyles.SVG) {
|
||||||
return ".svg"
|
return ".svg";
|
||||||
}
|
}
|
||||||
return ".png"
|
return ".png";
|
||||||
})
|
});
|
||||||
function cardClick() {
|
function cardClick() {
|
||||||
if (!props.card_id) return
|
if (!props.card_id) return;
|
||||||
emit("click")
|
emit("click");
|
||||||
}
|
}
|
||||||
|
|
||||||
const isZooming = ref<boolean>(false)
|
const isZooming = ref<boolean>(false);
|
||||||
|
|
||||||
function mouseenter(e: MouseEvent) {
|
function mouseenter(e: MouseEvent) {
|
||||||
// User is Right Clicking
|
// User is Right Clicking
|
||||||
if ((e.buttons & 2) == 2) {
|
if ((e.buttons & 2) == 2) {
|
||||||
isZooming.value = true
|
isZooming.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// goStore.hoveredCard = props.card_id
|
// goStore.hoveredCard = props.card_id
|
||||||
}
|
}
|
||||||
function mouseleave(e: MouseEvent) {
|
function mouseleave(e: MouseEvent) {
|
||||||
isZooming.value = false
|
isZooming.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rightClickDown(e: MouseEvent) {
|
function rightClickDown(e: MouseEvent) {
|
||||||
isZooming.value = true
|
isZooming.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rightClickUp(e: MouseEvent) {
|
function rightClickUp(e: MouseEvent) {
|
||||||
isZooming.value = false
|
isZooming.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function activateEffect(e: CustomEvent) {
|
function activateEffect(e: CustomEvent) {
|
||||||
console.log(e.detail, props.uuid)
|
console.log(e.detail, props.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
card.value?.style.setProperty("--random-seed", -Math.random() * 10 + 's')
|
card.value?.style.setProperty("--random-seed", -Math.random() * 10 + "s");
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="card" class="card" :class="{ active: childCount > 0, wrapped, unlocked: !props.locked, zoom: isZooming }"
|
<div
|
||||||
@contextmenu.prevent="false" @click.left="cardClick" @mousedown.right="rightClickDown"
|
ref="card"
|
||||||
@mouseup.right="rightClickUp" @mouseenter="mouseenter" @mouseleave="mouseleave">
|
class="card"
|
||||||
<div id="contextMenuButtons" :ref="(el) => { childCount = ((el as Element)?.childElementCount ?? 0) }">
|
:class="{
|
||||||
<slot></slot>
|
active: childCount > 0,
|
||||||
</div>
|
wrapped,
|
||||||
<template v-if="props.card_id">
|
unlocked: !props.locked,
|
||||||
<svg width="180" height="250" v-if="settingsStore.cardStyle == CardStyles.SVG" viewBox="0 0 298 417">
|
zoom: isZooming,
|
||||||
<use :xlink:href="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + extension + '#card' + props.card_id"
|
}"
|
||||||
@activate_effect="activateEffect($event)">
|
@contextmenu.prevent="false"
|
||||||
</use>
|
@click.left="cardClick"
|
||||||
</svg>
|
@mousedown.right="rightClickDown"
|
||||||
<img :class="`card_image`" v-else
|
@mouseup.right="rightClickUp"
|
||||||
:src="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + extension"
|
@mouseenter="mouseenter"
|
||||||
draggable="false">
|
@mouseleave="mouseleave"
|
||||||
</template>
|
>
|
||||||
|
<div
|
||||||
<img :class="`card_image`" v-else :src="'/cards/background.png'" draggable="false">
|
id="contextMenuButtons"
|
||||||
|
:ref="(el) => { childCount = ((el as Element)?.childElementCount ?? 0) }"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="props.card_id">
|
||||||
|
<svg
|
||||||
|
width="180"
|
||||||
|
height="250"
|
||||||
|
v-if="settingsStore.cardStyle == CardStyles.SVG"
|
||||||
|
viewBox="0 0 298 417"
|
||||||
|
>
|
||||||
|
<use
|
||||||
|
:xlink:href="
|
||||||
|
`/cards/${settingsStore.cardStyle}/` +
|
||||||
|
props.card_id.toString().padStart(3, '0') +
|
||||||
|
extension +
|
||||||
|
'#card' +
|
||||||
|
props.card_id
|
||||||
|
"
|
||||||
|
@activate_effect="activateEffect($event)"
|
||||||
|
></use>
|
||||||
|
</svg>
|
||||||
|
<img
|
||||||
|
:class="`card_image`"
|
||||||
|
v-else
|
||||||
|
:src="
|
||||||
|
`/cards/${settingsStore.cardStyle}/` +
|
||||||
|
props.card_id.toString().padStart(3, '0') +
|
||||||
|
extension
|
||||||
|
"
|
||||||
|
draggable="false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<img
|
||||||
|
:class="`card_image`"
|
||||||
|
v-else
|
||||||
|
:src="'/cards/background.png'"
|
||||||
|
draggable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.card {
|
.card {
|
||||||
--max-height: 250px;
|
--max-height: 250px;
|
||||||
--margin-bottom: calc(var(--max-height) * 0.05);
|
--margin-bottom: calc(var(--max-height) * 0.05);
|
||||||
/* max-width: 256px; */
|
/* max-width: 256px; */
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
margin-top: var(--margin-bottom);
|
margin-top: var(--margin-bottom);
|
||||||
transition: all 0.075s cubic-bezier(1, 1.81, .59, 1.42);
|
transition: all 0.075s cubic-bezier(1, 1.81, 0.59, 1.42);
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
max-height: var(--max-height);
|
max-height: var(--max-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.active {
|
.card.active {
|
||||||
cursor: pointer
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_image {
|
.card_image {
|
||||||
max-height: var(--max-height);
|
max-height: var(--max-height);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
height: var(--max-height);
|
height: var(--max-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.wrapped {
|
.card.wrapped {
|
||||||
height: 6px;
|
height: 1px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.wrapped .card_image {
|
.card.wrapped .card_image {
|
||||||
filter: drop-shadow(.5px .5px .5px gray) drop-shadow(-.5px -.5px .5px gray);
|
filter: drop-shadow(0.5px 0.5px 0.5px gray)
|
||||||
|
drop-shadow(-0.5px -0.5px 0.5px gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.unlocked {
|
.card.unlocked {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-bottom: var(--margin-bottom);
|
margin-bottom: var(--margin-bottom);
|
||||||
transform: translateY(calc(var(--margin-bottom)*-.25));
|
transform: translateY(calc(var(--margin-bottom) * -0.25));
|
||||||
filter: drop-shadow(calc(var(--margin-bottom)*.3) var(--margin-bottom) 1px rgba(0, 0, 0, .60));
|
filter: drop-shadow(
|
||||||
cursor: pointer;
|
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
|
||||||
|
);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.zoom {
|
.card.zoom {
|
||||||
transform: scale(200%);
|
transform: scale(200%);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
#contextMenuButtons {
|
#contextMenuButtons {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 99%;
|
width: 99%;
|
||||||
transform: translateY(-0px);
|
transform: translateY(-0px);
|
||||||
transition: 0.1s transform cubic-bezier(1, 1.81, .59, 1.42);
|
transition: 0.1s transform cubic-bezier(1, 1.81, 0.59, 1.42);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.active:hover #contextMenuButtons {
|
.card.active:hover #contextMenuButtons {
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style>
|
<style>
|
||||||
.card.unlocked>* {
|
.card.unlocked > * {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#contextMenuButtons>* {
|
#contextMenuButtons > * {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes gelatine {
|
@keyframes gelatine {
|
||||||
|
from,
|
||||||
|
to {
|
||||||
|
}
|
||||||
|
|
||||||
from,
|
25% {
|
||||||
to {}
|
transform: scale(1, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
25% {
|
50% {
|
||||||
transform: scale(1, 1.5);
|
transform: scale(1.5, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
75% {
|
||||||
transform: scale(1.5, 1);
|
transform: scale(1.1, 1.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
75% {
|
|
||||||
transform: scale(1.1, 1.3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg_resource_icon {
|
.svg_resource_icon {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
animation: gelatine 0.3s normal;
|
animation: gelatine 0.3s normal;
|
||||||
transition: transform .1s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
transition: transform 0.1s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg_resource_icon:active {
|
.svg_resource_icon:active {
|
||||||
animation: none;
|
animation: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg_resource_icon:hover {
|
.svg_resource_icon:hover {
|
||||||
transform: scale(130%);
|
transform: scale(130%);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -55,13 +55,24 @@ function endAnimation() {
|
|||||||
animationCallbacks.value.forEach((p) => p());
|
animationCallbacks.value.forEach((p) => p());
|
||||||
}
|
}
|
||||||
|
|
||||||
containerEvents.set(props.container._id, {
|
watch(
|
||||||
populateContainer,
|
props.container,
|
||||||
shuffleContainer,
|
(newValue, oldValue) => {
|
||||||
getCardsPosition,
|
if (oldValue) {
|
||||||
startAnimation,
|
containerEvents.delete(oldValue._id);
|
||||||
endAnimation,
|
}
|
||||||
});
|
if (newValue) {
|
||||||
|
containerEvents.set(newValue._id, {
|
||||||
|
populateContainer,
|
||||||
|
shuffleContainer,
|
||||||
|
getCardsPosition,
|
||||||
|
startAnimation,
|
||||||
|
endAnimation,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
async function onEnter(_el: any, done: () => void) {
|
async function onEnter(_el: any, done: () => void) {
|
||||||
animationCallbacks.value.push(done);
|
animationCallbacks.value.push(done);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { Container } from "~/netcode/interfaces";
|
|||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
market: Container;
|
market: Container;
|
||||||
|
marketStack: Container;
|
||||||
fire_gems: Container;
|
fire_gems: Container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +29,11 @@ function fireGemCardClick(e: string) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="market">
|
<div id="market">
|
||||||
<CardPreview :tilted="false" :card_id="undefined"></CardPreview>
|
<CardsGrouped
|
||||||
|
:container="marketStack"
|
||||||
|
:wrapped="true"
|
||||||
|
:hidden="true"
|
||||||
|
></CardsGrouped>
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<CardsGrouped
|
<CardsGrouped
|
||||||
:container="market"
|
:container="market"
|
||||||
|
|||||||
+23
-20
@@ -1,40 +1,43 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Player } from '~/netcode/Player';
|
import type { Player } from "~/netcode/interfaces";
|
||||||
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
player: Player;
|
player: Player;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="player-icon-container">
|
<div class="player-icon-container">
|
||||||
<img class="avatar" v-if="props.player.image" :src="props.player.image" draggable="false">
|
<img
|
||||||
<b class="player-name">{{ props.player.username }}</b>
|
class="avatar"
|
||||||
</div>
|
v-if="props.player.user.avatar"
|
||||||
|
:src="`https://cdn.discordapp.com/avatars/${props.player.user.userId}/${props.player.user.avatar}.webp`"
|
||||||
|
draggable="false"
|
||||||
|
/>
|
||||||
|
<b class="player-name">{{ props.player.user.username }}</b>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.player-icon-container {
|
.player-icon-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
border-radius: 25px;
|
border-radius: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-name {
|
.player-name {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,126 +1,137 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import goStore from '@/netcode';
|
import type { Game, Player } from "~/netcode/interfaces";
|
||||||
import type { Player } from "~/netcode/Player";
|
|
||||||
|
|
||||||
const emit = defineEmits(['click'])
|
const emit = defineEmits(["click"]);
|
||||||
|
|
||||||
|
|
||||||
const view = ref<"main" | "discard">("main")
|
|
||||||
|
|
||||||
function show(data: "main" | "discard") {
|
|
||||||
view.value = data
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
player: Player;
|
game: Game;
|
||||||
focused?: Player
|
player: Player;
|
||||||
|
focused?: boolean;
|
||||||
|
isTurn?: boolean;
|
||||||
|
self?: boolean;
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>()
|
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
isTurn: () => false,
|
||||||
|
self: () => false,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="player_list_element" @click="$emit('click')"
|
<div
|
||||||
:class="{ self: props.player == goStore.self, focused: props.focused == props.player, isTurn: props.player.team == goStore.current_game?.current_turn }">
|
class="player_list_element"
|
||||||
<div id="player_banner" class="small">
|
@click="$emit('click')"
|
||||||
<div class="ready-bubble not-ready" v-if="!props.player.ready && !goStore.current_game?.started">Pas encore
|
:class="{
|
||||||
prêt...
|
self,
|
||||||
</div>
|
focused,
|
||||||
<div class="ready-bubble ready" v-if="props.player.ready && !goStore.current_game?.started">Prêt!</div>
|
isTurn,
|
||||||
<div id="player_info">
|
}"
|
||||||
<PlayerIcon :player="props.player"></PlayerIcon>
|
>
|
||||||
</div>
|
<div id="player_banner" class="small">
|
||||||
<div id="player_stats">
|
<!-- <div
|
||||||
<template v-if="goStore.current_game?.started">
|
class="ready-bubble not-ready"
|
||||||
<PlayerStats :player="props.player">
|
v-if="!props.player.ready && !goStore.current_game?.started"
|
||||||
</PlayerStats>
|
>
|
||||||
</template>
|
Pas encore prêt...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div
|
||||||
|
class="ready-bubble ready"
|
||||||
|
v-if="props.player.ready && !goStore.current_game?.started"
|
||||||
|
>
|
||||||
|
Prêt!
|
||||||
|
</div> -->
|
||||||
|
<div id="player_info">
|
||||||
|
<PlayerIcon :player="props.player"></PlayerIcon>
|
||||||
|
</div>
|
||||||
|
<div id="player_stats">
|
||||||
|
<!-- <template v-if="goStore.current_game?.started"> -->
|
||||||
|
<PlayerStats :game="props.game" :player="props.player"> </PlayerStats>
|
||||||
|
<!-- </template> -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.player_list_element {
|
.player_list_element {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, .60));
|
filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, 0.6));
|
||||||
transform: translate(-2.5px, -7.5px);
|
transform: translate(-2.5px, -7.5px);
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition: all .1s;
|
transition: all 0.1s;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
cursor: pointer
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player_list_element::before {
|
.player_list_element::before {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: rgb(15, 179, 255);
|
background: rgb(15, 179, 255);
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player_list_element.focused {
|
.player_list_element.focused {
|
||||||
filter: unset;
|
filter: unset;
|
||||||
transform: unset;
|
transform: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player_list_element.isTurn::before {
|
.player_list_element.isTurn::before {
|
||||||
opacity: .1;
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player_list_element.self::before {
|
.player_list_element.self::before {
|
||||||
background: rgb(33, 177, 76);
|
background: rgb(33, 177, 76);
|
||||||
}
|
}
|
||||||
|
|
||||||
#player_banner {
|
#player_banner {
|
||||||
display: flex;
|
display: flex;
|
||||||
grid-area: player_stats;
|
grid-area: player_stats;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#player_banner.small {
|
#player_banner.small {
|
||||||
flex-direction: row
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
#player_banner>* {
|
#player_banner > * {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
#player_stats {
|
#player_stats {
|
||||||
display: flex;
|
display: flex;
|
||||||
grid-area: player_stats;
|
grid-area: player_stats;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ready-bubble {
|
.ready-bubble {
|
||||||
color: white;
|
color: white;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ready {
|
.ready {
|
||||||
background-color: green;
|
background-color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.not-ready {
|
.not-ready {
|
||||||
background-color: maroon;
|
background-color: maroon;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { endTurn, lockCard } from "~/netcode";
|
import { endTurn, joinGame, lockCard, startGame } from "~/netcode";
|
||||||
import type { Game, Player } from "~/netcode/interfaces";
|
import type { Game, Player } from "~/netcode/interfaces";
|
||||||
import { useTurnStore } from "~/stores/turnStore";
|
import { useTurnStore } from "~/stores/turnStore";
|
||||||
|
|
||||||
@@ -105,7 +105,6 @@ function boardCardClick(cardUUID: string) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="player" :class="{ turn: isPlayerTurn, self: isSelf }">
|
<div class="player" :class="{ turn: isPlayerTurn, self: isSelf }">
|
||||||
<div id="player_banner" class="big">test</div>
|
|
||||||
<div id="turn_buttons">
|
<div id="turn_buttons">
|
||||||
<button
|
<button
|
||||||
id="end_turn"
|
id="end_turn"
|
||||||
@@ -115,6 +114,12 @@ function boardCardClick(cardUUID: string) {
|
|||||||
>
|
>
|
||||||
END TURN
|
END TURN
|
||||||
</button>
|
</button>
|
||||||
|
<button class="end_turn_button turn_icon" @click="startGame(game._id)">
|
||||||
|
Start game
|
||||||
|
</button>
|
||||||
|
<button class="end_turn_button turn_icon" @click="joinGame(game._id)">
|
||||||
|
Join game
|
||||||
|
</button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="warning"
|
class="warning"
|
||||||
|
|||||||
@@ -1,18 +1,30 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Player } from "~/netcode/interfaces";
|
import { playSound } from "~/helpers/audioHelpers";
|
||||||
|
import type { Game, Player } from "~/netcode/interfaces";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
game: Game;
|
||||||
player: Player;
|
player: Player;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const team = computed(() =>
|
||||||
|
props.game.teams.find((t) =>
|
||||||
|
t.players.map((p) => p._id).includes(props.player._id)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const isTurn = computed(
|
||||||
|
() => team.value && team.value?._id == props.game.currentTurn.currentTeam
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="turn_icon">
|
<div class="turn_icon">
|
||||||
<img src="/img/champion-shield.png" class="icon_img" draggable="false" />
|
<img src="/img/champion-shield.png" class="icon_img" draggable="false" />
|
||||||
<span class="turn_icon_number">
|
<span class="turn_icon_number">
|
||||||
{{ player.team?.health }}
|
{{ team?.health }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="turn_icon" v-if="showTurnData">
|
<!-- <div class="turn_icon" v-if="showTurnData">
|
||||||
@@ -30,7 +42,7 @@ const props = defineProps<Props>();
|
|||||||
<div class="turn_icon">
|
<div class="turn_icon">
|
||||||
<img src="/img/fuck.svg" class="icon_img" draggable="false" />
|
<img src="/img/fuck.svg" class="icon_img" draggable="false" />
|
||||||
<span class="turn_icon_number">{{
|
<span class="turn_icon_number">{{
|
||||||
(player.turn?.discard_markers ?? 0) + (player.turn?.fuck_u_markers ?? 0)
|
(isTurn && (player.discardMarkers ?? 0) + (player.fuckUMarkers ?? 0)) || 0
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+21
-3
@@ -48,7 +48,25 @@ export async function whoami() {
|
|||||||
|
|
||||||
export async function createGame() {
|
export async function createGame() {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
await $fetch<User>(new URL("/games", config.public.endpoint).href, {
|
const res = await $fetch<Game>(new URL("/games", config.public.endpoint).href, {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
console.log(res)
|
||||||
|
navigateTo("/game/" + res._id)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startGame(game: string) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
const res = await $fetch<Game>(new URL(`games/${game}/start`, config.public.endpoint).href, {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function joinGame(game: string) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
const res = await $fetch<Game>(new URL(`games/${game}/join`, config.public.endpoint).href, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@@ -56,7 +74,7 @@ export async function createGame() {
|
|||||||
|
|
||||||
export async function endTurn(game: string) {
|
export async function endTurn(game: string) {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
await $fetch<User>(
|
await $fetch(
|
||||||
new URL(`games/${game}/endTurn`, config.public.endpoint).href,
|
new URL(`games/${game}/endTurn`, config.public.endpoint).href,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -67,7 +85,7 @@ export async function endTurn(game: string) {
|
|||||||
|
|
||||||
export async function lockCard(game: string, cardId: string) {
|
export async function lockCard(game: string, cardId: string) {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
await $fetch<User>(
|
await $fetch(
|
||||||
new URL(`games/${game}/turn/lockCard/${cardId}`, config.public.endpoint).href,
|
new URL(`games/${game}/turn/lockCard/${cardId}`, config.public.endpoint).href,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|||||||
@@ -16,10 +16,13 @@ export interface Game extends GameObject {
|
|||||||
marketStack: Container;
|
marketStack: Container;
|
||||||
teams: Team[];
|
teams: Team[];
|
||||||
currentTurn: PlayingTurn;
|
currentTurn: PlayingTurn;
|
||||||
|
started: boolean
|
||||||
|
owner: User
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Team extends GameObject {
|
export interface Team extends GameObject {
|
||||||
players: Player[];
|
players: Player[];
|
||||||
|
health: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Player extends GameObject {
|
export interface Player extends GameObject {
|
||||||
@@ -28,10 +31,14 @@ export interface Player extends GameObject {
|
|||||||
hand: Container;
|
hand: Container;
|
||||||
stack: Container;
|
stack: Container;
|
||||||
user: User;
|
user: User;
|
||||||
|
discardMarkers: number
|
||||||
|
fuckUMarkers: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User extends GameObject {
|
export interface User extends GameObject {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
avatar: string;
|
||||||
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Container extends GameObject {
|
export interface Container extends GameObject {
|
||||||
|
|||||||
+59
-19
@@ -3,9 +3,11 @@ import LoadingScreen from "~/components/LoadingScreen.vue";
|
|||||||
import { subscribe } from "~/netcode";
|
import { subscribe } from "~/netcode";
|
||||||
import { containerEvents, delay } from "~/netcode/events";
|
import { containerEvents, delay } from "~/netcode/events";
|
||||||
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
||||||
|
import { playSound } from "~/helpers/audioHelpers";
|
||||||
|
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const gameId = route.params.id;
|
const gameId = route.params.id;
|
||||||
@@ -76,9 +78,10 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
await containerEvents.get(data.container)?.startAnimation();
|
await containerEvents.get(data.container)?.startAnimation();
|
||||||
});
|
});
|
||||||
const fromContainer = containers.value[data.container.id as string];
|
const fromContainer = containers.value[data.container._id as string];
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
for (const card of data.container.cards) {
|
for (const card of data.container.cards) {
|
||||||
|
playSound("/sounds/distribute.mp3");
|
||||||
fromContainer.cards.push(card);
|
fromContainer.cards.push(card);
|
||||||
await delay(settingsStore.animationSpeed);
|
await delay(settingsStore.animationSpeed);
|
||||||
}
|
}
|
||||||
@@ -88,6 +91,8 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
});
|
});
|
||||||
} else if (data.type == "shuffleContainer") {
|
} else if (data.type == "shuffleContainer") {
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
|
playSound("/sounds/shuffle.mp3");
|
||||||
|
// TODO : IMPORTANT : find a better way than containerEvents
|
||||||
await containerEvents.get(data.container)?.shuffleContainer();
|
await containerEvents.get(data.container)?.shuffleContainer();
|
||||||
});
|
});
|
||||||
} else if (data.type == "distributeCards") {
|
} else if (data.type == "distributeCards") {
|
||||||
@@ -108,6 +113,7 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
|
playSound("/sounds/distribute.mp3");
|
||||||
toContainer.cards.push(card);
|
toContainer.cards.push(card);
|
||||||
await delay(settingsStore.animationSpeed);
|
await delay(settingsStore.animationSpeed);
|
||||||
});
|
});
|
||||||
@@ -119,16 +125,27 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
});
|
});
|
||||||
} else if (data.type == "endTurn") {
|
} else if (data.type == "endTurn") {
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
current_game.currentTurn.cardsLocked = [];
|
current_game.currentTurn = data.currentTurn;
|
||||||
current_game.currentTurn.effectsUsed = [];
|
|
||||||
current_game.currentTurn.damage = 0;
|
|
||||||
current_game.currentTurn.gold = 0;
|
|
||||||
await delay(settingsStore.animationSpeed);
|
await delay(settingsStore.animationSpeed);
|
||||||
|
const playingPlayer = current_game.teams.find(
|
||||||
|
(t) => t._id == current_game.currentTurn.currentTeam
|
||||||
|
)?.players[0];
|
||||||
|
console.log(playingPlayer);
|
||||||
|
if (playingPlayer) {
|
||||||
|
focusPlayer(playingPlayer);
|
||||||
|
await delay(settingsStore.animationSpeed);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else if (data.type == "lockCard") {
|
} else if (data.type == "lockCard") {
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
|
playSound("/sounds/lock.mp3");
|
||||||
current_game.currentTurn.cardsLocked.push(data.card);
|
current_game.currentTurn.cardsLocked.push(data.card);
|
||||||
});
|
});
|
||||||
|
} else if (data.type == "joinGame") {
|
||||||
|
queueAction(async () => {
|
||||||
|
playSound("/sounds/teleport.mp3");
|
||||||
|
current_game.teams.push(data.team);
|
||||||
|
});
|
||||||
} else if (data.type == "useEffect") {
|
} else if (data.type == "useEffect") {
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
current_game.currentTurn.effectsUsed.push(data.effect);
|
current_game.currentTurn.effectsUsed.push(data.effect);
|
||||||
@@ -141,8 +158,6 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
|
|
||||||
const playerList = computed(() =>
|
const playerList = computed(() =>
|
||||||
game.value!.teams.reduce((acc, t) => acc.concat(t.players), [] as Player[])
|
game.value!.teams.reduce((acc, t) => acc.concat(t.players), [] as Player[])
|
||||||
);
|
);
|
||||||
@@ -151,6 +166,13 @@ const selfPlayer = computed(() =>
|
|||||||
? playerList.value?.find((p) => p.user.userId == authStore.selfUser.userId)
|
? playerList.value?.find((p) => p.user.userId == authStore.selfUser.userId)
|
||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
|
const isTurn = computed(
|
||||||
|
() =>
|
||||||
|
selfPlayer.value &&
|
||||||
|
game.value &&
|
||||||
|
game.value.teams.find((t) => t.players.includes(selfPlayer.value!))?._id ==
|
||||||
|
game.value.currentTurn.currentTeam
|
||||||
|
);
|
||||||
|
|
||||||
// TODO : current turn sound
|
// TODO : current turn sound
|
||||||
|
|
||||||
@@ -161,6 +183,8 @@ const selfPlayer = computed(() =>
|
|||||||
const showResults = ref(false);
|
const showResults = ref(false);
|
||||||
const isWinner = ref(false);
|
const isWinner = ref(false);
|
||||||
const loaded = ref(false);
|
const loaded = ref(false);
|
||||||
|
const discard_unwrapped = ref(false);
|
||||||
|
const focusedPlayer = ref<Player>(selfPlayer.value ?? playerList.value[0]);
|
||||||
|
|
||||||
function showLoserScreen() {
|
function showLoserScreen() {
|
||||||
// playSound('/sounds/ding.mp3')
|
// playSound('/sounds/ding.mp3')
|
||||||
@@ -174,9 +198,6 @@ function showWinnerScreen() {
|
|||||||
isWinner.value = true;
|
isWinner.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const discard_unwrapped = ref(false);
|
|
||||||
const focusedPlayer = ref<Player>(selfPlayer.value ?? playerList.value[0]);
|
|
||||||
|
|
||||||
// const clientStore = useClientSideStore()
|
// const clientStore = useClientSideStore()
|
||||||
// const restack_discarded_champion = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CHAMPION, target)
|
// const restack_discarded_champion = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CHAMPION, target)
|
||||||
// const restack_discarded_card = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CARD, target)
|
// const restack_discarded_card = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CARD, target)
|
||||||
@@ -202,7 +223,10 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div @contextmenu.prevent="false" id="game_board" v-if="game">
|
<div @contextmenu.prevent="false" id="game_board" v-if="game">
|
||||||
<AnimatedBackground @ready="loaded = true"></AnimatedBackground>
|
<AnimatedBackground
|
||||||
|
@ready="loaded = true"
|
||||||
|
:isTurn="isTurn ?? false"
|
||||||
|
></AnimatedBackground>
|
||||||
<div id="stack_discard">
|
<div id="stack_discard">
|
||||||
<div id="stack">
|
<div id="stack">
|
||||||
<CardsGrouped
|
<CardsGrouped
|
||||||
@@ -223,14 +247,25 @@ onUnmounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MarketCards :market="game.market" :fire_gems="game.fireGems"></MarketCards>
|
<MarketCards
|
||||||
|
:market="game.market"
|
||||||
|
:fire_gems="game.fireGems"
|
||||||
|
:marketStack="game.marketStack"
|
||||||
|
></MarketCards>
|
||||||
|
|
||||||
<!-- <div id="player_list_container">
|
<div id="player_list_container">
|
||||||
<div id="player_list">
|
<div id="player_list">
|
||||||
<PlayerListElement v-for="p in playerList" :player="p" @click="focusPlayer(p)" :focused="focusedPlayer">
|
<PlayerListElement
|
||||||
</PlayerListElement>
|
v-for="p in playerList"
|
||||||
</div>
|
:player="p"
|
||||||
</div> -->
|
:game="game"
|
||||||
|
@click="focusPlayer(p)"
|
||||||
|
:focused="focusedPlayer == p"
|
||||||
|
:self="selfPlayer == p"
|
||||||
|
>
|
||||||
|
</PlayerListElement>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="current_player">
|
<div id="current_player">
|
||||||
<PlayerSlot
|
<PlayerSlot
|
||||||
@@ -273,7 +308,12 @@ onUnmounted(() => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#player_list,
|
#player_list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: inherit;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
#current_player {
|
#current_player {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
+8
-6
@@ -20,10 +20,13 @@ eventSource.addEventListener("message", (message) => {
|
|||||||
throw new Error("Couldn't delete game");
|
throw new Error("Couldn't delete game");
|
||||||
}
|
}
|
||||||
games.value.splice(index, 1);
|
games.value.splice(index, 1);
|
||||||
} else if (data.type == "update") {
|
} else if (data.type == "joinGame") {
|
||||||
throw new Error("not implemented");
|
games.value.find((g) => g._id == data.game)?.teams.push(data.team);
|
||||||
} else if (data.type == "start") {
|
} else if (data.type == "start") {
|
||||||
throw new Error("not implemented");
|
const targetGame = games.value.find((g) => g._id == data.game);
|
||||||
|
if (targetGame) {
|
||||||
|
targetGame.started = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,9 +61,8 @@ onUnmounted(() => {
|
|||||||
authStore.selfUser.userId == g.owner.userId ? 'own_game' : ''
|
authStore.selfUser.userId == g.owner.userId ? 'own_game' : ''
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template v-if="g.started && g.ended"> GAME OVER </template>
|
|
||||||
<template
|
<template
|
||||||
v-else-if="
|
v-if="
|
||||||
g.teams.every((t) =>
|
g.teams.every((t) =>
|
||||||
t.players.every(
|
t.players.every(
|
||||||
(p) => p.user.userId !== authStore.selfUser.userId
|
(p) => p.user.userId !== authStore.selfUser.userId
|
||||||
@@ -101,7 +103,7 @@ onUnmounted(() => {
|
|||||||
<img
|
<img
|
||||||
@click="router.push('/rules')"
|
@click="router.push('/rules')"
|
||||||
class="overlay-image"
|
class="overlay-image"
|
||||||
src="https://static.wikia.nocookie.net/umineko/img/9/9d/PC_Erika.Casual.Sprite_36.png"
|
src="https://static.wikia.nocookie.net/umineko/images/9/9d/PC_Erika.Casual.Sprite_36.png"
|
||||||
alt="pétasse"
|
alt="pétasse"
|
||||||
/>
|
/>
|
||||||
<div class="overlay-button">
|
<div class="overlay-button">
|
||||||
|
|||||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user