feat(frontend): バブルゲームを追加 (MisskeyIO#336)

This commit is contained in:
まっちゃとーにゅ 2024-01-07 15:19:06 +09:00 committed by GitHub
commit 7680129c92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 1075 additions and 4 deletions

1
locales/index.d.ts vendored
View File

@ -1190,6 +1190,7 @@ export interface Locale {
"decorate": string; "decorate": string;
"addMfmFunction": string; "addMfmFunction": string;
"enableQuickAddMfmFunction": string; "enableQuickAddMfmFunction": string;
"bubbleGame": string;
"abuseReportCategory": string; "abuseReportCategory": string;
"selectCategory": string; "selectCategory": string;
"reportComplete": string; "reportComplete": string;

View File

@ -1187,6 +1187,7 @@ seasonalScreenEffect: "季節に応じた画面の演出"
decorate: "デコる" decorate: "デコる"
addMfmFunction: "装飾を追加" addMfmFunction: "装飾を追加"
enableQuickAddMfmFunction: "高度なMFMのピッカーを表示する" enableQuickAddMfmFunction: "高度なMFMのピッカーを表示する"
bubbleGame: "バブルゲーム"
abuseReportCategory: "通報の種類" abuseReportCategory: "通報の種類"
selectCategory: "カテゴリを選択" selectCategory: "カテゴリを選択"
reportComplete: "通報完了" reportComplete: "通報完了"

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.root" :style="{ zIndex, top: `${y - 64}px`, left: `${x - 64}px` }"> <div :class="$style.root" :style="{ zIndex, top: `${y - 64}px`, left: `${x - 64}px` }">
<span class="text" :class="{ up }">+1</span> <span class="text" :class="{ up }">+{{ value }}</span>
</div> </div>
</template> </template>
@ -16,7 +16,9 @@ import * as os from '@/os.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
x: number; x: number;
y: number; y: number;
value?: number;
}>(), { }>(), {
value: 1,
}); });
const emit = defineEmits<{ const emit = defineEmits<{

File diff suppressed because it is too large Load Diff

View File

@ -531,6 +531,10 @@ export const routes = [{
path: '/clicker', path: '/clicker',
component: page(() => import('./pages/clicker.vue')), component: page(() => import('./pages/clicker.vue')),
loginRequired: true, loginRequired: true,
}, {
path: '/bubble-game',
component: page(() => import('./pages/drop-and-fusion.vue')),
loginRequired: true,
}, { }, {
path: '/timeline', path: '/timeline',
component: page(() => import('./pages/timeline.vue')), component: page(() => import('./pages/timeline.vue')),

View File

@ -154,7 +154,13 @@ export type OperationType = typeof operationTypes[number];
* @param soundStore * @param soundStore
* @param options `useCache`: `true` * @param options `useCache`: `true`
*/ */
export async function loadAudio(soundStore: SoundStore, options?: { useCache?: boolean; }) { export async function loadAudio(soundStore: {
type: Exclude<SoundType, '_driveFile_'>;
} | {
type: '_driveFile_';
fileId: string;
fileUrl: string;
}, options?: { useCache?: boolean; }) {
if (_DEV_) console.log('loading audio. opts:', options); if (_DEV_) console.log('loading audio. opts:', options);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (soundStore.type === null || (soundStore.type === '_driveFile_' && (!$i?.policies.canUseDriveFileInSoundSettings || !soundStore.fileUrl))) { if (soundStore.type === null || (soundStore.type === '_driveFile_' && (!$i?.policies.canUseDriveFileInSoundSettings || !soundStore.fileUrl))) {
@ -241,18 +247,31 @@ export async function playFile(soundStore: SoundStore) {
createSourceNode(buffer, soundStore.volume)?.start(); createSourceNode(buffer, soundStore.volume)?.start();
} }
export function createSourceNode(buffer: AudioBuffer, volume: number) : AudioBufferSourceNode | null { export async function playRaw(type: Exclude<SoundType, '_driveFile_'>, volume = 1, pan = 0, playbackRate = 1) {
const buffer = await loadAudio({ type });
if (!buffer) return;
createSourceNode(buffer, volume, pan, playbackRate)?.start();
}
export function createSourceNode(buffer: AudioBuffer, volume: number, pan = 0, playbackRate = 1) : AudioBufferSourceNode | null {
const masterVolume = defaultStore.state.sound_masterVolume; const masterVolume = defaultStore.state.sound_masterVolume;
if (isMute() || masterVolume === 0 || volume === 0) { if (isMute() || masterVolume === 0 || volume === 0) {
return null; return null;
} }
const panNode = ctx.createStereoPanner();
panNode.pan.value = pan;
const gainNode = ctx.createGain(); const gainNode = ctx.createGain();
gainNode.gain.value = masterVolume * volume; gainNode.gain.value = masterVolume * volume;
const soundSource = ctx.createBufferSource(); const soundSource = ctx.createBufferSource();
soundSource.buffer = buffer; soundSource.buffer = buffer;
soundSource.connect(gainNode).connect(ctx.destination); soundSource.playbackRate.value = playbackRate;
soundSource
.connect(panNode)
.connect(gainNode)
.connect(ctx.destination);
return soundSource; return soundSource;
} }

View File

@ -27,6 +27,11 @@ function toolsMenuItems(): MenuItem[] {
to: '/clicker', to: '/clicker',
text: '🍪👈', text: '🍪👈',
icon: 'ti ti-cookie', icon: 'ti ti-cookie',
}, {
type: 'link',
to: '/bubble-game',
text: i18n.ts.bubbleGame,
icon: 'ti ti-apple',
}, ($i && ($i.isAdmin || $i.policies.canManageCustomEmojis)) ? { }, ($i && ($i.isAdmin || $i.policies.canManageCustomEmojis)) ? {
type: 'link', type: 'link',
to: '/custom-emojis-manager', to: '/custom-emojis-manager',