feat: 开始界面

This commit is contained in:
unanmed 2024-02-04 19:28:09 +08:00
parent 1d7d177cae
commit 646f9e3ab0
10 changed files with 169 additions and 360 deletions

View File

@ -3400,13 +3400,10 @@ control.prototype.checkBgm = function () {
}; };
///// 设置屏幕放缩 ////// ///// 设置屏幕放缩 //////
control.prototype.setDisplayScale = function (delta) { control.prototype.setDisplayScale = function (i) {
var index = core.domStyle.availableScale.indexOf(core.domStyle.scale); const scale = core.domStyle.availableScale[i];
if (index < 0) return; if (!scale) return;
index = core.domStyle.scale = scale;
(index + delta + core.domStyle.availableScale.length) %
core.domStyle.availableScale.length;
core.domStyle.scale = core.domStyle.availableScale[index];
core.setLocalStorage('scale', core.domStyle.scale); core.setLocalStorage('scale', core.domStyle.scale);
core.resize(); core.resize();
}; };

View File

@ -602,6 +602,7 @@ core.prototype._afterLoadResources = function (callback) {
// if (core.plugin._afterLoadResources) core.plugin._afterLoadResources(); // if (core.plugin._afterLoadResources) core.plugin._afterLoadResources();
core.showStartAnimate(); core.showStartAnimate();
Mota.require('var', 'hook').emit('load');
if (callback) callback(); if (callback) callback();
}; };

View File

