diff --git a/dev-env/.engine/Ikemen_GO/Ikemen_GO_Linux b/dev-env/.engine/Ikemen_GO/Ikemen_GO_Linux new file mode 100755 index 0000000..63df3ae --- /dev/null +++ b/dev-env/.engine/Ikemen_GO/Ikemen_GO_Linux @@ -0,0 +1,3 @@ +#/bin/bash + +echo "Fake Ikemen" diff --git a/dev-env/.engine/Ikemen_GO/Ikemen_GO_MacOS b/dev-env/.engine/Ikemen_GO/Ikemen_GO_MacOS new file mode 100755 index 0000000..63df3ae --- /dev/null +++ b/dev-env/.engine/Ikemen_GO/Ikemen_GO_MacOS @@ -0,0 +1,3 @@ +#/bin/bash + +echo "Fake Ikemen" diff --git a/dev-env/.engine/run-ikemen.sh b/dev-env/.engine/run-ikemen.sh new file mode 100755 index 0000000..9f5e840 --- /dev/null +++ b/dev-env/.engine/run-ikemen.sh @@ -0,0 +1,84 @@ +#/bin/bash + +currentDirectory=$(dirname "$(realpath "$0")") +cd "$currentDirectory/Ikemen_GO" + +configPath="../../save/config.json" +motifDirectory="../../../motifs" +lifebarDirectory="../../lifebars" +stageDirectory="../../../stages" +characterDirectory="../../../chars" + +motif="motif/system.def" +lifebar="01/fight.def" +rounds=2 +characterOneColor=1 +characterTwoColor=1 +characterTwoAI=0 + +for i in "$@"; do + case $i in + -motif=*) + motif="${i#*=}" + shift + ;; + -lifebar=*) + lifebar="${i#*=}" + shift + ;; + -p1=*) + characterOne="${i#*=}" + shift + ;; + -p1.color=*) + characterOneColor="${i#*=}" + shift + ;; + -p2=*) + characterTwo="${i#*=}" + shift + ;; + -p2.color=*) + characterTwoColor="${i#*=}" + shift + ;; + -p2.ai=*) + characterTwoAI="${i#*=}" + shift + ;; + -s=*) + stage="${i#*=}" + shift + ;; + -rounds=*) + rounds="${i#*=}" + shift + ;; + *) + ;; + esac +done + +case "$OSTYPE" in + darwin*) #echo "It's a Mac!!" ; + ikemen="./Ikemen_GO_MacOS -AppleMagnifiedMode YES" + ;; + linux*) + ikemen="./Ikemen_GO_Linux" + ;; + *) + ikemen="./Ikemen_GO_Linux" + ;; +esac + +$ikemen \ + -config "$configPath" \ + -r "$motifDirectory/$motif" \ + -lifebar "$lifebarDirectory/$lifebar" \ + -s "$stageDirectory/$stage" \ + -rounds $rounds \ + -p1 "$characterDirectory/$characterOne" \ + -p1.color $characterOneColor \ + -p2 "$characterDirectory/$characterTwo" \ + -p2.color $characterTwoColor \ + -p2.ai $characterTwoAI diff --git a/dev-env/mugen.exe b/dev-env/lifebars/01/fight.def similarity index 100% rename from dev-env/mugen.exe rename to dev-env/lifebars/01/fight.def diff --git a/dev-env/motifs/system.def b/dev-env/motifs/system.def new file mode 100644 index 0000000..e3ab04c --- /dev/null +++ b/dev-env/motifs/system.def @@ -0,0 +1,76 @@ +[Info] +name = Quick Versus +author = neolao +versiondate = 01,26,2024 +mugenversion = 1.1 +localcoord = 1280,720 +;localcoord = 1920,1080 + +[Files] +spr = system.sff ;Filename of sprite data +snd = system.snd ;Filename of sound data +select = select.def ;Character and stage selection list +fight = fight.def ;Fight definition filename +font1 = f-4x6.def ;System fonts +font2 = f-6x9.def ;System fonts +font3 = jg.fnt ;System fonts +font4 = Open_Sans.def +font5 = default-3x5-bold.def +font6 = default-3x5.def +module = ;Ikemen feature: External Lua code + +[Music] + +[Title Info] + +[TitleBGdef] + +[TitleBG] +type = normal +spriteno = 0,0 + +[Select Info] + +[SelectBGdef] + +[SelectBG] +type = normal +spriteno = 0,0 + +[VS Screen] + +[VersusBGdef] + +[VersusBG] +type = normal +spriteno = 0,0 + +[Demo Mode] +[Continue Screen] + +[Game Over Screen] + +[Victory Screen] + +[VictoryBGdef] + +[VictoryBG] +type = normal +spriteno = 0,0 + +[Win Screen] + +[Default Ending] + +[End Credits] + +[Survival Results Screen] + +[Option Info] + +[OptionBGdef] + +[OptionBG] +type = normal +spriteno = 0,0 + diff --git a/dev-env/quick-versus.json b/dev-env/quick-versus.json index 3a7593f..bf39ccf 100644 --- a/dev-env/quick-versus.json +++ b/dev-env/quick-versus.json @@ -1,7 +1,9 @@ { "frame": true, + "motif": "system.def", + "lifebar": "01/fight.def", + "rounds": 2, "characterColumns": 3, - "ikemenExecutablePath": "mugen.exe", "sound": { "volume": 30, "background": "sound/title.mp3", @@ -11,7 +13,7 @@ "selectAILevel": "sound/confirm.wav", "moveCursor": "sound/move-cursor.wav", "cancel": "sound/cancel.wav" -}, + }, "categories": [ { "name": "Capcom", @@ -242,7 +244,7 @@ "y": "q", "l1": "d", "r1": "c", - "quit": "i" + "quit": "escape" }, "gamepad": { "left": "A17", diff --git a/index.js b/index.js index caab3b7..456967c 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ -const { execFile } = require("node:child_process"); +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); const { app, BrowserWindow, ipcMain } = require("electron"); const path = require("path"); const fs = require("fs"); @@ -14,6 +15,7 @@ try { function getCurrentDirectory() { let currentDirectory; if (process.argv.length >= 3) { + // TODO use a named option currentDirectory = path.normalize(process.argv[2]); } else if (isDev) { currentDirectory = path.resolve(app.getAppPath(), "dev-env"); @@ -33,6 +35,20 @@ function getCurrentDirectory() { return currentDirectory; } +function getConfiguration() { + const currentDirectory = getCurrentDirectory(); + const jsonFilePath = path.resolve(currentDirectory, "quick-versus.json"); + const yamlFilePath = path.resolve(currentDirectory, "quick-versus.yml"); + let config; + if (fs.existsSync(jsonFilePath)) { + config = require(jsonFilePath); + } else if (fs.existsSync(yamlFilePath)) { + config = configYaml(yamlFilePath); + } + + return config; +} + function createWindow() { let width = 1024; let height = 576; @@ -40,15 +56,7 @@ function createWindow() { let frame = false; try { - const currentDirectory = getCurrentDirectory(); - const jsonFilePath = path.resolve(currentDirectory, "quick-versus.json"); - const yamlFilePath = path.resolve(currentDirectory, "quick-versus.yml"); - let config; - if (fs.existsSync(jsonFilePath)) { - config = require(jsonFilePath); - } else if (fs.existsSync(yamlFilePath)) { - config = configYaml(yamlFilePath); - } + const config = getConfiguration(); if (config) { if (config.hasOwnProperty("width")) { @@ -99,10 +107,42 @@ function getVersion(event) { event.returnValue = version; } -async function executeFile (event, filePath, args, options) { - execFile(filePath, args, options, () => { - event.returnValue = true; - }); +async function launchGame(event, options) { + const directoryPath = getCurrentDirectory(); + const filePath = `${directoryPath}/.engine/run-ikemen.sh`; + const config = getConfiguration(); + + let command = `"${filePath}"`; + if (config.rounds) { + command += ` -rounds="${config.rounds}"`; + } + if (config.motif) { + command += ` -motif="${config.motif}"`; + } + if (config.lifebar) { + command += ` -lifebar="${config.lifebar}"`; + } + if (options.characterOne) { + command += ` -p1="${options.characterOne}"`; + } + if (options.characterOneColorIndex) { + command += ` -p1.color="${options.characterOneColorIndex}"`; + } + if (options.characterTwo) { + command += ` -p2="${options.characterTwo}"`; + } + if (options.characterTwoColorIndex) { + command += ` -p2.color="${options.characterTwoColorIndex}"`; + } + if (options.characterTwoAILevel) { + command += ` -p2.ai="${options.characterTwoAILevel}"`; + } + if (options.stage) { + command += ` -s="${options.stage}"`; + } + console.log(command); + await exec(command, { cwd: directoryPath }); + return true; } function getConfigYaml(event, filePath) { @@ -132,7 +172,7 @@ function getCurrentDirectoryExported(event) { async function start() { await app.whenReady(); ipcMain.on("getVersion", getVersion); - ipcMain.on("execFile", executeFile); + ipcMain.handle("launchGame", launchGame); ipcMain.on("existsSync", existsSync); ipcMain.on("readFileSync", readFileSync); ipcMain.on("resolve", resolve); diff --git a/preload.js b/preload.js index 520fc13..eed91da 100644 --- a/preload.js +++ b/preload.js @@ -1,7 +1,7 @@ const { contextBridge, ipcRenderer } = require("electron/renderer"); contextBridge.exposeInMainWorld("mainAPI", { - execFile: async (filePath, args, options) => ipcRenderer.send("execFile", filePath, args, options), + launchGame: (args) => ipcRenderer.invoke("launchGame", args), existsSync: (filePath) => ipcRenderer.sendSync("existsSync", filePath), readFileSync: (filePath) => ipcRenderer.sendSync("readFileSync", filePath), resolve: (...args) => ipcRenderer.sendSync("resolve", args), diff --git a/src/app.jsx b/src/app.jsx index 35394eb..776d361 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -95,21 +95,8 @@ export default function App() { } } - const ikemenPath = mainAPI.resolve(currentDirectory, configuration.ikemenExecutablePath); - if (!mainAPI.existsSync(ikemenPath)) { - return ( - -

