From d5936e7f3cb37743f99b7d84e2496c2341a2f6dc Mon Sep 17 00:00:00 2001 From: hundun Date: Mon, 8 Jan 2024 20:19:19 +0800 Subject: [PATCH 1/2] feat: choose option supports conditions --- .../controller/gamePlay/scriptExecutor.ts | 34 ++++--- .../gameScripts/choose/choose.module.scss | 16 ++++ .../src/Core/gameScripts/choose/index.tsx | 93 +++++++++++++++---- 3 files changed, 110 insertions(+), 33 deletions(-) diff --git a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts index 961b31aed..0106f7263 100644 --- a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts +++ b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts @@ -13,6 +13,25 @@ import { IBacklogItem } from '@/Core/Modules/backlog'; import { SYSTEM_CONFIG } from '@/config'; import { WebGAL } from '@/Core/WebGAL'; +export const whenChecker = (whenValue: string | undefined): boolean => { + if (whenValue == undefined) { + return true; + } + const valExpArr = whenValue.split(/([+\-*\/()>=|<=|==)/g); + const valExp = valExpArr + .map((e) => { + if (e.match(/[a-zA-Z]/)) { + if (e.match(/true/) || e.match(/false/)) { + return e; + } + return getValueFromState(e).toString(); + } else return e; + }) + .reduce((pre, curr) => pre + curr, ''); + return strIf(valExp) == true; +} + + /** * 语句执行器 * 执行语句,同步场景状态,并根据情况立即执行下一句或者加入backlog @@ -64,7 +83,7 @@ export const scriptExecutor = () => { variableInterpolation(); // 判断这个脚本要不要执行 - let runThis: number | boolean = true; + let runThis: boolean = true; let isHasWhenArg = false; let whenValue = ''; currentScript.args.forEach((e) => { @@ -76,18 +95,7 @@ export const scriptExecutor = () => { // 如果语句有 when if (isHasWhenArg) { // 先把变量解析出来 - const valExpArr = whenValue.split(/([+\-*\/()>=|<=|==)/g); - const valExp = valExpArr - .map((e) => { - if (e.match(/[a-zA-Z]/)) { - if (e.match(/true/) || e.match(/false/)) { - return e; - } - return getValueFromState(e).toString(); - } else return e; - }) - .reduce((pre, curr) => pre + curr, ''); - runThis = strIf(valExp); + runThis = whenChecker(whenValue); } // 执行语句 diff --git a/packages/webgal/src/Core/gameScripts/choose/choose.module.scss b/packages/webgal/src/Core/gameScripts/choose/choose.module.scss index 50efdcb77..bd0dcfec6 100644 --- a/packages/webgal/src/Core/gameScripts/choose/choose.module.scss +++ b/packages/webgal/src/Core/gameScripts/choose/choose.module.scss @@ -26,6 +26,22 @@ transition: background-color 0.5s, border 0.5s, font-weight 0.5s, box-shadow 0.5s; } +.Choose_item_disabled { + font-family: "WebgalUI", serif; + cursor: pointer; + min-width: 50%; + padding: 0.25em 1em 0.25em 1em; + font-size: 265%; + color: rgba(0, 0, 0, 1); + text-align: center; + border-radius: 4px; + border: 3px solid rgba(0, 0, 0, 0); + box-shadow: 0 0 25px rgba(0, 0, 0, 0.25); + background: rgba(255, 255, 255, 0.65); + margin: 0.25em 0 0.25em 0; + transition: background-color 0.5s, border 0.5s, font-weight 0.5s, box-shadow 0.5s; +} + .Choose_item:hover { //font-weight: bold; background: rgba(255, 255, 255, 0.9); diff --git a/packages/webgal/src/Core/gameScripts/choose/index.tsx b/packages/webgal/src/Core/gameScripts/choose/index.tsx index 5c1fa6ea4..39ed8e63e 100644 --- a/packages/webgal/src/Core/gameScripts/choose/index.tsx +++ b/packages/webgal/src/Core/gameScripts/choose/index.tsx @@ -10,40 +10,93 @@ import { textFont } from '@/store/userDataInterface'; import { PerformController } from '@/Core/Modules/perform/performController'; import { useSEByWebgalStore } from '@/hooks/useSoundEffect'; import { WebGAL } from '@/Core/WebGAL'; +import { whenChecker } from '@/Core/controller/gamePlay/scriptExecutor'; + + +class ChooseOption { + text: string; + jump: string; + jumpToScene: boolean; + showCondition?: string; + enableCondition?: string; + + constructor(text: string, jump: string) { + this.text = text; + this.jump = jump; + this.jumpToScene = jump.match(/\./) !== null; + } + + /** + * 格式: + * (showConditionVar>1)[enableConditionVar>2]=>text:jump + */ + static parse(script: string): ChooseOption { + const parts = script.split('=>'); + const conditonPart = parts.length > 1 ? parts[0] : null; + const mainPart = parts.length > 1 ? parts[1] : parts[0]; + const mainPartNodes = mainPart.split(':'); + + const option = new ChooseOption(mainPartNodes[0], mainPartNodes[1]); + if (conditonPart !== null) { + const showConditionPart = conditonPart.match(/\((.*)\)/); + if (showConditionPart) { + option.showCondition = showConditionPart[1]; + } + const enableConditionPart = conditonPart.match(/\[(.*)\]/); + if (enableConditionPart) { + option.enableCondition = enableConditionPart[1]; + } + } + return option; + } + +} + + + + /** * 显示选择枝 * @param sentence */ export const choose = (sentence: ISentence): IPerform => { - let chooseList = sentence.content.split('|'); - const chooseListFull = chooseList.map((e) => e.split(':')); + const chooseOptionScripts = sentence.content.split('|'); + const chooseOptions = chooseOptionScripts.map((e) => ChooseOption.parse(e)); const fontFamily = webgalStore.getState().userData.optionData.textboxFont; const font = fontFamily === textFont.song ? '"思源宋体", serif' : '"WebgalUI", serif'; const { playSeEnterChoose, playSeClickChoose } = useSEByWebgalStore(); - const chooseElements = chooseListFull.map((e, i) => { - return ( -
{ + // 运行时计算JSX.Element[] + const runtimeBuildList = (chooseListFull: ChooseOption[]) => { + return chooseListFull + .filter((e, i) => whenChecker(e.showCondition)) + .map((e, i) => { + const enable = whenChecker(e.enableCondition); + const className = enable ? styles.Choose_item : styles.Choose_item_disabled; + const onClick = enable ? () => { playSeClickChoose(); - if (e[1].match(/\./)) { - changeScene(e[1], e[0]); + if (e.jumpToScene) { + changeScene(e.jump, e.text); } else { - jmp(e[1]); + jmp(e.jump); } WebGAL.gameplay.performController.unmountPerform('choose'); - }} - onMouseEnter={playSeEnterChoose} - > - {e[0]} -
- ); - }); + } : () => {}; + return ( +
+ {e.text} +
+ ); + }) + }; ReactDOM.render( -
{chooseElements}
, +
{runtimeBuildList(chooseOptions)}
, document.getElementById('chooseContainer'), ); return { From 78c23a48d94508aa5c94454a4358e0f195fefbf7 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Thu, 18 Jan 2024 19:22:13 +0800 Subject: [PATCH 2/2] enhance style and script --- .../controller/gamePlay/scriptExecutor.ts | 11 ++-- .../gameScripts/choose/choose.module.scss | 6 +- .../src/Core/gameScripts/choose/index.tsx | 57 +++++++++---------- 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts index 0106f7263..3dc811366 100644 --- a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts +++ b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts @@ -14,9 +14,10 @@ import { SYSTEM_CONFIG } from '@/config'; import { WebGAL } from '@/Core/WebGAL'; export const whenChecker = (whenValue: string | undefined): boolean => { - if (whenValue == undefined) { + if (whenValue === undefined) { return true; } + // 先把变量解析出来 const valExpArr = whenValue.split(/([+\-*\/()>=|<=|==)/g); const valExp = valExpArr .map((e) => { @@ -28,9 +29,8 @@ export const whenChecker = (whenValue: string | undefined): boolean => { } else return e; }) .reduce((pre, curr) => pre + curr, ''); - return strIf(valExp) == true; -} - + return !!strIf(valExp); +}; /** * 语句执行器 @@ -83,7 +83,7 @@ export const scriptExecutor = () => { variableInterpolation(); // 判断这个脚本要不要执行 - let runThis: boolean = true; + let runThis = true; let isHasWhenArg = false; let whenValue = ''; currentScript.args.forEach((e) => { @@ -94,7 +94,6 @@ export const scriptExecutor = () => { }); // 如果语句有 when if (isHasWhenArg) { - // 先把变量解析出来 runThis = whenChecker(whenValue); } diff --git a/packages/webgal/src/Core/gameScripts/choose/choose.module.scss b/packages/webgal/src/Core/gameScripts/choose/choose.module.scss index bd0dcfec6..a5691c717 100644 --- a/packages/webgal/src/Core/gameScripts/choose/choose.module.scss +++ b/packages/webgal/src/Core/gameScripts/choose/choose.module.scss @@ -28,16 +28,16 @@ .Choose_item_disabled { font-family: "WebgalUI", serif; - cursor: pointer; + cursor: not-allowed; min-width: 50%; padding: 0.25em 1em 0.25em 1em; font-size: 265%; - color: rgba(0, 0, 0, 1); + color: rgba(142, 53, 74, 0.5); text-align: center; border-radius: 4px; border: 3px solid rgba(0, 0, 0, 0); box-shadow: 0 0 25px rgba(0, 0, 0, 0.25); - background: rgba(255, 255, 255, 0.65); + background: rgba(255, 255, 255, 0.5); margin: 0.25em 0 0.25em 0; transition: background-color 0.5s, border 0.5s, font-weight 0.5s, box-shadow 0.5s; } diff --git a/packages/webgal/src/Core/gameScripts/choose/index.tsx b/packages/webgal/src/Core/gameScripts/choose/index.tsx index 39ed8e63e..8df5272d3 100644 --- a/packages/webgal/src/Core/gameScripts/choose/index.tsx +++ b/packages/webgal/src/Core/gameScripts/choose/index.tsx @@ -12,26 +12,13 @@ import { useSEByWebgalStore } from '@/hooks/useSoundEffect'; import { WebGAL } from '@/Core/WebGAL'; import { whenChecker } from '@/Core/controller/gamePlay/scriptExecutor'; - class ChooseOption { - text: string; - jump: string; - jumpToScene: boolean; - showCondition?: string; - enableCondition?: string; - - constructor(text: string, jump: string) { - this.text = text; - this.jump = jump; - this.jumpToScene = jump.match(/\./) !== null; - } - /** * 格式: - * (showConditionVar>1)[enableConditionVar>2]=>text:jump + * (showConditionVar>1)[enableConditionVar>2]->text:jump */ - static parse(script: string): ChooseOption { - const parts = script.split('=>'); + public static parse(script: string): ChooseOption { + const parts = script.split('->'); const conditonPart = parts.length > 1 ? parts[0] : null; const mainPart = parts.length > 1 ? parts[1] : parts[0]; const mainPartNodes = mainPart.split(':'); @@ -49,13 +36,19 @@ class ChooseOption { } return option; } + public text: string; + public jump: string; + public jumpToScene: boolean; + public showCondition?: string; + public enableCondition?: string; + public constructor(text: string, jump: string) { + this.text = text; + this.jump = jump; + this.jumpToScene = jump.match(/\./) !== null; + } } - - - - /** * 显示选择枝 * @param sentence @@ -73,15 +66,17 @@ export const choose = (sentence: ISentence): IPerform => { .map((e, i) => { const enable = whenChecker(e.enableCondition); const className = enable ? styles.Choose_item : styles.Choose_item_disabled; - const onClick = enable ? () => { - playSeClickChoose(); - if (e.jumpToScene) { - changeScene(e.jump, e.text); - } else { - jmp(e.jump); - } - WebGAL.gameplay.performController.unmountPerform('choose'); - } : () => {}; + const onClick = enable + ? () => { + playSeClickChoose(); + if (e.jumpToScene) { + changeScene(e.jump, e.text); + } else { + jmp(e.jump); + } + WebGAL.gameplay.performController.unmountPerform('choose'); + } + : () => {}; return (
{ {e.text}
); - }) + }); }; + // eslint-disable-next-line react/no-deprecated ReactDOM.render(
{runtimeBuildList(chooseOptions)}
, document.getElementById('chooseContainer'), @@ -104,6 +100,7 @@ export const choose = (sentence: ISentence): IPerform => { duration: 1000 * 60 * 60 * 24, isHoldOn: false, stopFunction: () => { + // eslint-disable-next-line react/no-deprecated ReactDOM.render(
, document.getElementById('chooseContainer')); }, blockingNext: () => true,