Skip to content

Commit 18ed4c1

Browse files
feat: add MatchBoard, OpponentHeader, PlayerHeader, PartyBoard, QuestBoard components and integrate them into quest page
1 parent 7f01c9e commit 18ed4c1

File tree

6 files changed

+348
-0
lines changed

6 files changed

+348
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<script setup lang="ts">
2+
import PlayerCard from '~/components/Card/Card.vue'
3+
import Board from '~/components/Board.vue'
4+
import type { SpaceTimeSimulationOutput } from '../../utils/spaceTimeSimulation'
5+
6+
const props = defineProps<{
7+
cardTimeline: SpaceTimeSimulationOutput
8+
timeline: gsap.core.Timeline
9+
time: number
10+
}>()
11+
12+
13+
function handleReset() {
14+
props.timeline.restart()
15+
// Reset the health and morale of both players
16+
}
17+
</script>
18+
19+
<template>
20+
<div class="MatchBoard">
21+
<Board>
22+
<PlayerCard v-for="card in cardTimeline.time.opponent" :key="card.card.id" :card="card"
23+
:opponentLogs="cardTimeline.space.player" :playerLogs="cardTimeline.space.opponent" :time="time"
24+
:timeline="timeline" />
25+
</Board>
26+
<TimeControls :timeline="timeline" :time="time" @on-restart="handleReset" />
27+
<Board>
28+
<PlayerCard v-for="card in cardTimeline.time.player" :key="card.card.id" :card="card"
29+
:opponentLogs="cardTimeline.space.opponent" :playerLogs="cardTimeline.space.player" :time="time"
30+
:timeline="timeline" />
31+
</Board>
32+
</div>
33+
</template>
34+
35+
<style>
36+
.MatchBoard {
37+
display: grid;
38+
grid-template-columns: subgrid;
39+
grid-template-rows: 1fr auto 1fr;
40+
gap: var(--space-1);
41+
grid-column: span 12;
42+
}
43+
</style>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<script setup lang="ts">
2+
import PartyBoard from './PartyBoard.vue'
3+
import type { Character } from '~~/types'
4+
import type { User } from '../../types'
5+
import type { Card } from '../../types/card'
6+
import type { SpaceOutput } from '../../utils/spaceTimeSimulation'
7+
import BashLogs from '~/components/BashLog/BashLogs.vue'
8+
9+
defineProps<{
10+
bot: User;
11+
user: User;
12+
health: number
13+
shield: number
14+
logs: Pick<SpaceOutput, "healthLog" | "shieldLog">
15+
}>()
16+
17+
function getInfoDeck(deck: Card[]) {
18+
return deck.map(d => d.info)
19+
}
20+
</script>
21+
22+
<template>
23+
<PartyBoard>
24+
<div class="location border">
25+
<!-- <img :src="skeletonKing.field?.image?.default" alt="Location" /> -->
26+
</div>
27+
<PlayerCharacter :characters="bot.characters" :health="health" :shield="shield" :reverse="false" />
28+
<BashLogs :logs="logs" :playerInfoDeck="getInfoDeck(user.deck)" :opponentInfoDeck="getInfoDeck(bot.deck)"
29+
:modal-button="true" />
30+
</PartyBoard>
31+
</template>
32+
33+
<style></style>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template>
2+
<section class="PartyBoard">
3+
<slot></slot>
4+
</section>
5+
</template>
6+
7+
<style>
8+
section.PartyBoard {
9+
display: grid;
10+
grid-template-columns: subgrid;
11+
grid-column: span 12;
12+
gap: var(--space-1);
13+
}
14+
15+
section.PartyBoard>* {
16+
grid-column: span 4;
17+
}
18+
</style>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script setup lang="ts">
2+
import PartyBoard from './PartyBoard.vue'
3+
import type { Character } from '~~/types'
4+
5+
defineProps<{
6+
userCharacters: Character[]
7+
health: number
8+
shield: number
9+
}>()
10+
</script>
11+
12+
<template>
13+
<PartyBoard>
14+
<div class="location border">
15+
<!-- <img src="/treasure.jpg" alt="Location" /> -->
16+
</div>
17+
<PlayerCharacter :characters="userCharacters" :health="health" :shield="shield" :reverse="false" />
18+
<div class="location border">
19+
<div class="money">
20+
<Icon name="carbon:money" size="1.5em" />
21+
<p>9</p>
22+
<p>(+3)</p>
23+
</div>
24+
</div>
25+
</PartyBoard>
26+
</template>
27+
28+
<style>
29+
section.PartyBoard .location {
30+
position: relative;
31+
height: 100%;
32+
padding: var(--space-1);
33+
}
34+
35+
section.PartyBoard img {
36+
position: absolute;
37+
width: 100%;
38+
height: 100%;
39+
object-fit: cover;
40+
border-radius: var(--radius);
41+
}
42+
43+
section.PartyBoard .location .money {
44+
display: flex;
45+
align-items: center;
46+
gap: var(--space-1);
47+
background-color: var(--base-20);
48+
color: var(--base-120);
49+
border-radius: var(--radius);
50+
padding: var(--space-1);
51+
}
52+
</style>
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<script setup lang="ts">
2+
import { user, bot } from '../data/character'
3+
import { gsap } from 'gsap'
4+
import { spaceTimeSimulation } from '../../utils/spaceTimeSimulation'
5+
import { useSpace } from '~/composables/useSpace'
6+
7+
const time = ref(0)
8+
9+
const timeline = gsap.timeline({
10+
paused: true,
11+
onUpdate: () => {
12+
time.value = timeline.time()
13+
},
14+
})
15+
16+
const cardTimeline = spaceTimeSimulation({
17+
player: user,
18+
opponent: bot,
19+
matchDuration: 30
20+
})
21+
22+
const us = useSpace(timeline, cardTimeline.space.player, user.characters)
23+
24+
interface EventCard {
25+
id: string;
26+
image: string;
27+
name: string;
28+
description: string;
29+
effects: {
30+
image: string;
31+
description: string;
32+
}[];
33+
}
34+
35+
const events = [
36+
{
37+
id: 'village',
38+
image: '/village.jpg',
39+
name: 'Village',
40+
description: 'A peaceful village where you can rest and gather supplies.',
41+
effects: [
42+
{
43+
id: 'swamp-effect',
44+
image: '/village.jpg',
45+
description: 'Opens a store'
46+
}
47+
],
48+
}, {
49+
id: 'burial',
50+
image: '/burial.jpg',
51+
name: 'Burial',
52+
description: 'A solemn burial ground where you can pay your respects.',
53+
effects: [
54+
{
55+
id: 'swamp-effect',
56+
image: '/burial.jpg',
57+
description: 'Opens a store'
58+
}
59+
],
60+
}, {
61+
id: 'swamp',
62+
image: '/swamp.jpg',
63+
name: 'Swamp',
64+
description: 'A murky swamp filled with dangers and hidden treasures.',
65+
effects: [
66+
{
67+
id: 'swamp-effect',
68+
image: '/swamp.jpg',
69+
description: 'A free item'
70+
}
71+
],
72+
}
73+
]
74+
75+
</script>
76+
77+
<template>
78+
<main class="quest-wrapper">
79+
<div class="quest-events">
80+
81+
<div v-for="event in events" :key="event.id" class="event">
82+
<img :src="event.image" alt="Location" />
83+
<div class="prose">
84+
<h3>{{ event.name }}</h3>
85+
<p>{{ event.description }}</p>
86+
</div>
87+
<div v-for="effect in event.effects" :key="effect.id" class="eventEffects">
88+
<div class="effect base-accent">
89+
<img :src="effect.image" alt="Location" />
90+
<p>{{ effect.description }}</p>
91+
</div>
92+
</div>
93+
</div>
94+
95+
</div>
96+
97+
<PlayerHeader :userCharacters="user.characters" :health="us.health.value" :shield="us.shield.value" />
98+
</main>
99+
</template>
100+
101+
<style>
102+
main.quest-wrapper {
103+
--side-size: 17vh;
104+
105+
display: grid;
106+
grid-template-columns: repeat(12, 1fr);
107+
grid-template-rows: 1fr var(--side-size);
108+
gap: var(--space-1);
109+
110+
height: 100vh;
111+
112+
padding: var(--space-1);
113+
}
114+
115+
.quest-events {
116+
display: flex;
117+
justify-content: center;
118+
align-items: center;
119+
gap: var(--space-3);
120+
grid-column: 1 / -1;
121+
}
122+
123+
.quest-events .event {
124+
display: flex;
125+
flex-direction: column;
126+
gap: var(--space-1);
127+
128+
width: 220px;
129+
aspect-ratio: 1 / 1;
130+
padding: var(--space-1);
131+
background: var(--base-20);
132+
border-radius: var(--radius);
133+
}
134+
135+
.quest-events .event img {
136+
width: 100%;
137+
height: 100%;
138+
object-fit: cover;
139+
border-radius: var(--radius);
140+
}
141+
142+
.quest-events .event .eventEffects {
143+
display: flex;
144+
gap: var(--space-1);
145+
}
146+
147+
.quest-events .event .eventEffects .effect {
148+
display: flex;
149+
align-items: center;
150+
gap: var(--space-1);
151+
152+
background: var(--base-10);
153+
color: var(--base-100);
154+
155+
padding: var(--space-1);
156+
border-radius: var(--radius);
157+
width: 100%;
158+
}
159+
160+
.quest-events .event .eventEffects .effect img {
161+
--size: 30px;
162+
height: var(--size);
163+
width: var(--size);
164+
165+
object-fit: cover;
166+
border-radius: var(--radius);
167+
}
168+
169+
.quest-events .event .prose {
170+
display: flex;
171+
flex-direction: column;
172+
gap: var(--space-1);
173+
}
174+
</style>

apps/carbon/app/pages/quest.vue

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script setup lang="ts">
2+
import { user, bot } from '../data/character'
3+
import { gsap } from 'gsap'
4+
import { spaceTimeSimulation } from '../../utils/spaceTimeSimulation'
5+
import { useSpace } from '~/composables/useSpace'
6+
import QuestBoard from '~/components/QuestBoard.vue'
7+
8+
const time = ref(0)
9+
10+
const timeline = gsap.timeline({
11+
paused: true,
12+
onUpdate: () => {
13+
time.value = timeline.time()
14+
},
15+
})
16+
17+
const cardTimeline = spaceTimeSimulation({
18+
player: user,
19+
opponent: bot,
20+
matchDuration: 30
21+
})
22+
23+
const us = useSpace(timeline, cardTimeline.space.player, user.characters)
24+
</script>
25+
26+
<template>
27+
<QuestBoard :cardTimeline="cardTimeline" :timeline="timeline" :time="time" />
28+
</template>

0 commit comments

Comments
 (0)