Fix : switch to state based shuffle animation

This commit is contained in:
2024-07-04 22:07:48 +02:00
parent 25cf8a55e9
commit b1a874aaeb
11 changed files with 97 additions and 232 deletions
+3
View File
@@ -0,0 +1,3 @@
<html>
I LOVE LOADING SCREENS
</html>
+1 -1
View File
@@ -161,7 +161,7 @@ onUnmounted(() => {
<style scoped>
#background {
left: 0;
position: absolute;
position: fixed;
height: 100%;
width: 100%;
}
-2
View File
@@ -129,14 +129,12 @@ onMounted(() => {
.card {
--max-height: 250px;
--margin-bottom: calc(var(--max-height) * 0.05);
/* max-width: 256px; */
position: relative;
display: flex;
justify-content: center;
margin-bottom: 0px;
margin-top: var(--margin-bottom);
transition: all 0.075s cubic-bezier(1, 1.81, 0.59, 1.42);
isolation: isolate;
pointer-events: all;
max-height: var(--max-height);
}
+45 -41
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { containerEvents, delay } from "~/netcode/events";
import { delay } from "~/netcode/events";
import type { Container, PlayingTurn } from "~/netcode/interfaces";
export interface Props {
@@ -34,13 +34,13 @@ const shuffleAnimationSpeed = computed(
);
function populateContainer() {}
const rotate = ref(false);
async function shuffleContainer() {
rotate.value = true;
await delay(settingsStore.animationSpeed * 2);
rotate.value = false;
await delay(settingsStore.animationSpeed * 2);
}
// const rotate = ref(false);
// async function shuffleContainer() {
// rotate.value = true;
// await delay(settingsStore.animationSpeed * 2);
// rotate.value = false;
// await delay(settingsStore.animationSpeed * 2);
// }
function getCardsPosition(cards: string) {}
@@ -55,47 +55,44 @@ function endAnimation() {
animationCallbacks.value.forEach((p) => p());
}
watch(
props.container,
(newValue, oldValue) => {
if (oldValue) {
containerEvents.delete(oldValue._id);
}
if (newValue) {
containerEvents.set(newValue._id, {
populateContainer,
shuffleContainer,
getCardsPosition,
startAnimation,
endAnimation,
});
}
},
{ immediate: true }
);
// watch(
// props.container,
// (newValue, oldValue) => {
// if (oldValue) {
// containerEvents.delete(oldValue._id);
// }
// if (newValue) {
// containerEvents.set(newValue._id, {
// populateContainer,
// shuffleContainer,
// getCardsPosition,
// startAnimation,
// endAnimation,
// });
// }
// },
// { immediate: true }
// );
async function onEnter(_el: any, done: () => void) {
animationCallbacks.value.push(done);
}
// async function onEnter(_el: any, done: () => void) {
// animationCallbacks.value.push(done);
// }
// async function onLeave(_el: any, done: () => void) {
// animationCallbacks.value.push(done);
// }
async function onLeave(_el: any, done: () => void) {
animationCallbacks.value.push(done);
}
async function onBeforeEnter() {}
onUnmounted(() => {
containerEvents.delete(props.container._id);
// containerEvents.delete(props.container._id);
});
</script>
<template>
<div class="cards_container" :class="{ wrapped, rotate }">
<div class="cards_container" :class="{ wrapped, rotate:container.shuffling }">
<TransitionGroup
name="list"
@enter="onEnter"
@leave="onLeave"
@before-enter="onBeforeEnter"
>
<CardPreview
@click="$emit('cardClick', c._id)"
@@ -115,15 +112,21 @@ onUnmounted(() => {
</template>
<style scoped>
.list-move,
.list-enter-active,
.list-leave-active {
transition: all v-bind("animationSpeed") ease;
}
.list-leave-to,
/* .list-leave-to, */
.list-enter-from {
opacity: 0;
transform: translateX(30px);
/* transform: translateX(30px); */
}
.list-leave-active {
position: absolute;
height:unset;
}
.rotate {
@@ -133,13 +136,14 @@ onUnmounted(() => {
.cards_container {
display: flex;
flex-direction: row;
justify-content: center;
justify-content: space-evenly;
min-width: 200px;
transition: rotate v-bind("shuffleAnimationSpeed") ease;
}
.cards_container.wrapped {
flex-direction: column-reverse;
justify-content: center;
}
.cards_container.wrapped:before {
+10 -31
View File
@@ -258,10 +258,7 @@ function boardCardClick(cardUUID: string) {
}
#turn_buttons {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
grid-area: turn_buttons;
}
#end_turn {
@@ -273,32 +270,6 @@ function boardCardClick(cardUUID: string) {
visibility: hidden;
}
.stack,
.discard,
.cards_container {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap-reverse;
}
.stack {
grid-area: stack;
margin-left: 75px;
}
.discard {
margin-top: 40px;
grid-area: discard;
justify-content: start;
cursor: pointer;
pointer-events: none;
margin-left: 75px;
}
.discard.invisible {
visibility: hidden;
}
.player {
display: grid;
@@ -307,12 +278,20 @@ function boardCardClick(cardUUID: string) {
/* border-top: 5px solid black; */
grid-template-areas:
"player_stats"
"player";
"player"
"turn_buttons";
justify-items: center;
transition: all 1s;
}
#current_player_board {
grid-area: player;
display:flex;
flex-direction: column;
justify-content: center;
align-items: center;
max-width: 1200px;
}
.damage_button {
+13 -10
View File
@@ -2,21 +2,23 @@ import { useAuthStore } from "#imports";
export default defineNuxtRouteMiddleware(async (to, from) => {
const authStore = useAuthStore();
const config = useRuntimeConfig();
if (to.path == "/login") {
const code = to.query.code;
if (code) {
if (!Array.isArray(code)) {
try {
await authStore.whoami();
return navigateTo("/lobby");
} catch {
return navigateTo("/login");
}
} else {
if (!code) {
return navigateTo(config.public.discordLoginEndpoint, { external: true });
}
if (!Array.isArray(code)) {
try {
await authStore.whoami();
return navigateTo("/lobby");
} catch {
return navigateTo("/login");
}
} else {
return navigateTo("/login");
}
return navigateTo("/lobby");
}
// if (to.path == '/') {
@@ -69,4 +71,5 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
if (to.path !== "/") {
return navigateTo("/");
}
return navigateTo("/lobby");
});
+8 -8
View File
@@ -4,12 +4,12 @@ export function delay(delay: number) {
});
}
export type ContainerHandler = {
populateContainer: () => void;
shuffleContainer: () => void;
getCardsPosition: (cards: string) => any;
startAnimation: () => void;
endAnimation: () => void;
};
// export type ContainerHandler = {
// populateContainer: () => void;
// shuffleContainer: () => void;
// getCardsPosition: (cards: string) => any;
// startAnimation: () => void;
// endAnimation: () => void;
// };
export const containerEvents = reactive(new Map<string, ContainerHandler>());
// export const containerEvents = reactive(new Map<string, ContainerHandler>());
+5 -4
View File
@@ -16,8 +16,8 @@ export interface Game extends GameObject {
marketStack: Container;
teams: Team[];
currentTurn: PlayingTurn;
started: boolean
owner: User
started: boolean;
owner: User;
}
export interface Team extends GameObject {
@@ -31,8 +31,8 @@ export interface Player extends GameObject {
hand: Container;
stack: Container;
user: User;
discardMarkers: number
fuckUMarkers: number
discardMarkers: number;
fuckUMarkers: number;
}
export interface User extends GameObject {
@@ -43,6 +43,7 @@ export interface User extends GameObject {
export interface Container extends GameObject {
cards: Card[];
shuffling?: boolean;
}
export interface Card extends GameObject {
+12 -12
View File
@@ -1,7 +1,7 @@
<script setup lang="ts">
import LoadingScreen from "~/components/LoadingScreen.vue";
import { subscribe } from "~/netcode";
import { containerEvents, delay } from "~/netcode/events";
import { delay } from "~/netcode/events";
import { type Container, type Game, type Player } from "~/netcode/interfaces";
import { playSound } from "~/helpers/audioHelpers";
@@ -76,7 +76,7 @@ eventSource.addEventListener("message", async (message) => {
throw new Error("not implemented");
} else if (data.type == "populateContainer") {
queueAction(async () => {
await containerEvents.get(data.container)?.startAnimation();
// await containerEvents.get(data.container)?.startAnimation();
});
const fromContainer = containers.value[data.container._id as string];
queueAction(async () => {
@@ -87,20 +87,23 @@ eventSource.addEventListener("message", async (message) => {
}
});
queueAction(async () => {
await containerEvents.get(data.container)?.endAnimation();
// await containerEvents.get(data.container)?.endAnimation();
});
} else if (data.type == "shuffleContainer") {
queueAction(async () => {
playSound("/sounds/shuffle.mp3");
// TODO : IMPORTANT : find a better way than containerEvents
await containerEvents.get(data.container)?.shuffleContainer();
const container = containers.value[data.container as string];
container.shuffling = true
await delay(settingsStore.animationSpeed *2)
container.shuffling = false
await delay(settingsStore.animationSpeed *2)
});
} else if (data.type == "distributeCards") {
// containerEvents.get(data.from)?.getCardsPosition(data.cards)
queueAction(async () => {
containerEvents.get(data.from)?.startAnimation();
containerEvents.get(data.to)?.startAnimation();
// containerEvents.get(data.from)?.startAnimation();
// containerEvents.get(data.to)?.startAnimation();
});
const fromContainer = containers.value[data.from as string];
@@ -119,8 +122,8 @@ eventSource.addEventListener("message", async (message) => {
});
}
queueAction(async () => {
containerEvents.get(data.from)?.endAnimation();
containerEvents.get(data.to)?.endAnimation();
// containerEvents.get(data.from)?.endAnimation();
// containerEvents.get(data.to)?.endAnimation();
await delay(settingsStore.animationSpeed * 2);
});
} else if (data.type == "endTurn") {
@@ -315,9 +318,6 @@ onUnmounted(() => {
}
#current_player {
overflow: auto;
position: relative;
isolation: isolate;
display: flex;
flex-direction: column;
justify-content: center;
-16
View File
@@ -1,16 +0,0 @@
<script setup lang="ts">
// import goStore, { setReady } from "@/netcode";
</script>
<template>
<div class="root_page_div">
tehe
</div>
</template>
<style>
.root_page_div {
height: 100%;
}
</style>
-107
View File
@@ -1,107 +0,0 @@
<script setup lang="ts">
// import { navigateTo, useRuntimeConfig } from 'nuxt/app';
// import goStore, { netcode_create_game, join_game } from '../netcode';
const config = useRuntimeConfig()
async function discordLogin() {
await navigateTo(config.public.discordLoginEndpoint, {
external: true
})
}
</script>
<template>
<div class="background">
<div class="title">
Entrez dans le Royaume de Héron !
</div>
<div class="middle-row">
<div class="icon">
<CardPreview :card_id="undefined"></CardPreview>
</div>
<!-- <div v-if="goStore.current_game?.started">
<b>Mode spectateur</b>
</div> -->
<!-- <template v-if="!goStore.current_game?.started"> -->
<!-- <input type="text" v-model="username" />
<button @click="register(username)">LOGIN</button> -->
<!-- <button class="menu-button" @click="discordLogin()">Se connecter via Discord</button>
</template> -->
</div>
<footer>
<p>
Héron Realms n'est en aucun cas affilié à Hero Realms.<br>
Le concept et certains noms de cartes sont la propriété de Wise Wizard Games.<br>
Les illustrations sont la propriété de leurs auteurs respectifs (il y en a plein).<br>
Ce magnifique fond d'écran est tiré de Fire Emblem: Engage.<br>
Programmeur principal, owner du projet: Legonzaur
</p>
</footer>
</div>
</template>
<style scoped>
.background {
background-color: #f0f0f0;
background-image: url('https://www.pockettactics.com/wp-content/sites/pockettactics/2023/01/fire-emblem-engage-review-29.jpg');
background-size: cover;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.title {
font-family: 'Kanit', 'Roboto', sans-serif;
font-size: 64px;
color: white;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
margin-bottom: 100px;
}
.middle-row {
display: flex;
flex-direction: row;
gap: 100px;
margin-bottom: 100px;
}
.menu-button {
background-color: #4CAF50;
border: none;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
font-family: 'Roboto', sans-serif;
font-size: 16px;
margin: auto;
cursor: pointer;
border-radius: 12px;
padding: 20px 24px;
height: 120px;
transition-duration: 0.4s;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
footer {
position: absolute;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
color: white;
width: 100%;
font-family: 'Roboto', sans-serif;
font-size: 12px;
text-align: center;
}
</style>import { useRuntimeConfig, navigateTo } from 'nuxt/app';