- Ikemen executable file is missing: - {ikemenPath} -

-
- ); - } - const environment = { currentDirectory, - ikemenPath, configurationFilePath }; diff --git a/src/fight/fight.presenter.jsx b/src/fight/fight.presenter.jsx index ef42d7e..311b7c5 100644 --- a/src/fight/fight.presenter.jsx +++ b/src/fight/fight.presenter.jsx @@ -29,48 +29,34 @@ const BlackScreen = styled.div` export default function Fight() { const configuration = useConfiguration(); const navigation = useNavigation(); - const environment = useEnvironment(); const dispatch = useNavigationDispatch(); const backgroundSound = useBackgroundSound(); if (navigation.state === TRAINING_FIGHTING || navigation.state === VERSUS_FIGHTING) { - const options = [ - "-p1", - navigation.characterOne.definition, - "-p2", - navigation.characterTwo.definition, - "-s", - navigation.stage.definition, - "-rounds", - 2 - ]; - if (configuration.motif) { - options.push("-r", configuration.motif); - } + const options = { + characterOne: navigation.characterOne.definition, + characterTwo: navigation.characterTwo.definition, + stage: navigation.stage.definition + }; + if (navigation.characterOneColorIndex) { - options.push("-p1.color", navigation.characterOneColorIndex); + options.characterOneColorIndex = navigation.characterOneColorIndex; } if (navigation.characterTwoColorIndex) { - options.push("-p2.color", navigation.characterTwoColorIndex); + options.characterTwoColorIndex = navigation.characterTwoColorIndex; } if (navigation.characterTwoAILevel > 0) { - options.push("-p2.ai", navigation.characterTwoAILevel); + options.characterTwoAILevel = navigation.characterTwoAILevel; } backgroundSound.pause(); mainAPI.minimize(); - mainAPI.execFile( - environment.ikemenPath, - options, - { - cwd: environment.currentDirectory - } - ).then(() => { + mainAPI.launchGame(options).then(() => { dispatch(endFight()); backgroundSound.play(); mainAPI.restore(); }); - console.log(environment.ikemenPath, options); + console.log("launchGame", options); return Fighting ...; } diff --git a/src/input/useInput.hook.js b/src/input/useInput.hook.js index ebddf8c..30ee151 100644 --- a/src/input/useInput.hook.js +++ b/src/input/useInput.hook.js @@ -67,6 +67,7 @@ export default function useInput(keyboardMapping, gamepadMapping) { keyboard.addEventListener(keyboardMapping.l1, onPressL1); keyboard.addEventListener(keyboardMapping.r1, onPressR1); keyboard.addEventListener(keyboardMapping.quit, onPressQuit); + /* gamepad.addEventListener(gamepadMapping.left, onPressLeft); gamepad.addEventListener(gamepadMapping.right, onPressRight); gamepad.addEventListener(gamepadMapping.up, onPressUp); @@ -78,6 +79,7 @@ export default function useInput(keyboardMapping, gamepadMapping) { gamepad.addEventListener(gamepadMapping.l1, onPressL1); gamepad.addEventListener(gamepadMapping.r1, onPressR1); gamepad.addEventListener(gamepadMapping.quit, onPressQuit); + */ return () => { keyboard.removeEventListener(keyboardMapping.left, onPressLeft); @@ -91,6 +93,7 @@ export default function useInput(keyboardMapping, gamepadMapping) { keyboard.removeEventListener(keyboardMapping.l1, onPressL1); keyboard.removeEventListener(keyboardMapping.r1, onPressR1); keyboard.removeEventListener(keyboardMapping.quit, onPressQuit); + /* gamepad.removeEventListener(gamepadMapping.left, onPressLeft); gamepad.removeEventListener(gamepadMapping.right, onPressRight); gamepad.removeEventListener(gamepadMapping.up, onPressUp); @@ -102,6 +105,7 @@ export default function useInput(keyboardMapping, gamepadMapping) { gamepad.removeEventListener(gamepadMapping.l1, onPressL1); gamepad.removeEventListener(gamepadMapping.r1, onPressR1); gamepad.removeEventListener(gamepadMapping.quit, onPressQuit); + */ }; }, [emitter, keyboardMapping, gamepadMapping, keyboard, gamepad]);