Feat : allow buying cards

This commit is contained in:
2024-07-05 11:26:41 +02:00
parent 694e8429d1
commit b3df241313
6 changed files with 134 additions and 70 deletions
+9 -3
View File
@@ -5,7 +5,8 @@ export interface Props {
locked?: boolean;
wrapped?: boolean;
tilted?: boolean;
interactible?: boolean
interactible?: boolean;
noEffects?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
@@ -13,6 +14,7 @@ const props = withDefaults(defineProps<Props>(), {
tilted: () => true,
locked: () => true,
interactible: () => true,
noEffects: () => false,
});
const emit = defineEmits(["click"]);
@@ -74,6 +76,7 @@ onMounted(() => {
wrapped,
unlocked: !props.locked,
zoom: isZooming,
no_effects: noEffects || !props.locked,
}"
@contextmenu.prevent="false"
@click.left="cardClick"
@@ -168,7 +171,6 @@ onMounted(() => {
filter: drop-shadow(
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
);
cursor: pointer;
}
.card.zoom {
@@ -193,10 +195,14 @@ onMounted(() => {
}
</style>
<style>
.card.unlocked > * {
.card.no_effects svg > * {
pointer-events: none;
}
.card.no_effects {
cursor: pointer;
}
#contextMenuButtons > * {
flex: 1;
border-radius: 12px;
+7 -5
View File
@@ -7,11 +7,13 @@ export interface Props {
playingTurn?: PlayingTurn;
wrapped?: boolean;
hidden?: boolean;
noEffects?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
wrapped: () => false,
hidden: () => false,
noEffects: () => false,
});
const emit = defineEmits(["cardClick"]);
@@ -82,18 +84,17 @@ function endAnimation() {
// animationCallbacks.value.push(done);
// }
onUnmounted(() => {
// containerEvents.delete(props.container._id);
});
</script>
<template>
<div class="cards_container" :class="{ wrapped, rotate:container.shuffling }">
<TransitionGroup
name="list"
<div
class="cards_container"
:class="{ wrapped, rotate: container.shuffling }"
>
<TransitionGroup name="list">
<CardPreview
@click="$emit('cardClick', c._id)"
v-for="c in cards"
@@ -104,6 +105,7 @@ onUnmounted(() => {
:locked="
!playingTurn || playingTurn?.cardsLocked.includes(c._id.toString())
"
:noEffects="noEffects"
>
</CardPreview>
</TransitionGroup>
+6 -2
View File
@@ -1,7 +1,9 @@
<script setup lang="ts">
import type { Container } from "~/netcode/interfaces";
import { buyCard } from "~/netcode";
import type { Container, Game } from "~/netcode/interfaces";
export interface Props {
game: Game;
market: Container;
marketStack: Container;
fire_gems: Container;
@@ -19,7 +21,7 @@ const authStore = useAuthStore();
// const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
function marketCardClick(e: string) {
console.log(e);
buyCard(props.game._id, e);
}
function fireGemCardClick(e: string) {
@@ -38,12 +40,14 @@ function fireGemCardClick(e: string) {
<CardsGrouped
:container="market"
@cardClick="marketCardClick"
:noEffects="true"
></CardsGrouped>
<div class="separator"></div>
<CardsGrouped
:container="fire_gems"
:wrapped="true"
@cardClick="fireGemCardClick"
:noEffects="true"
></CardsGrouped>
</div>
</template>
+2 -2
View File
@@ -27,7 +27,7 @@ const isTurn = computed(
{{ team?.health }}
</span>
</div>
<!-- <div class="turn_icon" v-if="isTurn">
<div class="turn_icon" v-if="isTurn">
<img src="/img/gold.png" class="icon_img" draggable="false" />
<span class="turn_icon_number">
{{ game.currentTurn.gold }}
@@ -38,7 +38,7 @@ const isTurn = computed(
<span class="turn_icon_number">
{{ game.currentTurn.damage }}
</span>
</div> -->
</div>
<div class="turn_icon">
<img src="/img/fuck.svg" class="icon_img" draggable="false" />
<span class="turn_icon_number">{{
+48 -29
View File
@@ -48,45 +48,64 @@ export async function whoami() {
export async function createGame() {
const config = useRuntimeConfig();
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",
credentials: "include",
});
}
export async function endTurn(game: string) {
const config = useRuntimeConfig();
await $fetch(
new URL(`games/${game}/endTurn`, 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",
credentials: "include",
}
);
}
export async function endTurn(game: string) {
const config = useRuntimeConfig();
await $fetch(new URL(`games/${game}/endTurn`, config.public.endpoint).href, {
method: "POST",
credentials: "include",
});
}
export async function lockCard(game: string, cardId: string) {
const config = useRuntimeConfig();
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",
credentials: "include",
}
);
}
export async function buyCard(game: string, cardId: string) {
const config = useRuntimeConfig();
await $fetch(
new URL(`games/${game}/turn/buyCard/${cardId}`, config.public.endpoint)
.href,
{
method: "POST",
credentials: "include",
+38 -5
View File
@@ -93,10 +93,10 @@ eventSource.addEventListener("message", async (message) => {
queueAction(async () => {
playSound("/sounds/shuffle.mp3");
const container = containers.value[data.container as string];
container.shuffling = true
await delay(settingsStore.animationSpeed *2)
container.shuffling = false
await delay(settingsStore.animationSpeed *2)
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)
@@ -163,6 +163,15 @@ eventSource.addEventListener("message", async (message) => {
console.log(`adding damage amount : ` + data.operation);
current_game.currentTurn.damage = data.damage;
});
} else if (data.type == "team.updateHealth") {
queueAction(async () => {
const team = game.value?.teams.find((t) => t._id == data.team);
if (!team) {
throw new Error("Team not found");
}
console.log(`adding health amount : ` + data.operation);
team.health = data.health;
});
}
});
@@ -182,6 +191,9 @@ const isTurn = computed(
game.value.currentTurn.currentTeam
);
const turnChangeAnimationSpeed = computed(
() => settingsStore.animationSpeed * 2 + "ms"
);
// TODO : current turn sound
// TODO : winner screen
@@ -235,7 +247,8 @@ onUnmounted(() => {
@ready="loaded = true"
:isTurn="isTurn ?? false"
></AnimatedBackground>
<div id="stack_discard">
<Transition name="slide-left" mode="out-in">
<div id="stack_discard" :key="focusedPlayer._id">
<div id="stack">
<CardsGrouped
:container="focusedPlayer.stack"
@@ -254,8 +267,10 @@ onUnmounted(() => {
</CardsGrouped>
</div>
</div>
</Transition>
<MarketCards
:game="game"
:market="game.market"
:fire_gems="game.fireGems"
:marketStack="game.marketStack"
@@ -276,11 +291,14 @@ onUnmounted(() => {
</div>
<div id="current_player">
<Transition name="slide-left" mode="out-in">
<PlayerSlot
v-if="focusedPlayer"
:player="focusedPlayer"
:game="game!"
:key="focusedPlayer._id"
></PlayerSlot>
</Transition>
</div>
<ResultDialog
:isVisible="showResults"
@@ -402,4 +420,19 @@ onUnmounted(() => {
/* border: 5px solid #000; */
display: flex;
}
.slide-left-enter-active,
.slide-left-leave-active {
transition: all v-bind("turnChangeAnimationSpeed") ease-out;
}
.slide-left-enter-from {
opacity: 0;
transform: translateX(100%);
}
.slide-left-leave-to {
opacity: 0;
transform: translateX(-100%);
}
</style>