create-pixi-vn 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/template-react-vite-muijoy/README.md +39 -39
- package/template-react-vite-muijoy/src/App.tsx +2 -2
- package/template-react-vite-muijoy/src/components/GameSaveSlot.tsx +1 -1
- package/template-react-vite-muijoy/src/components/NextButton.tsx +1 -1
- package/template-react-vite-muijoy/src/components/ReturnMainMenuButton.tsx +2 -2
- package/template-react-vite-muijoy/src/i18n.ts +1 -1
- package/template-react-vite-muijoy/src/interceptors/OnKeyEventInterceptor.tsx +1 -1
- package/template-react-vite-muijoy/src/interceptors/RefreshEventInterceptor.tsx +2 -2
- package/template-react-vite-muijoy/src/interceptors/SkipAutoInterceptor.tsx +1 -1
- package/template-react-vite-muijoy/src/main.tsx +1 -1
- package/template-react-vite-muijoy/src/screens/ChoiceMenu.tsx +1 -1
- package/template-react-vite-muijoy/src/screens/GameSaveScreen.tsx +2 -2
- package/template-react-vite-muijoy/src/screens/MainMenu.tsx +2 -2
- package/template-react-vite-muijoy/src/screens/QuickTools.tsx +3 -3
- package/template-react-vite-muijoy/src/screens/modals/SaveLoadAlert.tsx +2 -2
- package/template-react-vite-muijoy/src/screens/settings/SaveLoadSettingButtons.tsx +2 -2
- package/template-react-vite-muijoy/src/use_query/useQueryLastSave.ts +1 -1
- package/template-react-vite-muijoy/src/use_query/useQuerySaves.ts +1 -1
- package/template-react-vite-muijoy-ink/README.md +68 -75
- package/template-react-vite-muijoy-ink/src/App.tsx +3 -3
- package/template-react-vite-muijoy-ink/src/components/GameSaveSlot.tsx +1 -1
- package/template-react-vite-muijoy-ink/src/components/NextButton.tsx +1 -1
- package/template-react-vite-muijoy-ink/src/components/ReturnMainMenuButton.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/i18n.ts +1 -1
- package/template-react-vite-muijoy-ink/src/interceptors/InkInitialization.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/interceptors/OnKeyEventInterceptor.tsx +1 -1
- package/template-react-vite-muijoy-ink/src/interceptors/RefreshEventInterceptor.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/interceptors/SkipAutoInterceptor.tsx +1 -1
- package/template-react-vite-muijoy-ink/src/main-ink.ink +1 -1
- package/template-react-vite-muijoy-ink/src/main.tsx +1 -1
- package/template-react-vite-muijoy-ink/src/screens/ChoiceMenu.tsx +1 -1
- package/template-react-vite-muijoy-ink/src/screens/GameSaveScreen.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/screens/MainMenu.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/screens/QuickTools.tsx +3 -3
- package/template-react-vite-muijoy-ink/src/screens/modals/SaveLoadAlert.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/screens/settings/SaveLoadSettingButtons.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/use_query/useQueryLastSave.ts +1 -1
- package/template-react-vite-muijoy-ink/src/use_query/useQuerySaves.ts +1 -1
- package/template-react-vite-muijoy-ink/src/{utilities → utils}/ink-utility.ts +8 -2
- package/template-react-vite-muijoy-ink-tauri/README.md +72 -79
- package/template-react-vite-muijoy-ink-tauri/package-lock.json +16 -0
- package/template-react-vite-muijoy-ink-tauri/src/App.tsx +3 -3
- package/template-react-vite-muijoy-ink-tauri/src/components/GameSaveSlot.tsx +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/components/NextButton.tsx +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/components/ReturnMainMenuButton.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/i18n.ts +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/interceptors/InkInitialization.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/interceptors/OnKeyEventInterceptor.tsx +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/interceptors/RefreshEventInterceptor.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/interceptors/SkipAutoInterceptor.tsx +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/main-ink.ink +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/main.tsx +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/screens/ChoiceMenu.tsx +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/screens/GameSaveScreen.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/screens/MainMenu.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/screens/QuickTools.tsx +3 -3
- package/template-react-vite-muijoy-ink-tauri/src/screens/modals/SaveLoadAlert.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/screens/settings/SaveLoadSettingButtons.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/use_query/useQueryLastSave.ts +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/use_query/useQuerySaves.ts +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/ink-utility.ts +8 -2
- package/template-react-vite-muijoy-tauri/README.md +44 -44
- package/template-react-vite-muijoy-tauri/src/App.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/components/GameSaveSlot.tsx +1 -1
- package/template-react-vite-muijoy-tauri/src/components/NextButton.tsx +1 -1
- package/template-react-vite-muijoy-tauri/src/components/ReturnMainMenuButton.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/i18n.ts +1 -1
- package/template-react-vite-muijoy-tauri/src/interceptors/OnKeyEventInterceptor.tsx +1 -1
- package/template-react-vite-muijoy-tauri/src/interceptors/RefreshEventInterceptor.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/interceptors/SkipAutoInterceptor.tsx +1 -1
- package/template-react-vite-muijoy-tauri/src/main.tsx +1 -1
- package/template-react-vite-muijoy-tauri/src/screens/ChoiceMenu.tsx +1 -1
- package/template-react-vite-muijoy-tauri/src/screens/GameSaveScreen.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/screens/MainMenu.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/screens/QuickTools.tsx +3 -3
- package/template-react-vite-muijoy-tauri/src/screens/modals/SaveLoadAlert.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/screens/settings/SaveLoadSettingButtons.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/use_query/useQueryLastSave.ts +1 -1
- package/template-react-vite-muijoy-tauri/src/use_query/useQuerySaves.ts +1 -1
- /package/template-react-vite-muijoy/src/{values/translations → locales}/strings_en.json +0 -0
- /package/template-react-vite-muijoy/src/{utilities → utils}/actions-utility.ts +0 -0
- /package/template-react-vite-muijoy/src/{utilities → utils}/assets-utility.ts +0 -0
- /package/template-react-vite-muijoy/src/{utilities → utils}/component-utility.ts +0 -0
- /package/template-react-vite-muijoy/src/{utilities → utils}/indexedDB-utility.ts +0 -0
- /package/template-react-vite-muijoy/src/{utilities → utils}/navigate-utility.ts +0 -0
- /package/template-react-vite-muijoy/src/{utilities → utils}/save-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink/src/{ink_labels → ink}/start.ink +0 -0
- /package/template-react-vite-muijoy-ink/src/{values/translations → locales}/strings_en.json +0 -0
- /package/template-react-vite-muijoy-ink/src/{utilities → utils}/actions-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink/src/{utilities → utils}/assets-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink/src/{utilities → utils}/component-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink/src/{utilities → utils}/indexedDB-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink/src/{utilities → utils}/navigate-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink/src/{utilities → utils}/save-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{ink_labels → ink}/start.ink +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{values/translations → locales}/strings_en.json +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/actions-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/assets-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/component-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/indexedDB-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/navigate-utility.ts +0 -0
- /package/template-react-vite-muijoy-ink-tauri/src/{utilities → utils}/save-utility.ts +0 -0
- /package/template-react-vite-muijoy-tauri/src/{values/translations → locales}/strings_en.json +0 -0
- /package/template-react-vite-muijoy-tauri/src/{utilities → utils}/actions-utility.ts +0 -0
- /package/template-react-vite-muijoy-tauri/src/{utilities → utils}/assets-utility.ts +0 -0
- /package/template-react-vite-muijoy-tauri/src/{utilities → utils}/component-utility.ts +0 -0
- /package/template-react-vite-muijoy-tauri/src/{utilities → utils}/indexedDB-utility.ts +0 -0
- /package/template-react-vite-muijoy-tauri/src/{utilities → utils}/navigate-utility.ts +0 -0
- /package/template-react-vite-muijoy-tauri/src/{utilities → utils}/save-utility.ts +0 -0
package/dist/index.mjs
CHANGED
|
@@ -47,7 +47,7 @@ Calls to async() callback can have unexpected results.`),l=!0,function(b,C){b?f(
|
|
|
47
47
|
Initializing git repository...`),s0.sync("git",["init","-b","main"],{cwd:e,stdio:"inherit"}),s0.sync("git",["add","."],{cwd:e,stdio:"inherit"}),console.log("Done."),console.log(`
|
|
48
48
|
Now, you can use GitHub Desktop upload your project to GitHub.`),console.log("GitHub Desktop: https://github.com/apps/desktop"))}catch{}}var q0=(e=>(e.VisualStudioCode="vscode",e.Cursor="cursor",e.Other="other",e))(q0||{});function sx(){return re.prompt([{type:"list",name:"ide",message:"Which IDE do you want to use?",choices:[{name:"Visual Studio Code",value:q0.VisualStudioCode},{name:"Cursor",value:q0.Cursor},{name:"Other",value:q0.Other}],default:q0.VisualStudioCode}])}async function xx({rootFolder:e,fileToOpen:t}){let{ide:n}=await sx();if(n!==void 0)try{let i="";switch(n){case"vscode":console.log(`
|
|
49
49
|
Opening in Visual Studio Code...`),i="code";break;case"cursor":console.log(`
|
|
50
|
-
Opening in Cursor...`),i="cursor";break}i&&(await se(i),s0.sync(i,[e],{stdio:"inherit"}),s0.sync(i,[`${e}/README.md`],{stdio:"inherit"}),t&&s0.sync(i,[`${e}/${t}`],{stdio:"inherit"}))}catch{console.error(`Could not open project using ${n}, since ${n} was not in your PATH`)}}var It=(e=>(e[e.VisualNovel=0]="VisualNovel",e))(It||{}),t0=(e=>(e[e.Ink=0]="Ink",e[e.Renpy=1]="Renpy",e[e.Typescript=2]="Typescript",e))(t0||{}),a0=(e=>(e[e.React=0]="React",e[e.Vue=1]="Vue",e[e.Angular=2]="Angular",e))(a0||{});const Vr="My Game",Gr="my-game",$t=[{type:It.VisualNovel,name:"Visual Novel",availableUI:[a0.React],availableNarrativeLanguages:[t0.Ink,t0.Typescript]}];var T0=(e=>(e[e.Yes=0]="Yes",e[e.No=1]="No",e[e.Cancel=2]="Cancel",e))(T0||{});function ux({packageName:e}){return re.prompt([{type:"list",name:"gameType",message:"Select the type of game you want to create:",choices:$t.map(t=>({name:t.name,value:t.type}))},{type:"list",name:"UIFramework",message:"Select the UI framework you want to use:",choices:({gameType:t})=>$t.find(n=>n.type===t)?.availableUI.map(n=>{let i="";switch(n){case a0.React:i=pe("React");break;case a0.Vue:i=Ti("Vue");break;case a0.Angular:i=zt("Angular");break}return{name:i,value:n}})},{type:"list",name:"narrativeLanguage",message:"Select the narrative language you want to use:",choices:({gameType:t})=>$t.find(n=>n.type===t)?.availableNarrativeLanguages.map(n=>{let i="";switch(n){case t0.Ink:i="Ink + Typescript";break;case t0.Renpy:i=Ri("Renpy");break;case t0.Typescript:i=pe("Typescript");break}return{name:i,value:n}})},{type:"list",name:"multidevice",message:"Which devices is the project intended for?",choices:[{name:"Web page",value:!1},{name:"Web page + Desktop + Mobile (Tauri)",value:!0}]},{type:"input",name:"identifier",message:"Project identifier:",default:`com.${e}.app`,required:!0,when:({multidevice:t})=>t}])}function Wr(e){return e?.trim().replace(/\/+$/g,"")}function cx(e){const t=I.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"}function lx(e){if(I.existsSync(e))for(const t of I.readdirSync(e))t!==".git"&&I.rmSync(M.resolve(e,t),{recursive:!0,force:!0})}function fx(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function Dx(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}async function dx({argTargetDir:e,targetDir:t}){const n=()=>t==="."?M.basename(M.resolve()):t;let i=await re.prompt([{type:"input",name:"projectName",message:"Project name:",default:Vr,required:!0,transformer:r=>Wr(r)||Vr,when:()=>!e,validate:r=>r?!0:"Project name cannot be empty"},{type:"input",name:"description",message:"Project description:",default:"A new game project"},{type:"input",name:"packageName",message:"Package name:",default:()=>Dx(n()),validate:r=>fx(r)||"Invalid package name. The name can only include URL-friendly characters."},{type:"list",name:"overwrite",message:"Overwrite existing files?",default:"yes",choices:[{description:"Remove existing files and continue",name:"Yes",value:T0.Yes},{description:"Keep existing files and continue",name:"Ignore",value:T0.No},{description:"Cancel operation",name:"Cancel",value:T0.Cancel}],when:({packageName:r=Gr})=>I.existsSync(r)&&!cx(r)}]);if(i.overwrite===T0.Cancel)throw new Error(zt("\u2716")+" Operation cancelled");return i}const hx=process.cwd(),px={_gitignore:".gitignore"};async function Ex(e){let t=e||Gr,n,{description:i,overwrite:r,packageName:o,projectName:x}=await dx({argTargetDir:e,targetDir:t}),{UIFramework:a,gameType:s,narrativeLanguage:u,multidevice:c,identifier:f}=await ux({packageName:o}),l;switch(s){case It.VisualNovel:switch(a){case a0.React:switch(u){case t0.Typescript:c?l="template-react-vite-muijoy-tauri":l="template-react-vite-muijoy",n="src/labels/startLabel.ts";break;case t0.Ink:c?l="template-react-vite-muijoy-ink-tauri":l="template-react-vite-muijoy-ink",n="src/
|
|
50
|
+
Opening in Cursor...`),i="cursor";break}i&&(await se(i),s0.sync(i,[e],{stdio:"inherit"}),s0.sync(i,[`${e}/README.md`],{stdio:"inherit"}),t&&s0.sync(i,[`${e}/${t}`],{stdio:"inherit"}))}catch{console.error(`Could not open project using ${n}, since ${n} was not in your PATH`)}}var It=(e=>(e[e.VisualNovel=0]="VisualNovel",e))(It||{}),t0=(e=>(e[e.Ink=0]="Ink",e[e.Renpy=1]="Renpy",e[e.Typescript=2]="Typescript",e))(t0||{}),a0=(e=>(e[e.React=0]="React",e[e.Vue=1]="Vue",e[e.Angular=2]="Angular",e))(a0||{});const Vr="My Game",Gr="my-game",$t=[{type:It.VisualNovel,name:"Visual Novel",availableUI:[a0.React],availableNarrativeLanguages:[t0.Ink,t0.Typescript]}];var T0=(e=>(e[e.Yes=0]="Yes",e[e.No=1]="No",e[e.Cancel=2]="Cancel",e))(T0||{});function ux({packageName:e}){return re.prompt([{type:"list",name:"gameType",message:"Select the type of game you want to create:",choices:$t.map(t=>({name:t.name,value:t.type}))},{type:"list",name:"UIFramework",message:"Select the UI framework you want to use:",choices:({gameType:t})=>$t.find(n=>n.type===t)?.availableUI.map(n=>{let i="";switch(n){case a0.React:i=pe("React");break;case a0.Vue:i=Ti("Vue");break;case a0.Angular:i=zt("Angular");break}return{name:i,value:n}})},{type:"list",name:"narrativeLanguage",message:"Select the narrative language you want to use:",choices:({gameType:t})=>$t.find(n=>n.type===t)?.availableNarrativeLanguages.map(n=>{let i="";switch(n){case t0.Ink:i="Ink + Typescript";break;case t0.Renpy:i=Ri("Renpy");break;case t0.Typescript:i=pe("Typescript");break}return{name:i,value:n}})},{type:"list",name:"multidevice",message:"Which devices is the project intended for?",choices:[{name:"Web page",value:!1},{name:"Web page + Desktop + Mobile (Tauri)",value:!0}]},{type:"input",name:"identifier",message:"Project identifier:",default:`com.${e}.app`,required:!0,when:({multidevice:t})=>t}])}function Wr(e){return e?.trim().replace(/\/+$/g,"")}function cx(e){const t=I.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"}function lx(e){if(I.existsSync(e))for(const t of I.readdirSync(e))t!==".git"&&I.rmSync(M.resolve(e,t),{recursive:!0,force:!0})}function fx(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function Dx(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}async function dx({argTargetDir:e,targetDir:t}){const n=()=>t==="."?M.basename(M.resolve()):t;let i=await re.prompt([{type:"input",name:"projectName",message:"Project name:",default:Vr,required:!0,transformer:r=>Wr(r)||Vr,when:()=>!e,validate:r=>r?!0:"Project name cannot be empty"},{type:"input",name:"description",message:"Project description:",default:"A new game project"},{type:"input",name:"packageName",message:"Package name:",default:()=>Dx(n()),validate:r=>fx(r)||"Invalid package name. The name can only include URL-friendly characters."},{type:"list",name:"overwrite",message:"Overwrite existing files?",default:"yes",choices:[{description:"Remove existing files and continue",name:"Yes",value:T0.Yes},{description:"Keep existing files and continue",name:"Ignore",value:T0.No},{description:"Cancel operation",name:"Cancel",value:T0.Cancel}],when:({packageName:r=Gr})=>I.existsSync(r)&&!cx(r)}]);if(i.overwrite===T0.Cancel)throw new Error(zt("\u2716")+" Operation cancelled");return i}const hx=process.cwd(),px={_gitignore:".gitignore"};async function Ex(e){let t=e||Gr,n,{description:i,overwrite:r,packageName:o,projectName:x}=await dx({argTargetDir:e,targetDir:t}),{UIFramework:a,gameType:s,narrativeLanguage:u,multidevice:c,identifier:f}=await ux({packageName:o}),l;switch(s){case It.VisualNovel:switch(a){case a0.React:switch(u){case t0.Typescript:c?l="template-react-vite-muijoy-tauri":l="template-react-vite-muijoy",n="src/labels/startLabel.ts";break;case t0.Ink:c?l="template-react-vite-muijoy-ink-tauri":l="template-react-vite-muijoy-ink",n="src/ink/start.ink";break;case t0.Renpy:throw new Error("There are no templates for this narrative language");default:throw new Error("Unknown narrative language")}break;case a0.Vue:case a0.Angular:throw new Error("There are no templates for this game type and UI framework");default:throw new Error("Unknown UI framework")}break;default:throw new Error("Unknown game type")}const D=M.join(hx,t);r===T0.Yes?lx(D):I.existsSync(D)||I.mkdirSync(D,{recursive:!0}),console.log(`
|
|
51
51
|
Scaffolding project in ${D}...`);const h=M.resolve(ni(import.meta.url),"../..",`${l}`),d=(C,p)=>{const m=M.join(D,px[C]??C);p?I.writeFileSync(m,p):zr(M.join(h,C),m)},E=I.readdirSync(h);for(const C of E)switch(C){case"package.json":case"vite.config.ts":case"index.html":let p=I.readFileSync(M.join(h,C),"utf-8");p=p.replace(/my-app-package-name/g,o),p=p.replace(/my-app-description/g,i),p=p.replace(/my-app-project-name/g,x),d(C,p);break;case".git":case"package-lock.json":break;default:d(C)}const F=M.join(D,"src-tauri");if(I.existsSync(F)){const C=I.readdirSync(F);for(const p of C)switch(p){case"Cargo.lock":case"Cargo.toml":case"tauri.conf.json":let m=I.readFileSync(M.join(F,p),"utf-8");m=m.replace(/my-app-package-name/g,o),m=m.replace(/my-app-description/g,i),m=m.replace(/my-app-project-name/g,x),m=m.replace(/com.my-app-project-name.app/g,f),d(M.join("src-tauri",p),m)}}const b=M.join(D,"_github");return I.existsSync(b)&&I.renameSync(b,M.join(D,".github")),console.log("Done."),{rootFolder:D,fileToOpen:n}}function bx(e,t){I.mkdirSync(t,{recursive:!0});for(const n of I.readdirSync(e)){const i=M.resolve(e,n),r=M.resolve(t,n);zr(i,r)}}function zr(e,t){I.statSync(e).isDirectory()?bx(e,t):I.copyFileSync(e,t)}function Fx(e){if(!e)return;const t=e.split(" ")[0].split("/");return{name:t[0],version:t[1]}}const Yr=$i(process.argv.slice(2),{default:{help:!1},alias:{h:"help",t:"template"},string:["_"]}),Hr=process.cwd(),mx=`Usage: create-pixi-vn [OPTION]... [DIRECTORY]
|
|
52
52
|
|
|
53
53
|
Create a new Pixi\u2019VN project.
|
package/package.json
CHANGED
|
@@ -18,44 +18,7 @@ The history modal is a list of all the dialogues and choices that have been disp
|
|
|
18
18
|
|
|
19
19
|
The settings modal allows you to change the text speed, go to full screen, edit theme colors, and change go to main menu. The settings for the audio have not been added nor the libraries to manage it, but I recommend adding them.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Before starting, you need to have Node.js installed on your computer. If you don't have it, you can download it [here](https://nodejs.org/).
|
|
24
|
-
|
|
25
|
-
### Recommended Visual Studio Code extensions
|
|
26
|
-
|
|
27
|
-
* [JavaScript and TypeScript Nightly](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-next): Provides JavaScript and TypeScript nightlies.
|
|
28
|
-
* [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint): Integrates ESLint into VS Code.
|
|
29
|
-
* [vscode-color-picker](https://marketplace.visualstudio.com/items?itemName=antiantisepticeye.vscode-color-picker): A color picker for Visual Studio Code.
|
|
30
|
-
* [Version Lens](https://marketplace.visualstudio.com/items?itemName=pflannery.vscode-versionlens): Shows the latest version for each package using code lens.
|
|
31
|
-
|
|
32
|
-
### Change the icon
|
|
33
|
-
|
|
34
|
-
You can change the icon of the game by replacing the images in the `public` folder.
|
|
35
|
-
|
|
36
|
-
### Installation
|
|
37
|
-
|
|
38
|
-
First, is necessary install the dependencies. To do this, open a terminal in the root folder of the project and run the following command:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Start the web application
|
|
45
|
-
|
|
46
|
-
To start the web application, run the following command:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
npm start
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This command will start the development server. Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
|
|
53
|
-
|
|
54
|
-
#### Debugging the web application
|
|
55
|
-
|
|
56
|
-
If you are using Visual Studio Code, you can use the debug configuration provided with the template. To do this, after launching `npm start`, go to the debug section and select the `Launch Chrome` configuration.
|
|
57
|
-
|
|
58
|
-
## Keyboard shortcuts (hotkeys)
|
|
21
|
+
### Keyboard shortcuts (hotkeys)
|
|
59
22
|
|
|
60
23
|
* `Space` or `Enter`: Continue the dialogue.
|
|
61
24
|
* `Keep Space` or `Keep Enter`: Skip the dialogue.
|
|
@@ -65,7 +28,7 @@ If you are using Visual Studio Code, you can use the debug configuration provide
|
|
|
65
28
|
* `Esc`: Open the settings modal.
|
|
66
29
|
* `Shift` + `V`: Hide the UI (Show only the canvas).
|
|
67
30
|
|
|
68
|
-
|
|
31
|
+
### Used libraries
|
|
69
32
|
|
|
70
33
|
This template uses the following libraries:
|
|
71
34
|
|
|
@@ -93,6 +56,43 @@ Text libraries:
|
|
|
93
56
|
* [i18next](https://www.i18next.com/): A library that gives the possibility to manage multiple translations in the application.
|
|
94
57
|
* [Reacr Markdown](https://www.npmjs.com/package/react-markdown): A library that allows you to render markdown in React components.
|
|
95
58
|
|
|
59
|
+
## How to use
|
|
60
|
+
|
|
61
|
+
Before starting, you need to have Node.js installed on your computer. If you don't have it, you can download it [here](https://nodejs.org/).
|
|
62
|
+
|
|
63
|
+
### Recommended Visual Studio Code extensions
|
|
64
|
+
|
|
65
|
+
* [JavaScript and TypeScript Nightly](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-next): Provides JavaScript and TypeScript nightlies.
|
|
66
|
+
* [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint): Integrates ESLint into VS Code.
|
|
67
|
+
* [vscode-color-picker](https://marketplace.visualstudio.com/items?itemName=antiantisepticeye.vscode-color-picker): A color picker for Visual Studio Code.
|
|
68
|
+
* [Version Lens](https://marketplace.visualstudio.com/items?itemName=pflannery.vscode-versionlens): Shows the latest version for each package using code lens.
|
|
69
|
+
|
|
70
|
+
### Change the icon
|
|
71
|
+
|
|
72
|
+
You can change the icon of the game by replacing the images in the `public` folder.
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
First, is necessary install the dependencies. To do this, open a terminal in the root folder of the project and run the following command:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm install
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Start the web application
|
|
83
|
+
|
|
84
|
+
To start the web application, run the following command:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm start
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This command will start the development server. Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
|
|
91
|
+
|
|
92
|
+
### Debugging the web application
|
|
93
|
+
|
|
94
|
+
If you are using Visual Studio Code, you can use the debug configuration provided with the template. To do this, after launching `npm start`, go to the debug section and select the `Launch Chrome` configuration.
|
|
95
|
+
|
|
96
96
|
## Distribution
|
|
97
97
|
|
|
98
98
|
### Web application
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { lazy, Suspense } from "react";
|
|
2
2
|
import { ErrorBoundary } from "react-error-boundary";
|
|
3
3
|
import LoadingScreen from "./screens/LoadingScreen";
|
|
4
|
-
import { defineAssets } from "./
|
|
5
|
-
import { initializeIndexedDB } from "./
|
|
4
|
+
import { defineAssets } from "./utils/assets-utility";
|
|
5
|
+
import { initializeIndexedDB } from "./utils/indexedDB-utility";
|
|
6
6
|
|
|
7
7
|
export default function App() {
|
|
8
8
|
const Home = lazy(async () => {
|
|
@@ -9,7 +9,7 @@ import TypographyShadow from "../components/TypographyShadow";
|
|
|
9
9
|
import { MAIN_MENU_ROUTE } from '../constans';
|
|
10
10
|
import GameSaveData from '../models/GameSaveData';
|
|
11
11
|
import useQuerySaves from '../use_query/useQuerySaves';
|
|
12
|
-
import { downloadGameSave } from '../
|
|
12
|
+
import { downloadGameSave } from '../utils/save-utility';
|
|
13
13
|
|
|
14
14
|
export default function GameSaveSlot({ saveId, onDelete, onLoad, onOverwriteSave, onSave }: {
|
|
15
15
|
saveId: number,
|
|
@@ -10,7 +10,7 @@ import { hideInterfaceState } from '../atoms/hideInterfaceState';
|
|
|
10
10
|
import { nextStepLoadingState } from '../atoms/nextStepLoadingState';
|
|
11
11
|
import { skipEnabledState } from '../atoms/skipEnabledState';
|
|
12
12
|
import { INTERFACE_DATA_USE_QUEY_KEY, useQueryCanGoNext } from '../use_query/useQueryInterface';
|
|
13
|
-
import { useMyNavigate } from '../
|
|
13
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
14
14
|
|
|
15
15
|
export default function NextButton() {
|
|
16
16
|
const [skip, setSkip] = useRecoilState(skipEnabledState)
|
|
@@ -6,8 +6,8 @@ import { useLocation } from 'react-router-dom';
|
|
|
6
6
|
import { useSetRecoilState } from 'recoil';
|
|
7
7
|
import { openSettingsState } from '../atoms/openSettingsState';
|
|
8
8
|
import ModalDialogCustom from '../components/ModalDialog';
|
|
9
|
-
import { gameEnd } from '../
|
|
10
|
-
import { useMyNavigate } from '../
|
|
9
|
+
import { gameEnd } from '../utils/actions-utility';
|
|
10
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
11
11
|
|
|
12
12
|
export default function ReturnMainMenuButton() {
|
|
13
13
|
const openSettings = useSetRecoilState(openSettingsState);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import i18n from 'i18next';
|
|
2
2
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
3
3
|
import { initReactI18next } from 'react-i18next';
|
|
4
|
-
import strings_en from '../src/
|
|
4
|
+
import strings_en from '../src/locales/strings_en.json';
|
|
5
5
|
|
|
6
6
|
const getUserLang = (): string => {
|
|
7
7
|
let userLang: string = navigator.language || "en";
|
|
@@ -8,7 +8,7 @@ import { hideInterfaceState } from '../atoms/hideInterfaceState';
|
|
|
8
8
|
import { saveLoadAlertState } from '../atoms/saveLoadAlertState';
|
|
9
9
|
import useQueryLastSave, { LAST_SAVE_USE_QUEY_KEY } from '../use_query/useQueryLastSave';
|
|
10
10
|
import { SAVES_USE_QUEY_KEY } from '../use_query/useQuerySaves';
|
|
11
|
-
import { putSaveIntoIndexDB } from '../
|
|
11
|
+
import { putSaveIntoIndexDB } from '../utils/save-utility';
|
|
12
12
|
|
|
13
13
|
export default function EventInterceptor() {
|
|
14
14
|
const [hideInterface, setHideInterface] = useRecoilState(hideInterfaceState);
|
|
@@ -3,8 +3,8 @@ import { useCallback, useEffect } from 'react';
|
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
4
|
import { LOADING_ROUTE, MAIN_MENU_ROUTE } from '../constans';
|
|
5
5
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
6
|
-
import { useMyNavigate } from '../
|
|
7
|
-
import { addRefreshSave, loadRefreshSave } from '../
|
|
6
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
7
|
+
import { addRefreshSave, loadRefreshSave } from '../utils/save-utility';
|
|
8
8
|
|
|
9
9
|
export default function RefreshSaveEventInterceptor() {
|
|
10
10
|
const navigate = useMyNavigate();
|
|
@@ -9,7 +9,7 @@ import { nextStepLoadingState } from '../atoms/nextStepLoadingState';
|
|
|
9
9
|
import { skipEnabledState } from '../atoms/skipEnabledState';
|
|
10
10
|
import { typewriterIsAnimatedState } from '../atoms/typewriterIsAnimatedState';
|
|
11
11
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
12
|
-
import { useMyNavigate } from '../
|
|
12
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
13
13
|
|
|
14
14
|
export default function SkipAutoInterceptor() {
|
|
15
15
|
const navigate = useMyNavigate();
|
|
@@ -2,7 +2,7 @@ import { canvas, narration } from '@drincs/pixi-vn'
|
|
|
2
2
|
import { createRoot } from 'react-dom/client'
|
|
3
3
|
import App from './App'
|
|
4
4
|
import './index.css'
|
|
5
|
-
import { gameEnd } from './
|
|
5
|
+
import { gameEnd } from './utils/actions-utility'
|
|
6
6
|
import './values/characters'
|
|
7
7
|
|
|
8
8
|
// Canvas setup with PIXI
|
|
@@ -11,7 +11,7 @@ import { dialogueCardHeightState } from '../atoms/dialogueCardHeightState';
|
|
|
11
11
|
import { hideInterfaceState } from '../atoms/hideInterfaceState';
|
|
12
12
|
import ChoiceButton from '../components/ChoiceButton';
|
|
13
13
|
import { INTERFACE_DATA_USE_QUEY_KEY, useQueryChoiceMenuOptions } from '../use_query/useQueryInterface';
|
|
14
|
-
import { useMyNavigate } from '../
|
|
14
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
15
15
|
|
|
16
16
|
export default function ChoiceMenu({ fullscreen = true }: {
|
|
17
17
|
fullscreen?: boolean,
|
|
@@ -14,8 +14,8 @@ import GameSaveSlot from '../components/GameSaveSlot';
|
|
|
14
14
|
import ModalDialogCustom from '../components/ModalDialog';
|
|
15
15
|
import { MAIN_MENU_ROUTE } from '../constans';
|
|
16
16
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
17
|
-
import { useMyNavigate } from '../
|
|
18
|
-
import { downloadGameSave, loadGameSaveFromFile } from '../
|
|
17
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
18
|
+
import { downloadGameSave, loadGameSaveFromFile } from '../utils/save-utility';
|
|
19
19
|
|
|
20
20
|
export default function GameSaveScreen() {
|
|
21
21
|
const [open, setOpen] = useRecoilState(openGameSaveScreenState);
|
|
@@ -14,8 +14,8 @@ import { NARRATION_ROUTE } from '../constans';
|
|
|
14
14
|
import startLabel from '../labels/startLabel';
|
|
15
15
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
16
16
|
import useQueryLastSave from '../use_query/useQueryLastSave';
|
|
17
|
-
import { useMyNavigate } from '../
|
|
18
|
-
import { loadSave } from '../
|
|
17
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
18
|
+
import { loadSave } from '../utils/save-utility';
|
|
19
19
|
|
|
20
20
|
export default function MainMenu() {
|
|
21
21
|
const navigate = useMyNavigate();
|
|
@@ -16,9 +16,9 @@ import TextMenuButton from '../components/TextMenuButton';
|
|
|
16
16
|
import { INTERFACE_DATA_USE_QUEY_KEY, useQueryCanGoBack } from '../use_query/useQueryInterface';
|
|
17
17
|
import useQueryLastSave, { LAST_SAVE_USE_QUEY_KEY } from '../use_query/useQueryLastSave';
|
|
18
18
|
import { SAVES_USE_QUEY_KEY } from '../use_query/useQuerySaves';
|
|
19
|
-
import { goBack } from '../
|
|
20
|
-
import { useMyNavigate } from '../
|
|
21
|
-
import { putSaveIntoIndexDB } from '../
|
|
19
|
+
import { goBack } from '../utils/actions-utility';
|
|
20
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
21
|
+
import { putSaveIntoIndexDB } from '../utils/save-utility';
|
|
22
22
|
|
|
23
23
|
export default function QuickTools() {
|
|
24
24
|
const setOpenSettings = useSetRecoilState(openSettingsState);
|
|
@@ -11,8 +11,8 @@ import ModalConfirmation from '../../components/ModalConfirmation';
|
|
|
11
11
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../../use_query/useQueryInterface';
|
|
12
12
|
import { LAST_SAVE_USE_QUEY_KEY } from '../../use_query/useQueryLastSave';
|
|
13
13
|
import { SAVES_USE_QUEY_KEY } from '../../use_query/useQuerySaves';
|
|
14
|
-
import { useMyNavigate } from '../../
|
|
15
|
-
import { deleteSaveFromIndexDB, loadSave, putSaveIntoIndexDB } from '../../
|
|
14
|
+
import { useMyNavigate } from '../../utils/navigate-utility';
|
|
15
|
+
import { deleteSaveFromIndexDB, loadSave, putSaveIntoIndexDB } from '../../utils/save-utility';
|
|
16
16
|
|
|
17
17
|
export default function SaveLoadAlert() {
|
|
18
18
|
const navigate = useMyNavigate();
|
|
@@ -16,8 +16,8 @@ import SettingButton from '../../components/SettingButton';
|
|
|
16
16
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../../use_query/useQueryInterface';
|
|
17
17
|
import useQueryLastSave, { LAST_SAVE_USE_QUEY_KEY } from '../../use_query/useQueryLastSave';
|
|
18
18
|
import { SAVES_USE_QUEY_KEY } from '../../use_query/useQuerySaves';
|
|
19
|
-
import { useMyNavigate } from '../../
|
|
20
|
-
import { downloadGameSave, loadGameSaveFromFile, putSaveIntoIndexDB } from '../../
|
|
19
|
+
import { useMyNavigate } from '../../utils/navigate-utility';
|
|
20
|
+
import { downloadGameSave, loadGameSaveFromFile, putSaveIntoIndexDB } from '../../utils/save-utility';
|
|
21
21
|
|
|
22
22
|
export default function SaveLoadSettingButtons() {
|
|
23
23
|
const navigate = useMyNavigate();
|
|
@@ -18,6 +18,45 @@ The history modal is a list of all the dialogues and choices that have been disp
|
|
|
18
18
|
|
|
19
19
|
The settings modal allows you to change the text speed, go to full screen, edit theme colors, and change go to main menu. The settings for the audio have not been added nor the libraries to manage it, but I recommend adding them.
|
|
20
20
|
|
|
21
|
+
### Keyboard shortcuts (hotkeys)
|
|
22
|
+
|
|
23
|
+
* `Space` or `Enter`: Continue the dialogue.
|
|
24
|
+
* `Keep Space` or `Keep Enter`: Skip the dialogue.
|
|
25
|
+
* `Shift` + `S`: Quick save the game.
|
|
26
|
+
* `Shift` + `L`: Quick load the game.
|
|
27
|
+
* `Shift` + `H`: Open the history modal.
|
|
28
|
+
* `Esc`: Open the settings modal.
|
|
29
|
+
* `Shift` + `V`: Hide the UI (Show only the canvas).
|
|
30
|
+
|
|
31
|
+
### Used libraries
|
|
32
|
+
|
|
33
|
+
This template uses the following libraries:
|
|
34
|
+
|
|
35
|
+
Core libraries:
|
|
36
|
+
|
|
37
|
+
* [Pixi’VN](https://www.npmjs.com/package/@drincs/pixi-vn): A visual novel library.
|
|
38
|
+
* [Pixi’VN - *ink* Integration](https://www.npmjs.com/package/@drincs/pixi-vn-ink): A library that provides integration with the *ink* language.
|
|
39
|
+
* [Vite](https://vitejs.dev/): A build tool that aims to provide a faster and leaner development experience for modern web projects.
|
|
40
|
+
* [Vite Checker](https://www.npmjs.com/package/vite-plugin-checker): A Vite plugin that checks TypeScript types and ESLint on each build.
|
|
41
|
+
* [PWA Vite Plugin](https://vite-pwa-org.netlify.app): A Vite plugin that provides PWA support. This allows the possibility of installing the game as a Progressive Web App.
|
|
42
|
+
* [Recoil](https://recoiljs.org/): A state management library for React.
|
|
43
|
+
* [React Router](https://reactrouter.com/): A library that provides routing for React applications.
|
|
44
|
+
* [Tanstack Query](https://tanstack.com/tanstack-query/): A library that provides a set of tools for getting, caching, and updating game data.
|
|
45
|
+
<img width="44" alt="image" src="https://github.com/user-attachments/assets/bf70dddc-68c0-48f4-9c41-74c22f54e3d1">
|
|
46
|
+
You can use the following button to show Tanstack Query interactions with the game. (the button will be automatically hidden when released)
|
|
47
|
+
|
|
48
|
+
UI libraries:
|
|
49
|
+
|
|
50
|
+
* [Mui Joy](https://mui.com/joy-ui/getting-started/): A React UI framework that provides a set of components and styles for building a website.
|
|
51
|
+
* [Motion](https://motion.dev/): A simple yet powerful motion library for React.
|
|
52
|
+
* [Notistack](https://iamhosseindhv.com/notistack): A library that provides snackbar notifications for React.
|
|
53
|
+
* [React Color Palette](https://www.npmjs.com/package/react-color-palette): A library that provides a color picker for React.
|
|
54
|
+
|
|
55
|
+
Text libraries:
|
|
56
|
+
|
|
57
|
+
* [i18next](https://www.i18next.com/): A library that gives the possibility to manage multiple translations in the application.
|
|
58
|
+
* [Reacr Markdown](https://www.npmjs.com/package/react-markdown): A library that allows you to render markdown in React components.
|
|
59
|
+
|
|
21
60
|
## How to use
|
|
22
61
|
|
|
23
62
|
Before starting, you need to have Node.js installed on your computer. If you don't have it, you can download it [here](https://nodejs.org/).
|
|
@@ -34,31 +73,42 @@ Before starting, you need to have Node.js installed on your computer. If you don
|
|
|
34
73
|
|
|
35
74
|
You can change the icon of the game by replacing the images in the `public` folder.
|
|
36
75
|
|
|
37
|
-
|
|
76
|
+
## *ink* - Custom hashtag scripts
|
|
38
77
|
|
|
39
|
-
|
|
78
|
+
By using the [onInkHashtagScript](https://pixi-vn.web.app/ink/ink-hashtag.html) function, in this template the following features have been added.
|
|
79
|
+
|
|
80
|
+
**Moving between screens**: This feature allows you to navigate between different screens. The syntax is as follows:
|
|
81
|
+
|
|
82
|
+
`#` + `navigate` + `[route]`
|
|
40
83
|
|
|
41
|
-
|
|
84
|
+
`route`: The route/path to navigate to. Read more about routes in the [Router documentation](https://pixi-vn.web.app/start/interface-navigate.html).
|
|
42
85
|
|
|
43
86
|
```ink
|
|
44
|
-
|
|
45
|
-
INCLUDE ink_labels/start.ink
|
|
46
|
-
INCLUDE ink_labels/second.ink
|
|
47
|
-
-> start
|
|
87
|
+
#navigate /narration
|
|
48
88
|
```
|
|
49
89
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
90
|
+
**Rename the character**: This feature allows you to change the name of the character speaking. The syntax is as follows:
|
|
91
|
+
|
|
92
|
+
`#` + `rename` + `[character id]` + `[new name]`
|
|
93
|
+
|
|
94
|
+
### *ink* - ink files in the project
|
|
95
|
+
|
|
96
|
+
The `ink` folder contains the *ink* files that will be used in the game. In this project, all files `.ink`, that are in the `ink` folder, will be included automatically in the project. You can change this behavior by modifying the `src/utils/ink-utility.ts` file.
|
|
55
97
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
98
|
+
### *ink* - Writing/testing the narrative with Inky
|
|
99
|
+
|
|
100
|
+
To write and test the narrative, you can use the **Inky editor**. Inky is a tool for writing interactive fiction using the Ink language. Of course, the special features introduced by pixi-vn will not be ignored by Inky. You can download it [here](https://www.inklestudios.com/ink/).
|
|
101
|
+
|
|
102
|
+
To use Inky with this template, you can open the `src/main.ink` file in Inky.
|
|
103
|
+
|
|
104
|
+
```ink
|
|
105
|
+
// main.ink
|
|
106
|
+
INCLUDE ink/start.ink
|
|
107
|
+
INCLUDE ink/second.ink
|
|
108
|
+
-> start
|
|
59
109
|
```
|
|
60
110
|
|
|
61
|
-
|
|
111
|
+
## Installation
|
|
62
112
|
|
|
63
113
|
First, is necessary install the dependencies. To do this, open a terminal in the root folder of the project and run the following command:
|
|
64
114
|
|
|
@@ -66,7 +116,7 @@ First, is necessary install the dependencies. To do this, open a terminal in the
|
|
|
66
116
|
npm install
|
|
67
117
|
```
|
|
68
118
|
|
|
69
|
-
|
|
119
|
+
## Start the web application
|
|
70
120
|
|
|
71
121
|
To start the web application, run the following command:
|
|
72
122
|
|
|
@@ -76,67 +126,10 @@ npm start
|
|
|
76
126
|
|
|
77
127
|
This command will start the development server. Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
|
|
78
128
|
|
|
79
|
-
|
|
129
|
+
### Debugging the web application
|
|
80
130
|
|
|
81
131
|
If you are using Visual Studio Code, you can use the debug configuration provided with the template. To do this, after launching `npm start`, go to the debug section and select the `Launch Chrome` configuration.
|
|
82
132
|
|
|
83
|
-
## Keyboard shortcuts (hotkeys)
|
|
84
|
-
|
|
85
|
-
* `Space` or `Enter`: Continue the dialogue.
|
|
86
|
-
* `Keep Space` or `Keep Enter`: Skip the dialogue.
|
|
87
|
-
* `Shift` + `S`: Quick save the game.
|
|
88
|
-
* `Shift` + `L`: Quick load the game.
|
|
89
|
-
* `Shift` + `H`: Open the history modal.
|
|
90
|
-
* `Esc`: Open the settings modal.
|
|
91
|
-
* `Shift` + `V`: Hide the UI (Show only the canvas).
|
|
92
|
-
|
|
93
|
-
## Custom hashtag scripts
|
|
94
|
-
|
|
95
|
-
By using the [onInkHashtagScript](https://pixi-vn.web.app/ink/ink-hashtag.html) function, in this template the following features have been added.
|
|
96
|
-
|
|
97
|
-
**Moving between screens**: This feature allows you to navigate between different screens. The syntax is as follows:
|
|
98
|
-
|
|
99
|
-
`#` + `navigate` + `[route]`
|
|
100
|
-
|
|
101
|
-
`route`: The route/path to navigate to. Read more about routes in the [Router documentation](https://pixi-vn.web.app/start/interface-navigate.html).
|
|
102
|
-
|
|
103
|
-
```ink
|
|
104
|
-
#navigate /narration
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Rename the character**: This feature allows you to change the name of the character speaking. The syntax is as follows:
|
|
108
|
-
|
|
109
|
-
`#` + `rename` + `[character id]` + `[new name]`
|
|
110
|
-
|
|
111
|
-
## Used libraries
|
|
112
|
-
|
|
113
|
-
This template uses the following libraries:
|
|
114
|
-
|
|
115
|
-
Core libraries:
|
|
116
|
-
|
|
117
|
-
* [Pixi’VN](https://www.npmjs.com/package/@drincs/pixi-vn): A visual novel library.
|
|
118
|
-
* [Pixi’VN - Ink Integration](https://www.npmjs.com/package/@drincs/pixi-vn-ink): A library that provides integration with the Ink language.
|
|
119
|
-
* [Vite](https://vitejs.dev/): A build tool that aims to provide a faster and leaner development experience for modern web projects.
|
|
120
|
-
* [Vite Checker](https://www.npmjs.com/package/vite-plugin-checker): A Vite plugin that checks TypeScript types and ESLint on each build.
|
|
121
|
-
* [PWA Vite Plugin](https://vite-pwa-org.netlify.app): A Vite plugin that provides PWA support. This allows the possibility of installing the game as a Progressive Web App.
|
|
122
|
-
* [Recoil](https://recoiljs.org/): A state management library for React.
|
|
123
|
-
* [React Router](https://reactrouter.com/): A library that provides routing for React applications.
|
|
124
|
-
* [Tanstack Query](https://tanstack.com/tanstack-query/): A library that provides a set of tools for getting, caching, and updating game data.
|
|
125
|
-
<img width="44" alt="image" src="https://github.com/user-attachments/assets/bf70dddc-68c0-48f4-9c41-74c22f54e3d1">
|
|
126
|
-
You can use the following button to show Tanstack Query interactions with the game. (the button will be automatically hidden when released)
|
|
127
|
-
|
|
128
|
-
UI libraries:
|
|
129
|
-
|
|
130
|
-
* [Mui Joy](https://mui.com/joy-ui/getting-started/): A React UI framework that provides a set of components and styles for building a website.
|
|
131
|
-
* [Motion](https://motion.dev/): A simple yet powerful motion library for React.
|
|
132
|
-
* [Notistack](https://iamhosseindhv.com/notistack): A library that provides snackbar notifications for React.
|
|
133
|
-
* [React Color Palette](https://www.npmjs.com/package/react-color-palette): A library that provides a color picker for React.
|
|
134
|
-
|
|
135
|
-
Text libraries:
|
|
136
|
-
|
|
137
|
-
* [i18next](https://www.i18next.com/): A library that gives the possibility to manage multiple translations in the application.
|
|
138
|
-
* [Reacr Markdown](https://www.npmjs.com/package/react-markdown): A library that allows you to render markdown in React components.
|
|
139
|
-
|
|
140
133
|
## Distribution
|
|
141
134
|
|
|
142
135
|
### Web application
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { lazy, Suspense } from "react";
|
|
2
2
|
import { ErrorBoundary } from "react-error-boundary";
|
|
3
3
|
import LoadingScreen from "./screens/LoadingScreen";
|
|
4
|
-
import { defineAssets } from "./
|
|
5
|
-
import { initializeIndexedDB } from "./
|
|
6
|
-
import { importAllInkLabels } from "./
|
|
4
|
+
import { defineAssets } from "./utils/assets-utility";
|
|
5
|
+
import { initializeIndexedDB } from "./utils/indexedDB-utility";
|
|
6
|
+
import { importAllInkLabels } from "./utils/ink-utility";
|
|
7
7
|
|
|
8
8
|
export default function App() {
|
|
9
9
|
const Home = lazy(async () => {
|
|
@@ -9,7 +9,7 @@ import TypographyShadow from "../components/TypographyShadow";
|
|
|
9
9
|
import { MAIN_MENU_ROUTE } from '../constans';
|
|
10
10
|
import GameSaveData from '../models/GameSaveData';
|
|
11
11
|
import useQuerySaves from '../use_query/useQuerySaves';
|
|
12
|
-
import { downloadGameSave } from '../
|
|
12
|
+
import { downloadGameSave } from '../utils/save-utility';
|
|
13
13
|
|
|
14
14
|
export default function GameSaveSlot({ saveId, onDelete, onLoad, onOverwriteSave, onSave }: {
|
|
15
15
|
saveId: number,
|
|
@@ -10,7 +10,7 @@ import { hideInterfaceState } from '../atoms/hideInterfaceState';
|
|
|
10
10
|
import { nextStepLoadingState } from '../atoms/nextStepLoadingState';
|
|
11
11
|
import { skipEnabledState } from '../atoms/skipEnabledState';
|
|
12
12
|
import { INTERFACE_DATA_USE_QUEY_KEY, useQueryCanGoNext } from '../use_query/useQueryInterface';
|
|
13
|
-
import { useMyNavigate } from '../
|
|
13
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
14
14
|
|
|
15
15
|
export default function NextButton() {
|
|
16
16
|
const [skip, setSkip] = useRecoilState(skipEnabledState)
|
|
@@ -6,8 +6,8 @@ import { useLocation } from 'react-router-dom';
|
|
|
6
6
|
import { useSetRecoilState } from 'recoil';
|
|
7
7
|
import { openSettingsState } from '../atoms/openSettingsState';
|
|
8
8
|
import ModalDialogCustom from '../components/ModalDialog';
|
|
9
|
-
import { gameEnd } from '../
|
|
10
|
-
import { useMyNavigate } from '../
|
|
9
|
+
import { gameEnd } from '../utils/actions-utility';
|
|
10
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
11
11
|
|
|
12
12
|
export default function ReturnMainMenuButton() {
|
|
13
13
|
const openSettings = useSetRecoilState(openSettingsState);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import i18n from 'i18next';
|
|
2
2
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
3
3
|
import { initReactI18next } from 'react-i18next';
|
|
4
|
-
import strings_en from '../src/
|
|
4
|
+
import strings_en from '../src/locales/strings_en.json';
|
|
5
5
|
|
|
6
6
|
const getUserLang = (): string => {
|
|
7
7
|
let userLang: string = navigator.language || "en";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { initializeInk } from '../
|
|
4
|
-
import { useMyNavigate } from '../
|
|
3
|
+
import { initializeInk } from '../utils/ink-utility';
|
|
4
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
5
5
|
|
|
6
6
|
export default function InkInitialization() {
|
|
7
7
|
const navigate = useMyNavigate();
|
|
@@ -8,7 +8,7 @@ import { hideInterfaceState } from '../atoms/hideInterfaceState';
|
|
|
8
8
|
import { saveLoadAlertState } from '../atoms/saveLoadAlertState';
|
|
9
9
|
import useQueryLastSave, { LAST_SAVE_USE_QUEY_KEY } from '../use_query/useQueryLastSave';
|
|
10
10
|
import { SAVES_USE_QUEY_KEY } from '../use_query/useQuerySaves';
|
|
11
|
-
import { putSaveIntoIndexDB } from '../
|
|
11
|
+
import { putSaveIntoIndexDB } from '../utils/save-utility';
|
|
12
12
|
|
|
13
13
|
export default function EventInterceptor() {
|
|
14
14
|
const [hideInterface, setHideInterface] = useRecoilState(hideInterfaceState);
|
|
@@ -3,8 +3,8 @@ import { useCallback, useEffect } from 'react';
|
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
4
|
import { LOADING_ROUTE, MAIN_MENU_ROUTE } from '../constans';
|
|
5
5
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
6
|
-
import { useMyNavigate } from '../
|
|
7
|
-
import { addRefreshSave, loadRefreshSave } from '../
|
|
6
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
7
|
+
import { addRefreshSave, loadRefreshSave } from '../utils/save-utility';
|
|
8
8
|
|
|
9
9
|
export default function RefreshSaveEventInterceptor() {
|
|
10
10
|
const navigate = useMyNavigate();
|
|
@@ -9,7 +9,7 @@ import { nextStepLoadingState } from '../atoms/nextStepLoadingState';
|
|
|
9
9
|
import { skipEnabledState } from '../atoms/skipEnabledState';
|
|
10
10
|
import { typewriterIsAnimatedState } from '../atoms/typewriterIsAnimatedState';
|
|
11
11
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
12
|
-
import { useMyNavigate } from '../
|
|
12
|
+
import { useMyNavigate } from '../utils/navigate-utility';
|
|
13
13
|
|
|
14
14
|
export default function SkipAutoInterceptor() {
|
|
15
15
|
const navigate = useMyNavigate();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
INCLUDE
|
|
1
|
+
INCLUDE ink/start.ink
|
|
2
2
|
-> start
|