diff --git a/.gitignore b/.gitignore index 41acb0977..2407e5202 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,7 @@ dist-ssr stats.html packages/webgal/public/game.old packages/parser/build +packages/parser_legacy/build packages/webgal/src/Core/util/pixiPerformManager/initRegister.ts +packages/parser-ng/src/parser.js +packages/parser-ng/src/parser.js.map diff --git a/packages/parser-ng/.babelrc b/packages/parser-ng/.babelrc new file mode 100644 index 000000000..cc4476abb --- /dev/null +++ b/packages/parser-ng/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "entry", + "corejs": "3.6.4", + "modules": false + }, + "@babel/preset-typescript" + ] + ], + "exclude": "node_modules/**" +} diff --git a/packages/parser-ng/.gitignore b/packages/parser-ng/.gitignore new file mode 100644 index 000000000..549164b2f --- /dev/null +++ b/packages/parser-ng/.gitignore @@ -0,0 +1,4 @@ +coverage +node_modules +.idea +.vscode diff --git a/packages/parser-ng/.npmignore b/packages/parser-ng/.npmignore new file mode 100644 index 000000000..7bcd9b489 --- /dev/null +++ b/packages/parser-ng/.npmignore @@ -0,0 +1,6 @@ +coverage +test +.babelrc +rollup.config.js +tsconfig.json +tsconfig.node.json diff --git a/packages/parser-ng/.prettierrc b/packages/parser-ng/.prettierrc new file mode 100644 index 000000000..33f6d8eaf --- /dev/null +++ b/packages/parser-ng/.prettierrc @@ -0,0 +1,19 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "requirePragma": false, + "insertPragma": false, + "proseWrap": "preserve", + "htmlWhitespaceSensitivity": "css", + "endOfLine": "lf", + "embeddedLanguageFormatting": "auto" +} diff --git a/packages/parser-ng/LICENSE b/packages/parser-ng/LICENSE new file mode 100644 index 000000000..a612ad981 --- /dev/null +++ b/packages/parser-ng/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/packages/parser-ng/README.md b/packages/parser-ng/README.md new file mode 100644 index 000000000..f6348d365 --- /dev/null +++ b/packages/parser-ng/README.md @@ -0,0 +1,29 @@ +# WebGAL Parser: The Next Generation + +## Development + +### Run all tests + +```sh +yarn test +``` + +### Run a specific test + +```sh +yarn test -t TEST_NAME +``` + +### Trace the parsing process + +Since this print a verbose test tree, we typically use for a specific test: + +```sh +yarn test-trace -t TEST_NAME +``` + +Or, if all tests are needed: + +```sh +yarn test-trace +``` diff --git a/packages/parser-ng/package.json b/packages/parser-ng/package.json new file mode 100644 index 000000000..2bbedd881 --- /dev/null +++ b/packages/parser-ng/package.json @@ -0,0 +1,51 @@ +{ + "name": "webgal-parser-ng", + "version": "4.5.13", + "description": "WebGAL script parser", + "scripts": { + "test": "yarn parser && vitest", + "test-trace": "yarn parser --trace && vitest", + "coverage": "vitest run --coverage", + "build": "rimraf -rf ./build && rollup --config", + "build-ci": "yarn parser && rollup --config", + "debug": "tsx test/debug.ts", + "dev": "tsx src/index.ts", + "parser": "npx peggy -o src/parser.js --format es src/parser.pegjs -m" + }, + "types": "./build/types/index.d.ts", + "module": "./build/es/index.js", + "main": "./build/cjs/index.js", + "author": "tinyAdapter ", + "license": "MPL-2.0", + "dependencies": { + "lodash": "^4.17.21", + "tsx": "^3.12.7" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^23.0.2", + "@rollup/plugin-json": "^5.0.1", + "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-typescript": "^9.0.2", + "@types/lodash": "^4.14.189", + "@types/node": "^18.14.0", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "@vitest/coverage-c8": "^0.28.5", + "eslint": "^8.13.0", + "eslint-config-alloy": "^4.5.1", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.29.4", + "lint-staged": "^12.3.7", + "prettier": "^2.6.2", + "rollup": "^3.3.0", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-terser": "^7.0.2", + "rollup-plugin-typescript2": "^0.34.1", + "ts-node": "^10.9.1", + "tslib": "^2.4.1", + "typescript": "^4.9.3", + "vitest": "^0.28.5" + }, + "type": "module" +} diff --git a/packages/parser-ng/rollup.config.js b/packages/parser-ng/rollup.config.js new file mode 100644 index 000000000..787b18bc7 --- /dev/null +++ b/packages/parser-ng/rollup.config.js @@ -0,0 +1,69 @@ +import typescript from "rollup-plugin-typescript2"; +import resolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; + +const mode = process.env.MODE ?? 'prod'; +const isProd = mode === "prod"; + +export default [ + { + input: `./src/index.ts`, + output: + { + file: "./build/es/index.js", + format: "es", + sourcemap: !isProd + }, + plugins: [ + resolve(), commonjs(), typescript({ + useTsconfigDeclarationDir: true, + tsconfigOverride: { + compilerOptions: { + sourceMap: !isProd, + declarationDir: "build/es" + }, include: ["src"] + } + })] + }, { + input: `./src/index.ts`, + output: [ + { + file: "./build/cjs/index.cjs", + exports: "named", + format: "cjs", + sourcemap: !isProd + }, + ], + plugins: [ + resolve(), commonjs(), typescript({ + useTsconfigDeclarationDir: true, + tsconfigOverride: { + compilerOptions: { + sourceMap: !isProd, + declarationDir: "build/cjs" + }, include: ["src"] + } + })], + }, + { + input: `./src/index.ts`, + output: [ + { + file: "./build/umd/index.global.js", + name: 'webgalParser', + format: 'iife', + sourcemap: !isProd + }, + ], + plugins: [ + resolve(), commonjs(), typescript({ + useTsconfigDeclarationDir: true, + tsconfigOverride: { + compilerOptions: { + sourceMap: !isProd, + declarationDir: "build/types" + }, include: ["src"] + } + })], + } +]; diff --git a/packages/parser-ng/src/config/scriptConfig.ts b/packages/parser-ng/src/config/scriptConfig.ts new file mode 100644 index 000000000..c8463fd7b --- /dev/null +++ b/packages/parser-ng/src/config/scriptConfig.ts @@ -0,0 +1,50 @@ +import {commandType} from '../interface/sceneInterface'; + +export const SCRIPT_CONFIG = [ + { scriptString: 'intro', scriptType: commandType.intro }, + { scriptString: 'changeBg', scriptType: commandType.changeBg }, + { scriptString: 'changeFigure', scriptType: commandType.changeFigure }, + { scriptString: 'miniAvatar', scriptType: commandType.miniAvatar }, + { scriptString: 'changeScene', scriptType: commandType.changeScene }, + { scriptString: 'choose', scriptType: commandType.choose }, + { scriptString: 'end', scriptType: commandType.end }, + { scriptString: 'bgm', scriptType: commandType.bgm }, + { scriptString: 'playVideo', scriptType: commandType.video }, + { + scriptString: 'setComplexAnimation', + scriptType: commandType.setComplexAnimation, + }, + { scriptString: 'setFilter', scriptType: commandType.setFilter }, + { scriptString: 'pixiInit', scriptType: commandType.pixiInit }, + { scriptString: 'pixiPerform', scriptType: commandType.pixi }, + { scriptString: 'label', scriptType: commandType.label }, + { scriptString: 'jumpLabel', scriptType: commandType.jumpLabel }, + { scriptString: 'setVar', scriptType: commandType.setVar }, + { scriptString: 'callScene', scriptType: commandType.callScene }, + { scriptString: 'showVars', scriptType: commandType.showVars }, + { scriptString: 'unlockCg', scriptType: commandType.unlockCg }, + { scriptString: 'unlockBgm', scriptType: commandType.unlockBgm }, + { scriptString: 'say', scriptType: commandType.say }, + { scriptString: 'filmMode', scriptType: commandType.filmMode }, + { scriptString: 'callScene', scriptType: commandType.callScene }, + { scriptString: 'setTextbox', scriptType: commandType.setTextbox }, + { scriptString: 'setAnimation', scriptType: commandType.setAnimation }, + { scriptString: 'playEffect', scriptType: commandType.playEffect }, + { scriptString: 'applyStyle', scriptType: commandType.applyStyle }, +]; +export const ADD_NEXT_ARG_LIST = [ + commandType.bgm, + commandType.pixi, + commandType.pixiInit, + commandType.label, + commandType.if, + commandType.miniAvatar, + commandType.setVar, + commandType.unlockBgm, + commandType.unlockCg, + commandType.filmMode, + commandType.playEffect, +]; + +export type ConfigMap = Map; +export type ConfigItem = { scriptString: string; scriptType: commandType }; diff --git a/packages/parser-ng/src/configParser/configParser.ts b/packages/parser-ng/src/configParser/configParser.ts new file mode 100644 index 000000000..cca9e66ec --- /dev/null +++ b/packages/parser-ng/src/configParser/configParser.ts @@ -0,0 +1,72 @@ +import { argsParser } from '../scriptParser/argsParser'; + +interface IOptionItem { + key: string; + value: string | number | boolean; +} +interface IConfigItem { + command: string; + args: string[]; + options: IOptionItem[]; +} + +export type WebgalConfig = IConfigItem[]; + +function configLineParser(inputLine: string): IConfigItem { + const options: Array = []; + let command: string; + + let newSentenceRaw = inputLine.split(';')[0]; + if (newSentenceRaw === '') { + // 注释提前返回 + return { + command: '', + args: [], + options: [], + }; + } + // 截取命令 + const getCommandResult = /\s*:\s*/.exec(newSentenceRaw); + + // 没有command + if (getCommandResult === null) { + command = ''; + } else { + command = newSentenceRaw.substring(0, getCommandResult.index); + // 划分命令区域和content区域 + newSentenceRaw = newSentenceRaw.substring( + getCommandResult.index + 1, + newSentenceRaw.length, + ); + } + // 截取 Options 区域 + const getOptionsResult = / -/.exec(newSentenceRaw); + // 获取到参数 + if (getOptionsResult) { + const optionsRaw = newSentenceRaw.substring( + getOptionsResult.index, + newSentenceRaw.length, + ); + newSentenceRaw = newSentenceRaw.substring(0, getOptionsResult.index); + for (const e of argsParser(optionsRaw, (name, _) => { + return name; + })) { + options.push(e); + } + } + return { + command, + args: newSentenceRaw + .split('|') + .map((e) => e.trim()) + .filter((e) => e !== ''), + options, + }; +} + +export function configParser(configText: string): WebgalConfig { + const configLines = configText.replaceAll(`\r`, '').split('\n'); + return configLines + .map((e) => configLineParser(e)) + .filter((e) => e.command !== ''); +} diff --git a/packages/parser-ng/src/index.ts b/packages/parser-ng/src/index.ts new file mode 100644 index 000000000..449286448 --- /dev/null +++ b/packages/parser-ng/src/index.ts @@ -0,0 +1,163 @@ +import * as p from './parser'; +import { configParser, WebgalConfig } from './configParser/configParser'; +import { commandType, IAsset } from "./interface/sceneInterface"; +import { fileType } from "./interface/assets"; +import { SyntaxError as parserSyntaxError } from './parser'; +import { contentParser } from './scriptParser/contentParser'; +import { assetsScanner } from './scriptParser/assetsScanner'; +import { subSceneScanner } from './scriptParser/subSceneScanner'; +import { uniqWith } from 'lodash'; +import { IWebGALStyleObj, scss2cssinjsParser } from './styleParser'; +export { SyntaxError as parserSyntaxError } from './parser'; +import { + ADD_NEXT_ARG_LIST, + SCRIPT_CONFIG, + ConfigMap, + ConfigItem, +} from './config/scriptConfig'; +import { sceneParser } from './sceneParser'; + +export class NewSceneParser { + + private readonly assetsPrefetcher; + private readonly assetSetter; + private readonly ADD_NEXT_ARG_LIST; + private readonly SCRIPT_CONFIG; + + public constructor(assetsPrefetcher: ((assetList: Array) => void), + assetSetter: (fileName: string, assetType: fileType) => string, + ADD_NEXT_ARG_LIST: Array, SCRIPT_CONFIG: Array) { + this.assetsPrefetcher = assetsPrefetcher; + this.assetSetter = assetSetter; + this.ADD_NEXT_ARG_LIST = ADD_NEXT_ARG_LIST; + this.SCRIPT_CONFIG = SCRIPT_CONFIG; + } + + public parse(rawScene: string, sceneName: string, sceneUrl: string) { + let result; + try { + result = p.parse(rawScene); + } catch (e) { + throw parserSyntaxError(`ERROR: parsing scene "${rawScene}" error with ${e}`); + } + + let assetsList: Array = []; // 场景资源列表 + let subSceneList: Array = []; // 子场景列表 + + // 开始资源的预加载 + assetsList = uniqWith(assetsList); // 去重 + this.assetsPrefetcher(assetsList); + + result.sentenceList.forEach((sentence) => { + // 为了向后兼容性,我们单独抽取choose命令的原始语句 + if (sentence.command === commandType.choose) { + const r = sentence.args.find(obj => obj.key === 'contentRawRange'); + sentence.content = rawScene.substring(r.value[0], r.value[1]); + } + + // 将语句内容里的文件名转为相对或绝对路径 + const content = contentParser(sentence.content, sentence.command, this.assetSetter); + + // 扫描语句携带资源 + const sentenceAssets = assetsScanner(sentence.command, content, sentence.args); + + // 扫描语句携带子场景 + const subScene = subSceneScanner(sentence.command, content); + + // 添加至语句解析结果 + sentence.sentenceAssets = sentenceAssets; + sentence.subScene = subScene; + + // 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList + assetsList = [...assetsList, ...sentenceAssets]; + subSceneList = [...subSceneList, ...subScene]; + }); + + return result; + } + + public parseConfig(configText: string) { + return configParser(configText); + } + + public stringifyConfig(config: WebgalConfig) { + return config + .reduce( + (previousValue, curr) => + (previousValue + `${curr.command}:${curr.args.join('|')}${curr.options.length <= 0 ? '' : curr.options.reduce((p, c) => (p + ' -' + c.key + '=' + c.value), '')};\n`), + '' + ); + } + + public parseScssToWebgalStyleObj(scssString: string): IWebGALStyleObj { + return scss2cssinjsParser(scssString); + } + +} + +export default class SceneParser { + private readonly SCRIPT_CONFIG_MAP: ConfigMap; + constructor( + private readonly assetsPrefetcher: (assetList: IAsset[]) => void, + private readonly assetSetter: ( + fileName: string, + assetType: fileType, + ) => string, + private readonly ADD_NEXT_ARG_LIST: number[], + SCRIPT_CONFIG_INPUT: ConfigItem[] | ConfigMap, + ) { + if (Array.isArray(SCRIPT_CONFIG_INPUT)) { + this.SCRIPT_CONFIG_MAP = new Map(); + SCRIPT_CONFIG_INPUT.forEach((config) => { + this.SCRIPT_CONFIG_MAP.set(config.scriptString, config); + }); + } else { + this.SCRIPT_CONFIG_MAP = SCRIPT_CONFIG_INPUT; + } + } + /** + * 解析场景 + * @param rawScene 原始场景 + * @param sceneName 场景名称 + * @param sceneUrl 场景url + * @return 解析后的场景 + */ + parse(rawScene: string, sceneName: string, sceneUrl: string) { + return sceneParser( + rawScene, + sceneName, + sceneUrl, + this.assetsPrefetcher, + this.assetSetter, + this.ADD_NEXT_ARG_LIST, + this.SCRIPT_CONFIG_MAP, + ); + } + + parseConfig(configText: string) { + return configParser(configText); + } + + stringifyConfig(config: WebgalConfig) { + return config.reduce( + (previousValue, curr) => + previousValue + + `${curr.command}:${curr.args.join('|')}${ + curr.options.length <= 0 + ? '' + : curr.options.reduce( + (p, c) => p + ' -' + c.key + '=' + c.value, + '', + ) + };\n`, + '', + ); + } + + parseScssToWebgalStyleObj(scssString: string): IWebGALStyleObj{ + return scss2cssinjsParser(scssString); + } + +} + +export { ADD_NEXT_ARG_LIST, SCRIPT_CONFIG }; diff --git a/packages/parser-ng/src/interface/assets.ts b/packages/parser-ng/src/interface/assets.ts new file mode 100644 index 000000000..0fb0e2cfa --- /dev/null +++ b/packages/parser-ng/src/interface/assets.ts @@ -0,0 +1,12 @@ +/** + * 内置资源类型的枚举 + */ +export enum fileType { + background, + bgm, + figure, + scene, + tex, + vocal, + video, +} diff --git a/packages/parser-ng/src/interface/runtimeInterface.ts b/packages/parser-ng/src/interface/runtimeInterface.ts new file mode 100644 index 000000000..d10f30fbd --- /dev/null +++ b/packages/parser-ng/src/interface/runtimeInterface.ts @@ -0,0 +1,9 @@ +/** + * 子场景结束后回到父场景的入口 + * @interface sceneEntry + */ +export interface sceneEntry { + sceneName: string; // 场景名称 + sceneUrl: string; // 场景url + continueLine: number; // 继续原场景的行号 +} diff --git a/packages/parser-ng/src/interface/sceneInterface.ts b/packages/parser-ng/src/interface/sceneInterface.ts new file mode 100644 index 000000000..e5419af3b --- /dev/null +++ b/packages/parser-ng/src/interface/sceneInterface.ts @@ -0,0 +1,105 @@ +/** + * 语句类型 + */ +import { sceneEntry } from './runtimeInterface'; +import { fileType } from './assets'; + +export enum commandType { + say, // 对话 + changeBg, // 更改背景 + changeFigure, // 更改立绘 + bgm, // 更改背景音乐 + video, // 播放视频 + pixi, // pixi演出 + pixiInit, // pixi初始化 + intro, // 黑屏文字演示 + miniAvatar, // 小头像 + changeScene, // 切换场景 + choose, // 分支选择 + end, // 结束游戏 + setComplexAnimation, // 动画演出 + setFilter, // 设置效果 + label, // 标签 + jumpLabel, // 跳转标签 + chooseLabel, // 选择标签 + setVar, // 设置变量 + if, // 条件跳转 + callScene, // 调用场景 + showVars, + unlockCg, + unlockBgm, + filmMode, + setTextbox, + setAnimation, + playEffect, + setTempAnimation, + comment, + setTransform, + setTransition, + getUserInput, + applyStyle +} + +/** + * 单个参数接口 + * @interface arg + */ +export interface arg { + key: string; // 参数键 + value: string | boolean | number; // 参数值 +} + +/** + * 资源接口 + * @interface IAsset + */ +export interface IAsset { + name: string; // 资源名称 + type: fileType; // 资源类型 + url: string; // 资源url + lineNumber: number; // 触发资源语句的行号 +} + +/** + * 单条语句接口 + * @interface ISentence + */ +export interface ISentence { + command: commandType; // 语句类型 + commandRaw: string; // 命令的原始内容,方便调试 + content: string; // 语句内容 + args: Array; // 参数列表 + sentenceAssets: Array; // 语句携带的资源列表 + subScene: Array; // 语句包含子场景列表 +} + +/** + * 场景接口 + * @interface IScene + */ +export interface IScene { + sceneName: string; // 场景名称 + sceneUrl: string; // 场景url + sentenceList: Array; // 语句列表 + assetsList: Array; // 资源列表 + subSceneList: Array; // 子场景的url列表 +} + +/** + * 当前的场景数据 + * @interface ISceneData + */ +export interface ISceneData { + currentSentenceId: number; // 当前语句ID + sceneStack: Array; // 场景栈 + currentScene: IScene; // 当前场景数据 +} + +/** + * 处理后的命令接口 + * @interface parsedCommand + */ +export interface parsedCommand { + type: commandType; + additionalArgs: Array; +} diff --git a/packages/parser-ng/src/parser.pegjs b/packages/parser-ng/src/parser.pegjs new file mode 100644 index 000000000..5313f4459 --- /dev/null +++ b/packages/parser-ng/src/parser.pegjs @@ -0,0 +1,979 @@ +{{ + const commandType = { + say: 0, // 对话 + changeBg: 1, // 更改背景 + changeFigure: 2, // 更改立绘 + bgm: 3, // 更改背景音乐 + video: 4, // 播放视频 + pixi: 5, // pixi演出 + pixiInit: 6, // pixi初始化 + intro: 7, // 黑屏文字演示 + miniAvatar: 8, // 小头像 + changeScene: 9, // 切换场景 + choose: 10, // 分支选择 + end: 11, // 结束游戏 + setComplexAnimation: 12, // 动画演出 + setFilter: 13, // 设置效果 + label: 14, // 标签 + jumpLabel: 15, // 跳转标签 + chooseLabel: 16, // 选择标签 + setVar: 17, // 设置变量 + if: 18, // 条件跳转 + callScene: 19, // 调用场景 + showVars: 20, + unlockCg: 21, + unlockBgm: 22, + filmMode: 23, + setTextbox: 24, + setAnimation: 25, + playEffect: 26, + setTempAnimation: 27, + comment: 28, + setTransform: 29, + setTransition: 30, + getUserInput: 31 + }; + + + function buildList(head, tail, index) { + return [head].concat(extractList(tail, index)); + } + + function extractList(list, index) { + return list.map(function(element) { return element[index]; }); + } + + function optionalList(value) { + return value !== null ? value : []; + } + + function optionalString(value) { + return value != null ? value : ""; + } + + function filterNulls(value) { + return value.filter(function(element) { return element != null; }); + } + + function processVocalFileName(args) { + return args.map((arg) => { + if (arg.key.toLowerCase().match(/.ogg|.mp3|.wav/)) { + return { + key: "vocal", + value: arg.key + }; + } + return arg; + }); + } + + function processNone(content) { + if (content === "" || content.toLowerCase() === "none") { + return ""; + } + return content; + } +}} + +{ + // ----- Error Handling ----- + let errors = []; + function report(message, loc = location()) { + errors.push({ + location: `${loc.start.offset}(${loc.start.line}:${loc.start.column})..${loc.end.offset}(${loc.end.line}:${loc.end.column})`, + message, + }); + } +} + + +// ----- Entrypoint ----- + +Start + = program:Program EOF { return { sentenceList: program, errors }; } + / program:Program REPORT { return { sentenceList: program, errors }; } + +REPORT + = .+ { report("parsing cannot preceed"); } + +Program + = body:SourceElements? { + return optionalList(body); + } + +SourceElements + = head:SourceElement CommentSegment? tail:(SourceElementTail)* { + return buildList(head, tail, 1); + } + +SourceElementTail + = EOS SourceElement CommentSegment? + / SKIPToNextStatement SourceElement CommentSegment? + +SKIPToNextStatement + = REPORTNonCompletedParsing LineTerminator + +REPORTNonCompletedParsing + = NonLineTerminator+ { + report("non-completed parsing"); + } + +NonLineTerminator + = !(LineTerminatorSequence) SourceCharacter + +CommentSymbol + = ";" + +CommentSegment + = _ CommentSymbol @$Comment + +SourceElement "source element" + = Statement + // / FunctionDeclaration + +// ----- Arguments ----- + +ArgList "arguments" + = head:Arg tail:(&__ Arg)* { + return buildList(head, tail, 1); + } + +Arg "argument" + = &__ ArgStart @ArgBody + +ArgStart + = " -" + +ArgBody + = @ArgWithValue / @ArgWithoutValue + +ArgWithValue "argument with value" + = key:ArgKey "=" value:StringLiteralAllowWhiteSpace { + value = value.trim() + + if (value === "none") { + value = ""; + } else if (value === "true" || value === "false") { + value = (value === "true"); + } else { + const number = Number(value); + if (!isNaN(number)) { + value = number; + } + } + + return { key, value }; + } + +ArgWithoutValue "argument without value" + = key:ArgKey { + return { key, value: true }; + } + +// ----- Reserved Words & Tokens ----- + +ReservedWord "reserve word" + = Keyword + // / ArgKeyword + +Keyword + = ChangeBgToken + + +ChangeBgToken "'changeBg'" = @"changeBg" !IdentifierPart +ChangeFigureToken "'changeFigure'" = @"changeFigure" !IdentifierPart +BgmToken "'bgm'" = @"bgm" !IdentifierPart +VideoToken "'playVideo'" = @"playVideo" !IdentifierPart // NOT SAME +PixiToken "'pixiPerform'" = @"pixiPerform" !IdentifierPart // NOT SAME +PixiInitToken "'pixiInit'" = @"pixiInit" !IdentifierPart +IntroToken "'intro'" = @"intro" !IdentifierPart +MiniAvatarToken "'miniAvatar'" = @"miniAvatar" !IdentifierPart +ChangeSceneToken "'changeScene'" = @"changeScene" !IdentifierPart +ChooseToken "'choose'" = @"choose" !IdentifierPart +EndToken "'end'" = @"end" !IdentifierPart +SetComplexAnimationToken "'setComplexAnimation'" = @"setComplexAnimation" !IdentifierPart +SetFilterToken "'setFilter'" = @"setFilter" !IdentifierPart +LabelToken "'label'" = @"label" !IdentifierPart +JumpLabelToken "'jumpLabel'" = @"jumpLabel" !IdentifierPart +ChooseLabelToken "'chooseLabel'" = @"chooseLabel" !IdentifierPart +SetVarToken "'setVar'" = @"setVar" !IdentifierPart +IfToken "'if'" = @"if" !IdentifierPart +CallSceneToken "'callScene'" = @"callScene" !IdentifierPart +ShowVarsToken "'showVars'" = @"showVars" !IdentifierPart +UnlockCgToken "'unlockCg'" = @"unlockCg" !IdentifierPart +UnlockBgmToken "'unlockBgm'" = @"unlockBgm" !IdentifierPart +FilmModeToken "'filmMode'" = @"filmMode" !IdentifierPart +SetTextboxToken "'setTextbox'" = @"setTextbox" !IdentifierPart +SetAnimationToken "'setAnimation'" = @"setAnimation" !IdentifierPart +PlayEffectToken "'playEffect'" = @"playEffect" !IdentifierPart +SetTempAnimationToken "'setTempAnimation'" = @"setTempAnimation" !IdentifierPart +CommentToken "'comment'" = @"comment" !IdentifierPart // NO HANDLER +SetTransformToken "'setTransform'" = @"setTransform" !IdentifierPart +SetTransitionToken "'setTransition'" = @"setTransition" !IdentifierPart +GetUserInputToken "'getUserInput'" = @"getUserInput" !IdentifierPart + + +/* +Currently, we do not need to check all argument keys. But the key should be +more strict than the value, e.g., do not allow symbols and special characters, +and should not be empty. +*/ +ArgKey + = $KeyCharacter+ + +KeyCharacter + = !(CommentSymbol / "=" / BraceCharacterSequence / WhiteSpace / LineTerminator / EOS / ArgStart) SourceCharacter { return text(); } + +// ArgKeyword +// = NextToken +// / LeftToken +// / TransformToken + +// NextToken "'next'" = @"next" !IdentifierPart +// LeftToken "'left'" = @"left" !IdentifierPart +// TransformToken "'transform'" = @"transform" !IdentifierPart + +// ----- String ----- + +StringLiteral "string" + = "'" sequence:SingleStringCharacter* "'" { return sequence.join(""); } + / '"' sequence:DoubleStringCharacter* '"' { return sequence.join(""); } + / sequence:StringCharacter* { return sequence.join("") } + +StringLiteralAllowWhiteSpace "string allow white space" + = "'" sequence:SingleStringCharacter* "'" { return sequence.join(""); } + / '"' sequence:DoubleStringCharacter* '"' { return sequence.join(""); } + / sequence:StringCharacterAllowWhiteSpace* { return sequence.join(""); } + +SingleStringCharacter + = !("'" / "\\" / LineTerminator) SourceCharacter { return text(); } + / "\\" sequence:EscapeSequence { return sequence; } + +DoubleStringCharacter + = !('"' / "\\" / LineTerminator) SourceCharacter { return text(); } + / "\\" sequence:EscapeSequence { return sequence; } + +StringCharacter + = !(CommentSymbol / LineTerminator / EOS / WhiteSpace / ArgStart) SourceCharacter { return text(); } + +StringCharacterAllowWhiteSpace + = !(CommentSymbol / LineTerminator / EOS / ArgStart) SourceCharacter { return text(); } + +// ----- String: Escape ----- + +EscapeSequence + = CharacterEscapeSequence + / "0" !DecimalDigit { return "\0"; } + / HexEscapeSequence + / UnicodeEscapeSequence + +CharacterEscapeSequence + = SingleEscapeCharacter + / NonEscapeCharacter + +SingleEscapeCharacter + = "'" + / '"' + / "\\" + / "b" { return "\b"; } + / "f" { return "\f"; } + / "n" { return "\n"; } + / "r" { return "\r"; } + / "t" { return "\t"; } + / "v" { return "\v"; } + +BraceCharacterSequence + = "{" + / "}" + / "(" + / ")" + +NonEscapeCharacter + = !(EscapeCharacter / LineTerminator) SourceCharacter { return text(); } + +EscapeCharacter + = SingleEscapeCharacter + / DecimalDigit + / "x" + / "u" + +DecimalDigit + = [0-9] + +HexEscapeSequence + = "x" digits:$(HexDigit HexDigit) { + return String.fromCharCode(parseInt(digits, 16)); + } + +UnicodeEscapeSequence + = "u" digits:$(HexDigit HexDigit HexDigit HexDigit) { + return String.fromCharCode(parseInt(digits, 16)); + } + +// ----- Identifier ----- + +IdentifierStart + = UnicodeLetter + / "$" + / "_" + / "\\" sequence:UnicodeEscapeSequence { return sequence; } + +HexDigit + = [0-9a-f]i + +IdentifierPart + = IdentifierStart + / UnicodeCombiningMark + / UnicodeDigit + / UnicodeConnectorPunctuation + / "\u200C" + / "\u200D" + +UnicodeLetter + = Lu + / Ll + / Lt + / Lm + / Lo + / Nl + +UnicodeCombiningMark + = Mn + / Mc + +UnicodeDigit + = Nd + +UnicodeConnectorPunctuation + = Pc + +// ----- Character, Space & Line Terminators ----- + +SourceCharacter + = . + +LineTerminator "line terminator" + = [\n\r\u2028\u2029] + +LineTerminatorSequence "end of line" + = "\n" + / "\r\n" + / "\r" + / "\u2028" + / "\u2029" + +WhiteSpace "whitespace" + = "\t" + / "\v" + / "\f" + / " " + / "\u00A0" + / "\uFEFF" + / Zs + +// Mandatory white space +_M_ + = (WhiteSpace / LineTerminatorSequence)+ + +__ + = (WhiteSpace / LineTerminatorSequence)* + +_ + = (WhiteSpace)* + +Comment + = $(!LineTerminator SourceCharacter)* + +EOS + = _ ";" Comment LineTerminatorSequence + / _ LineTerminatorSequence + +EOF + = !. + +// ----- Statements ----- + +EmptyStatement + = _ comment:CommentSegment { + comment = optionalString(comment); + + return { + command: commandType.comment, + commandRaw: "comment", + content: comment, + args: [], + } + } + / &(_ LineTerminatorSequence) { + return { + command: commandType.comment, + commandRaw: "comment", + content: "", + args: [], + } + } + +ChangeBgStatement "changeBg statement" + = ChangeBgToken __ ":" fileName:StringLiteral args:ArgList? { + args = optionalList(args); + fileName = processNone(fileName.trim()); + + return { + command: commandType.changeBg, + commandRaw: "changeBg", + content: fileName, + args, + }; + } + +ChangeFigureStatement "changeFigure statement" + = ChangeFigureToken __ ":" fileName:StringLiteral args:ArgList? { + args = optionalList(args); + fileName = processNone(fileName.trim()); + + return { + command: commandType.changeFigure, + commandRaw: "changeFigure", + content: fileName, + args, + }; + } + +BgmStatement "bgm statement" + = BgmToken __ ":" fileName:StringLiteral args:ArgList? { + args = optionalList(args); + fileName = processNone(fileName.trim()); + + return { + command: commandType.bgm, + commandRaw: "bgm", + content: fileName, + args, + }; + } + +VideoStatement "video statement" + = VideoToken __ ":" fileName:StringLiteral args:ArgList? { + args = optionalList(args); + fileName = processNone(fileName.trim()); + + return { + command: commandType.video, + commandRaw: "playVideo", + content: fileName, + args, + }; + } + +PixiStatement "pixi statement" + = PixiToken __ ":" performName:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.pixi, + commandRaw: "pixiPerform", + content: performName, + args, + }; + } + +PixiInitStatement "pixiInit statement" + = PixiInitToken { + return { + command: commandType.pixiInit, + commandRaw: "pixiInit", + content: "", + args: [], + }; + } + +IntroStatement "intro statement" + = IntroToken __ ":" lines:StringLiteralAllowWhiteSpace args:ArgList? { + args = optionalList(args); + + return { + command: commandType.intro, + commandRaw: "intro", + content: processNone(lines.trim()), + args, + }; + } + +MiniAvatarStatement "miniAvatar statement" + = MiniAvatarToken __ ":" fileName:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.miniAvatar, + commandRaw: "miniAvatar", + content: processNone(fileName.trim()), + args, + }; + } + +ChangeSceneStatement "changeScene statement" + = ChangeSceneToken __ ":" fileName:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.changeScene, + commandRaw: "changeScene", + content: processNone(fileName.trim()), + args, + }; + } + +ChooseStatement "choose statement" + = ChooseToken __ ":" choices:ChoiceList { + choices.choiceList = optionalList(choices.choiceList); + + return { + command: commandType.choose, + commandRaw: "choose", + content: "", + args: [ + { key: "choices", value: choices.choiceList }, + { key: "contentRawRange", value: choices.contentRawRange } + ], + }; + } + +ChoiceList "choices" + = head:Choice tail:(VerticalBar Choice)* { + const loc = location(); + + return { + contentRawRange: [loc.start.offset, loc.end.offset], + choiceList: buildList(head, tail, 1) + }; + } + +VerticalBar + = "|" + +Choice "choice" + = "(" sexp:NoParenthesisExpression ")" "[" cexp:NoBracketExpression "]" "->" text:ChoiceTextLiteral ":" dest:ChoiceDestinationLiteral { + return { + showExpression: sexp, + clickExpression: cexp, + text, + destination: dest, + } + } + / text:ChoiceTextLiteral ":" dest:ChoiceDestinationLiteral { + return { + showExpression: "", + clickExpression: "", + text, + destination: dest, + } + } + +NoParenthesisExpression + = sequence:NoParenthesisExpressionCharacter* { return sequence.join(""); } + +NoParenthesisExpressionCharacter + = !(LineTerminator / EOS / ")") SourceCharacter { return text(); } + +NoBracketExpression + = sequence:NoBracketExpressionCharacter* { return sequence.join(""); } + +NoBracketExpressionCharacter + = !(LineTerminator / EOS / "]") SourceCharacter { return text(); } + +ChoiceTextLiteral + = $ChoiceTextCharacter* + +ChoiceTextCharacter + = !(CommentSymbol / LineTerminator / EOS / ":") SourceCharacter { return text(); } + +ChoiceDestinationLiteral + = $ChoiceDestinationCharacter* + +ChoiceDestinationCharacter + = !(CommentSymbol / LineTerminator / EOS / VerticalBar) SourceCharacter { return text(); } + +EndStatement "end statement" + = EndToken { + return { + command: commandType.end, + commandRaw: "end", + content: "", + args: [], + }; + } + +SetComplexAnimationStatement "setComplexAnimation statement" + = SetComplexAnimationToken __ ":" animationName:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.setComplexAnimation, + commandRaw: "setComplexAnimation", + content: animationName, + args, + }; + } + +SetFilterStatement "setFilter statement" + = SetFilterToken { + return { + command: commandType.setFilter, + commandRaw: "setFilter", + content: "", + args: [], + }; + } + +LabelStatement "label statement" + = LabelToken __ ":" labelName:StringLiteral { + return { + command: commandType.label, + commandRaw: "label", + content: labelName, + args: [], + }; + } + +JumpLabelStatement "jumpLabel statement" + = JumpLabelToken __ ":" labelName:StringLiteral { + return { + command: commandType.jumpLabel, + commandRaw: "jumpLabel", + content: labelName, + args: [], + }; + } + +SetVarStatement "setVar statement" + /* Internal variables */ + = SetVarToken __ ":" kv:InternalArgWithValue args:ArgList? { + // we prefix variableName and expression with `#` to separate it from + // user-defined arguments + args = optionalList(args); + + return { + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: kv.key }, + { key: "#internalExpression", value: kv.value }, + ].concat(args), + }; + } + /* Other variables */ + / SetVarToken __ ":" kv:ArgWithValue args:ArgList? { + args = optionalList(args); + + return { + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: kv.key }, + { key: "#expression", value: kv.value }, + ].concat(args), + }; + } + +InternalArgWithValue "argument with value" + = key:ArgKey "=" "(" value:InternalArgLiteral ")" { + if (value === "none") { + value = ""; + } else if (value === "true" || value === "false") { + value = (value === "true"); + } else { + const number = Number(value); + if (!isNaN(number)) { + value = number; + } + } + + return { key, value }; + } + +InternalArgLiteral "internal argument" + = $InternalArgCharacter+ + +InternalArgCharacter + = !(CommentSymbol / ")" / LineTerminator / EOS / "=") SourceCharacter { return text(); } + +CallSceneStatement "callScene statement" + = CallSceneToken __ ":" sceneName:StringLiteral { + return { + command: commandType.callScene, + commandRaw: "callScene", + content: sceneName, + args: [], + }; + } + +ShowVarsStatement "showVars statement" + = ShowVarsToken { + return { + command: commandType.showVars, + commandRaw: "showVars", + content: "", + args: [], + }; + } + +UnlockCgStatement "unlockCg statement" + = UnlockCgToken __ ":" name:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.unlockCg, + commandRaw: "unlockCg", + content: name, + args, + }; + } + +UnlockBgmStatement "unlockBgm statement" + = UnlockBgmToken __ ":" name:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.unlockBgm, + commandRaw: "unlockBgm", + content: name, + args, + }; + } + +FilmModeStatement "filmMode statement" + = FilmModeToken __ ":" content:StringLiteralAllowWhiteSpace { + content = processNone(content.trim()); + + return { + command: commandType.filmMode, + commandRaw: "filmMode", + content, + args: [], + }; + } + +SetTextboxStatement "setTextbox statement" + = SetTextboxToken __ ":" content:StringLiteral { + return { + command: commandType.setTextbox, + commandRaw: "setTextbox", + content, + args: [], + }; + } + +SetAnimationStatement "setAnimation statement" + = SetAnimationToken __ ":" content:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.setAnimation, + commandRaw: "setAnimation", + content, + args, + }; + } + +SetTransitionStatement "setTransition statement" + = SetTransitionToken __ ":" args:ArgList? { + args = optionalList(args); + + return { + command: commandType.setTransition, + commandRaw: "setTransition", + content: "", + args, + }; + } + +PlayEffectStatement "playEffect statement" + = PlayEffectToken __ ":" name:StringLiteral args:ArgList? { + name = processNone(name.trim()); + args = optionalList(args); + + return { + command: commandType.playEffect, + commandRaw: "playEffect", + content: name, + args, + }; + } + +SetTempAnimationStatement "setTempAnimation statement" + = SetTempAnimationToken __ ":" "[" json:NoBracketExpression "]" args:ArgList? { + // Here, we do a trick by directly check whether a bracket is in the + // expression since we don't want to add extra cost on parsing JSON. + // The direct check holds because the content will never encounter a + // close bracket. + args = optionalList(args); + + return { + command: commandType.setTempAnimation, + commandRaw: "setTempAnimation", + content: `[${json}]`, + args, + }; + } + +SetTransformStatement "setTransform statement" + = SetTransformToken __ ":" json:StringLiteral args:ArgList? { + args = optionalList(args); + + return { + command: commandType.setTransform, + commandRaw: "setTransform", + content: json, + args, + }; + } + +GetUserInputStatement "getUserInput statement" + = GetUserInputToken __ ":" into:ArgKey args:ArgList? { + args = optionalList(args); + + return { + command: commandType.getUserInput, + commandRaw: "getUserInput", + content: into, + args, + }; + } + + +SayStatement "say statement" + = speaker:SpeakerLiteral ":" content:StringLiteralAllowWhiteSpace args:ArgList? { + args = optionalList(args); + args = processVocalFileName(args); + + return { + command: commandType.say, + commandRaw: speaker, + content: content.trim(), + args: [{ key: "speaker", value: speaker }].concat(args), + } + } + / content:NonEmptyStringLiteralAllowWhiteSpace args:ArgList? { + args = optionalList(args); + + return { + command: commandType.say, + commandRaw: "say", + content: content.trim(), + args, + } + } + +NonEmptyStringLiteralAllowWhiteSpace + = $StringCharacterAllowWhiteSpace+ + +SpeakerLiteral + = $SpeakerCharacter* + +SpeakerCharacter + = !(CommentSymbol / ":" / LineTerminator / EOS / ArgStart) SourceCharacter { return text(); } + + +/*****************************************************************************/ +/****************** ! REMEMBER TO ADD NEW STATEMENTS HERE ! ******************/ +/*****************************************************************************/ +Statement "statement" + = ChangeBgStatement + / ChangeFigureStatement + / BgmStatement + / VideoStatement + / PixiStatement + / PixiInitStatement + / IntroStatement + / MiniAvatarStatement + / ChangeSceneStatement + / ChooseStatement + / EndStatement + / SetComplexAnimationStatement + / SetFilterStatement + / LabelStatement + / JumpLabelStatement + / SetVarStatement + / CallSceneStatement + / ShowVarsStatement + / UnlockCgStatement + / UnlockBgmStatement + / FilmModeStatement + / SetTextboxStatement + / SetAnimationStatement + / SetTransitionStatement + / PlayEffectStatement + / SetTempAnimationStatement + / SetTransformStatement + / GetUserInputStatement +// if all commands failed, it should be a say statement +// (either with or without ':') + / SayStatement +// if still cannot match, it may be a comment without command or an empty line +// (which is also a comment) + / EmptyStatement +// if still cannot match, it should be an error + / ERRORStatement +/*****************************************************************************/ +/****************** ! REMEMBER TO ADD NEW STATEMENTS HERE ! ******************/ +/*****************************************************************************/ +ERRORStatement = err:$(!EOS .)+ { report("unexpected statement `" + err + "`"); }; + + +// ----- Unicode Character Categories ----- +// +// Extracted from the following Unicode Character Database file: +// +// http://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedGeneralCategory.txt +// +// Unix magic used: +// +// grep "; $CATEGORY" DerivedGeneralCategory.txt | # Filter characters +// cut -f1 -d " " | # Extract code points +// grep -v '[0-9a-fA-F]\{5\}' | # Exclude non-BMP characters +// sed -e 's/\.\./-/' | # Adjust formatting +// sed -e 's/\([0-9a-fA-F]\{4\}\)/\\u\1/g' | # Adjust formatting +// tr -d '\n' # Join lines +// +// ECMA-262 allows using Unicode 3.0 or later, version 8.0.0 was the latest one +// at the time of writing. +// +// Non-BMP characters are completely ignored to avoid surrogate pair handling +// (detecting surrogate pairs isn't possible with a simple character class and +// other methods would degrade performance). I don't consider it a big deal as +// even parsers in JavaScript engines of common browsers seem to ignore them. + +// Letter, Lowercase +Ll = [\u0061-\u007A\u00B5\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137-\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148-\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C-\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA-\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9-\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC-\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF-\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F-\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0-\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB-\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE-\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0561-\u0587\u13F8-\u13FD\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6-\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FC7\u1FD0-\u1FD3\u1FD6-\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6-\u1FF7\u210A\u210E-\u210F\u2113\u212F\u2134\u2139\u213C-\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65-\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73-\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3-\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7B5\uA7B7\uA7FA\uAB30-\uAB5A\uAB60-\uAB65\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A] + +// Letter, Modifier +Lm = [\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0374\u037A\u0559\u0640\u06E5-\u06E6\u07F4-\u07F5\u07FA\u081A\u0824\u0828\u0971\u0E46\u0EC6\u10FC\u17D7\u1843\u1AA7\u1C78-\u1C7D\u1D2C-\u1D6A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\u2D6F\u2E2F\u3005\u3031-\u3035\u303B\u309D-\u309E\u30FC-\u30FE\uA015\uA4F8-\uA4FD\uA60C\uA67F\uA69C-\uA69D\uA717-\uA71F\uA770\uA788\uA7F8-\uA7F9\uA9CF\uA9E6\uAA70\uAADD\uAAF3-\uAAF4\uAB5C-\uAB5F\uFF70\uFF9E-\uFF9F] + +// Letter, Other +Lo = [\u00AA\u00BA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05F0-\u05F2\u0620-\u063F\u0641-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0-\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0CF1-\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065-\u1066\u106E-\u1070\u1075-\u1081\u108E\u10D0-\u10FA\u10FD-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE-\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5-\u1CF6\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A-\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC] + +// Letter, Titlecase +Lt = [\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC] + +// Letter, Uppercase +Lu = [\u0041-\u005A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178-\u0179\u017B\u017D\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018B\u018E-\u0191\u0193-\u0194\u0196-\u0198\u019C-\u019D\u019F-\u01A0\u01A2\u01A4\u01A6-\u01A7\u01A9\u01AC\u01AE-\u01AF\u01B1-\u01B3\u01B5\u01B7-\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A-\u023B\u023D-\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9-\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0-\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E-\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D-\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AD\uA7B0-\uA7B4\uA7B6\uFF21-\uFF3A] + +// Mark, Spacing Combining +Mc = [\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E-\u094F\u0982-\u0983\u09BE-\u09C0\u09C7-\u09C8\u09CB-\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB-\u0ACC\u0B02-\u0B03\u0B3E\u0B40\u0B47-\u0B48\u0B4B-\u0B4C\u0B57\u0BBE-\u0BBF\u0BC1-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82-\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7-\u0CC8\u0CCA-\u0CCB\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82-\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2-\u0DF3\u0F3E-\u0F3F\u0F7F\u102B-\u102C\u1031\u1038\u103B-\u103C\u1056-\u1057\u1062-\u1064\u1067-\u106D\u1083-\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6\u17BE-\u17C5\u17C7-\u17C8\u1923-\u1926\u1929-\u192B\u1930-\u1931\u1933-\u1938\u1A19-\u1A1A\u1A55\u1A57\u1A61\u1A63-\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43-\u1B44\u1B82\u1BA1\u1BA6-\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2-\u1BF3\u1C24-\u1C2B\u1C34-\u1C35\u1CE1\u1CF2-\u1CF3\u302E-\u302F\uA823-\uA824\uA827\uA880-\uA881\uA8B4-\uA8C3\uA952-\uA953\uA983\uA9B4-\uA9B5\uA9BA-\uA9BB\uA9BD-\uA9C0\uAA2F-\uAA30\uAA33-\uAA34\uAA4D\uAA7B\uAA7D\uAAEB\uAAEE-\uAAEF\uAAF5\uABE3-\uABE4\uABE6-\uABE7\uABE9-\uABEA\uABEC] + +// Mark, Nonspacing +Mn = [\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2-\u09E3\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B62-\u0B63\u0B82\u0BC0\u0BCD\u0C00\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC6\u0CCC-\u0CCD\u0CE2-\u0CE3\u0D01\u0D41-\u0D44\u0D4D\u0D62-\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099-\u309A\uA66F\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1\uA802\uA806\uA80B\uA825-\uA826\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F] + +// Number, Decimal Digit +Nd = [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19] + +// Number, Letter +Nl = [\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF] + +// Punctuation, Connector +Pc = [\u005F\u203F-\u2040\u2054\uFE33-\uFE34\uFE4D-\uFE4F\uFF3F] + +// Separator, Space +Zs = [\u0020\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000] \ No newline at end of file diff --git a/packages/parser-ng/src/sceneParser.ts b/packages/parser-ng/src/sceneParser.ts new file mode 100644 index 000000000..9d2a72b83 --- /dev/null +++ b/packages/parser-ng/src/sceneParser.ts @@ -0,0 +1,66 @@ +import { + commandType, + IAsset, + IScene, + ISentence, +} from './interface/sceneInterface'; +import { scriptParser } from './scriptParser/scriptParser'; +import uniqWith from 'lodash/uniqWith'; +import { fileType } from './interface/assets'; +import { ConfigMap } from './config/scriptConfig'; + +/** + * 场景解析器 + * @param rawScene 原始场景 + * @param sceneName 场景名称 + * @param sceneUrl 场景url + * @param assetsPrefetcher + * @param assetSetter + * @param ADD_NEXT_ARG_LIST + * @param SCRIPT_CONFIG_MAP + * @return {IScene} 解析后的场景 + */ +export const sceneParser = ( + rawScene: string, + sceneName: string, + sceneUrl: string, + assetsPrefetcher: (assetList: Array) => void, + assetSetter: (fileName: string, assetType: fileType) => string, + ADD_NEXT_ARG_LIST: commandType[], + SCRIPT_CONFIG_MAP: ConfigMap, +): IScene => { + const rawSentenceList = rawScene.split('\n'); // 原始句子列表 + + // 去分号留到后面去做了,现在注释要单独处理 + const rawSentenceListWithoutEmpty = rawSentenceList; + // .map((sentence) => sentence.split(";")[0]) + // .filter((sentence) => sentence.trim() !== ""); + let assetsList: Array = []; // 场景资源列表 + let subSceneList: Array = []; // 子场景列表 + const sentenceList: Array = rawSentenceListWithoutEmpty.map( + (sentence) => { + const returnSentence: ISentence = scriptParser( + sentence, + assetSetter, + ADD_NEXT_ARG_LIST, + SCRIPT_CONFIG_MAP, + ); + // 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList + assetsList = [...assetsList, ...returnSentence.sentenceAssets]; + subSceneList = [...subSceneList, ...returnSentence.subScene]; + return returnSentence; + }, + ); + + // 开始资源的预加载 + assetsList = uniqWith(assetsList); // 去重 + assetsPrefetcher(assetsList); + + return { + sceneName: sceneName, // 场景名称 + sceneUrl: sceneUrl, + sentenceList: sentenceList, // 语句列表 + assetsList: assetsList, // 资源列表 + subSceneList: subSceneList, // 子场景列表 + }; +}; diff --git a/packages/parser-ng/src/scriptParser/argsParser.ts b/packages/parser-ng/src/scriptParser/argsParser.ts new file mode 100644 index 000000000..9cff77451 --- /dev/null +++ b/packages/parser-ng/src/scriptParser/argsParser.ts @@ -0,0 +1,71 @@ +import { arg } from '../interface/sceneInterface'; +import { fileType } from '../interface/assets'; + +/** + * 参数解析器 + * @param argsRaw 原始参数字符串 + * @param assetSetter + * @return {Array} 解析后的参数列表 + */ +export function argsParser( + argsRaw: string, + assetSetter: (fileName: string, assetType: fileType) => string, +): Array { + const returnArrayList: Array = []; + // 处理参数 + // 不要去空格 + let newArgsRaw = argsRaw.replace(/ /g, ' '); + // 分割参数列表 + let rawArgsList: Array = newArgsRaw.split(' -'); + // 去除空字符串 + rawArgsList = rawArgsList.filter((e) => { + return e !== ''; + }); + rawArgsList.forEach((e) => { + const equalSignIndex = e.indexOf('='); + let argName = e.slice(0, equalSignIndex); + let argValue: string | undefined = e.slice(equalSignIndex + 1); + if (equalSignIndex < 0) { + argName = e; + argValue = undefined; + } + // 判断是不是语音参数 + if (argName.toLowerCase().match(/.ogg|.mp3|.wav/)) { + returnArrayList.push({ + key: 'vocal', + value: assetSetter(e, fileType.vocal), + }); + } else { + // 判断是不是省略参数 + if (argValue === undefined) { + returnArrayList.push({ + key: argName, + value: true, + }); + } else { + // 是字符串描述的布尔值 + if (argValue === 'true' || argValue === 'false') { + returnArrayList.push({ + key: argName, + value: argValue === 'true', + }); + } else { + // 是数字 + if (!isNaN(Number(argValue))) { + returnArrayList.push({ + key: argName, + value: Number(argValue), + }); + } else { + // 是普通参数 + returnArrayList.push({ + key: argName, + value: argValue, + }); + } + } + } + } + }); + return returnArrayList; +} diff --git a/packages/parser-ng/src/scriptParser/assetsScanner.ts b/packages/parser-ng/src/scriptParser/assetsScanner.ts new file mode 100644 index 000000000..cdff61be5 --- /dev/null +++ b/packages/parser-ng/src/scriptParser/assetsScanner.ts @@ -0,0 +1,76 @@ +import { arg, commandType, IAsset } from '../interface/sceneInterface'; +import { fileType } from '../interface/assets'; + +/** + * 根据语句类型、语句内容、参数列表,扫描该语句可能携带的资源 + * @param command 语句类型 + * @param content 语句内容 + * @param args 参数列表 + * @return {Array} 语句携带的参数列表 + */ +export const assetsScanner = ( + command: commandType, + content: string, + args: Array, +): Array => { + let hasVocalArg = false; + const returnAssetsList: Array = []; + if (command === commandType.say) { + args.forEach((e) => { + if (e.key === 'vocal') { + hasVocalArg = true; + returnAssetsList.push({ + name: e.value as string, + url: e.value as string, + lineNumber: 0, + type: fileType.vocal, + }); + } + }); + } + if (content === 'none' || content === '') { + return returnAssetsList; + } + // 处理语句携带的资源 + if (command === commandType.changeBg) { + returnAssetsList.push({ + name: content, + url: content, + lineNumber: 0, + type: fileType.background, + }); + } + if (command === commandType.changeFigure) { + returnAssetsList.push({ + name: content, + url: content, + lineNumber: 0, + type: fileType.figure, + }); + } + if (command === commandType.miniAvatar) { + returnAssetsList.push({ + name: content, + url: content, + lineNumber: 0, + type: fileType.figure, + }); + } + if (command === commandType.video) { + returnAssetsList.push({ + name: content, + url: content, + lineNumber: 0, + type: fileType.video, + }); + } + if (command === commandType.bgm) { + returnAssetsList.push({ + name: content, + url: content, + lineNumber: 0, + type: fileType.bgm, + }); + } + return returnAssetsList; +}; diff --git a/packages/parser-ng/src/scriptParser/commandParser.ts b/packages/parser-ng/src/scriptParser/commandParser.ts new file mode 100644 index 000000000..b08655881 --- /dev/null +++ b/packages/parser-ng/src/scriptParser/commandParser.ts @@ -0,0 +1,65 @@ +import { ConfigMap } from '../config/scriptConfig'; +import { commandType, parsedCommand } from '../interface/sceneInterface'; + +/** + * 处理命令 + * @param commandRaw + * @param ADD_NEXT_ARG_LIST + * @param SCRIPT_CONFIG_MAP + * @return {parsedCommand} 处理后的命令 + */ +export const commandParser = ( + commandRaw: string, + ADD_NEXT_ARG_LIST: commandType[], + SCRIPT_CONFIG_MAP: ConfigMap, +): parsedCommand => { + let returnCommand: parsedCommand = { + type: commandType.say, // 默认是say + additionalArgs: [], + }; + // 开始处理命令内容 + const type: commandType = getCommandType( + commandRaw, + ADD_NEXT_ARG_LIST, + SCRIPT_CONFIG_MAP, + ); + returnCommand.type = type; + // 如果是对话,加上额外的参数 + if (type === commandType.say && commandRaw !== 'say') { + returnCommand.additionalArgs.push({ + key: 'speaker', + value: commandRaw, + }); + } + returnCommand = addNextArg(returnCommand, type, ADD_NEXT_ARG_LIST); + return returnCommand; +}; + +/** + * 根据command原始值判断是什么命令 + * @param command command原始值 + * @param ADD_NEXT_ARG_LIST + * @param SCRIPT_CONFIG_MAP + * @return {commandType} 得到的command类型 + */ +function getCommandType( + command: string, + ADD_NEXT_ARG_LIST: commandType[], + SCRIPT_CONFIG_MAP: ConfigMap, +): commandType { + return SCRIPT_CONFIG_MAP.get(command)?.scriptType ?? commandType.say; +} + +function addNextArg( + commandToParse: parsedCommand, + thisCommandType: commandType, + ADD_NEXT_ARG_LIST: commandType[], +) { + if (ADD_NEXT_ARG_LIST.includes(thisCommandType)) { + commandToParse.additionalArgs.push({ + key: 'next', + value: true, + }); + } + return commandToParse; +} diff --git a/packages/parser-ng/src/scriptParser/contentParser.ts b/packages/parser-ng/src/scriptParser/contentParser.ts new file mode 100644 index 000000000..cbb6fd161 --- /dev/null +++ b/packages/parser-ng/src/scriptParser/contentParser.ts @@ -0,0 +1,70 @@ +import { commandType } from '../interface/sceneInterface'; +import { fileType } from '../interface/assets'; + +/** + * 解析语句内容的函数,主要作用是把文件名改为绝对地址或相对地址(根据使用情况而定) + * @param contentRaw 原始语句内容 + * @param type 语句类型 + * @param assetSetter + * @return {string} 解析后的语句内容 + */ +export const contentParser = ( + contentRaw: string, + type: commandType, + assetSetter: any, +) => { + if (contentRaw === 'none' || contentRaw === '') { + return ''; + } + switch (type) { + case commandType.playEffect: + return assetSetter(contentRaw, fileType.vocal); + case commandType.changeBg: + return assetSetter(contentRaw, fileType.background); + case commandType.changeFigure: + return assetSetter(contentRaw, fileType.figure); + case commandType.bgm: + return assetSetter(contentRaw, fileType.bgm); + case commandType.callScene: + return assetSetter(contentRaw, fileType.scene); + case commandType.changeScene: + return assetSetter(contentRaw, fileType.scene); + case commandType.miniAvatar: + return assetSetter(contentRaw, fileType.figure); + case commandType.video: + return assetSetter(contentRaw, fileType.video); + case commandType.choose: + return getChooseContent(contentRaw, assetSetter); + case commandType.unlockBgm: + return assetSetter(contentRaw, fileType.bgm); + case commandType.unlockCg: + return assetSetter(contentRaw, fileType.background); + default: + return contentRaw; + } +}; + +function getChooseContent(contentRaw: string, assetSetter: any): string { + const chooseList = contentRaw.split(/(? = []; + const chooseValueList: Array = []; + for (const e of chooseList) { + chooseKeyList.push(e.split(/(? { + if (e.match(/\./)) { + return assetSetter(e, fileType.scene); + } else { + return e; + } + }); + let ret = ''; + for (let i = 0; i < chooseKeyList.length; i++) { + if (i !== 0) { + ret = ret + '|'; + } + ret = ret + `${chooseKeyList[i]}:${parsedChooseList[i]}`; + } + return ret; +} diff --git a/packages/parser-ng/src/scriptParser/scriptParser.ts b/packages/parser-ng/src/scriptParser/scriptParser.ts new file mode 100644 index 000000000..10bbfe197 --- /dev/null +++ b/packages/parser-ng/src/scriptParser/scriptParser.ts @@ -0,0 +1,114 @@ +import { + arg, + commandType, + IAsset, + ISentence, + parsedCommand, +} from '../interface/sceneInterface'; +import { commandParser } from './commandParser'; +import { argsParser } from './argsParser'; +import { contentParser } from './contentParser'; +import { assetsScanner } from './assetsScanner'; +import { subSceneScanner } from './subSceneScanner'; +import { ConfigMap } from '../config/scriptConfig'; + +/** + * 语句解析器 + * @param sentenceRaw 原始语句 + * @param assetSetter + * @param ADD_NEXT_ARG_LIST + * @param SCRIPT_CONFIG_MAP + */ +export const scriptParser = ( + sentenceRaw: string, + assetSetter: any, + ADD_NEXT_ARG_LIST: commandType[], + SCRIPT_CONFIG_MAP: ConfigMap, +): ISentence => { + let command: commandType; // 默认为对话 + let content: string; // 语句内容 + let subScene: Array; // 语句携带的子场景(可能没有) + const args: Array = []; // 语句参数列表 + let sentenceAssets: Array; // 语句携带的资源列表 + let parsedCommand: parsedCommand; // 解析后的命令 + let commandRaw: string; + + // 正式开始解析 + + // 去分号 + let newSentenceRaw = sentenceRaw.split(/(?} 子场景列表 + */ +import { commandType } from '../interface/sceneInterface'; + +export const subSceneScanner = ( + command: commandType, + content: string, +): Array => { + const subSceneList: Array = []; + if ( + command === commandType.changeScene || + command === commandType.callScene + ) { + subSceneList.push(content); + } + if (command === commandType.choose) { + const chooseList = content.split('|'); + const chooseValue = chooseList.map((e) => e.split(':')[1] ?? ''); + chooseValue.forEach((e) => { + if (e.match(/\./)) { + subSceneList.push(e); + } + }); + } + return subSceneList; +}; diff --git a/packages/parser-ng/src/styleParser/index.ts b/packages/parser-ng/src/styleParser/index.ts new file mode 100644 index 000000000..a97d0f621 --- /dev/null +++ b/packages/parser-ng/src/styleParser/index.ts @@ -0,0 +1,39 @@ +export interface IWebGALStyleObj { + classNameStyles: Record; + others: string; +} + +export function scss2cssinjsParser(scssString: string): IWebGALStyleObj { + const [classNameStyles, others] = parseCSS(scssString); + return { + classNameStyles, + others, + }; +} + +/** + * GPT 4 写的,临时用,以后要重构!!! + * TODO:用人类智能重构,要是用着一直没问题,也不是不可以 trust AI + * @param css + */ +function parseCSS(css: string): [Record, string] { + const result: Record = {}; + let specialRules = ''; + let matches; + + // 使用非贪婪匹配,尝试正确处理任意层次的嵌套 + const classRegex = /\.([^{\s]+)\s*{((?:[^{}]*|{[^}]*})*)}/g; + const specialRegex = /(@[^{]+{\s*(?:[^{}]*{[^}]*}[^{}]*)+\s*})/g; + + while ((matches = classRegex.exec(css)) !== null) { + const key = matches[1]; + const value = matches[2].trim().replace(/\s*;\s*/g, ';\n'); + result[key] = value; + } + + while ((matches = specialRegex.exec(css)) !== null) { + specialRules += matches[1].trim() + '\n'; + } + + return [result, specialRules.trim()]; +} diff --git a/packages/parser-ng/test/bgm.test.ts b/packages/parser-ng/test/bgm.test.ts new file mode 100644 index 000000000..ccd4f8436 --- /dev/null +++ b/packages/parser-ng/test/bgm.test.ts @@ -0,0 +1,56 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("bgm-1", async () => { + expectContainEqual(`bgm:夏影.mp3;`, + [{ + command: commandType.bgm, + commandRaw: "bgm", + content: "夏影.mp3", + args: [], + sentenceAssets: [{ name: '夏影.mp3', url: '夏影.mp3', lineNumber: 0, type: fileType.bgm }], + subScene: [] + }] + ); +}); + +test("bgm-2", async () => { + expectContainEqual(`bgm:夏影.mp3 -volume=30;`, + [{ + command: commandType.bgm, + commandRaw: "bgm", + content: "夏影.mp3", + args: [{ key: "volume", value: 30 }], + sentenceAssets: [{ name: '夏影.mp3', url: '夏影.mp3', lineNumber: 0, type: fileType.bgm }], + subScene: [] + }] + ); +}); + +test("bgm-3", async () => { + expectContainEqual(`bgm:夏影.mp3 -enter=3000;`, + [{ + command: commandType.bgm, + commandRaw: "bgm", + content: "夏影.mp3", + args: [{ key: "enter", value: 3000 }], + sentenceAssets: [{ name: '夏影.mp3', url: '夏影.mp3', lineNumber: 0, type: fileType.bgm }], + subScene: [] + }] + ); +}); + +test("bgm-4", async () => { + expectContainEqual(`bgm:none -enter=3000;`, + [{ + command: commandType.bgm, + commandRaw: "bgm", + content: "", + args: [{ key: "enter", value: 3000 }], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/callScene.test.ts b/packages/parser-ng/test/callScene.test.ts new file mode 100644 index 000000000..acf2bdc53 --- /dev/null +++ b/packages/parser-ng/test/callScene.test.ts @@ -0,0 +1,16 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("callScene-1", async () => { + expectContainEqual(`callScene:Chapter-2.txt;`, + [{ + command: commandType.callScene, + commandRaw: "callScene", + content: "Chapter-2.txt", + args: [], + sentenceAssets: [], + subScene: ["Chapter-2.txt"] + }] + ); +}); diff --git a/packages/parser-ng/test/changeBg.test.ts b/packages/parser-ng/test/changeBg.test.ts new file mode 100644 index 000000000..cf906ae33 --- /dev/null +++ b/packages/parser-ng/test/changeBg.test.ts @@ -0,0 +1,130 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("changeBg-1", async () => { + expectContainEqual(`changeBg:1.jpg -left="https://example-url.com" -next; 引号字符串允许包含任何特殊字符`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "1.jpg", + args: [ + { key: "left", value: "https://example-url.com" }, + { key: "next", value: true } + ], + sentenceAssets: [{ name: '1.jpg', url: '1.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); + +test("changeBg-2", async () => { + expectContainEqual(`changeBg:2-1.jpg -left=" ; 不匹配的引号不会被解析为引号字符串`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "2-1.jpg", + args: [ + { key: "left", value: '"' } + ], + sentenceAssets: [{ name: '2-1.jpg', url: '2-1.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); + +test("changeBg-3", async () => { + expectContainEqual( +`changeBg:3_1.jpg -transform='{"hello": "world"}' ; JSON字符串`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "3_1.jpg", + args: [ + { key: "transform", value: '{"hello": "world"}' } + ], + sentenceAssets: [{ name: '3_1.jpg', url: '3_1.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); + +test("changeBg-4", async () => { + expectContainEqual(`changeBg:4-4-4.jpg -transform={"hello":"world"} ; 不加单引号也可以,但不能有空格`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "4-4-4.jpg", + args: [ + { key: "transform", value: '{"hello":"world"}' } + ], + sentenceAssets: [{ name: '4-4-4.jpg', url: '4-4-4.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); + +test("changeBg-5", async () => { + expectContainEqual(`changeBg:5.jpg -transform="{"hello": "world"}" ; 显然这个会解析失败`, [ + { + command: commandType.changeBg, + commandRaw: "changeBg", + content: "5.jpg", + args: [ + { key: "transform", value: '{' } + ], + sentenceAssets: [{ name: '5.jpg', url: '5.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + } + ], [{ + location: '29(1:30)..61(1:62)', + message: "parsing cannot preceed" + }]); +}); + +test("changeBg-6", async () => { + expectContainEqual(`changeBg:6.jpg -transform="{\\"hello\\": \\"world\\"}" ; 但引号字符串支持转义又比较好地弥补了这一点`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "6.jpg", + args: [ + { key: "transform", value: '{"hello": "world"}' } + ], + sentenceAssets: [{ name: '6.jpg', url: '6.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); + +test("changeBg-7", async () => { + expectContainEqual(`changeBg:7.jpg -next=true ; 不含引号的值直接解析`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "7.jpg", + args: [ + { key: "next", value: true } + ], + sentenceAssets: [{ name: '7.jpg', url: '7.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); + +test("changeBg-8", async () => { + expectContainEqual(`changeBg:8.jpg -next -left=none ; 测试多个参数`, + [{ + command: commandType.changeBg, + commandRaw: "changeBg", + content: "8.jpg", + args: [ + { key: "next", value: true }, + { key: "left", value: "" } + ], + sentenceAssets: [{ name: '8.jpg', url: '8.jpg', lineNumber: 0, type: fileType.background }], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/changeFigure.test.ts b/packages/parser-ng/test/changeFigure.test.ts new file mode 100644 index 000000000..a87006440 --- /dev/null +++ b/packages/parser-ng/test/changeFigure.test.ts @@ -0,0 +1,64 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("changeFigure-1", async () => { + expectContainEqual(`changeFigure:testFigure02.png -next; 改变人物立绘`, + [{ + command: commandType.changeFigure, + commandRaw: "changeFigure", + content: "testFigure02.png", + args: [ + { key: "next", value: true }, + ], + sentenceAssets: [ + { + name: 'testFigure02.png', + url: 'testFigure02.png', + lineNumber: 0, + type: fileType.figure + } + ], + subScene: [] + }] + ); +}); + +test("changeFigure-2", async () => { + expectContainEqual(`changeFigure:testFigure03.png -left -id=test1; 一个初始位置在右侧的自由立绘`, + [{ + command: commandType.changeFigure, + commandRaw: "changeFigure", + content: "testFigure03.png", + args: [ + { key: "left", value: true }, + { key: "id", value: 'test1' }, + ], + sentenceAssets: [ + { + name: 'testFigure03.png', + url: 'testFigure03.png', + lineNumber: 0, + type: fileType.figure + } + ], + subScene: [] + }] + ); +}); + +test("changeFigure-2", async () => { + expectContainEqual(`changeFigure:none -id=test1; 通过 id 关闭立绘`, + [{ + command: commandType.changeFigure, + commandRaw: "changeFigure", + content: "", + args: [ + { key: "id", value: 'test1' }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/changeScene.test.ts b/packages/parser-ng/test/changeScene.test.ts new file mode 100644 index 000000000..0776db952 --- /dev/null +++ b/packages/parser-ng/test/changeScene.test.ts @@ -0,0 +1,16 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("changeScene-1", async () => { + expectContainEqual(`changeScene:Chapter-2.txt;`, + [{ + command: commandType.changeScene, + commandRaw: "changeScene", + content: "Chapter-2.txt", + args: [], + sentenceAssets: [], + subScene: ["Chapter-2.txt"] + }] + ); +}); diff --git a/packages/parser-ng/test/choose.test.ts b/packages/parser-ng/test/choose.test.ts new file mode 100644 index 000000000..1b8abb6ad --- /dev/null +++ b/packages/parser-ng/test/choose.test.ts @@ -0,0 +1,106 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("choose-1", async () => { + expectContainEqual(`choose:叫住她:Chapter-2.txt|回家:Chapter-3.txt;`, + [{ + command: commandType.choose, + commandRaw: "choose", + content: "叫住她:Chapter-2.txt|回家:Chapter-3.txt", + args: [ + { + key: "choices", + value: [ + { + showExpression: "", + clickExpression: "", + text: "叫住她", + destination: "Chapter-2.txt" + }, + { + showExpression: "", + clickExpression: "", + text: "回家", + destination: "Chapter-3.txt" + } + ] + }, + { + key: "contentRawRange", + value: [7, 41], + } + ], + sentenceAssets: [], + subScene: ["Chapter-2.txt", "Chapter-3.txt"] + }]); +}); + +test("choose-2", async () => { + expectContainEqual(`choose:(showConditionVar>1)[enableConditionVar>2]->叫住她:Chapter-2.txt|回家:Chapter-3.txt;`, + [{ + command: commandType.choose, + commandRaw: "choose", + content: "(showConditionVar>1)[enableConditionVar>2]->叫住她:Chapter-2.txt|回家:Chapter-3.txt", + args: [ + { + key: "choices", + value: [ + { + showExpression: "showConditionVar>1", + clickExpression: "enableConditionVar>2", + text: "叫住她", + destination: "Chapter-2.txt" + }, + { + showExpression: "", + clickExpression: "", + text: "回家", + destination: "Chapter-3.txt" + } + ] + }, + { + key: "contentRawRange", + value: [7, 85], + } + ], + sentenceAssets: [], + subScene: ["Chapter-2.txt", "Chapter-3.txt"] + }] + ); +}); + +test("choose-3", async () => { + expectContainEqual(`choose:分支 1:label_1|分支 2:label_2;`, + [{ + command: commandType.choose, + commandRaw: "choose", + content: "分支 1:label_1|分支 2:label_2", + args: [ + { + key: "choices", + value: [ + { + showExpression: "", + clickExpression: "", + text: "分支 1", + destination: "label_1" + }, + { + showExpression: "", + clickExpression: "", + text: "分支 2", + destination: "label_2" + } + ] + }, + { + key: "contentRawRange", + value: [7, 32], + } + ], + sentenceAssets: [], + subScene: [] + }]); +}); diff --git a/packages/parser-ng/test/comment.test.ts b/packages/parser-ng/test/comment.test.ts new file mode 100644 index 000000000..c3bebfa51 --- /dev/null +++ b/packages/parser-ng/test/comment.test.ts @@ -0,0 +1,17 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("comment-1", async () => { + expectContainEqual(` +`, + [{ + command: commandType.comment, + commandRaw: "comment", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }]); +}); diff --git a/packages/parser-ng/test/debug-linebreak.ts b/packages/parser-ng/test/debug-linebreak.ts new file mode 100644 index 000000000..03e32dff7 --- /dev/null +++ b/packages/parser-ng/test/debug-linebreak.ts @@ -0,0 +1,13 @@ +import {sceneTextPreProcess} from "../src/sceneTextPreProcessor"; +import * as fsp from "fs/promises"; + + +async function debug() { + const sceneRaw = await fsp.readFile('test/test-resources/line-break.txt'); + const sceneText = sceneRaw.toString(); + const result = sceneTextPreProcess(sceneText) + console.log(result) + console.log(result.split('\n').length) +} + +debug(); diff --git a/packages/parser-ng/test/debug.ts b/packages/parser-ng/test/debug.ts new file mode 100644 index 000000000..cf58e6467 --- /dev/null +++ b/packages/parser-ng/test/debug.ts @@ -0,0 +1,27 @@ +import * as fsp from "fs/promises"; +import SceneParser, {ADD_NEXT_ARG_LIST, SCRIPT_CONFIG} from "../src"; + + +async function debug() { + const sceneRaw = await fsp.readFile('test/test-resources/var.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "var", "/var.txt"); + console.log(result) + const configFesult = parser.parseConfig(` +Game_name:欢迎使用WebGAL!; +Game_key:0f86dstRf; +Title_img:WebGAL_New_Enter_Image.png; +Title_bgm:s_Title.mp3; +Title_logos: 1.png | 2.png | Image Logo.png| -show -active=false -add=op! -count=3;This is a fake config, do not reference anything. + `) + console.log(configFesult) + console.log(parser.stringifyConfig(configFesult)) +} + +debug(); diff --git a/packages/parser-ng/test/debugCssParser.ts b/packages/parser-ng/test/debugCssParser.ts new file mode 100644 index 000000000..039aac4b6 --- /dev/null +++ b/packages/parser-ng/test/debugCssParser.ts @@ -0,0 +1,18 @@ +import * as fsp from "fs/promises"; +import SceneParser, {ADD_NEXT_ARG_LIST, SCRIPT_CONFIG} from "../src"; + + +async function debug() { + const sceneRaw = await fsp.readFile('test/test-resources/debug.scss'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const configFesult = parser.parseScssToWebgalStyleObj(sceneText) + console.log(configFesult) +} + +debug(); diff --git a/packages/parser-ng/test/end.test.ts b/packages/parser-ng/test/end.test.ts new file mode 100644 index 000000000..7e5dcf8a8 --- /dev/null +++ b/packages/parser-ng/test/end.test.ts @@ -0,0 +1,16 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual } from './util'; + +test("end-1", async () => { + expectContainEqual(`end;`, + [{ + command: commandType.end, + commandRaw: "end", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/errorHandling.test.ts b/packages/parser-ng/test/errorHandling.test.ts new file mode 100644 index 000000000..c535c1d45 --- /dev/null +++ b/packages/parser-ng/test/errorHandling.test.ts @@ -0,0 +1,74 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("err-1", async () => { + expectContainEqual(`end:shouldNotAddContentHere -(); +end;`, + [ + { + command: commandType.end, + commandRaw: "end", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.end, + commandRaw: "end", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + } + ], + [ + { + location: '3(1:4)..32(1:33)', + message: "non-completed parsing" + } + ] + ); +}); + +test("err-2", async () => { + expectContainEqual(`one command:is not affected -next +end:shouldNotAddContentHere -() +another command:is not affected as well`, [ + { + command: commandType.say, + commandRaw: "one command", + content: "is not affected", + args: [ + { key: "speaker", value: "one command" }, + { key: "next", value: true } + ], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.end, + commandRaw: "end", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.say, + commandRaw: "another command", + content: "is not affected as well", + args: [ + { key: "speaker", value: "another command" }, + ], + sentenceAssets: [], + subScene: [] + } + ], [ + { + location: '37(2:4)..65(2:32)', + message: "non-completed parsing" + } + ]); +}); \ No newline at end of file diff --git a/packages/parser-ng/test/filmMode.test.ts b/packages/parser-ng/test/filmMode.test.ts new file mode 100644 index 000000000..e28266b81 --- /dev/null +++ b/packages/parser-ng/test/filmMode.test.ts @@ -0,0 +1,42 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("filmMode-1", async () => { + expectContainEqual(`filmMode:Film Mode Test;`, + [{ + command: commandType.filmMode, + commandRaw: "filmMode", + content: "Film Mode Test", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("filmMode-2", async () => { + expectContainEqual(`filmMode:none;`, + [{ + command: commandType.filmMode, + commandRaw: "filmMode", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("filmMode-3", async () => { + expectContainEqual(`filmMode:;`, + [{ + command: commandType.filmMode, + commandRaw: "filmMode", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/getUserInput.test.ts b/packages/parser-ng/test/getUserInput.test.ts new file mode 100644 index 000000000..dc808f016 --- /dev/null +++ b/packages/parser-ng/test/getUserInput.test.ts @@ -0,0 +1,19 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual } from './util'; + +test("getUserInput-1", async () => { + expectContainEqual(`getUserInput:name -title=如何称呼你 -buttonText=确认; 将用户输入写入 name 变量中`, + [{ + command: commandType.getUserInput, + commandRaw: "getUserInput", + content: "name", + args: [ + { key: "title", value: "如何称呼你" }, + { key: "buttonText", value: "确认" } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/integration.disablefornow.ts b/packages/parser-ng/test/integration.disablefornow.ts new file mode 100644 index 000000000..f0ea3183b --- /dev/null +++ b/packages/parser-ng/test/integration.disablefornow.ts @@ -0,0 +1,197 @@ +import { SceneParser } from "../src/index"; +import { ADD_NEXT_ARG_LIST, SCRIPT_CONFIG } from "../src/config/scriptConfig"; +import { expect, test } from "vitest"; +import { commandType, ISentence } from "../src/interface/sceneInterface"; +import * as fsp from 'fs/promises'; +import { fileType } from "../src/interface/assets"; + + +test("label", async () => { + const sceneRaw = await fsp.readFile('test/test-resources/start.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "start", "/start.txt"); + const expectSentenceItem: ISentence = { + command: commandType.label, + commandRaw: "label", + content: "end", + args: [ + { key: "next", value: true } + ], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("args", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/start.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "start", "/start.txt"); + const expectSentenceItem: ISentence = { + command: commandType.changeFigure, + commandRaw: "changeFigure", + content: "m2.png", + args: [ + { key: "left", value: true }, + { key: "next", value: true } + ], + sentenceAssets: [{ name: "m2.png", url: 'm2.png', type: fileType.figure, lineNumber: 0 }], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("choose", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/choose.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "choose", "/choose.txt"); + console.error(result.errors); + const expectSentenceItem: ISentence = { + command: commandType.choose, + commandRaw: "choose", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("long-script", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/long-script.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + console.log('line count:', sceneText.split('\n').length); + console.time('parse-time-consumed'); + const result = parser.parse(sceneText, "start", "/start.txt"); + console.timeEnd('parse-time-consumed'); + const expectSentenceItem: ISentence = { + command: commandType.label, + commandRaw: "label", + content: "end", + args: [ + { key: "next", value: true } + ], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("var", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/var.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "var", "/var.txt"); + const expectSentenceItem: ISentence = { + command: commandType.say, + commandRaw: "WebGAL", + content: "a=1?", + args: [{ key: 'speaker', value: 'WebGAL' }, { key: 'when', value: "a==1" }], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("config", async () => { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const configFesult = parser.parseConfig(` +Game_name:欢迎使用WebGAL!; +Game_key:0f86dstRf; +Title_img:WebGAL_New_Enter_Image.png; +Title_bgm:s_Title.mp3; +Title_logos: 1.png | 2.png | Image Logo.png| -show -active=false -add=op! -count=3;This is a fake config, do not reference anything. + `); + expect(configFesult).toContainEqual({ + command: 'Title_logos', + args: ['1.png', '2.png', 'Image Logo.png'], + options: [ + { key: 'show', value: true }, + { key: 'active', value: false }, + { key: 'add', value: 'op!' }, + { key: 'count', value: 3 }, + ] + }); +}); + +test("config-stringify", async () => { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const configFesult = parser.parseConfig(` +Game_name:欢迎使用WebGAL!; +Game_key:0f86dstRf; +Title_img:WebGAL_New_Enter_Image.png; +Title_bgm:s_Title.mp3; +Title_logos: 1.png | 2.png | Image Logo.png| -show -active=false -add=op! -count=3;This is a fake config, do not reference anything. + `); + const stringifyResult = parser.stringifyConfig(configFesult); + const configResult2 = parser.parseConfig(stringifyResult); + expect(configResult2).toContainEqual({ + command: 'Title_logos', + args: ['1.png', '2.png', 'Image Logo.png'], + options: [ + { key: 'show', value: true }, + { key: 'active', value: false }, + { key: 'add', value: 'op!' }, + { key: 'count', value: 3 }, + ] + }); +}); + + +test("say statement", async () => { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(`say:123 -speaker=xx;`, 'test', 'test'); + expect(result.sentenceList).toContainEqual({ + command: commandType.say, + commandRaw: "say", + content: "123", + args: [{ key: 'speaker', value: 'xx' }], + sentenceAssets: [], + subScene: [] + }); +}); diff --git a/packages/parser-ng/test/intro.test.ts b/packages/parser-ng/test/intro.test.ts new file mode 100644 index 000000000..363ddf692 --- /dev/null +++ b/packages/parser-ng/test/intro.test.ts @@ -0,0 +1,42 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("intro-1", async () => { + expectContainEqual(`intro:回忆不需要适合的剧本,|反正一说出口,|都成了戏言。;`, + [{ + command: commandType.intro, + commandRaw: "intro", + content: "回忆不需要适合的剧本,|反正一说出口,|都成了戏言。", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("intro-2", async () => { + expectContainEqual(`intro:回忆不需要适合的剧本,|反正一说出口,|都成了戏言。 -hold;`, + [{ + command: commandType.intro, + commandRaw: "intro", + content: "回忆不需要适合的剧本,|反正一说出口,|都成了戏言。", + args: [{ key: "hold", value: true }], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("intro-3", async () => { + expectContainEqual(`intro:你好|欢迎来到 WebGAL 的世界;`, + [{ + command: commandType.intro, + commandRaw: "intro", + content: "你好|欢迎来到 WebGAL 的世界", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/jumpLabel.test.ts b/packages/parser-ng/test/jumpLabel.test.ts new file mode 100644 index 000000000..b447694a0 --- /dev/null +++ b/packages/parser-ng/test/jumpLabel.test.ts @@ -0,0 +1,16 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("jumpLabel-1", async () => { + expectContainEqual(`jumpLabel:label_1; // 跳转到 label_1`, + [{ + command: commandType.jumpLabel, + commandRaw: "jumpLabel", + content: "label_1", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/label.test.ts b/packages/parser-ng/test/label.test.ts new file mode 100644 index 000000000..93e106461 --- /dev/null +++ b/packages/parser-ng/test/label.test.ts @@ -0,0 +1,16 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("label-1", async () => { + expectContainEqual(`label:label_1; // 创建名为 label_1 的 label`, + [{ + command: commandType.label, + commandRaw: "label", + content: "label_1", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/miniAvatar.test.ts b/packages/parser-ng/test/miniAvatar.test.ts new file mode 100644 index 000000000..acae3b53b --- /dev/null +++ b/packages/parser-ng/test/miniAvatar.test.ts @@ -0,0 +1,50 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("miniAvatar-1", async () => { + expectContainEqual(`miniAvatar:minipic_test.png; 在左下角显示minipic_test.png`, + [{ + command: commandType.miniAvatar, + commandRaw: "miniAvatar", + content: "minipic_test.png", + args: [], + sentenceAssets: [ + { + name: 'minipic_test.png', + url: 'minipic_test.png', + lineNumber: 0, + type: fileType.figure + } + ], + subScene: [] + }] + ); +}); + +test("miniAvatar-2", async () => { + expectContainEqual(`miniAvatar:none; 关闭这个小头像`, + [{ + command: commandType.miniAvatar, + commandRaw: "miniAvatar", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("miniAvatar-3", async () => { + expectContainEqual(`miniAvatar:; 关闭这个小头像`, + [{ + command: commandType.miniAvatar, + commandRaw: "miniAvatar", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/parser.test.ts b/packages/parser-ng/test/parser.test.ts new file mode 100644 index 000000000..05161f6b4 --- /dev/null +++ b/packages/parser-ng/test/parser.test.ts @@ -0,0 +1,196 @@ +import SceneParser from "../src/index"; +import { ADD_NEXT_ARG_LIST, SCRIPT_CONFIG } from "../src/config/scriptConfig"; +import { expect, test } from "vitest"; +import { commandType, ISentence } from "../src/interface/sceneInterface"; +import * as fsp from 'fs/promises'; +import { fileType } from "../src/interface/assets"; + +test("label", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/start.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "start", "/start.txt"); + const expectSentenceItem: ISentence = { + command: commandType.label, + commandRaw: "label", + content: "end", + args: [ + { key: "next", value: true } + ], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("args", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/start.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "start", "/start.txt"); + const expectSentenceItem: ISentence = { + command: commandType.changeFigure, + commandRaw: "changeFigure", + content: "m2.png", + args: [ + { key: "left", value: true }, + { key: "next", value: true } + ], + sentenceAssets: [{ name: "m2.png", url: 'm2.png', type: fileType.figure, lineNumber: 0 }], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("choose", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/choose.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "choose", "/choose.txt"); + const expectSentenceItem: ISentence = { + command: commandType.choose, + commandRaw: "choose", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("long-script", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/long-script.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + console.log('line count:', sceneText.split('\n').length); + console.time('parse-time-consumed'); + const result = parser.parse(sceneText, "start", "/start.txt"); + console.timeEnd('parse-time-consumed'); + const expectSentenceItem: ISentence = { + command: commandType.label, + commandRaw: "label", + content: "end", + args: [ + { key: "next", value: true } + ], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("var", async () => { + + const sceneRaw = await fsp.readFile('test/test-resources/var.txt'); + const sceneText = sceneRaw.toString(); + + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(sceneText, "var", "/var.txt"); + const expectSentenceItem: ISentence = { + command: commandType.say, + commandRaw: "WebGAL", + content: "a=1?", + args: [{ key: 'speaker', value: 'WebGAL' }, { key: 'when', value: "a==1" }], + sentenceAssets: [], + subScene: [] + }; + expect(result.sentenceList).toContainEqual(expectSentenceItem); +}); + +test("config", async () => { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const configFesult = parser.parseConfig(` +Game_name:欢迎使用WebGAL!; +Game_key:0f86dstRf; +Title_img:WebGAL_New_Enter_Image.png; +Title_bgm:s_Title.mp3; +Title_logos: 1.png | 2.png | Image Logo.png| -show -active=false -add=op! -count=3;This is a fake config, do not reference anything. + `); + expect(configFesult).toContainEqual({ + command: 'Title_logos', + args: ['1.png', '2.png', 'Image Logo.png'], + options: [ + { key: 'show', value: true }, + { key: 'active', value: false }, + { key: 'add', value: 'op!' }, + { key: 'count', value: 3 }, + ] + }); +}); + +test("config-stringify", async () => { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const configFesult = parser.parseConfig(` +Game_name:欢迎使用WebGAL!; +Game_key:0f86dstRf; +Title_img:WebGAL_New_Enter_Image.png; +Title_bgm:s_Title.mp3; +Title_logos: 1.png | 2.png | Image Logo.png| -show -active=false -add=op! -count=3;This is a fake config, do not reference anything. + `); + const stringifyResult = parser.stringifyConfig(configFesult); + const configResult2 = parser.parseConfig(stringifyResult); + expect(configResult2).toContainEqual({ + command: 'Title_logos', + args: ['1.png', '2.png', 'Image Logo.png'], + options: [ + { key: 'show', value: true }, + { key: 'active', value: false }, + { key: 'add', value: 'op!' }, + { key: 'count', value: 3 }, + ] + }); +}); + + +test("say statement", async () => { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(`say:123 -speaker=xx;`, 'test', 'test'); + expect(result.sentenceList).toContainEqual({ + command: commandType.say, + commandRaw: "say", + content: "123", + args: [{ key: 'speaker', value: 'xx' }], + sentenceAssets: [], + subScene: [] + }); +}); diff --git a/packages/parser-ng/test/parserMultiline.test.ts b/packages/parser-ng/test/parserMultiline.test.ts new file mode 100644 index 000000000..42815bcd2 --- /dev/null +++ b/packages/parser-ng/test/parserMultiline.test.ts @@ -0,0 +1,148 @@ +import { sceneTextPreProcess } from "../src/sceneTextPreProcessor"; +import { expect, test } from "vitest"; + +test("parser-multiline-basic", async () => { + const testScene = `changeFigure:a.png -left + -next + -id=id1 + +saySomething`; + const expected = `changeFigure:a.png -left -next -id=id1 +;_WEBGAL_LINE_BREAK_ -next +;_WEBGAL_LINE_BREAK_ -id=id1 + +saySomething`; + + const preprocessedScene = sceneTextPreProcess(testScene); + expect(preprocessedScene).toEqual(expected); +}); + + +test("parser-multiline-disable-when-encounter-concat-1", async () => { + const testScene = `intro:aaa + |bbb -concat +`; + const expected = `intro:aaa + |bbb -concat +`; + + const preprocessedScene = sceneTextPreProcess(testScene); + expect(preprocessedScene).toEqual(expected); +}); + + +test("parser-multiline-disable-when-encounter-concat-2", async () => { + const testScene = `intro:aaa + |bbb + |ccc -concat +`; + const expected = `intro:aaa|bbb +;_WEBGAL_LINE_BREAK_ |bbb + |ccc -concat +`; + + const preprocessedScene = sceneTextPreProcess(testScene); + expect(preprocessedScene).toEqual(expected); +}); + +test("parser-multiline-user-force-allow-multiline-in-concat", async () => { + const testScene = String.raw`intro:aaa\ +|bbb\ +|ccc -concat +`; + const expected = `intro:aaa|bbb|ccc -concat +;_WEBGAL_LINE_BREAK_|bbb +;_WEBGAL_LINE_BREAK_|ccc -concat +`; + + const preprocessedScene = sceneTextPreProcess(testScene); + expect(preprocessedScene).toEqual(expected); +}); + +test("parser-multiline-others-same-as-before", async () => { + const testScene = `听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +`; + + const preprocessedScene = sceneTextPreProcess(testScene); + expect(preprocessedScene).toEqual(testScene); +}); + +test("parser-multiline-full", async () => { + const testScene = `changeFigure:a.png -left + -next + -id=id1 + +intro:aaa + |bbb|ccc + |ddd + -next; + +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好 +|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left + -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 + -v1.wav; +changeFigure:stand2.png + -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back + -target=fig-left + -next; + +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 + -v5.wav; +`; + + const expected = `changeFigure:a.png -left -next -id=id1 +;_WEBGAL_LINE_BREAK_ -next +;_WEBGAL_LINE_BREAK_ -id=id1 + +intro:aaa|bbb|ccc|ddd -next; +;_WEBGAL_LINE_BREAK_ |bbb|ccc +;_WEBGAL_LINE_BREAK_ |ddd +;_WEBGAL_LINE_BREAK_ -next; + +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好 +|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +;_WEBGAL_LINE_BREAK_ -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +;_WEBGAL_LINE_BREAK_ -v1.wav; +changeFigure:stand2.png -right -next; +;_WEBGAL_LINE_BREAK_ -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +;_WEBGAL_LINE_BREAK_ -target=fig-left +;_WEBGAL_LINE_BREAK_ -next; + +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +;_WEBGAL_LINE_BREAK_ -v5.wav; +`; + + const preprocessedScene = sceneTextPreProcess(testScene); + expect(preprocessedScene).toEqual(expected); +}); diff --git a/packages/parser-ng/test/pixi.test.ts b/packages/parser-ng/test/pixi.test.ts new file mode 100644 index 000000000..ea02299d4 --- /dev/null +++ b/packages/parser-ng/test/pixi.test.ts @@ -0,0 +1,29 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("pixi-1", async () => { + expectContainEqual(`pixiInit;`, + [{ + command: commandType.pixiInit, + commandRaw: "pixiInit", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("pixi-2", async () => { + expectContainEqual(`pixiPerform:rain; // 添加一个下雨的特效`, + [{ + command: commandType.pixi, + commandRaw: "pixiPerform", + content: "rain", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/playEffect.test.ts b/packages/parser-ng/test/playEffect.test.ts new file mode 100644 index 000000000..458077020 --- /dev/null +++ b/packages/parser-ng/test/playEffect.test.ts @@ -0,0 +1,51 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("playEffect-1", async () => { + expectContainEqual(`playEffect:xxx.mp3;`, + [{ + command: commandType.playEffect, + commandRaw: "playEffect", + content: "xxx.mp3", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("playEffect-2", async () => { + expectContainEqual(`playEffect:xxx.mp3 -volume=30;`, + [{ + command: commandType.playEffect, + commandRaw: "playEffect", + content: "xxx.mp3", + args: [{ key: "volume", value: 30 }], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("playEffect-3", async () => { + expectContainEqual(`playEffect:xxx.mp3 -id=xxx; +playEffect:none -id=xxx; // 停止这个循环的效果音`, [ + { + command: commandType.playEffect, + commandRaw: "playEffect", + content: "xxx.mp3", + args: [{ key: "id", value: "xxx" }], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.playEffect, + commandRaw: "playEffect", + content: "", + args: [{ key: "id", value: "xxx" }], + sentenceAssets: [], + subScene: [] + } + ]); +}); diff --git a/packages/parser-ng/test/playVideo.test.ts b/packages/parser-ng/test/playVideo.test.ts new file mode 100644 index 000000000..f6a100dfa --- /dev/null +++ b/packages/parser-ng/test/playVideo.test.ts @@ -0,0 +1,17 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("playVideo-1", async () => { + expectContainEqual(`playVideo:OP.mp4;`, + [{ + command: commandType.video, + commandRaw: "playVideo", + content: "OP.mp4", + args: [], + sentenceAssets: [{ name: 'OP.mp4', url: 'OP.mp4', lineNumber: 0, type: fileType.video }], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/say.test.ts b/packages/parser-ng/test/say.test.ts new file mode 100644 index 000000000..797d18522 --- /dev/null +++ b/packages/parser-ng/test/say.test.ts @@ -0,0 +1,112 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; +import { fileType } from "../src/interface/assets"; + +test("say-1", async () => { + expectContainEqual(`雪之下雪乃:你到得真早;`, + [{ + command: commandType.say, + commandRaw: "雪之下雪乃", + content: "你到得真早", + args: [ + { key: "speaker", value: "雪之下雪乃" }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("say-2", async () => { + expectContainEqual(`对不起,等很久了吗?;`, + [{ + command: commandType.say, + commandRaw: "say", + content: "对不起,等很久了吗?", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("say-3", async () => { + expectContainEqual(`:这是一句旁白;`, + [{ + command: commandType.say, + commandRaw: "", + content: "这是一句旁白", + args: [ + { key: "speaker", value: "" }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("say-4", async () => { + expectContainEqual(`WebGAL:a=1? -when=a==1;`, + [{ + command: commandType.say, + commandRaw: "WebGAL", + content: "a=1?", + args: [ + { key: "speaker", value: "WebGAL" }, + { key: "when", value: "a==1" }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("say-5", async () => { + expectContainEqual(`WebGAL: 你 打 字 带 空 格 -when=a==1;`, + [{ + command: commandType.say, + commandRaw: "WebGAL", + content: "你 打 字 带 空 格", + args: [ + { key: "speaker", value: "WebGAL" }, + { key: "when", value: "a==1" }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("say-6", async () => { + expectContainEqual(`WebGAL: 你 打 字 带 空 格 -when=a==1;`, + [{ + command: commandType.say, + commandRaw: "WebGAL", + content: "你 打 字 带 空 格", + args: [ + { key: "speaker", value: "WebGAL" }, + { key: "when", value: "a==1" }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("say-7", async () => { + expectContainEqual(`比企谷八幡:刚到而已 -V3.ogg -volume=30;`, + [{ + command: commandType.say, + commandRaw: "比企谷八幡", + content: "刚到而已", + args: [ + { key: "speaker", value: "比企谷八幡" }, + { key: "vocal", value: "V3.ogg" }, + { key: "volume", value: 30 }, + ], + sentenceAssets: [{ name: 'V3.ogg', url: 'V3.ogg', lineNumber: 0, type: fileType.vocal }], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/setAnimation.test.ts b/packages/parser-ng/test/setAnimation.test.ts new file mode 100644 index 000000000..29b95f504 --- /dev/null +++ b/packages/parser-ng/test/setAnimation.test.ts @@ -0,0 +1,29 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("setAnimation-1", async () => { + expectContainEqual(`; // 为中间立绘设置一个从下方进入的动画,并转到下一句 +setAnimation:enter-from-bottom -target=fig-center -next;`, + [ + { + command: commandType.comment, + commandRaw: "comment", + content: " // 为中间立绘设置一个从下方进入的动画,并转到下一句", + args: [], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.setAnimation, + commandRaw: "setAnimation", + content: "enter-from-bottom", + args: [ + { key: "target", value: "fig-center" }, + { key: "next", value: true }, + ], + sentenceAssets: [], + subScene: [] + } + ]); +}); diff --git a/packages/parser-ng/test/setTempAnimation.test.ts b/packages/parser-ng/test/setTempAnimation.test.ts new file mode 100644 index 000000000..900da8600 --- /dev/null +++ b/packages/parser-ng/test/setTempAnimation.test.ts @@ -0,0 +1,19 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("setTempAnimation-1", async () => { + expectContainEqual(`setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0}, {"position": {"x": 400,"y": 0},"duration": 250}, {"position": {"x": 600,"y": 0},"duration": 500}, {"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next;`, + [{ + command: commandType.setTempAnimation, + commandRaw: "setTempAnimation", + content: `[{"position": {"x": 500,"y": 0},"duration": 0}, {"position": {"x": 400,"y": 0},"duration": 250}, {"position": {"x": 600,"y": 0},"duration": 500}, {"position": {"x": 500,"y": 0},"duration": 250}]`, + args: [ + { key: "target", value: "fig-left" }, + { key: "next", value: true } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); \ No newline at end of file diff --git a/packages/parser-ng/test/setTextbox.test.ts b/packages/parser-ng/test/setTextbox.test.ts new file mode 100644 index 000000000..2932d52bd --- /dev/null +++ b/packages/parser-ng/test/setTextbox.test.ts @@ -0,0 +1,29 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("setTextbox-1", async () => { + expectContainEqual(`setTextbox:hide; // 关闭文本框`, + [{ + command: commandType.setTextbox, + commandRaw: "setTextbox", + content: "hide", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setTextbox-2", async () => { + expectContainEqual(`setTextbox:on; // 可以是除 hide 以外的任意值。`, + [{ + command: commandType.setTextbox, + commandRaw: "setTextbox", + content: "on", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/setTransform.test.ts b/packages/parser-ng/test/setTransform.test.ts new file mode 100644 index 000000000..b8aabfa59 --- /dev/null +++ b/packages/parser-ng/test/setTransform.test.ts @@ -0,0 +1,19 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("setTransform-1", async () => { + expectContainEqual(`setTransform:{"position":{"x":100,"y":0}} -target=fig-center -duration=0;`, + [{ + command: commandType.setTransform, + commandRaw: "setTransform", + content: '{"position":{"x":100,"y":0}}', + args: [ + { key: "target", value: "fig-center" }, + { key: "duration", value: 0 } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/setTransition.test.ts b/packages/parser-ng/test/setTransition.test.ts new file mode 100644 index 000000000..dd23ac33d --- /dev/null +++ b/packages/parser-ng/test/setTransition.test.ts @@ -0,0 +1,20 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("setTransition-1", async () => { + expectContainEqual(`setTransition: -target=fig-center -enter=enter-from-bottom -exit=exit;`, + [{ + command: commandType.setTransition, + commandRaw: "setTransition", + content: "", + args: [ + { key: "target", value: "fig-center" }, + { key: "enter", value: "enter-from-bottom" }, + { key: "exit", value: "exit" }, + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/setVar.test.ts b/packages/parser-ng/test/setVar.test.ts new file mode 100644 index 000000000..73ae7ed40 --- /dev/null +++ b/packages/parser-ng/test/setVar.test.ts @@ -0,0 +1,161 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("setVar-1", async () => { + expectContainEqual(`setVar:a=1; // 可以设置数字`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: 1 } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-2", async () => { + expectContainEqual(`setVar:a=true; // 可以设置布尔值`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: true } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-3", async () => { + expectContainEqual(`setVar:a=人物名称; // 可以设置字符串`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: "人物名称" } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-4", async () => { + expectContainEqual(`setVar:a=random();`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: "random()" } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-5", async () => { + expectContainEqual(`setVar:a=5+a*5;`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: "5+a*5" } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-6", async () => { + expectContainEqual(`setVar:a=5+a*5;`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: "5+a*5" } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-7", async () => { + expectContainEqual(`setVar:a=1; +setVar:b=a+1;`, [ + { + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: 1 } + ], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "b" }, + { key: "#expression", value: "a+1" } + ], + sentenceAssets: [], + subScene: [] + }, + ]); +}); + +test("setVar-8", async () => { + expectContainEqual(`setVar:a=1 -global;`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#expression", value: 1 }, + { key: "global", value: true } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); + +test("setVar-9", async () => { + expectContainEqual(`setVar:a=($stage.bgm.volume) -global;`, + [{ + command: commandType.setVar, + commandRaw: "setVar", + content: "", + args: [ + { key: "#variableName", value: "a" }, + { key: "#internalExpression", value: "$stage.bgm.volume" }, + { key: "global", value: true } + ], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/showVars.test.ts b/packages/parser-ng/test/showVars.test.ts new file mode 100644 index 000000000..d7d05fa16 --- /dev/null +++ b/packages/parser-ng/test/showVars.test.ts @@ -0,0 +1,16 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual } from './util'; + +test("showVars-1", async () => { + expectContainEqual(`showVars;`, + [{ + command: commandType.showVars, + commandRaw: "showVars", + content: "", + args: [], + sentenceAssets: [], + subScene: [] + }] + ); +}); diff --git a/packages/parser-ng/test/test-resources/choose.txt b/packages/parser-ng/test/test-resources/choose.txt new file mode 100644 index 000000000..adcacf08f --- /dev/null +++ b/packages/parser-ng/test/test-resources/choose.txt @@ -0,0 +1,5 @@ +choose:; +choose:|; +choose:fff:; +choose::ff; +choose:|:ff; diff --git a/packages/parser-ng/test/test-resources/debug.scss b/packages/parser-ng/test/test-resources/debug.scss new file mode 100644 index 000000000..bffd61c0b --- /dev/null +++ b/packages/parser-ng/test/test-resources/debug.scss @@ -0,0 +1,64 @@ +.Title_main { + width: 100%; + height: 100%; + position: absolute; + z-index: 13; +} + +.Title_buttonList { + font-family: "思源宋体", serif; + display: flex; + position: absolute; + left: 0; + min-width: 25%; + height: 100%; + justify-content: center; + align-items: flex-start; + flex-flow: column; + transition: background 0.75s; + padding-left: 120px; +} + +.Title_button { + font-weight: bold; + text-align: center; + flex: 0 1 auto; + cursor: pointer; + padding: 1em 2em 1em 2em; + margin: 20px 0; + transition: all 0.33s; + background: rgba(255, 255, 255, 0.15); + backdrop-filter: blur(5px); + border-radius: 4px; + transform: skewX(-10deg); + background: linear-gradient(to right, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.1)); + + &:hover { + font-weight: bold; + text-shadow: 0 0 10px rgba(255, 255, 255, 1); + padding: 1em 6em 1em 3em; + } + &:active { + font-weight: bold; + } +} + +.Title_button_text { + color: transparent; + background: linear-gradient(135deg, #fdfbfb 0%, #dcddde 100%); + -webkit-background-clip: text; + padding: 0 0.5em 0 0.5em; + font-size: 200%; + font-family: WebgalUI, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + letter-spacing: 0.15em; +} + +.Title_backup_background { + width: 100%; + height: 100%; + position: absolute; + z-index: 13; + background: linear-gradient(135deg, #fdfbfb 0%, #dcddde 100%); +} + + diff --git a/packages/parser-ng/test/test-resources/line-break.txt b/packages/parser-ng/test/test-resources/line-break.txt new file mode 100644 index 000000000..750e21cae --- /dev/null +++ b/packages/parser-ng/test/test-resources/line-break.txt @@ -0,0 +1,38 @@ +changeFigure:a.png -left + -next + + + -id=id1 + +intro:aaa + |bbb|ccc + |ddd + -next; + +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好 +|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left + -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 + -v1.wav; +changeFigure:stand2.png + -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back + -target=fig-left + + + -next; + +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 + -v5.wav; diff --git a/packages/parser-ng/test/test-resources/long-script.txt b/packages/parser-ng/test/test-resources/long-script.txt new file mode 100644 index 000000000..548a33a72 --- /dev/null +++ b/packages/parser-ng/test/test-resources/long-script.txt @@ -0,0 +1,3672 @@ +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; +; WebGAL 引擎会默认读取 start.txt 作为初始场景,因此请不要删除,并在初始场景内跳转到其他场景 +bgm:s_Title.mp3; +unlockBgm:s_Title.mp3 -name=雲を追いかけて; +intro:你好|欢迎来到 WebGAL 的世界; +changeBg:bg.png -next; +unlockCg:bg.png -name=良夜; // 解锁CG并赋予名称 +changeFigure:stand.png -left -next; +setAnimation:enter-from-left -target=fig-left -next; +WebGAL:欢迎使用 WebGAL!这是一款全新的网页端视觉小说引擎。 -v1.wav; +changeFigure:stand2.png -right -next; +WebGAL 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav; +由于这个特性,如果你将 WebGAL 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav; +setAnimation:move-front-and-back -target=fig-left -next; +听起来是不是非常吸引人? -v4.wav; +changeFigure:none -right -next; +setAnimation:l2c -target=fig-left -next; +WebGAL 引擎也具有动画系统和特效系统,使用 WebGAL 开发的游戏可以拥有很好的表现效果。 -v5.wav; +pixiInit; +pixiPerform:snow; +比如,这个下起小雪的特效。 -v6.wav; +除此以外,分支选择的功能也必不可少。 -v7.wav; +你可以通过以下两个分支了解 WebGAL 的更多故事。 -v8.wav; +pixiInit; +choose:WebGAL 发展历程:choose1|WebGAL 冷知识:choose2; + +;分支1 +label:choose1; +WebGAL 的开发初衷是能够让更多人可以更方便地制作属于自己的视觉小说。 -v9.wav; +在一开始,WebGAL 只具备很少的功能,仅仅能支持立绘和背景的显示、语音播放和分支选择。 -v10.wav; +在经历一年的发展后,现在已经是支持了很多优秀的表现效果的引擎了! -v11.wav; +除此以外,WebGAL 编辑器的加入也使得制作和导出一个游戏更加方便快捷。 -v12.wav; +jumpLabel:end; + +;分支2 +label:choose2; +这个演示游戏使用的素材是 AI 生成的。 -v13.wav; +WebGAL 项目只用了一年不到就在 GitHub 获得了 1000 星标! -v14.wav; +WebGAL 的开发历程,是一个在开发中学习开发的过程。因此她经历了3次重构,并且每次几乎都是推倒重来式的。 -v15.wav; +WebGAL 的脚本语言是为了简化制作难度而全新设计的! -v16.wav; + +;结束分支 +label:end; +为了更接近桌面端视觉小说引擎的能力,我们支持很多快捷键以及可跳转的剧情回溯。 -v17.wav; +按下菜单中的“回想”按钮或者向上滚动鼠标滚轮试试吧! -v18.wav; +快速存读挡、丰富的选项、自动播放以及快进等功能,也是应有尽有。 -v19.wav; +setTempAnimation:[{"position": {"x": 500,"y": 0},"duration": 0},{"position": {"x": 400,"y": 0},"duration": 250},{"position": {"x": 600,"y": 0},"duration": 500},{"position": {"x": 500,"y": 0},"duration": 250}] -target=fig-left -next; +当然,这不算什么,因为大多数成熟的引擎都有这些功能。但是在 Web 端,这却是很少见的。 -v20.wav; +我们为可能初次开发游戏的开发者提供了美观的通用 UI 和丰富的预设功能与动画。所以你可以没有顾虑地快速开始制作游戏。 -v21.wav; +WebGAL 项目组期待你的作品能够在 WebGAL 上呈现!只需要一个链接就可以让万千用户立刻开始享受你的作品。 -v22.wav; +感谢你关注 WebGAL 项目! -v23.wav; +end; diff --git a/packages/parser-ng/test/test-resources/start.txt b/packages/parser-ng/test/test-resources/start.txt new file mode 100644 index 000000000..a1240cea9 --- /dev/null +++ b/packages/parser-ng/test/test-resources/start.txt @@ -0,0 +1,105 @@ +; 初始场景,以及特效演示 +changeBg:c4.jpg -next; +unlockCg:c4.jpg -name=街前; 解锁部分CG +unlockCg:xgmain.jpeg -name=星光咖啡馆与死神之蝶; +unlockBgm:s_Title.mp3 -name=Smiling-Swinging!!; +WebGAL:特效系统是3.9.2版本新引入的系统,你想要看特效的演示吗?; +choose:观看特效演示:demo|我不要看特效,直接来吧!:toStart; +label:demo; +pixiInit; +pixiPerform:rain; +WebGAL:现在展示的是下雨的特效。; +pixiInit; +pixiPerform:snow; +WebGAL:现在展示的是下雪的特效。; +setTextbox:hide; +pixiInit; +setTextbox:on -next; +WebGAL:特效的演示已经结束,现在我们正式开始吧!; + +; 正式场景 +label:toStart; +playVideo:OP.mp4; +changeBg:c3.jpg -next; +unlockCg:c3.jpg -name=cafe; +changeFigure:m2.png -left -next; +bgm:cb1.mp3; +unlockBgm:cb1.mp3 -name=ひとすじの光明; +setAnimation:enter-from-left -target=fig-left -next; +米咖多:蛋包饭是栞那做的,但红茶是夏目泡的。 -v1.ogg; +昂晴:......; +顺便问一下,你是打算做什么的?; +changeFigure:m1.png -left -next; +米咖多:就是倒饮料。然后咖啡和红茶的冲泡方式我还是记住了的。 -v2.ogg; +昂晴:这、这样么......; +:这猫爪子真的能泡茶么。; +拿得了水壶吗?就凭他那个肉球爪子......; +难道这些也是凭借猫妖的奇特力量做到的吗?; +changeFigure:none -left -next; +changeFigure:k1.png -next; +setAnimation:enter-from-bottom -target=fig-center -next; +栞那:那么,你想先尝哪个? -v3.ogg; +choose:品尝蛋包饭:dbf|品尝红茶:hc; + +; 栞那选项 +label:dbf; +昂晴:总之,先确认下蛋包饭的味道吧; +changeFigure:k2.png -next; +栞那:明白了,交给我吧 -v4.ogg; +changeFigure:none -next; +changeFigure:m2.png -left -next; +changeFigure:k3.png -right -next; +setAnimation:enter-from-left -target=fig-left -next; +setAnimation:enter-from-right -target=fig-right -next; +栞那:那么米咖多先生,我去做一下试作品 -v5.ogg; +米咖多:嗯。去吧 -v6.ogg; +changeFigure:none -left -next; +changeFigure:none -right -next; +changeFigure:k4.png -next; +setAnimation:enter-from-bottom -target=fig-center -next; +栞那:那么高岭同学,我们移动到厨房吧 -v7.ogg; +changeFigure:none -next; +bgm:cb2.mp3; +unlockBgm:cb2.mp3 -name=Tea Break; +changeBg:c2.jpg; +unlockCg:c2.jpg -name=厨房; +changeFigure:k2.png -next; +栞那:话不多说开始做吧 -v8.ogg; +jumpLabel:end; + +; 夏目选项 +label:hc; +changeFigure:none -next; +changeFigure:m1.png -left -next; +changeFigure:k1.png -right -next; +setAnimation:enter-from-left -target=fig-left -next; +setAnimation:enter-from-right -target=fig-right -next; +米咖多:那么就是,夏目了吧 -v9.ogg; +changeFigure:k6.png -right -next; +栞那:她刚去休息,要不要我叫回来呢? -v10.ogg; +昂晴:没事,我自己去吧; +changeFigure:none -left -next; +changeFigure:none -right -next; +bgm:cb2.mp3; +changeBg:c1.jpg -next; +unlockCg:c1.jpg -name=休息室; +:我先敲了敲门; +miniAvatar:n1.png; +夏目:哪位? -v11.ogg; +昂晴:我是高岭,可以进去吗?; +夏目:可以,没问题 -v12.ogg; +昂晴:打搅了; +miniAvatar:none; +changeFigure:n4.png -next; +昂晴:打搅你休息了; +夏目:不用在意,怎么了? -v13.ogg; +changeFigure:n2.png -next; +:她并没有无精打采,比想象中精神多了; +昂晴:问道拿手菜谱,就听说四季同学泡的红茶味道不错,我也想品尝一下; +夏目:明白了,那我们回去吧 -v14.ogg; +jumpLabel:end; + +; 结束场景 +label:end; +changeFigure:none -next; +WebGAL:基础演出的展示已经结束。; diff --git a/packages/parser-ng/test/test-resources/var.txt b/packages/parser-ng/test/test-resources/var.txt new file mode 100644 index 000000000..8185817d4 --- /dev/null +++ b/packages/parser-ng/test/test-resources/var.txt @@ -0,0 +1,11 @@ +setVar:a=1; +WebGAL:a=1? -when=a==1; + +;正常解析 +WebGAL:test; + +; : 异常测试 +WebGAL : test; + +分号后应该被截断;看不到我! +转义分号后应该不截断\;能看到我! diff --git a/packages/parser-ng/test/unlockBgm.test.ts b/packages/parser-ng/test/unlockBgm.test.ts new file mode 100644 index 000000000..99848b33b --- /dev/null +++ b/packages/parser-ng/test/unlockBgm.test.ts @@ -0,0 +1,28 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("unlockBgm-1", async () => { + expectContainEqual(`; // 解锁bgm并赋予名称 +unlockBgm:s_Title.mp3 -name=Smiling-Swinging!!!;`, + [ + { + command: commandType.comment, + commandRaw: "comment", + content: " // 解锁bgm并赋予名称", + args: [], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.unlockBgm, + commandRaw: "unlockBgm", + content: "s_Title.mp3", + args: [ + { key: "name", value: "Smiling-Swinging!!!" }, + ], + sentenceAssets: [], + subScene: [] + } + ]); +}); diff --git a/packages/parser-ng/test/unlockCg.test.ts b/packages/parser-ng/test/unlockCg.test.ts new file mode 100644 index 000000000..902f770a0 --- /dev/null +++ b/packages/parser-ng/test/unlockCg.test.ts @@ -0,0 +1,29 @@ +import { test } from "vitest"; +import { commandType } from "../src/interface/sceneInterface"; +import { expectContainEqual, expectThrow } from './util'; + +test("unlockCg-1", async () => { + expectContainEqual(`; // 解锁CG并赋予名称 +unlockCg:xgmain.jpeg -name=星光咖啡馆与死神之蝶 -series=1;`, + [ + { + command: commandType.comment, + commandRaw: "comment", + content: " // 解锁CG并赋予名称", + args: [], + sentenceAssets: [], + subScene: [] + }, + { + command: commandType.unlockCg, + commandRaw: "unlockCg", + content: "xgmain.jpeg", + args: [ + { key: "name", value: "星光咖啡馆与死神之蝶" }, + { key: "series", value: 1 } + ], + sentenceAssets: [], + subScene: [] + } + ]); +}); diff --git a/packages/parser-ng/test/util.ts b/packages/parser-ng/test/util.ts new file mode 100644 index 000000000..5e6900217 --- /dev/null +++ b/packages/parser-ng/test/util.ts @@ -0,0 +1,39 @@ + +import SceneParser, { parserSyntaxError } from "../src/index"; +import { ADD_NEXT_ARG_LIST, SCRIPT_CONFIG } from "../src/config/scriptConfig"; +import { expect } from "vitest"; +import { IError, ISentence } from "../src/interface/sceneInterface"; +import { chai } from 'vitest'; + +chai.config.truncateThreshold = 100000; + +export function expectContainEqual(rawScene: string, expectedSentenceItem: Array, errors: Array = []) { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + const result = parser.parse(rawScene, "start", "/start.txt"); + + expect(result.sentenceList).toEqual(expectedSentenceItem); + // if (Array.isArray(expectedSentenceItem)) { + // expectedSentenceItem.forEach((s) => expect(result.sentenceList).toContainEqual(s)); + // } else { + // expect(result.sentenceList).toEqual(expectedSentenceItem); + // } + + if (errors) { + for (const error of errors) { + expect(result.errors).toContainEqual(error); + } + } +} + +export function expectThrow(rawScene: string) { + const parser = new SceneParser((assetList) => { + }, (fileName, assetType) => { + return fileName; + }, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG); + + expect(() => parser.parse(rawScene, "start", "/start.txt")).toThrow(parserSyntaxError); +} \ No newline at end of file diff --git a/packages/parser-ng/tsconfig.json b/packages/parser-ng/tsconfig.json new file mode 100644 index 000000000..5fb839743 --- /dev/null +++ b/packages/parser-ng/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "build/types", + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "noImplicitAny": false, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "src" + ], + "references": [{ "path": "./tsconfig.node.json"}] +} diff --git a/packages/parser-ng/tsconfig.node.json b/packages/parser-ng/tsconfig.node.json new file mode 100644 index 000000000..fde6cf327 --- /dev/null +++ b/packages/parser-ng/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "module": "esnext", + "moduleResolution": "node" + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/yarn.lock b/yarn.lock index b88df2e51..95928d036 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4824,7 +4824,7 @@ rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" -rollup@^3.27.1, rollup@^3.29.5: +rollup@^3.27.1, rollup@^3.29.5, rollup@^3.3.0: version "3.29.5" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.5.tgz#8a2e477a758b520fb78daf04bca4c522c1da8a54" integrity sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==