mirror of
https://github.com/motajs/template.git
synced 2026-10-10 14:47:22 +08:00
feat(09-02): rewire cross-dir consumers, add package-root ./ui barrel, delete render/ui
- render/index.tsx: imports now '../ui' / '../ui/load'; remove the './ui' re-export (dead link + D-69)
- render/action.ts: import './ui' -> '../ui'
- client.ts: import './render/ui/load' -> './ui/load'
- index.ts: add export * from './ui' (ui surface kept via package root)
- delete render/ui/{title,load,index}; remove the now-empty render/ui directory
This commit is contained in:
parent
964f479270
commit
2ed60467a1
@ -41,7 +41,7 @@ import { WebLoadStarter } from '@motajs/loader';
|
||||
import { IRendererUsing, RendererUsing } from '@motajs/render-vue';
|
||||
import { IUIController, UIController } from '@motajs/system';
|
||||
import { createApp } from './render';
|
||||
import { LoadSceneUI } from './render/ui/load';
|
||||
import { LoadSceneUI } from './ui/load';
|
||||
import { createUIPropsBase } from './ui/func';
|
||||
|
||||
export class ClientCore extends CoreState implements IClientCore {
|
||||
|
||||
@ -9,6 +9,7 @@ export function create() {
|
||||
export * from './action';
|
||||
export * from './fallback';
|
||||
export * from './render';
|
||||
export * from './ui';
|
||||
|
||||
export * from './client';
|
||||
export * from './core';
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
openViewMap,
|
||||
openReplay,
|
||||
openStatistics
|
||||
} from './ui';
|
||||
} from '../ui';
|
||||
import { ElementLocator } from '@motajs/render';
|
||||
|
||||
export function createAction() {
|
||||
|
||||
@ -3,12 +3,12 @@ import { defineComponent } from 'vue';
|
||||
import { DEFAULT_FONT, MAIN_HEIGHT, MAIN_WIDTH } from '../shared';
|
||||
import { createElements } from '@user/client-base';
|
||||
import { mainRenderer } from './renderer';
|
||||
import { createUI } from './ui';
|
||||
import { createUI } from '../ui';
|
||||
import { createAction } from './action';
|
||||
import { sceneController } from './scene';
|
||||
import { createWeather } from './weather';
|
||||
import { createApp } from './renderer';
|
||||
import { LoadSceneUI } from './ui/load';
|
||||
import { LoadSceneUI } from '../ui/load';
|
||||
|
||||
export function createGameRenderer() {
|
||||
const App = defineComponent(_props => {
|
||||
@ -36,7 +36,6 @@ export function createRender() {
|
||||
}
|
||||
|
||||
export * from './fx';
|
||||
export * from './ui';
|
||||
export * from './utils';
|
||||
export * from './weather';
|
||||
export * from './renderer';
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import { createMainController } from './controller';
|
||||
|
||||
export function createUI() {
|
||||
createMainController();
|
||||
}
|
||||
|
||||
export * from './controller';
|
||||
export * from './main';
|
||||
export * from './save';
|
||||
export * from './settings';
|
||||
export * from './statistics';
|
||||
export * from './statusBar';
|
||||
export * from './toolbar';
|
||||
export * from './viewmap';
|
||||
@ -1,161 +0,0 @@
|
||||
import { DefaultProps } from '@motajs/render-vue';
|
||||
import {
|
||||
GameUI,
|
||||
SetupComponentOptions,
|
||||
IUIDefaultPropsBase
|
||||
} from '@motajs/system';
|
||||
import { defineComponent } from 'vue';
|
||||
import {
|
||||
FULL_LOC,
|
||||
LOAD_BYTE_HEIGHT,
|
||||
LOAD_BYTE_LENGTH,
|
||||
LOAD_BYTE_LINE_WIDTH,
|
||||
LOAD_FONT_COLOR,
|
||||
LOAD_LOADED_COLOR,
|
||||
LOAD_TASK_CENTER_HEIGHT,
|
||||
LOAD_TASK_LINE_WIDTH,
|
||||
LOAD_TASK_RADIUS,
|
||||
LOAD_UNLOADED_COLOR,
|
||||
MAIN_WIDTH
|
||||
} from '../../shared';
|
||||
import { ElementLocator, Font, MotaOffscreenCanvas2D } from '@motajs/render';
|
||||
import { transitioned } from '../use';
|
||||
import { cosh, CurveMode, linear } from '@motajs/animate';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { sleep } from '@motajs/common';
|
||||
import { GameTitleUI } from './title';
|
||||
import { client } from '../../core';
|
||||
|
||||
export interface ILoadProps extends IUIDefaultPropsBase, DefaultProps {}
|
||||
|
||||
const loadSceneProps = {
|
||||
props: ['controller', 'instance']
|
||||
} satisfies SetupComponentOptions<ILoadProps>;
|
||||
|
||||
export const LoadScene = defineComponent<ILoadProps>(props => {
|
||||
const loader = client.loader;
|
||||
const taskFont = new Font('Verdana', 24);
|
||||
const byteFont = new Font('Verdana', 12);
|
||||
|
||||
/** 当前加载进度 */
|
||||
const taskProgress = transitioned(0, 500, cosh(2, CurveMode.EaseOut))!;
|
||||
const byteProgress = transitioned(0, 500, cosh(2, CurveMode.EaseOut))!;
|
||||
const alpha = transitioned(1, 400, linear())!;
|
||||
|
||||
// 两个进度条的位置
|
||||
const taskLoc: ElementLocator = [
|
||||
MAIN_WIDTH / 2,
|
||||
LOAD_TASK_CENTER_HEIGHT,
|
||||
LOAD_TASK_RADIUS * 2 + LOAD_TASK_LINE_WIDTH * 2,
|
||||
LOAD_TASK_RADIUS * 2 + LOAD_TASK_LINE_WIDTH * 2,
|
||||
0.5,
|
||||
0.5
|
||||
];
|
||||
const byteLoc: ElementLocator = [
|
||||
MAIN_WIDTH / 2,
|
||||
LOAD_BYTE_HEIGHT,
|
||||
LOAD_BYTE_LENGTH + LOAD_BYTE_LINE_WIDTH,
|
||||
LOAD_BYTE_LINE_WIDTH * 2 + byteFont.size,
|
||||
0.5,
|
||||
0.5
|
||||
];
|
||||
|
||||
const loadEnd = async () => {
|
||||
alpha.set(0);
|
||||
await sleep(400);
|
||||
props.controller.closeAll();
|
||||
props.controller.open(GameTitleUI, {});
|
||||
};
|
||||
|
||||
const startLoad = async () => {
|
||||
for await (const _ of loader.start()) {
|
||||
taskProgress.set(loader.manager.getLoadedTasks());
|
||||
byteProgress.set(loader.manager.getLoadedByte());
|
||||
}
|
||||
loadEnd();
|
||||
};
|
||||
|
||||
// 开始加载
|
||||
startLoad();
|
||||
|
||||
/** 渲染加载任务进度 */
|
||||
const renderTaskList = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineWidth = LOAD_TASK_LINE_WIDTH;
|
||||
ctx.font = taskFont.string();
|
||||
const loaded = loader.manager.getLoadedTasks();
|
||||
const total = loader.manager.getAddedTasks();
|
||||
// 这里使用渐变参数,因为要有动画效果
|
||||
const progress = clamp(taskProgress.value / total, 0, 1);
|
||||
const cx = taskLoc[2]! / 2;
|
||||
const cy = taskLoc[3]! / 2;
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, LOAD_TASK_RADIUS, 0, Math.PI * 2);
|
||||
ctx.strokeStyle = LOAD_UNLOADED_COLOR;
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
const end = progress * Math.PI * 2 - Math.PI / 2;
|
||||
ctx.arc(cx, cy, LOAD_TASK_RADIUS, -Math.PI / 2, end);
|
||||
ctx.strokeStyle = LOAD_LOADED_COLOR;
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = LOAD_FONT_COLOR;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(`${loaded} / ${total}`, cx, cy + 3);
|
||||
};
|
||||
|
||||
/** 渲染加载字节进度 */
|
||||
const renderByteList = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineWidth = LOAD_BYTE_LINE_WIDTH;
|
||||
ctx.font = byteFont.string();
|
||||
const total = loader.manager.getTotalByte();
|
||||
const loaded = loader.manager.getLoadedByte();
|
||||
// 这里使用渐变参数,因为要有动画效果
|
||||
const progress = clamp(byteProgress.value / total, 0, 1);
|
||||
const sx = LOAD_BYTE_LINE_WIDTH;
|
||||
const sy = byteFont.size + LOAD_BYTE_LINE_WIDTH;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(sx, sy);
|
||||
ctx.lineTo(sx + LOAD_BYTE_LENGTH, sy);
|
||||
ctx.strokeStyle = LOAD_UNLOADED_COLOR;
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(sx, sy);
|
||||
ctx.lineTo(sx + progress * LOAD_BYTE_LENGTH, sy);
|
||||
ctx.strokeStyle = LOAD_LOADED_COLOR;
|
||||
ctx.stroke();
|
||||
ctx.textAlign = 'right';
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillStyle = LOAD_FONT_COLOR;
|
||||
const loadedMB = (loaded / 2 ** 20).toFixed(2);
|
||||
const totalMB = (total / 2 ** 20).toFixed(2);
|
||||
const percent = loader.manager.getByteRatio() * 100;
|
||||
ctx.fillText(
|
||||
`${loadedMB}MB / ${totalMB}MB | ${percent.toFixed(2)}%`,
|
||||
byteLoc[2]! - LOAD_BYTE_LINE_WIDTH,
|
||||
byteLoc[3]! - LOAD_BYTE_LINE_WIDTH * 2
|
||||
);
|
||||
};
|
||||
|
||||
return () => (
|
||||
<container loc={FULL_LOC} alpha={alpha.ref.value}>
|
||||
<custom
|
||||
loc={taskLoc}
|
||||
render={renderTaskList}
|
||||
bindings={[taskProgress.ref]}
|
||||
nocache
|
||||
/>
|
||||
<custom
|
||||
loc={byteLoc}
|
||||
render={renderByteList}
|
||||
bindings={[byteProgress.ref]}
|
||||
nocache
|
||||
/>
|
||||
</container>
|
||||
);
|
||||
}, loadSceneProps);
|
||||
|
||||
export const LoadSceneUI = new GameUI('load-scene', LoadScene);
|
||||
@ -1,484 +0,0 @@
|
||||
import { DefaultProps } from '@motajs/render-vue';
|
||||
import {
|
||||
GameUI,
|
||||
SetupComponentOptions,
|
||||
IUIDefaultPropsBase
|
||||
} from '@motajs/system';
|
||||
import { defineComponent, nextTick, onMounted, ref } from 'vue';
|
||||
import {
|
||||
BUTTONS_HEIGHT,
|
||||
BUTTONS_WIDTH,
|
||||
BUTTONS_X,
|
||||
BUTTONS_Y,
|
||||
HALF_HEIGHT,
|
||||
HALF_WIDTH,
|
||||
MAIN_HEIGHT,
|
||||
MAIN_WIDTH,
|
||||
TITLE_BACKGROUND_IMAGE,
|
||||
TITLE_FILL,
|
||||
TITLE_STROKE,
|
||||
TITLE_STROKE_WIDTH,
|
||||
TITLE_X,
|
||||
TITLE_Y
|
||||
} from '../../shared';
|
||||
import { ElementLocator, Font } from '@motajs/render';
|
||||
import {
|
||||
ITransitionedController,
|
||||
transitioned,
|
||||
transitionedColor,
|
||||
useKey
|
||||
} from '../use';
|
||||
import { ExitFullscreen, Fullscreen, SoundVolume } from '@user/client-base';
|
||||
import { mainSetting, triggerFullscreen } from '@motajs/legacy-ui';
|
||||
import { saveLoad } from './save';
|
||||
import { MainSceneUI } from './main';
|
||||
import { adjustCover } from '@user/client-base';
|
||||
import { cosh, CurveMode, linear } from '@motajs/animate';
|
||||
import { sleep } from '@motajs/common';
|
||||
import { client } from '../../core';
|
||||
|
||||
const enum TitleButton {
|
||||
StartGame,
|
||||
LoadGame,
|
||||
Replay
|
||||
}
|
||||
|
||||
interface ButtonItem {
|
||||
code: TitleButton;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface ButtonOption {
|
||||
code: number;
|
||||
color: string;
|
||||
name: string;
|
||||
hard: string;
|
||||
colorTrans: ITransitionedController<string>;
|
||||
}
|
||||
|
||||
export interface GameTitleProps extends DefaultProps, IUIDefaultPropsBase {}
|
||||
|
||||
const gameTitleProps = {
|
||||
props: ['controller', 'instance']
|
||||
} satisfies SetupComponentOptions<GameTitleProps>;
|
||||
|
||||
export const GameTitle = defineComponent<GameTitleProps>(props => {
|
||||
const materials = client.materials;
|
||||
const bg = materials.getImageByAlias(TITLE_BACKGROUND_IMAGE);
|
||||
|
||||
//#region 计算背景图
|
||||
const [width, height] = adjustCover(
|
||||
bg?.width ?? MAIN_WIDTH,
|
||||
bg?.height ?? MAIN_HEIGHT,
|
||||
MAIN_WIDTH,
|
||||
MAIN_HEIGHT
|
||||
);
|
||||
|
||||
//#region 标题设置
|
||||
|
||||
/** 当前是否全屏 */
|
||||
const fullscreen = ref(!!document.fullscreenElement);
|
||||
/** 是否开启了声音 */
|
||||
const soundOpened = ref(true);
|
||||
/** 是否在选择难度界面 */
|
||||
const selectHard = ref(false);
|
||||
|
||||
/** 开始界面按钮定义,你可以在这新增自己的按钮 */
|
||||
const buttonItems: ButtonItem[] = [
|
||||
{
|
||||
code: TitleButton.StartGame,
|
||||
color: 'rgb(40, 194, 255)',
|
||||
name: '开始游戏'
|
||||
},
|
||||
{
|
||||
code: TitleButton.LoadGame,
|
||||
color: 'rgb(0, 255, 55)',
|
||||
name: '读取存档'
|
||||
},
|
||||
{
|
||||
code: TitleButton.Replay,
|
||||
color: 'rgb(255, 251, 0)',
|
||||
name: '录像回放'
|
||||
}
|
||||
];
|
||||
|
||||
/** 开始界面按钮 */
|
||||
const buttons = buttonItems.map<ButtonOption>(v => {
|
||||
return {
|
||||
code: v.code,
|
||||
color: v.color,
|
||||
name: v.name,
|
||||
hard: '',
|
||||
colorTrans: transitionedColor(
|
||||
'#fff',
|
||||
400,
|
||||
cosh(2, CurveMode.EaseOut)
|
||||
)!,
|
||||
scale: transitioned(1, 400, cosh(2, CurveMode.EaseOut))!
|
||||
};
|
||||
});
|
||||
|
||||
/** 选择难度界面按钮 */
|
||||
const hard = main.levelChoose.map<ButtonOption>(v => {
|
||||
return {
|
||||
code: v.hard,
|
||||
color: core.arrayToRGBA(v.color!),
|
||||
name: v.title,
|
||||
hard: v.name,
|
||||
colorTrans: transitionedColor(
|
||||
'#fff',
|
||||
400,
|
||||
cosh(2, CurveMode.EaseOut)
|
||||
)!,
|
||||
scale: transitioned(1, 400, cosh(2, CurveMode.EaseOut))!
|
||||
};
|
||||
});
|
||||
// 返回按钮
|
||||
hard.push({
|
||||
code: -1,
|
||||
color: '#aaa',
|
||||
name: '返回',
|
||||
hard: '',
|
||||
colorTrans: transitionedColor('#fff', 400, cosh(2, CurveMode.EaseOut))!
|
||||
});
|
||||
|
||||
/** 声音设置按钮的颜色 */
|
||||
const soundColor = transitionedColor(
|
||||
'#ddd',
|
||||
400,
|
||||
cosh(2, CurveMode.EaseOut)
|
||||
)!;
|
||||
|
||||
/** 开始界面按钮的不透明度,选择难度界面的不透明度使用 `1-buttonsAlpha` 计算 */
|
||||
const buttonsAlpha = transitioned(1, 300, linear())!;
|
||||
/** 开始界面的不透明度 */
|
||||
const mainAlpha = transitioned(0, 600, linear())!;
|
||||
|
||||
const buttonFilter = `
|
||||
drop-shadow(3px 3px 5px rgba(0, 0, 0, 0.4))
|
||||
drop-shadow(0px 0px 2px rgba(255, 255, 255, 0.5))
|
||||
`;
|
||||
|
||||
const titleFont = Font.defaults({ size: 72 });
|
||||
const buttonFont = Font.defaults({ size: 24, weight: 600 });
|
||||
|
||||
/** 开始界面按钮的高度 */
|
||||
const buttonHeight = (buttons.length - 1) * 40 + 60;
|
||||
/** 选择难度界面按钮的高度 */
|
||||
const hardHeight = (hard.length - 1) * 40 + 60;
|
||||
/** 按钮的背景框高度 */
|
||||
const rectHeight = transitioned(
|
||||
buttonHeight,
|
||||
600,
|
||||
cosh(2, CurveMode.EaseOut)
|
||||
)!;
|
||||
|
||||
//#region 按钮功能
|
||||
|
||||
/**
|
||||
* 在开始界面和选择难度界面切换
|
||||
*/
|
||||
const toggleHard = async () => {
|
||||
if (selectHard.value) {
|
||||
// 当前在难度界面,将要切换至开始界面
|
||||
enterMain(0);
|
||||
rectHeight.set(buttonHeight);
|
||||
} else {
|
||||
// 当前在开始界面,将要切换至难度界面
|
||||
enterHard(0);
|
||||
rectHeight.set(hardHeight);
|
||||
}
|
||||
buttonsAlpha.set(0);
|
||||
await sleep(300);
|
||||
selectHard.value = !selectHard.value;
|
||||
buttonsAlpha.set(1);
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击读取存档按钮
|
||||
*/
|
||||
const loadGame = async () => {
|
||||
const loc: ElementLocator = [0, 0, MAIN_WIDTH, MAIN_HEIGHT];
|
||||
const success = await saveLoad(props.controller, loc);
|
||||
if (success) {
|
||||
props.controller.close(props.instance);
|
||||
props.controller.open(MainSceneUI, {});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击录像回放按钮
|
||||
*/
|
||||
const replay = () => {
|
||||
core.chooseReplayFile();
|
||||
};
|
||||
|
||||
/**
|
||||
* 选择难度并开始游戏
|
||||
* @param hard 选择的难度
|
||||
*/
|
||||
const startGame = async (hard: string) => {
|
||||
mainAlpha.set(0);
|
||||
await sleep(600);
|
||||
props.controller.close(props.instance);
|
||||
props.controller.open(MainSceneUI, {});
|
||||
nextTick(() => {
|
||||
core.startGame(hard);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击按钮时触发
|
||||
* @param code 选中的按钮的代码
|
||||
*/
|
||||
const clickButton = (code: number, index: number) => {
|
||||
if (selectHard.value) {
|
||||
if (index === hard.length - 1) {
|
||||
// 选中了最后一个按钮
|
||||
toggleHard();
|
||||
return;
|
||||
}
|
||||
const item = hard[index];
|
||||
startGame(item.name);
|
||||
} else {
|
||||
switch (code) {
|
||||
case TitleButton.StartGame:
|
||||
toggleHard();
|
||||
break;
|
||||
case TitleButton.LoadGame:
|
||||
loadGame();
|
||||
break;
|
||||
case TitleButton.Replay:
|
||||
replay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//#region 键盘操作
|
||||
|
||||
const selected = ref(0);
|
||||
|
||||
const [key] = useKey();
|
||||
key.realize(
|
||||
'@start_up',
|
||||
() => {
|
||||
selected.value--;
|
||||
if (selected.value < 0) {
|
||||
selected.value = 0;
|
||||
}
|
||||
if (selectHard.value) {
|
||||
enterHard(selected.value);
|
||||
} else {
|
||||
enterMain(selected.value);
|
||||
}
|
||||
},
|
||||
{ type: 'down' }
|
||||
)
|
||||
.realize(
|
||||
'@start_down',
|
||||
() => {
|
||||
selected.value++;
|
||||
if (selectHard.value) {
|
||||
if (selected.value > hard.length - 1) {
|
||||
selected.value = hard.length - 1;
|
||||
}
|
||||
enterHard(selected.value);
|
||||
} else {
|
||||
if (selected.value > buttons.length - 1) {
|
||||
selected.value = buttons.length - 1;
|
||||
}
|
||||
enterMain(selected.value);
|
||||
}
|
||||
},
|
||||
{ type: 'down' }
|
||||
)
|
||||
.realize('confirm', () => {
|
||||
if (selectHard.value) {
|
||||
clickButton(hard[selected.value].code, selected.value);
|
||||
} else {
|
||||
clickButton(buttons[selected.value].code, selected.value);
|
||||
}
|
||||
});
|
||||
|
||||
//#region 鼠标操作
|
||||
|
||||
soundOpened.value = mainSetting.getValue('audio.bgmEnabled', true);
|
||||
if (soundOpened.value) {
|
||||
soundColor.set('#ddd');
|
||||
} else {
|
||||
soundColor.set('#d22');
|
||||
}
|
||||
|
||||
const enterMain = (index: number) => {
|
||||
buttons.forEach((v, i) => {
|
||||
if (index !== i) {
|
||||
v.colorTrans.set('#fff');
|
||||
} else {
|
||||
v.colorTrans.set(v.color);
|
||||
}
|
||||
});
|
||||
selected.value = index;
|
||||
};
|
||||
|
||||
const enterHard = (index: number) => {
|
||||
hard.forEach((v, i) => {
|
||||
if (index !== i) {
|
||||
v.colorTrans.set('#fff');
|
||||
} else {
|
||||
v.colorTrans.set(v.color);
|
||||
}
|
||||
});
|
||||
selected.value = index;
|
||||
};
|
||||
|
||||
const toggleSound = () => {
|
||||
soundOpened.value = !soundOpened.value;
|
||||
mainSetting.setValue('audio.bgmEnabled', soundOpened.value);
|
||||
if (soundOpened.value) {
|
||||
soundColor.set('#ddd');
|
||||
} else {
|
||||
soundColor.set('#d22');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleFullscreen = async () => {
|
||||
await triggerFullscreen(!fullscreen.value);
|
||||
fullscreen.value = !!document.fullscreenElement;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
enterMain(0);
|
||||
mainAlpha.set(1);
|
||||
});
|
||||
|
||||
return () => (
|
||||
<container
|
||||
loc={[0, 0, MAIN_WIDTH, MAIN_HEIGHT]}
|
||||
alpha={mainAlpha.ref.value}
|
||||
>
|
||||
<image
|
||||
image={bg}
|
||||
loc={[HALF_WIDTH, HALF_HEIGHT, width, height]}
|
||||
anc={[0.5, 0.5]}
|
||||
zIndex={0}
|
||||
/>
|
||||
<text
|
||||
text={core.firstData.title}
|
||||
loc={[TITLE_X, TITLE_Y]}
|
||||
anc={[0.5, 0.5]}
|
||||
fillStyle={TITLE_FILL}
|
||||
strokeStyle={TITLE_STROKE}
|
||||
font={titleFont}
|
||||
strokeWidth={TITLE_STROKE_WIDTH}
|
||||
/>
|
||||
<container
|
||||
zIndex={15}
|
||||
loc={[BUTTONS_X, BUTTONS_Y, BUTTONS_WIDTH, BUTTONS_HEIGHT]}
|
||||
anc={[0.5, 0]}
|
||||
>
|
||||
<g-rectr
|
||||
loc={[2, BUTTONS_HEIGHT / 2]}
|
||||
width={BUTTONS_WIDTH - 4}
|
||||
height={rectHeight.ref.value - 4}
|
||||
anc={[0, 0.5]}
|
||||
circle={[16]}
|
||||
fill
|
||||
stroke
|
||||
fillStyle="rgba(50, 54, 159, 0.7)"
|
||||
strokeStyle="rgba(255, 204, 0, 1)"
|
||||
lineWidth={3}
|
||||
zIndex={0}
|
||||
/>
|
||||
<container
|
||||
hidden={selectHard.value}
|
||||
loc={[0, BUTTONS_HEIGHT / 2, BUTTONS_WIDTH, buttonHeight]}
|
||||
anc={[0, 0.5]}
|
||||
alpha={buttonsAlpha.ref.value}
|
||||
zIndex={5}
|
||||
>
|
||||
{buttons.map((v, i) => {
|
||||
const x = BUTTONS_WIDTH / 2;
|
||||
const y = 30 + i * 40;
|
||||
return (
|
||||
<text
|
||||
text={v.name}
|
||||
font={buttonFont}
|
||||
loc={[x, y, void 0, void 0, 0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
filter={buttonFilter}
|
||||
fillStyle={v.colorTrans.ref.value}
|
||||
onEnter={() => enterMain(i)}
|
||||
onClick={() => clickButton(v.code, i)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</container>
|
||||
<container
|
||||
hidden={!selectHard.value}
|
||||
loc={[0, BUTTONS_HEIGHT / 2, BUTTONS_WIDTH, hardHeight]}
|
||||
anc={[0, 0.5]}
|
||||
alpha={buttonsAlpha.ref.value}
|
||||
>
|
||||
{hard.map((v, i) => {
|
||||
const x = BUTTONS_WIDTH / 2;
|
||||
const y = 30 + i * 40;
|
||||
return (
|
||||
<text
|
||||
text={v.name}
|
||||
font={buttonFont}
|
||||
loc={[x, y, void 0, void 0, 0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
filter={buttonFilter}
|
||||
fillStyle={v.colorTrans.ref.value}
|
||||
onEnter={() => enterHard(i)}
|
||||
onClick={() => clickButton(v.code, i)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</container>
|
||||
</container>
|
||||
<container
|
||||
zIndex={15}
|
||||
loc={[MAIN_WIDTH - 20, MAIN_HEIGHT - 20, 120, 40, 1, 1]}
|
||||
>
|
||||
<g-rectr
|
||||
loc={[0, 0, 120, 40]}
|
||||
circle={[20]}
|
||||
fillStyle="rgba(0, 0, 0, 0.72)"
|
||||
/>
|
||||
<SoundVolume
|
||||
loc={[20, 0, 40, 40]}
|
||||
cursor="pointer"
|
||||
strokeStyle={soundColor.ref.value}
|
||||
onClick={toggleSound}
|
||||
/>
|
||||
{!fullscreen.value ? (
|
||||
<Fullscreen
|
||||
loc={[60, 0, 40, 40]}
|
||||
onClick={toggleFullscreen}
|
||||
cursor="pointer"
|
||||
/>
|
||||
) : (
|
||||
<ExitFullscreen
|
||||
loc={[60, 0, 40, 40]}
|
||||
onClick={toggleFullscreen}
|
||||
cursor="pointer"
|
||||
/>
|
||||
)}
|
||||
<g-line
|
||||
line={[25, 35, 55, 5]}
|
||||
strokeStyle="gray"
|
||||
lineWidth={3}
|
||||
lineCap="round"
|
||||
zIndex={5}
|
||||
noevent
|
||||
hidden={soundOpened.value}
|
||||
/>
|
||||
</container>
|
||||
</container>
|
||||
);
|
||||
}, gameTitleProps);
|
||||
|
||||
export const GameTitleUI = new GameUI('game-title', GameTitle);
|
||||
Loading…
Reference in New Issue
Block a user