@ -1,9 +1,4 @@
///<reference path="../../src/types/core.d.ts" /> ///<reference path="../../src/types/core.d.ts" />
/*
loader.js负责对资源的加载
*/
'use strict'; 'use strict';
function loader() { function loader() {
@ -32,7 +27,6 @@ loader.prototype._load = function (callback) {
loader.prototype._load_sync = function (callback) { loader.prototype._load_sync = function (callback) {
this._loadAnimates_sync(); this._loadAnimates_sync();
if (main.mode === 'play') return callback();
this._loadMusic_sync(); this._loadMusic_sync();
core.loader._loadMaterials_sync(function () { core.loader._loadMaterials_sync(function () {
core.loader._loadExtraImages_sync(function () { core.loader._loadExtraImages_sync(function () {
@ -116,7 +110,6 @@ loader.prototype._load_async = function (callback) {
// ----- 加载资源文件 ------ // // ----- 加载资源文件 ------ //
loader.prototype._loadMaterials_sync = function (callback) { loader.prototype._loadMaterials_sync = function (callback) {
if (main.mode === 'play') return callback();
this._setStartLoadTipText('正在加载资源文件...'); this._setStartLoadTipText('正在加载资源文件...');
this.loadImages( this.loadImages(
'materials', 'materials',
@ -156,7 +149,6 @@ loader.prototype._loadMaterials_afterLoad = function () {
// ------ 加载使用的图片 ------ // // ------ 加载使用的图片 ------ //
loader.prototype._loadExtraImages_sync = function (callback) { loader.prototype._loadExtraImages_sync = function (callback) {
if (main.mode === 'play') return callback();
core.material.images.images = {}; core.material.images.images = {};
this._setStartLoadTipText('正在加载图片文件...'); this._setStartLoadTipText('正在加载图片文件...');
core.loadImages( core.loadImages(
@ -199,7 +191,6 @@ loader.prototype._loadExtraImages_async = function (onprogress, onfinished) {
// ------ 加载自动元件 ------ // // ------ 加载自动元件 ------ //
loader.prototype._loadAutotiles_sync = function (callback) { loader.prototype._loadAutotiles_sync = function (callback) {
if (main.mode === 'play') return callback();
core.material.images.autotile = {}; core.material.images.autotile = {};
var keys = Object.keys(core.material.icons.autotile); var keys = Object.keys(core.material.icons.autotile);
var autotiles = {}; var autotiles = {};
@ -229,7 +220,6 @@ loader.prototype._loadAutotiles_async = function (onprogress, onfinished) {
}; };
loader.prototype._loadAutotiles_afterLoad = function (keys, autotiles) { loader.prototype._loadAutotiles_afterLoad = function (keys, autotiles) {
if (main.mode === 'play') return;
// autotile需要保证顺序 // autotile需要保证顺序
keys.forEach(function (v) { keys.forEach(function (v) {
core.material.images.autotile[v] = autotiles[v]; core.material.images.autotile[v] = autotiles[v];
@ -243,7 +233,6 @@ loader.prototype._loadAutotiles_afterLoad = function (keys, autotiles) {
// ------ 加载额外素材 ------ // // ------ 加载额外素材 ------ //
loader.prototype._loadTilesets_sync = function (callback) { loader.prototype._loadTilesets_sync = function (callback) {
if (main.mode === 'play') return callback();
core.material.images.tilesets = {}; core.material.images.tilesets = {};
this._setStartLoadTipText('正在加载额外素材...'); this._setStartLoadTipText('正在加载额外素材...');
this.loadImages( this.loadImages(
@ -251,6 +240,7 @@ loader.prototype._loadTilesets_sync = function (callback) {
core.tilesets, core.tilesets,
core.material.images.tilesets, core.material.images.tilesets,
function () { function () {
core.loader._loadTilesets_afterLoad();
callback(); callback();
} }
); );
@ -264,15 +254,28 @@ loader.prototype._loadTilesets_async = function (onprogress, onfinished) {
core.material.images.tilesets, core.material.images.tilesets,
onprogress, onprogress,
function () { function () {
core.loader._loadTilesets_afterLoad();
onfinished(); onfinished();
} }
); );
}; };
loader.prototype._loadTilesets_afterLoad = function () {
// 检查宽高是32倍数如果出错在控制台报错
for (var imgName in core.material.images.tilesets) {
var img = core.material.images.tilesets[imgName];
if (img.width % 32 != 0 || img.height % 32 != 0) {
console.warn('警告!' + imgName + '的宽或高不是32的倍数');
}
if (img.width * img.height > 32 * 32 * 3000) {
console.warn('警告!' + imgName + '上的图块素材个数大于3000');
}
}
};
// ------ 实际加载一系列图片 ------ // // ------ 实际加载一系列图片 ------ //
loader.prototype.loadImages = function (dir, names, toSave, callback) { loader.prototype.loadImages = function (dir, names, toSave, callback) {
if (main.mode === 'play') return callback();
if (!names || names.length == 0) { if (!names || names.length == 0) {
if (callback) callback(); if (callback) callback();
return; return;
@ -310,9 +313,7 @@ loader.prototype.loadImage = function (dir, imgName, callback) {
}; };
image.src = 'project/' + dir + '/' + name + '?v=' + main.version; image.src = 'project/' + dir + '/' + name + '?v=' + main.version;
if (name.endsWith('.gif')) callback(imgName, null); if (name.endsWith('.gif')) callback(imgName, null);
} catch (e) { } catch (e) {}
console.error(e);
}
}; };
// ------ 从zip中加载一系列图片 ------ // // ------ 从zip中加载一系列图片 ------ //
@ -363,14 +364,13 @@ loader.prototype.loadImagesFromZip = function (
// ------ 加载动画文件 ------ // // ------ 加载动画文件 ------ //
loader.prototype._loadAnimates_sync = function () { loader.prototype._loadAnimates_sync = function () {
if (main.mode === 'play') return;
this._setStartLoadTipText('正在加载动画文件...'); this._setStartLoadTipText('正在加载动画文件...');
if (main.supportBunch) { if (main.supportBunch) {
if (core.animates.length > 0) { if (core.animates.length > 0) {
core.http( core.http(
'GET', 'GET',
'/all/__all_animates__?v=' + '__all_animates__?v=' +
main.version + main.version +
'&id=' + '&id=' +
core.animates.join(','), core.animates.join(','),
@ -403,7 +403,6 @@ loader.prototype._loadAnimates_sync = function () {
core.material.animates[t] = core.loader._loadAnimate(content); core.material.animates[t] = core.loader._loadAnimate(content);
}, },
function (e) { function (e) {
console.error(e);
core.material.animates[t] = null; core.material.animates[t] = null;
}, },
'text/plain; charset=x-user-defined' 'text/plain; charset=x-user-defined'
@ -449,7 +448,6 @@ loader.prototype._loadAnimate = function (content) {
image.src = t2; image.src = t2;
data.images.push(image); data.images.push(image);
} catch (e) { } catch (e) {
console.error(e);
data.images.push(null); data.images.push(null);
} }
} }
@ -473,7 +471,6 @@ loader.prototype._loadAnimate = function (content) {
}); });
return data; return data;
} catch (e) { } catch (e) {
console.error(e);
return null; return null;
} }
}; };
@ -524,20 +521,19 @@ loader.prototype.loadOneMusic = function (name) {
if (main.bgmRemote) if (main.bgmRemote)
music.src = main.bgmRemoteRoot + core.firstData.name + '/' + name; music.src = main.bgmRemoteRoot + core.firstData.name + '/' + name;
else music.src = 'project/bgms/' + name; else music.src = 'project/bgms/' + name;
music.loop = 'loop'; Mota.require('var', 'bgm').add(`bgms.${name}`, music);
core.material.bgms[name] = music;
}; };
loader.prototype.loadOneSound = function (name) { loader.prototype.loadOneSound = function (name) {
const sound = Mota.require('var', 'sound');
core.http( core.http(
'GET', 'GET',
'project/sounds/' + name + '?v=' + main.version, 'project/sounds/' + name + '?v=' + main.version,
null, null,
function (data) { function (data) {
core.loader._loadOneSound_decodeData(name, data); sound.add(`sounds.${name}`, data);
}, },
function (e) { function (e) {
console.error(e);
core.material.sounds[name] = null; core.material.sounds[name] = null;
}, },
null, null,
@ -562,12 +558,10 @@ loader.prototype._loadOneSound_decodeData = function (name, data) {
core.material.sounds[name] = buffer; core.material.sounds[name] = buffer;
}, },
function (e) { function (e) {
console.error(e);
core.material.sounds[name] = null; core.material.sounds[name] = null;
} }
); );
} catch (e) { } catch (e) {
console.error(e);
core.material.sounds[name] = null; core.material.sounds[name] = null;
} }
}; };

View File

@ -411,7 +411,7 @@ main.prototype.loadAsync = async function (mode, callback) {
main.core = core; main.core = core;
// 自动放缩最大化 // 自动放缩最大化
let auto = Mota.require('var', 'mainSetting').getValue('autoSclae'); let auto = Mota.require('var', 'mainSetting').getValue('autoScale', true);
if (auto && !core.domStyle.isVertical) { if (auto && !core.domStyle.isVertical) {
try { try {

View File

@ -313,7 +313,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"splitImages": [] "splitImages": []
}, },
"firstData": { "firstData": {
"title": "人类:开天辟地", "title": "魔塔样板",
"name": "HumanBreak", "name": "HumanBreak",
"version": "Ver 2.7.3.1", "version": "Ver 2.7.3.1",
"floorId": "MT0", "floorId": "MT0",

View File

@ -1,13 +1,5 @@
import { BgmController, bgm } from './audio/bgm'; import { BgmController, bgm } from './audio/bgm';
import { SoundController, SoundEffect, sound } from './audio/sound'; import { SoundController, SoundEffect, sound } from './audio/sound';
import { readyAllResource } from './loader/load';
import {
Resource,
ResourceStore,
ZippedResource,
resource,
zipResource
} from './loader/resource';
import { Focus, GameUi, UiController } from './main/custom/ui'; import { Focus, GameUi, UiController } from './main/custom/ui';
import { GameStorage } from './main/storage'; import { GameStorage } from './main/storage';
import './main/init/'; import './main/init/';
@ -30,10 +22,6 @@ import { Hotkey } from './main/custom/hotkey';
import { Keyboard } from './main/custom/keyboard'; import { Keyboard } from './main/custom/keyboard';
import './main/layout'; import './main/layout';
function ready() {
readyAllResource();
}
// ----- 类注册 // ----- 类注册
Mota.register('class', 'AudioPlayer', AudioPlayer); Mota.register('class', 'AudioPlayer', AudioPlayer);
Mota.register('class', 'BgmController', BgmController); Mota.register('class', 'BgmController', BgmController);
@ -44,13 +32,10 @@ Mota.register('class', 'GameUi', GameUi);
Mota.register('class', 'Hotkey', Hotkey); Mota.register('class', 'Hotkey', Hotkey);
Mota.register('class', 'Keyboard', Keyboard); Mota.register('class', 'Keyboard', Keyboard);
Mota.register('class', 'MotaSetting', MotaSetting); Mota.register('class', 'MotaSetting', MotaSetting);
Mota.register('class', 'Resource', Resource);
Mota.register('class', 'ResourceStore', ResourceStore);
Mota.register('class', 'SettingDisplayer', SettingDisplayer); Mota.register('class', 'SettingDisplayer', SettingDisplayer);
Mota.register('class', 'SoundController', SoundController); Mota.register('class', 'SoundController', SoundController);
Mota.register('class', 'SoundEffect', SoundEffect); Mota.register('class', 'SoundEffect', SoundEffect);
Mota.register('class', 'UiController', UiController); Mota.register('class', 'UiController', UiController);
Mota.register('class', 'ZippedResource', ZippedResource);
// ----- 函数注册 // ----- 函数注册
// ----- 变量注册 // ----- 变量注册
@ -61,11 +46,7 @@ Mota.register('var', 'sound', sound);
Mota.register('var', 'gameKey', gameKey); Mota.register('var', 'gameKey', gameKey);
Mota.register('var', 'mainSetting', mainSetting); Mota.register('var', 'mainSetting', mainSetting);
Mota.register('var', 'KeyCode', KeyCode); Mota.register('var', 'KeyCode', KeyCode);
Mota.register('var', 'resource', resource);
Mota.register('var', 'zipResource', zipResource);
Mota.register('var', 'settingStorage', settingStorage); Mota.register('var', 'settingStorage', settingStorage);
Mota.register('var', 'status', status); Mota.register('var', 'status', status);
// ----- 模块注册 // ----- 模块注册
ready();

View File

@ -35,6 +35,9 @@ fixedUi.register(
); );
fixedUi.showAll(); fixedUi.showAll();
let loaded = false;
let mounted = false;
const hook = Mota.require('var', 'hook'); const hook = Mota.require('var', 'hook');
hook.once('mounted', () => { hook.once('mounted', () => {
const ui = document.getElementById('ui-main')!; const ui = document.getElementById('ui-main')!;
@ -57,6 +60,15 @@ hook.once('mounted', () => {
fixed.style.display = 'none'; fixed.style.display = 'none';
}); });
// todo: 暂时先这么搞,之后重写加载界面,需要改成先显示加载界面,加载完毕后再打开这个界面 if (loaded && !mounted) {
fixedUi.open('start'); fixedUi.open('start');
}
mounted = true;
});
hook.once('load', () => {
if (mounted) {
// todo: 暂时先这么搞,之后重写加载界面,需要改成先显示加载界面,加载完毕后再打开这个界面
fixedUi.open('start');
}
loaded = true;
}); });

View File

@ -7,22 +7,12 @@ import type {
IndexedEventEmitter IndexedEventEmitter
} from '@/core/common/eventEmitter'; } from '@/core/common/eventEmitter';
import type { loading } from './game'; import type { loading } from './game';
import type {
Resource,
ResourceStore,
ResourceType,
ZippedResource
} from '@/core/loader/resource';
import type { Hotkey } from '@/core/main/custom/hotkey'; import type { Hotkey } from '@/core/main/custom/hotkey';
import type { Keyboard } from '@/core/main/custom/keyboard'; import type { Keyboard } from '@/core/main/custom/keyboard';
import type { CustomToolbar } from '@/core/main/custom/toolbar'; import type { CustomToolbar } from '@/core/main/custom/toolbar';
import type { Focus, GameUi, UiController } from '@/core/main/custom/ui'; import type { Focus, GameUi, UiController } from '@/core/main/custom/ui';
import type { gameListener, hook } from './game'; import type { gameListener, hook } from './game';
import type { import type { MotaSetting, SettingDisplayer } from '@/core/main/setting';
MotaSetting,
SettingDisplayer,
SettingStorage
} from '@/core/main/setting';
import type { GameStorage } from '@/core/main/storage'; import type { GameStorage } from '@/core/main/storage';
import type { DamageEnemy, EnemyCollection } from './enemy/damage'; import type { DamageEnemy, EnemyCollection } from './enemy/damage';
import type { specials } from './enemy/special'; import type { specials } from './enemy/special';
@ -41,9 +31,6 @@ interface ClassInterface {
GameStorage: typeof GameStorage; GameStorage: typeof GameStorage;
MotaSetting: typeof MotaSetting; MotaSetting: typeof MotaSetting;
SettingDisplayer: typeof SettingDisplayer; SettingDisplayer: typeof SettingDisplayer;
Resource: typeof Resource;
ZippedResource: typeof ZippedResource;
ResourceStore: typeof ResourceStore;
Focus: typeof Focus; Focus: typeof Focus;
GameUi: typeof GameUi; GameUi: typeof GameUi;
UiController: typeof UiController; UiController: typeof UiController;
@ -85,9 +72,7 @@ interface VariableInterface {
// isMobile: boolean; // isMobile: boolean;
bgm: BgmController; bgm: BgmController;
sound: SoundController; sound: SoundController;
resource: ResourceStore<Exclude<ResourceType, 'zip'>>; settingStorage: GameStorage;
zipResource: ResourceStore<'zip'>;
settingStorage: GameStorage<SettingStorage>;
status: Ref<boolean>; status: Ref<boolean>;
// 定义于游戏进程,渲染进程依然可用 // 定义于游戏进程,渲染进程依然可用
haloSpecials: number[]; haloSpecials: number[];

View File

@ -31,10 +31,7 @@ export function has<T>(v: T): v is NonNullable<T> {
} }
export function maxGameScale(n: number = 0) { export function maxGameScale(n: number = 0) {
const index = core.domStyle.availableScale.indexOf(core.domStyle.scale); core.control.setDisplayScale(core.domStyle.availableScale.length - 1 - n);
core.control.setDisplayScale(
core.domStyle.availableScale.length - 1 - index - n
);
if (!core.isPlaying() && core.flags.enableHDCanvas) { if (!core.isPlaying() && core.flags.enableHDCanvas) {
// @ts-ignore // @ts-ignore
core.domStyle.ratio = Math.max( core.domStyle.ratio = Math.max(

View File

@ -3,7 +3,7 @@
<div id="start-div"> <div id="start-div">
<img id="background" src="/project/images/bg.jpg" /> <img id="background" src="/project/images/bg.jpg" />
<div id="start-main"> <div id="start-main">
<div id="title">人类开天辟地</div> <div id="title">{{ name }}</div>
<div id="settings"> <div id="settings">
<div <div
id="sound" id="sound"
@ -25,7 +25,7 @@
@click="setFullscreen" @click="setFullscreen"
/> />
</div> </div>
<div id="background-gradient"></div> <!-- <div id="background-gradient"></div>
<div id="buttons"> <div id="buttons">
<right-outlined id="cursor" /> <right-outlined id="cursor" />
<TransitionGroup name="start"> <TransitionGroup name="start">
@ -36,8 +36,6 @@
:key="v" :key="v"
:selected="selected === v" :selected="selected === v"
:showed="showed" :showed="showed"
:index="i"
:length="text[i].length"
@click="clickStartButton(v)" @click="clickStartButton(v)"
@mouseenter=" @mouseenter="
movein( movein(
@ -48,6 +46,44 @@
>{{ text[i] }}</span >{{ text[i] }}</span
> >
</TransitionGroup> </TransitionGroup>
</div> -->
<div id="buttons-container">
<div id="buttons">
<template v-if="!inHard">
<span
class="start-button"
id="start-game"
@click="clickStartButton('start-game')"
>开始游戏</span
>
<span
class="start-button"
id="load-game"
@click="clickStartButton('load-game')"
>读取存档</span
>
<span
class="start-button"
id="replay"
@click="clickStartButton('replay')"
>录像回放</span
>
</template>
<template v-else>
<span
class="start-button hard-button"
v-for="hard of hards"
@click="clickHard(hard.name)"
>{{ hard.title }}</span
>
<span
class="start-button"
id="back"
@click="inHard = false"
>返回</span
>
</template>
</div>
</div> </div>
</div> </div>
<div id="listen" @mousemove="onmove"></div> <div id="listen" @mousemove="onmove"></div>
@ -56,21 +92,18 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'; import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { import {
RightOutlined,
SoundOutlined, SoundOutlined,
FullscreenOutlined, FullscreenOutlined,
FullscreenExitOutlined FullscreenExitOutlined
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import { sleep } from 'mutate-animate'; import { sleep } from 'mutate-animate';
import { Matrix4 } from '../plugin/webgl/matrix'; import { Matrix4 } from '../plugin/webgl/matrix';
import { doByInterval, keycode } from '../plugin/utils'; import { nextFrame, triggerFullscreen } from '../plugin/utils';
import { triggerFullscreen } from '../plugin/utils';
import { isMobile } from '../plugin/use'; import { isMobile } from '../plugin/use';
import { GameUi } from '@/core/main/custom/ui'; import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/init/hotkey'; import { gameKey } from '@/core/main/init/hotkey';
import { mainUi } from '@/core/main/init/ui';
import { CustomToolbar } from '@/core/main/custom/toolbar'; import { CustomToolbar } from '@/core/main/custom/toolbar';
import { mainSetting } from '@/core/main/setting'; import { mainSetting } from '@/core/main/setting';
import { bgm as mainBgm } from '@/core/audio/bgm'; import { bgm as mainBgm } from '@/core/audio/bgm';
@ -80,74 +113,43 @@ const props = defineProps<{
ui: GameUi; ui: GameUi;
}>(); }>();
const name = core.firstData.title;
const hards = main.levelChoose;
const inHard = ref(false);
let startdiv: HTMLDivElement; let startdiv: HTMLDivElement;
let start: HTMLDivElement; let start: HTMLDivElement;
let main: HTMLDivElement; let mainDiv: HTMLDivElement;
let cursor: HTMLElement;
let background: HTMLImageElement; let background: HTMLImageElement;
let buttons: HTMLSpanElement[] = [];
let played: boolean;
const soundChecked = ref(false); const soundChecked = ref(false);
const fullscreen = ref(!!document.fullscreenElement); const fullscreen = ref(!!document.fullscreenElement);
const showed = ref(false);
const text1 = ['开始游戏', '读取存档', '录像回放', '查看成就'].reverse();
const text2 = ['轮回', '分支', '观测', '回忆'].reverse();
const ids = ['start-game', 'load-game', 'replay', 'achievement'].reverse();
const hardIds = ['easy', 'hard-hard', 'back'].reverse();
const hard = ['简单', '困难', '返回'].reverse();
const text = ref(text1);
const toshow = reactive<string[]>([]);
const selected = ref('start-game');
function resize() { function resize() {
if (!window.core) return; if (!window.core) return;
const scale = core.domStyle.scale;
const h = core._PY_;
const height = h * scale;
const width = height * 1.5;
if (!isMobile) {
startdiv.style.width = `${width}px`;
startdiv.style.height = `${height}px`;
main.style.fontSize = `${scale * 16}px`;
} else {
startdiv.style.width = `${window.innerWidth}px`;
startdiv.style.height = `${(window.innerHeight * 2) / 3}px`;
main.style.fontSize = `${scale * 8}px`;
}
}
function showCursor() { nextFrame(() => {
cursor.style.opacity = '1'; const scale = core.domStyle.scale;
setCursor(buttons[0], 0); console.log(scale);
} const h = core._PY_;
const height = h * scale;
/** const width = height * 1.5;
* 设置光标位置 if (!isMobile) {
*/ startdiv.style.width = `${width}px`;
function setCursor(ele: HTMLSpanElement, i: number) { startdiv.style.height = `${height}px`;
const style = getComputedStyle(ele); mainDiv.style.fontSize = `${scale * 16}px`;
cursor.style.top = `${ } else {
parseFloat(style.height) * (i + 0.5) - startdiv.style.width = `${window.innerWidth}px`;
parseFloat(style.marginBottom) * (1 - i) startdiv.style.height = `${(window.innerHeight * 2) / 3}px`;
}px`; mainDiv.style.fontSize = `${scale * 8}px`;
cursor.style.left = `${ }
parseFloat(style.left) - 20 * core.domStyle.scale });
}px`;
} }
async function clickStartButton(id: string) { async function clickStartButton(id: string) {
if (id === 'start-game') showHard(); if (id === 'start-game') {
if (id === 'back') setButtonAnimate(); inHard.value = true;
if (id === 'easy' || id === 'hard-hard') {
start.style.opacity = '0';
await sleep(600);
core.startGame(id === 'easy' ? 'easy' : 'hard');
} }
if (id === 'load-game') { if (id === 'load-game') {
core.dom.gameGroup.style.display = 'block'; core.dom.gameGroup.style.display = 'block';
@ -155,9 +157,12 @@ async function clickStartButton(id: string) {
core.load(); core.load();
} }
if (id === 'replay') core.chooseReplayFile(); if (id === 'replay') core.chooseReplayFile();
if (id === 'achievement') { }
mainUi.open('achievement');
} async function clickHard(hard: string) {
start.style.opacity = '0';
await sleep(600);
core.startGame(hard);
} }
function onmove(e: MouseEvent) { function onmove(e: MouseEvent) {
@ -182,31 +187,6 @@ function onmove(e: MouseEvent) {
}px)matrix3d(${end})`; }px)matrix3d(${end})`;
} }
function movein(button: HTMLElement, i: number) {
setCursor(button, i);
selected.value = button.id;
}
gameKey.use(props.ui.symbol);
gameKey
.realize('@start_up', () => {
const i = toshow.indexOf(selected.value);
const next = toshow[i + 1];
if (!next) return;
selected.value = next;
setCursor(buttons[toshow.length - i - 2], toshow.length - i - 2);
})
.realize('@start_down', () => {
const i = toshow.indexOf(selected.value);
const next = toshow[i - 1];
if (!next) return;
selected.value = next;
setCursor(buttons[toshow.length - i], toshow.length - i);
})
.realize('confirm', () => {
clickStartButton(selected.value);
});
function bgm() { function bgm() {
core.triggerBgm(); core.triggerBgm();
soundChecked.value = !soundChecked.value; soundChecked.value = !soundChecked.value;
@ -215,119 +195,26 @@ function bgm() {
} }
async function setFullscreen() { async function setFullscreen() {
const index = toshow.length - toshow.indexOf(selected.value) - 1;
await triggerFullscreen(!fullscreen.value); await triggerFullscreen(!fullscreen.value);
requestAnimationFrame(() => { requestAnimationFrame(() => {
fullscreen.value = !!document.fullscreenElement; fullscreen.value = !!document.fullscreenElement;
setCursor(buttons[index], index);
}); });
} }
/**
* 初始 -> 难度
*/
async function showHard() {
cursor.style.transition =
'left 0.4s ease-out, top 0.4s ease-out, opacity 0.4s linear';
cursor.style.opacity = '0';
buttons.forEach(v => (v.style.transition = ''));
await doByInterval(
Array(4).fill(() => ids.unshift(toshow.pop()!)),
150
);
await sleep(250);
text.value = hard;
await doByInterval(
Array(3).fill(() => toshow.push(hardIds.shift()!)),
150
);
selected.value = 'easy';
nextTick(() => {
buttons = toshow
.map(v => document.getElementById(v) as HTMLSpanElement)
.reverse();
cursor.style.opacity = '1';
setCursor(buttons[0], 0);
});
await sleep(600);
buttons.forEach(
v =>
(v.style.transition =
'transform 0.3s ease-out, color 0.3s ease-out')
);
}
/**
* 难度 | -> 初始
*/
async function setButtonAnimate() {
if (toshow.length > 0) {
cursor.style.transition =
'left 0.4s ease-out, top 0.4s ease-out, opacity 0.4s linear';
cursor.style.opacity = '0';
buttons.forEach(v => (v.style.transition = ''));
await doByInterval(
Array(3).fill(() => hardIds.unshift(toshow.pop()!)),
150
);
}
text.value = text1;
if (played) {
text.value = text2;
}
await sleep(250);
await doByInterval(
Array(4).fill(() => toshow.push(ids.shift()!)),
150
);
selected.value = 'start-game';
nextTick(() => {
buttons = toshow
.map(v => document.getElementById(v) as HTMLSpanElement)
.reverse();
cursor.style.opacity = '1';
setCursor(buttons[0], 0);
buttons.forEach((v, i) => {});
});
if (!showed.value) await sleep(1200);
else await sleep(600);
buttons.forEach(
v =>
(v.style.transition =
'transform 0.3s ease-out, color 0.3s ease-out')
);
}
onMounted(async () => { onMounted(async () => {
cursor = document.getElementById('cursor')!;
startdiv = document.getElementById('start-div') as HTMLDivElement; startdiv = document.getElementById('start-div') as HTMLDivElement;
main = document.getElementById('start-main') as HTMLDivElement; mainDiv = document.getElementById('start-main') as HTMLDivElement;
start = document.getElementById('start') as HTMLDivElement; start = document.getElementById('start') as HTMLDivElement;
background = document.getElementById('background') as HTMLImageElement; background = document.getElementById('background') as HTMLImageElement;
const loading = Mota.require('var', 'loading'); window.addEventListener('resize', resize);
resize();
loading.once('coreInit', async () => { soundChecked.value = mainSetting.getValue('audio.bgmEnabled', true);
window.addEventListener('resize', resize); mainBgm.changeTo(main.startBgm);
resize();
soundChecked.value = mainSetting.getValue('audio.bgmEnabled', true);
mainBgm.changeTo('title.mp3');
nextFrame(() => {
start.style.opacity = '1'; start.style.opacity = '1';
if (played) {
text.value = text2;
hard.splice(1, 0, '挑战');
}
setButtonAnimate().then(() => (showed.value = true));
await sleep(1000);
showCursor();
await sleep(1200);
}); });
CustomToolbar.closeAll(); CustomToolbar.closeAll();
@ -423,59 +310,68 @@ onUnmounted(() => {
5px 5px 5px rgba(0, 0, 0, 0.4); 5px 5px 5px rgba(0, 0, 0, 0.4);
filter: brightness(1.8); filter: brightness(1.8);
user-select: none; user-select: none;
animation: opacity 3s ease-out 0.5s 1 normal forwards; color: transparent;
}
#buttons-container {
display: flex;
width: 100%;
flex-direction: column;
justify-content: center;
align-items: center;
bottom: 10%;
position: absolute;
height: auto;
font-size: 120%;
} }
#buttons { #buttons {
border: 2px solid white;
border-radius: 10px;
padding: 1% 0;
backdrop-filter: blur(5px);
background-image: linear-gradient(
to bottom,
rgba(76, 73, 255, 0.6),
rgba(106, 40, 145, 0.6)
);
display: flex; display: flex;
flex-direction: column-reverse; align-items: center;
justify-content: center;
position: absolute; position: absolute;
left: 18%;
bottom: 10%; bottom: 10%;
filter: brightness(120%) contrast(110%); filter: brightness(120%) contrast(110%);
z-index: 1; z-index: 1;
flex-direction: column;
#cursor { transition: height 0.2s ease;
text-shadow: 2px 2px 3px black; width: 20%;
position: absolute;
opacity: 0;
animation: cursor 2.5s linear 0s infinite normal running;
transition: left 0.4s ease-out, top 0.4s ease-out,
opacity 1.5s ease-out;
}
.start-button { .start-button {
position: relative; position: relative;
font: bold 1.5em 'normal';
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4), text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4),
0px 0px 1px rgba(255, 255, 255, 0.3); 0px 0px 1px rgba(255, 255, 255, 0.3);
background-clip: text; background-clip: text;
-webkit-background-clip: text; -webkit-background-clip: text;
font-weight: bold;
color: transparent;
transition: all 0.2s linear;
box-shadow: 0px 0px 8px #0008;
border-radius: 6px;
padding: 1% 5%;
width: 70%;
text-wrap: nowrap;
text-align: center;
} }
.start-button[index='1'][length='4'] { .start-button:hover {
left: 7.5%; transform: scale(120%);
} }
.start-button[index='2'][length='4'] { .hard-button {
left: 15%; background-image: linear-gradient(
} to bottom,
rgb(255, 255, 255),
.start-button[index='3'][length='4'] { rgb(255, 0, 0)
left: 22.5%; );
}
.start-button[index='1'][length='2'] {
left: 15%;
}
.start-button[index='2'][length='2'] {
left: 30%;
}
.start-button[index='3'][length='2'] {
left: 45%;
} }
#start-game { #start-game {
@ -484,7 +380,7 @@ onUnmounted(() => {
rgb(255, 255, 255), rgb(255, 255, 255),
rgb(0, 255, 255) rgb(0, 255, 255)
); );
margin-bottom: 8%; margin-bottom: 2%;
} }
#load-game { #load-game {
@ -493,7 +389,7 @@ onUnmounted(() => {
rgb(255, 255, 255), rgb(255, 255, 255),
rgb(0, 255, 55) rgb(0, 255, 55)
); );
margin-bottom: 8%; margin-bottom: 2%;
} }
#replay { #replay {
@ -502,34 +398,7 @@ onUnmounted(() => {
rgb(255, 255, 255), rgb(255, 255, 255),
rgb(255, 251, 0) rgb(255, 251, 0)
); );
margin-bottom: 8%; margin-bottom: 2%;
}
#achievement {
background-image: linear-gradient(
to bottom,
rgb(255, 255, 255),
rgb(0, 208, 255)
);
margin-bottom: 8%;
}
#easy {
background-image: linear-gradient(
to bottom,
rgb(255, 255, 255),
rgb(87, 255, 72)
);
margin-bottom: 16%;
}
#hard-hard {
background-image: linear-gradient(
to bottom,
rgb(255, 255, 255),
rgb(255, 0, 0)
);
margin-bottom: 16%;
} }
#back { #back {
@ -538,7 +407,7 @@ onUnmounted(() => {
rgb(255, 255, 255), rgb(255, 255, 255),
rgb(132, 132, 132) rgb(132, 132, 132)
); );
margin-bottom: 16%; margin-bottom: 2%;
} }
} }
@ -603,33 +472,6 @@ onUnmounted(() => {
transform: scale(115%) translate(7.5%); transform: scale(115%) translate(7.5%);
} }
@keyframes cursor {
from {
transform: rotateX(0deg) scaleY(0.7);
}
to {
transform: rotateX(360deg) scaleY(0.7);
}
}
@keyframes gradient {
from {
left: -100%;
}
to {
left: 100%;
}
}
@keyframes opacity {
from {
color: #bbb;
}
to {
color: transparent;
}
}
.start-enter-active { .start-enter-active {
transition: all 1.2s ease-out; transition: all 1.2s ease-out;
} }