summaryrefslogtreecommitdiff
path: root/packages/frontend
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2024-01-13 14:57:06 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2024-01-13 14:57:06 +0900
commitd246f6c3607714f58a12517c92940810deea1db4 (patch)
treeaab9f9e2a88112e39b6c0936d9a117eaa90dd09c /packages/frontend
parentclean up (diff)
downloadmisskey-d246f6c3607714f58a12517c92940810deea1db4.tar.gz
misskey-d246f6c3607714f58a12517c92940810deea1db4.tar.bz2
misskey-d246f6c3607714f58a12517c92940810deea1db4.zip
enhance(drop-and-fusion): some tweaks
Diffstat (limited to 'packages/frontend')
-rw-r--r--packages/frontend/assets/drop-and-fusion/go.pngbin0 -> 31115 bytes
-rw-r--r--packages/frontend/assets/drop-and-fusion/ready.pngbin0 -> 34674 bytes
-rw-r--r--packages/frontend/src/pages/drop-and-fusion.game.vue277
-rw-r--r--packages/frontend/src/pages/drop-and-fusion.vue28
4 files changed, 185 insertions, 120 deletions
diff --git a/packages/frontend/assets/drop-and-fusion/go.png b/packages/frontend/assets/drop-and-fusion/go.png
new file mode 100644
index 0000000000..37468f1395
--- /dev/null
+++ b/packages/frontend/assets/drop-and-fusion/go.png
Binary files differ
diff --git a/packages/frontend/assets/drop-and-fusion/ready.png b/packages/frontend/assets/drop-and-fusion/ready.png
new file mode 100644
index 0000000000..10a87fcf58
--- /dev/null
+++ b/packages/frontend/assets/drop-and-fusion/ready.png
Binary files differ
diff --git a/packages/frontend/src/pages/drop-and-fusion.game.vue b/packages/frontend/src/pages/drop-and-fusion.game.vue
index f0fdc4d491..c42c2fc971 100644
--- a/packages/frontend/src/pages/drop-and-fusion.game.vue
+++ b/packages/frontend/src/pages/drop-and-fusion.game.vue
@@ -4,135 +4,163 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div :class="$style.root">
- <div v-if="!gameLoaded" :class="$style.loadingScreen">
- Loading...
- </div>
- <!-- ↓に対してTransitionコンポーネントを使うと何故かkeyを指定していてもキャッシュが効かず様々なコンポーネントが都度再評価されてパフォーマンスが低下する -->
- <div v-show="gameLoaded" class="_gaps_s">
- <div :class="$style.header">
- <div :class="[$style.frame, $style.headerTitle]">
- <div :class="$style.frameInner">
- <b>BUBBLE GAME</b>
- <div>- {{ gameMode }} -</div>
- </div>
- </div>
- <div :class="[$style.frame, $style.frameH]">
- <div :class="$style.frameInner">
- <MkButton inline small @click="hold">HOLD</MkButton>
- <img v-if="holdingStock" :src="getTextureImageUrl(holdingStock.mono)" style="width: 32px; margin-left: 8px; vertical-align: bottom;"/>
- </div>
- <div :class="[$style.frameInner, $style.stock]" style="text-align: center;">
- <TransitionGroup
- :enterActiveClass="$style.transition_stock_enterActive"
- :leaveActiveClass="$style.transition_stock_leaveActive"
- :enterFromClass="$style.transition_stock_enterFrom"
- :leaveToClass="$style.transition_stock_leaveTo"
- :moveClass="$style.transition_stock_move"
- >
- <img v-for="x in stock" :key="x.id" :src="getTextureImageUrl(x.mono)" style="width: 32px; vertical-align: bottom;"/>
- </TransitionGroup>
- </div>
+<MkSpacer :contentMax="800">
+ <div :class="$style.root">
+ <div v-if="!gameLoaded" :class="$style.loadingScreen">
+ <div>
+ Loading...
</div>
</div>
- <div ref="containerEl" :class="[$style.gameContainer, { [$style.gameOver]: isGameOver && !replaying }]" @contextmenu.stop.prevent @click.stop.prevent="onClick" @touchmove.stop.prevent="onTouchmove" @touchend="onTouchend" @mousemove="onMousemove">
- <img v-if="defaultStore.state.darkMode" src="/client-assets/drop-and-fusion/frame-dark.svg" :class="$style.mainFrameImg"/>
- <img v-else src="/client-assets/drop-and-fusion/frame-light.svg" :class="$style.mainFrameImg"/>
- <canvas ref="canvasEl" :class="$style.canvas"/>
+ <!-- ↓に対してTransitionコンポーネントを使うと何故かkeyを指定していてもキャッシュが効かず様々なコンポーネントが都度再評価されてパフォーマンスが低下する -->
+ <div v-show="gameLoaded" class="_gaps_s">
+ <div v-if="readyGo === 'ready'" :class="$style.readyGo_bg">
+ </div>
<Transition
- :enterActiveClass="$style.transition_combo_enterActive"
- :leaveActiveClass="$style.transition_combo_leaveActive"
- :enterFromClass="$style.transition_combo_enterFrom"
- :leaveToClass="$style.transition_combo_leaveTo"
- :moveClass="$style.transition_combo_move"
+ :enterActiveClass="$style.transition_zoom_enterActive"
+ :leaveActiveClass="$style.transition_zoom_leaveActive"
+ :enterFromClass="$style.transition_zoom_enterFrom"
+ :leaveToClass="$style.transition_zoom_leaveTo"
+ :moveClass="$style.transition_zoom_move"
+ mode="default"
>
- <div v-show="combo > 1" :class="$style.combo" :style="{ fontSize: `${100 + ((comboPrev - 2) * 15)}%` }">{{ comboPrev }} Chain!</div>
+ <div v-if="readyGo === 'ready'" :class="$style.readyGo_ready">
+ <img src="/client-assets/drop-and-fusion/ready.png" :class="$style.readyGo_img"/>
+ </div>
+ <div v-else-if="readyGo === 'go'" :class="$style.readyGo_go">
+ <img src="/client-assets/drop-and-fusion/go.png" :class="$style.readyGo_img"/>
+ </div>
</Transition>
- <div v-if="!isGameOver && !replaying" :class="$style.dropperContainer" :style="{ left: dropperX + 'px' }">
- <!--<img v-if="currentPick" src="/client-assets/drop-and-fusion/dropper.png" :class="$style.dropper" :style="{ left: dropperX + 'px' }"/>-->
+
+ <div :class="$style.header">
+ <div :class="[$style.frame, $style.headerTitle]">
+ <div :class="$style.frameInner">
+ <b>BUBBLE GAME</b>
+ <div>- {{ gameMode }} -</div>
+ </div>
+ </div>
+ <div :class="[$style.frame, $style.frameH]">
+ <div :class="$style.frameInner">
+ <MkButton inline small @click="hold">HOLD</MkButton>
+ <img v-if="holdingStock" :src="getTextureImageUrl(holdingStock.mono)" style="width: 32px; margin-left: 8px; vertical-align: bottom;"/>
+ </div>
+ <div :class="[$style.frameInner, $style.stock]" style="text-align: center;">
+ <TransitionGroup
+ :enterActiveClass="$style.transition_stock_enterActive"
+ :leaveActiveClass="$style.transition_stock_leaveActive"
+ :enterFromClass="$style.transition_stock_enterFrom"
+ :leaveToClass="$style.transition_stock_leaveTo"
+ :moveClass="$style.transition_stock_move"
+ >
+ <img v-for="x in stock" :key="x.id" :src="getTextureImageUrl(x.mono)" style="width: 32px; vertical-align: bottom;"/>
+ </TransitionGroup>
+ </div>
+ </div>
+ </div>
+
+ <div ref="containerEl" :class="[$style.gameContainer, { [$style.gameOver]: isGameOver && !replaying }]" @contextmenu.stop.prevent @click.stop.prevent="onClick" @touchmove.stop.prevent="onTouchmove" @touchend="onTouchend" @mousemove="onMousemove">
+ <img v-if="defaultStore.state.darkMode" src="/client-assets/drop-and-fusion/frame-dark.svg" :class="$style.mainFrameImg"/>
+ <img v-else src="/client-assets/drop-and-fusion/frame-light.svg" :class="$style.mainFrameImg"/>
+ <canvas ref="canvasEl" :class="$style.canvas"/>
<Transition
- :enterActiveClass="$style.transition_picked_enterActive"
- :leaveActiveClass="$style.transition_picked_leaveActive"
- :enterFromClass="$style.transition_picked_enterFrom"
- :leaveToClass="$style.transition_picked_leaveTo"
- :moveClass="$style.transition_picked_move"
- mode="out-in"
+ :enterActiveClass="$style.transition_combo_enterActive"
+ :leaveActiveClass="$style.transition_combo_leaveActive"
+ :enterFromClass="$style.transition_combo_enterFrom"
+ :leaveToClass="$style.transition_combo_leaveTo"
+ :moveClass="$style.transition_combo_move"
>
- <img v-if="currentPick" :key="currentPick.id" :src="getTextureImageUrl(currentPick.mono)" :class="$style.currentMono" :style="{ marginBottom: -((currentPick?.mono.sizeY * viewScale) / 2) + 'px', left: -((currentPick?.mono.sizeX * viewScale) / 2) + 'px', width: `${currentPick?.mono.sizeX * viewScale}px` }"/>
+ <div v-show="combo > 1" :class="$style.combo" :style="{ fontSize: `${100 + ((comboPrev - 2) * 15)}%` }">{{ comboPrev }} Chain!</div>
</Transition>
- <template v-if="dropReady && currentPick">
- <img src="/client-assets/drop-and-fusion/drop-arrow.svg" :class="$style.currentMonoArrow"/>
- <div :class="$style.dropGuide"/>
- </template>
- </div>
- <div v-if="isGameOver && !replaying" :class="$style.gameOverLabel">
- <div class="_gaps_s">
- <img src="/client-assets/drop-and-fusion/gameover.png" style="width: 200px; max-width: 100%; display: block; margin: auto; margin-bottom: -5px;"/>
- <div>SCORE: <MkNumber :value="score"/>{{ gameMode === 'yen' ? '円' : 'pt' }}</div>
- <div>MAX CHAIN: <MkNumber :value="maxCombo"/></div>
- <div v-if="gameMode === 'yen'">TOTAL EARNINGS: <b><MkNumber :value="yenTotal ?? score"/>円</b></div>
+ <div v-if="!isGameOver && !replaying" :class="$style.dropperContainer" :style="{ left: dropperX + 'px' }">
+ <!--<img v-if="currentPick" src="/client-assets/drop-and-fusion/dropper.png" :class="$style.dropper" :style="{ left: dropperX + 'px' }"/>-->
+ <Transition
+ :enterActiveClass="$style.transition_picked_enterActive"
+ :leaveActiveClass="$style.transition_picked_leaveActive"
+ :enterFromClass="$style.transition_picked_enterFrom"
+ :leaveToClass="$style.transition_picked_leaveTo"
+ :moveClass="$style.transition_picked_move"
+ mode="out-in"
+ >
+ <img v-if="currentPick" :key="currentPick.id" :src="getTextureImageUrl(currentPick.mono)" :class="$style.currentMono" :style="{ marginBottom: -((currentPick?.mono.sizeY * viewScale) / 2) + 'px', left: -((currentPick?.mono.sizeX * viewScale) / 2) + 'px', width: `${currentPick?.mono.sizeX * viewScale}px` }"/>
+ </Transition>
+ <template v-if="dropReady && currentPick">
+ <img src="/client-assets/drop-and-fusion/drop-arrow.svg" :class="$style.currentMonoArrow"/>
+ <div :class="$style.dropGuide"/>
+ </template>
</div>
- </div>
- <div v-if="replaying" :class="$style.replayIndicator"><span :class="$style.replayIndicatorText"><i class="ti ti-player-play"></i> {{ i18n.ts.replaying }}</span></div>
- </div>
- <div v-if="replaying" :class="$style.frame">
- <div :class="$style.frameInner">
- <div style="background: #0004;">
- <div style="height: 10px; background: var(--accent); will-change: width;" :style="{ width: `${(currentFrame / endedAtFrame) * 100}%` }"></div>
+ <div v-if="isGameOver && !replaying" :class="$style.gameOverLabel">
+ <div class="_gaps_s">
+ <img src="/client-assets/drop-and-fusion/gameover.png" style="width: 200px; max-width: 100%; display: block; margin: auto; margin-bottom: -5px;"/>
+ <div>SCORE: <MkNumber :value="score"/>{{ gameMode === 'yen' ? '円' : 'pt' }}</div>
+ <div>MAX CHAIN: <MkNumber :value="maxCombo"/></div>
+ <div v-if="gameMode === 'yen'">TOTAL EARNINGS: <b><MkNumber :value="yenTotal ?? score"/>円</b></div>
+ </div>
</div>
+ <div v-if="replaying" :class="$style.replayIndicator"><span :class="$style.replayIndicatorText"><i class="ti ti-player-play"></i> {{ i18n.ts.replaying }}</span></div>
</div>
- <div :class="$style.frameInner">
- <div class="_buttonsCenter">
- <MkButton @click="endReplay"><i class="ti ti-player-stop"></i> END</MkButton>
- <MkButton :primary="replayPlaybackRate === 4" @click="replayPlaybackRate = replayPlaybackRate === 4 ? 1 : 4"><i class="ti ti-player-track-next"></i> x4</MkButton>
- <MkButton :primary="replayPlaybackRate === 16" @click="replayPlaybackRate = replayPlaybackRate === 16 ? 1 : 16"><i class="ti ti-player-track-next"></i> x16</MkButton>
+
+ <div v-if="replaying" :class="$style.frame">
+ <div :class="$style.frameInner">
+ <div style="background: #0004;">
+ <div style="height: 10px; background: var(--accent); will-change: width;" :style="{ width: `${(currentFrame / endedAtFrame) * 100}%` }"></div>
+ </div>
</div>
- </div>
- </div>
- <div v-if="isGameOver" :class="$style.frame">
- <div :class="$style.frameInner">
- <div class="_buttonsCenter">
- <MkButton primary rounded @click="backToTitle">{{ i18n.ts.backToTitle }}</MkButton>
- <MkButton primary rounded @click="replay">{{ i18n.ts.showReplay }}</MkButton>
- <MkButton primary rounded @click="share">{{ i18n.ts.share }}</MkButton>
- <MkButton rounded @click="exportLog">Copy replay data</MkButton>
+ <div :class="$style.frameInner">
+ <div class="_buttonsCenter">
+ <MkButton @click="endReplay"><i class="ti ti-player-stop"></i> END</MkButton>
+ <MkButton :primary="replayPlaybackRate === 4" @click="replayPlaybackRate = replayPlaybackRate === 4 ? 1 : 4"><i class="ti ti-player-track-next"></i> x4</MkButton>
+ <MkButton :primary="replayPlaybackRate === 16" @click="replayPlaybackRate = replayPlaybackRate === 16 ? 1 : 16"><i class="ti ti-player-track-next"></i> x16</MkButton>
+ </div>
</div>
</div>
- </div>
- <div style="display: flex;">
- <div :class="$style.frame" style="flex: 1; margin-right: 10px;">
+
+ <div v-if="isGameOver" :class="$style.frame">
<div :class="$style.frameInner">
- <div>SCORE: <b><MkNumber :value="score"/>{{ gameMode === 'yen' ? '円' : 'pt' }}</b></div>
- <div>HIGH SCORE: <b v-if="highScore"><MkNumber :value="highScore"/>{{ gameMode === 'yen' ? '円' : 'pt' }}</b><b v-else>-</b></div>
- <div v-if="gameMode === 'yen'">TOTAL EARNINGS: <b v-if="yenTotal"><MkNumber :value="yenTotal"/>円</b><b v-else>-</b></div>
+ <div class="_buttonsCenter">
+ <MkButton primary rounded @click="backToTitle">{{ i18n.ts.backToTitle }}</MkButton>
+ <MkButton primary rounded @click="replay">{{ i18n.ts.showReplay }}</MkButton>
+ <MkButton primary rounded @click="share">{{ i18n.ts.share }}</MkButton>
+ <MkButton rounded @click="exportLog">Copy replay data</MkButton>
+ </div>
</div>
</div>
- <div :class="[$style.frame]" style="margin-left: auto;">
- <div :class="$style.frameInner" style="text-align: center;">
- <div @click="showConfig = !showConfig"><i class="ti ti-settings"></i></div>
+
+ <div style="display: flex;">
+ <div :class="$style.frame" style="flex: 1; margin-right: 10px;">
+ <div :class="$style.frameInner">
+ <div>SCORE: <b><MkNumber :value="score"/>{{ gameMode === 'yen' ? '円' : 'pt' }}</b></div>
+ <div>HIGH SCORE: <b v-if="highScore"><MkNumber :value="highScore"/>{{ gameMode === 'yen' ? '円' : 'pt' }}</b><b v-else>-</b></div>
+ <div v-if="gameMode === 'yen'">TOTAL EARNINGS: <b v-if="yenTotal"><MkNumber :value="yenTotal"/>円</b><b v-else>-</b></div>
+ </div>
+ </div>
+ <div :class="[$style.frame]" style="margin-left: auto;">
+ <div :class="$style.frameInner" style="text-align: center;">
+ <div @click="showConfig = !showConfig"><i class="ti ti-settings"></i></div>
+ </div>
</div>
</div>
- </div>
- <div v-if="showConfig" :class="$style.frame">
- <div :class="$style.frameInner">
- <div class="_gaps">
- <MkRange v-model="bgmVolume" :min="0" :max="1" :step="0.01" :textConverter="(v) => `${Math.floor(v * 100)}%`" :continuousUpdate="true" @dragEnded="(v) => updateSettings('bgmVolume', v)">
- <template #label>BGM {{ i18n.ts.volume }}</template>
- </MkRange>
- <MkRange v-model="sfxVolume" :min="0" :max="1" :step="0.01" :textConverter="(v) => `${Math.floor(v * 100)}%`" :continuousUpdate="true" @dragEnded="(v) => updateSettings('sfxVolume', v)">
- <template #label>{{ i18n.ts.sfx }} {{ i18n.ts.volume }}</template>
- </MkRange>
+
+ <div v-if="showConfig" :class="$style.frame">
+ <div :class="$style.frameInner">
+ <div class="_gaps">
+ <MkRange v-model="bgmVolume" :min="0" :max="1" :step="0.01" :textConverter="(v) => `${Math.floor(v * 100)}%`" :continuousUpdate="true" @dragEnded="(v) => updateSettings('bgmVolume', v)">
+ <template #label>BGM {{ i18n.ts.volume }}</template>
+ </MkRange>
+ <MkRange v-model="sfxVolume" :min="0" :max="1" :step="0.01" :textConverter="(v) => `${Math.floor(v * 100)}%`" :continuousUpdate="true" @dragEnded="(v) => updateSettings('sfxVolume', v)">
+ <template #label>{{ i18n.ts.sfx }} {{ i18n.ts.volume }}</template>
+ </MkRange>
+ </div>
</div>
</div>
- </div>
- <div :class="$style.frame">
- <div :class="$style.frameInner">
- <MkButton v-if="!isGameOver && !replaying" full danger @click="surrender">Surrender</MkButton>
- <MkButton v-else full @click="restart">Retry</MkButton>
+
+ <div :class="$style.frame">
+ <div :class="$style.frameInner">
+ <MkButton v-if="!isGameOver && !replaying" full danger @click="surrender">Surrender</MkButton>
+ <MkButton v-else full @click="restart">Retry</MkButton>
+ </div>
</div>
</div>
</div>
-</div>
+</MkSpacer>
</template>
<script lang="ts" setup>
@@ -439,6 +467,7 @@ const maxCombo = ref(0);
const dropReady = ref(true);
const isGameOver = ref(false);
const gameLoaded = ref(false);
+const readyGo = ref<'ready' | 'go' | null>('ready');
const highScore = ref<number | null>(null);
const yenTotal = ref<number | null>(null);
const showConfig = ref(false);
@@ -579,6 +608,13 @@ async function start() {
window.requestAnimationFrame(tick);
gameLoaded.value = true;
+
+ window.setTimeout(() => {
+ readyGo.value = 'go';
+ window.setTimeout(() => {
+ readyGo.value = null;
+ }, 1000);
+ }, 1500);
}
function onClick(ev: MouseEvent) {
@@ -650,6 +686,7 @@ function reset() {
comboPrev.value = 0;
maxCombo.value = 0;
gameLoaded.value = false;
+ readyGo.value = false;
}
function dispose() {
@@ -1128,6 +1165,36 @@ definePageMetadata({
padding: 32px;
}
+.readyGo_bg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 100;
+ backdrop-filter: blur(4px);
+}
+
+.readyGo_ready,
+.readyGo_go {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 101;
+ pointer-events: none;
+}
+
+.readyGo_img {
+ display: block;
+ width: 250px;
+ max-width: 100%;
+}
+
.frame {
padding: 7px;
background: #8C4F26;
diff --git a/packages/frontend/src/pages/drop-and-fusion.vue b/packages/frontend/src/pages/drop-and-fusion.vue
index 80c466a2b1..0e8713ad63 100644
--- a/packages/frontend/src/pages/drop-and-fusion.vue
+++ b/packages/frontend/src/pages/drop-and-fusion.vue
@@ -4,16 +4,16 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<MkSpacer :contentMax="800">
- <Transition
- :enterActiveClass="$style.transition_zoom_enterActive"
- :leaveActiveClass="$style.transition_zoom_leaveActive"
- :enterFromClass="$style.transition_zoom_enterFrom"
- :leaveToClass="$style.transition_zoom_leaveTo"
- :moveClass="$style.transition_zoom_move"
- mode="out-in"
- >
- <div v-if="!gameStarted" :class="$style.root">
+<Transition
+ :enterActiveClass="$style.transition_zoom_enterActive"
+ :leaveActiveClass="$style.transition_zoom_leaveActive"
+ :enterFromClass="$style.transition_zoom_enterFrom"
+ :leaveToClass="$style.transition_zoom_leaveTo"
+ :moveClass="$style.transition_zoom_move"
+ mode="out-in"
+>
+ <MkSpacer v-if="!gameStarted" :contentMax="800">
+ <div :class="$style.root">
<div class="_gaps">
<div :class="$style.frame" style="text-align: center;">
<div :class="$style.frameInner">
@@ -78,11 +78,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
- <div v-else>
- <XGame :gameMode="gameMode" :mute="mute" @end="onGameEnd"/>
- </div>
- </Transition>
-</MkSpacer>
+ </MkSpacer>
+ <XGame v-else :gameMode="gameMode" :mute="mute" @end="onGameEnd"/>
+</Transition>
</template>
<script lang="ts" setup>