├── .gitignore ├── .npmignore ├── README.md ├── config.json ├── creator ├── add │ ├── android.js │ └── scene.js ├── androidCommands │ └── androidCommands.js ├── build │ ├── build.js │ └── build_android.js ├── newProject │ └── newProject.js └── serve │ └── serve.js ├── index.js ├── lib ├── files.js ├── helpers.js └── log.js ├── package-lock.json ├── package.json ├── questions └── newProject.js ├── repos.json ├── scaffolding ├── android │ └── capacitor.config.json ├── files │ ├── .editorconfig │ ├── .phaser_cli │ ├── def │ │ └── globals.d.ts │ ├── game │ │ ├── assets │ │ │ └── phaser3_cli.png │ │ ├── css │ │ │ └── normalize.css │ │ ├── gamma │ │ │ ├── core.ts │ │ │ └── templates.ts │ │ ├── index.html │ │ └── src │ │ │ ├── Bootloader.ts │ │ │ ├── config.ts │ │ │ ├── constants.ts │ │ │ ├── main.ts │ │ │ └── scenes │ │ │ └── MainScene.ts │ ├── package.json │ ├── tsconfig.json │ ├── tslint.json │ ├── vendor │ │ └── phaser │ │ │ └── phaser.min.js │ └── webpack.config.js └── scene.ts └── server_gamma_core ├── controller.js └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | RECURSOS/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phaser3 CLI 2 | 3 | ![Imgur](https://i.imgur.com/PXv0Vvx.png) 4 | 5 | [![dependencies Status](https://david-dm.org/gammafp/phaser3-cli/status.svg)](https://david-dm.org/gammafp/phaser3-cli) ![npm](https://img.shields.io/npm/v/phaser3-cli.svg) ![GitHub issues](https://img.shields.io/github/issues/gammafp/phaser3-cli.svg) 6 | 7 | ---- 8 | 9 | ## The Goal of Phaser3 CLI 10 | 11 | Accelerate your development time, phaser 3 CLI bridles you tools so you can create more in less time. We know you like to focus on what matters most your game so we make it easy for you to set up. 12 | 13 | # Getting Started - Local Development 14 | 15 | ## Prerequisites 16 | - Make sure that you have Node 10.9 or later installed. See instructions [here](https://nodejs.org/en/download/). 17 | 18 | ## Installation 19 | To get started locally, follow these instructions: 20 | 21 | 1. Install Phaser3 CLI with: 22 | ```bash 23 | > npm i -g phaser3-cli 24 | ``` 25 | 26 | ## Usage 27 | 1. Create a new project: 28 | ```bash 29 | > phaser new mygame 30 | ``` 31 | 2. Going to folder 32 | ```bash 33 | > cd mygame 34 | ``` 35 | 3. Start the server 36 | 37 | ```bash 38 | > phaser serve 39 | ``` 40 | --- 41 | You can add a scene with: 42 | ```bash 43 | > phaser add scene 44 | ``` 45 | 46 | --- 47 | ## Android 48 | ## ¡Important: You need have installed Android Studio! 49 | You can add a android project with capacitor: 50 | 1. Add capacitor android project 51 | ```bash 52 | > phaser add android 53 | ``` 54 | 2. Build your android project (Android Studio): 55 | ```bash 56 | > phaser build android 57 | ``` 58 | 59 | 3. Update your project when you modify your game files 60 | ```bash 61 | > phaser android copy 62 | ``` 63 | 64 | 65 | --- 66 | ## Web 67 | You can build your web package with: 68 | ```bash 69 | > phaser build 70 | ``` 71 | 72 | And enjoy you game dev :D -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "route_base_project": "game", 3 | "port_server_gamma_core": "43010" 4 | } -------------------------------------------------------------------------------- /creator/add/android.js: -------------------------------------------------------------------------------- 1 | const files = require('../../lib/files'); 2 | const log = require('../../lib/log'); 3 | const ora = require('ora'); 4 | const command = require('child_process'); 5 | const config_routes = require('../../config.json'); 6 | 7 | 8 | // Inicia un proyecto con android 9 | module.exports = (sceneNames) => { 10 | const spinner = ora(`Downloading capacitor, be patient...\n`); 11 | 12 | spinner.start(); 13 | // Configuramos el capacitor.config.json 14 | const app_id = JSON.parse(files.readFile('./package.json')).name; 15 | const config_project_file = files.readFile(`./${config_routes.route_base_project}/src/config.ts`); 16 | let app_name = config_project_file.match(/title: *['a-z A-Z0-9.12]*/); 17 | app_name = (app_name === null) ? 'default_name' : app_name[0].split(':')[1].replace(/['"]/g, '').trim(); 18 | app_name = (app_name === '') ? 'default_name' : app_name; 19 | 20 | let capacitor_config = files.readFile(`${files.getCurrentDirectory()}/scaffolding/android/capacitor.config.json`); 21 | capacitor_config = capacitor_config 22 | .replace('{{app_id}}', app_id) 23 | .replace('{{app_name}}', app_name); 24 | 25 | files.writeFileAsync(`./capacitor.config.json`, capacitor_config).then( 26 | (err) => { 27 | if (err) { 28 | log.danger(err); 29 | return; 30 | } 31 | // Instalamos el nucleo de capacitor 32 | command.exec(`npm i --save @capacitor/core @capacitor/cli`, (err, stdout, stderr) => { 33 | if (err) { 34 | log.danger(err); 35 | return; 36 | } 37 | spinner.succeed('Capacitor is installed.'); 38 | spinner.text = 'Installing android, be patient'; 39 | spinner.start(); 40 | // Instalamos android 41 | command.exec(`npm run build-install-android && npx cap add android`, (err, stdout, stderr) => { 42 | if (err) { 43 | log.danger(err); 44 | return; 45 | } 46 | 47 | spinner.succeed('Android is installed'); 48 | log.success('You can create your android app with android studio now :)'); 49 | log.success('Open your android proyect with: phaser build android'); 50 | }); 51 | }); 52 | 53 | }); 54 | } -------------------------------------------------------------------------------- /creator/add/scene.js: -------------------------------------------------------------------------------- 1 | const files = require('../../lib/files'); 2 | const log = require('../../lib/log'); 3 | const {sceneNameToUpperCase, getSceneRoute} = require('../../lib/helpers'); 4 | 5 | const ora = require('ora'); 6 | 7 | const config_routes = require('../../config.json'); 8 | 9 | const configURL = `./${config_routes.route_base_project}/src/config.ts`; 10 | 11 | const regexImports = /export *[c|C][o|O][n|N][s|S][t|T] *[c|C][o|O][n|N][f|F][i|I][g|G] *: * (.*)=/; 12 | const regexScene = /"?scene"? *: *[\n\t\r\s\[\w,]*[\w]/; 13 | 14 | module.exports = (sceneNames) => { 15 | if (sceneNames.length > 0) { 16 | if (files.fileExists('.phaser_cli')) { 17 | if(files.fileExists(configURL)) { 18 | let data = files.readFile(configURL); 19 | if(regexImports.test(data)) { 20 | if(regexScene.test(data)) { 21 | const spinner = ora(`Creating scene...\n`); 22 | sceneNames.map((sceneName) => { 23 | // TODO: Comprobar si la escena ya existe 24 | const route = getSceneRoute(sceneName).replace('./', ''); 25 | const name = sceneNameToUpperCase(sceneName); 26 | 27 | const newImport = `\nimport { ${name} } from './${route}/${name}';\n\n`; 28 | 29 | const matchSplit = data.match(regexImports)[0]; 30 | 31 | const importsSplit = data.split(regexImports); 32 | const imports = importsSplit[0].trim() + newImport; 33 | 34 | const configJSON = imports + matchSplit + importsSplit[2] 35 | 36 | const importScene = configJSON.replace(regexScene, (find) => { 37 | return `${find},\n ${name}`; 38 | }); 39 | data = importScene; 40 | 41 | // --> Copiar archivo para crear la escena 42 | // Nos ayuda a setear la ruta en scene o en rutas definidas por el usuario 43 | const sceneScaffold = files.readFile(`${files.getCurrentDirectory()}/scaffolding/scene.ts`) 44 | .replace(/{sceneName}/g, name); 45 | 46 | const sceneRoute =`${config_routes.route_base_project}/src/${route}/${name}.ts`; 47 | files.writeFile(sceneRoute, sceneScaffold); 48 | }); 49 | // --> Escribir escena 50 | files.writeFile(configURL, data); 51 | spinner.succeed('Scene created'); 52 | 53 | } else { 54 | log.danger('The scene can be create.\nscene have a bad structure.'); 55 | } 56 | } else { 57 | log.danger('The scene can be create.\nThe "export const CONFIG: any" is missing.'); 58 | } 59 | } else { 60 | log.danger('The file config.ts is missing :('); 61 | log.danger("The scene can't be create."); 62 | } 63 | } else { 64 | log.no_project(); 65 | } 66 | } else { 67 | log.danger('The name of scene is missing'); 68 | } 69 | } -------------------------------------------------------------------------------- /creator/androidCommands/androidCommands.js: -------------------------------------------------------------------------------- 1 | const command = require('child_process'); 2 | const ora = require('ora'); 3 | const log = require('../../lib/log'); 4 | 5 | // Actualiza proyectos existentes 6 | module.exports = { 7 | copy: () => { 8 | const spinner = ora(`Updating the project of Android Studio...\n`); 9 | spinner.start(); 10 | command.exec('npm run build-install-android', (err, stdout, stderr) => { 11 | if (err) { 12 | log.danger(err); 13 | return; 14 | } 15 | spinner.succeed(); 16 | const exec = command.spawn('npx', [ 17 | 'cap', 18 | 'copy' 19 | ], {shell: true}); 20 | 21 | exec.stdout.on('data', function(data) { 22 | console.log(data.toString()); 23 | }); 24 | exec.stderr.on('data', function(data) { 25 | console.log(data.toString()); 26 | }); 27 | }); 28 | } 29 | } -------------------------------------------------------------------------------- /creator/build/build.js: -------------------------------------------------------------------------------- 1 | const files = require('../../lib/files'); 2 | const log = require('../../lib/log'); 3 | const command = require('child_process'); 4 | const ora = require('ora'); 5 | 6 | module.exports = () => { 7 | if (files.fileExists('.phaser_cli')) { 8 | const spinner = ora(`Building game, be patient...\n`); 9 | spinner.start(); 10 | command.exec('npm run build', (err, stdout, stderr) => { 11 | if (err) { 12 | log.danger(err); 13 | return; 14 | } 15 | spinner.succeed('Game builded.'); 16 | log.success('Your game is in the "dist" folder :)'); 17 | }); 18 | } else { 19 | log.no_project(); 20 | } 21 | }; -------------------------------------------------------------------------------- /creator/build/build_android.js: -------------------------------------------------------------------------------- 1 | const files = require('../../lib/files'); 2 | const log = require('../../lib/log'); 3 | const command = require('child_process'); 4 | const ora = require('ora'); 5 | 6 | module.exports = () => { 7 | if (files.fileExists('.phaser_cli')) { 8 | const spinner = ora(`Open Android Studio, be patient...\n`); 9 | spinner.start(); 10 | command.exec('npm run build-android', (err, stdout, stderr) => { 11 | if (err) { 12 | log.danger(err); 13 | return; 14 | } 15 | }); 16 | spinner.succeed('Android studio is open.'); 17 | log.success('Your must create a apk with Android Studio, good look :D'); 18 | } else { 19 | log.no_project(); 20 | } 21 | }; -------------------------------------------------------------------------------- /creator/newProject/newProject.js: -------------------------------------------------------------------------------- 1 | const files = require('../../lib/files'); 2 | const newProjectQuestion = require('../../questions/newProject'); 3 | const ora = require('ora'); 4 | const command = require('child_process'); 5 | const emoji = require('node-emoji'); 6 | 7 | const log = require('../../lib/log'); 8 | 9 | const regexFolderName = /^(?:[a-zA-Z0-9-~][a-zA-Z0-9-._~]*)?[a-zA-Z0-9-~][a-zA-Z0-9-._~]*$/g; 10 | 11 | const repoURL = 'https://raw.githubusercontent.com/gammafp/phaser3-cli/master/repos.json'; 12 | 13 | const config_routes = require('../../config.json'); 14 | 15 | module.exports = async (folder) => { 16 | if (!files.directoryExists(folder)) { 17 | if (regexFolderName.test(folder)) { 18 | 19 | const newFolder = folder; 20 | const spinner = ora(`Creating scaffolding.\n`); 21 | 22 | const result = await newProjectQuestion.askPhaserConfig(); 23 | 24 | // Creación del scaffolding y configuración de las variables recibidas 25 | spinner.start(); 26 | 27 | let repository = await files.readFileFromURL(repoURL); 28 | if (repository.search('phaser') === -1) { 29 | spinner.fail('Fail download repositories.'); 30 | return false; 31 | } 32 | 33 | repository = JSON.parse(repository); 34 | 35 | files.copyFiles(`${files.getCurrentDirectory()}/scaffolding/files`, `./${newFolder}`, (err) => { 36 | if (err) { 37 | return console.error(err); 38 | } 39 | 40 | // -> Remplazo de nombres 41 | const packageJSON = files.readFile(`./${newFolder}/package.json`) 42 | .replace('{name}', newFolder); 43 | files.writeFile(`./${newFolder}/package.json`, packageJSON); 44 | 45 | 46 | 47 | let physics = ''; 48 | if (result.physics === 'matter') { 49 | physics = `\n physics: {\n default: 'matter',\n matter: {\n gravity: {\n y: 500\n }\n }\n },`; 50 | } else if (result.physics === 'arcade') { 51 | physics = `\n physics: {\n default: 'arcade',\n arcade: {\n gravity: {\n y: 500\n }\n }\n },`; 52 | } 53 | 54 | // Change config title name 55 | const configFile = files.readFile(`${newFolder}/${config_routes.route_base_project}/src/config.ts`) 56 | .replace('{title}', result.title) 57 | .replace('{type}', result.type) 58 | .replace('{width}', result.width) 59 | .replace('{height}', result.height) 60 | .replace('{pixelart}', result.pixelArt) 61 | .replace('{physics}', physics); 62 | 63 | files.writeFile(`${newFolder}/${config_routes.route_base_project}/src/config.ts`, configFile); 64 | 65 | const indexHTMLFile = files.readFile(`${newFolder}/${config_routes.route_base_project}/index.html`) 66 | .replace('{title}', result.title) 67 | files.writeFile(`${newFolder}/${config_routes.route_base_project}/index.html`, indexHTMLFile); 68 | 69 | spinner.succeed(`Scaffolding created.`); 70 | 71 | // -> Instalar dependencias 72 | spinner.text = 'Donwload Phaser :)'; 73 | spinner.start(); 74 | // Phaser definitions 75 | files.downloadFiles(`./${newFolder}/def/phaser.d.ts`, repository.phaserdef); 76 | // Download Phaser 77 | files.downloadFiles(`./${newFolder}/vendor/phaser/phaser.min.js`, repository.phaser); 78 | spinner.succeed(emoji.emojify(':heart:') + ' Phaser download has finished ' + emoji.emojify(':heart:')); 79 | 80 | spinner.text = 'Installing dependencies please be patient...'; 81 | spinner.start(); 82 | 83 | command.exec(`cd ${newFolder} && npm i`, (err, stdout, stderr) => { 84 | if (err) { 85 | log.danger(err); 86 | return; 87 | } 88 | spinner.succeed('The dependencies are installed.'); 89 | log.success('Enjoy your game development :)'); 90 | }); 91 | 92 | }); 93 | 94 | } else { 95 | log.danger(`The folder name "${folder}" it is incorrect.`); 96 | } 97 | } else { 98 | log.danger('This folder already exists!'); 99 | } 100 | } -------------------------------------------------------------------------------- /creator/serve/serve.js: -------------------------------------------------------------------------------- 1 | const files = require('../../lib/files'); 2 | const log = require('../../lib/log'); 3 | const command = require('child_process'); 4 | 5 | 6 | module.exports = () => { 7 | if (files.fileExists('.phaser_cli')) { 8 | const exec = command.spawn('npm', [ 9 | 'run', 10 | 'dev' 11 | ], {shell: true}); 12 | 13 | exec.stdout.on('data', function(data) { 14 | console.log(data.toString()); 15 | }); 16 | exec.stderr.on('data', function(data) { 17 | console.log(data.toString()); 18 | }); 19 | } else { 20 | log.no_project(); 21 | } 22 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const program = require('commander'); 4 | 5 | const pjson = require('./package.json'); 6 | const log = require('./lib/log'); 7 | 8 | // Lógica de carpetas para distintos trabajos 9 | const newProject = require('./creator/newProject/newProject'); 10 | const execServe = require('./creator/serve/serve'); 11 | const execBuild = require('./creator/build/build'); 12 | const execBuildAndroid = require('./creator/build/build_android'); 13 | const addScene = require('./creator/add/scene'); 14 | 15 | const addAndroid = require('./creator/add/android'); 16 | const androidCommands = require('./creator/androidCommands/androidCommands'); 17 | 18 | // Agregar server gamma/core 19 | const gammaCoreServer = require('./server_gamma_core/server'); 20 | 21 | program 22 | .version(pjson.version) 23 | .command('new [folder_name]') 24 | .action((folder_name) => { 25 | log.welcome(); 26 | if (folder_name === undefined) { 27 | log.danger('you need add a folder name'); 28 | } else { 29 | newProject(folder_name); 30 | } 31 | }); 32 | 33 | program 34 | .command('serve') 35 | .action(() => { 36 | log.success('\nStarting server...'); 37 | execServe(); 38 | gammaCoreServer(); 39 | }); 40 | 41 | program 42 | .command('build [args...]') 43 | .action((type) => { 44 | if (type.length === 0) { 45 | // Build to web 46 | log.success('\nBuilding your game...'); 47 | execBuild(); 48 | } 49 | 50 | if (type[0] === 'android') { 51 | execBuildAndroid(); 52 | } 53 | }); 54 | 55 | program 56 | .command('add [args...]') 57 | .action((type, sceneName) => { 58 | if (type === 'scene') { 59 | if (sceneName.length > 0) { 60 | addScene(sceneName); 61 | } else { 62 | log.danger('Error: The name scene is missing:\n\tphaser add scene '); 63 | } 64 | } 65 | if (type === 'android') { 66 | addAndroid(); 67 | } 68 | }); 69 | 70 | // Android command 71 | program 72 | .command('android ') 73 | .action((type) => { 74 | if (type === 'copy') { 75 | androidCommands.copy(); 76 | } else { 77 | log.danger('Error: The android command does not exists'); 78 | } 79 | }); 80 | 81 | program 82 | .command('test') 83 | .action(() => { 84 | gammaCoreServer(); 85 | }); 86 | program.parse(process.argv) -------------------------------------------------------------------------------- /lib/files.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | const https = require('https'); 4 | 5 | 6 | /** Nos ayudará a comprobar los archivos que ya existen y crear carpetas */ 7 | module.exports = { 8 | 9 | // Obtener rutas 10 | getCurrentDirectory: () => path.dirname(require.main.filename), 11 | getCurrentDirectoryBase: () => { 12 | return path.basename(process.cwd()); 13 | }, 14 | 15 | // Lectura, descarga y escritura de ficheros 16 | readFile: (url) => fs.readFileSync(path.normalize(url), { 17 | encoding: 'utf-8' 18 | }), 19 | downloadFiles: (urlFile, urlDownload) => { 20 | const phaserDef = fs.createWriteStream(path.normalize(urlFile)); 21 | 22 | https.get(urlDownload, function(response) { 23 | response.pipe(phaserDef); 24 | }); 25 | }, 26 | readFileFromURL: (url) => { 27 | return new Promise((resolve, reject) => { 28 | https.get(url, function(resp) { 29 | resp.on('data', (chunk) => { 30 | resolve(chunk.toString()); 31 | }); 32 | }); 33 | }); 34 | }, 35 | writeFile: (url, data) => fs.outputFileSync(path.normalize(url), data, {encoding:'utf8', flag:'w'}), 36 | writeFileAsync: (url, data) => fs.outputFile(path.normalize(url), data, {encoding:'utf8', flag:'w'}), 37 | // Copia y creación de carpetas 38 | copyFiles: (a, b, callback) => { 39 | try { 40 | fs.copySync(a, b) 41 | callback(false); 42 | } catch(error) { 43 | callback(error); 44 | } 45 | }, 46 | 47 | // Comprobación de existencia de archivos y directorios 48 | directoryExists: (filePath) => { 49 | try { 50 | return fs.statSync(path.normalize(filePath)).isDirectory(); 51 | } catch (err) { 52 | return false; 53 | } 54 | }, 55 | fileExists: (file) => { 56 | try { 57 | return fs.statSync(path.normalize(file)).isFile(); 58 | } catch (err) { 59 | return false; 60 | } 61 | } 62 | }; -------------------------------------------------------------------------------- /lib/helpers.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | module.exports = { 3 | getSceneRoute: (sceneName) => { 4 | const route = path.dirname(sceneName).trim(); 5 | return (sceneName.search(/\\|\//) !== -1) ? `${route}` : route.replace('.', 'scenes'); 6 | }, 7 | sceneNameToUpperCase: (sceneName) => { 8 | let name = path.basename(sceneName); 9 | return (name.trim(), name.charAt(0).toUpperCase() + name.slice(1)).replace(/_[\w]/g, (find) => { 10 | return find[find.length - 1].toUpperCase(); 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /lib/log.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const figlet = require('figlet'); 3 | 4 | module.exports = { 5 | welcome: () => { 6 | console.log( 7 | chalk.yellow( 8 | figlet.textSync('Phaser3-cli', { 9 | font: 'Small', 10 | horizontalLayout: 'full' 11 | }) 12 | ) 13 | ); 14 | console.log(chalk.green('\tBy Gammafp\n\n\n\n')); 15 | }, 16 | no_project: () => { 17 | const warning = chalk.hex('#EE5A24'); 18 | console.log(warning('This is not a valid project.')); 19 | }, 20 | 21 | success: (msj) => { 22 | console.log(chalk.cyan(msj)); 23 | }, 24 | danger: (msj) => { 25 | const warning = chalk.hex('#EE5A24'); 26 | console.log(warning(msj)); 27 | } 28 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser3-cli", 3 | "version": "0.0.6", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-escapes": { 8 | "version": "3.2.0", 9 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 10 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" 11 | }, 12 | "ansi-regex": { 13 | "version": "3.0.0", 14 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 15 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 16 | }, 17 | "ansi-styles": { 18 | "version": "3.2.1", 19 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 20 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 21 | "requires": { 22 | "color-convert": "^1.9.0" 23 | } 24 | }, 25 | "chalk": { 26 | "version": "2.4.2", 27 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 28 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 29 | "requires": { 30 | "ansi-styles": "^3.2.1", 31 | "escape-string-regexp": "^1.0.5", 32 | "supports-color": "^5.3.0" 33 | } 34 | }, 35 | "chardet": { 36 | "version": "0.7.0", 37 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 38 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 39 | }, 40 | "cli-cursor": { 41 | "version": "2.1.0", 42 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 43 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 44 | "requires": { 45 | "restore-cursor": "^2.0.0" 46 | } 47 | }, 48 | "cli-spinners": { 49 | "version": "2.1.0", 50 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.1.0.tgz", 51 | "integrity": "sha512-8B00fJOEh1HPrx4fo5eW16XmE1PcL1tGpGrxy63CXGP9nHdPBN63X75hA1zhvQuhVztJWLqV58Roj2qlNM7cAA==" 52 | }, 53 | "cli-width": { 54 | "version": "2.2.0", 55 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 56 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" 57 | }, 58 | "clone": { 59 | "version": "1.0.4", 60 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 61 | "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" 62 | }, 63 | "color-convert": { 64 | "version": "1.9.3", 65 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 66 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 67 | "requires": { 68 | "color-name": "1.1.3" 69 | } 70 | }, 71 | "color-name": { 72 | "version": "1.1.3", 73 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 74 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 75 | }, 76 | "commander": { 77 | "version": "2.20.0", 78 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", 79 | "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" 80 | }, 81 | "defaults": { 82 | "version": "1.0.3", 83 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", 84 | "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", 85 | "requires": { 86 | "clone": "^1.0.2" 87 | } 88 | }, 89 | "escape-string-regexp": { 90 | "version": "1.0.5", 91 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 92 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 93 | }, 94 | "external-editor": { 95 | "version": "3.0.3", 96 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", 97 | "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", 98 | "requires": { 99 | "chardet": "^0.7.0", 100 | "iconv-lite": "^0.4.24", 101 | "tmp": "^0.0.33" 102 | } 103 | }, 104 | "figlet": { 105 | "version": "1.2.1", 106 | "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.1.tgz", 107 | "integrity": "sha512-qc8gycfnnfOmfvPl7Fi3JeTbcvdmbZkckyUVGGAM02je7Ookvu+bBfKy1I4FKqTsQHCs3ARJ76ip/k98r+OQuQ==" 108 | }, 109 | "figures": { 110 | "version": "2.0.0", 111 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 112 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 113 | "requires": { 114 | "escape-string-regexp": "^1.0.5" 115 | } 116 | }, 117 | "fs-extra": { 118 | "version": "8.0.1", 119 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.0.1.tgz", 120 | "integrity": "sha512-W+XLrggcDzlle47X/XnS7FXrXu9sDo+Ze9zpndeBxdgv88FHLm1HtmkhEwavruS6koanBjp098rUpHs65EmG7A==", 121 | "requires": { 122 | "graceful-fs": "^4.1.2", 123 | "jsonfile": "^4.0.0", 124 | "universalify": "^0.1.0" 125 | } 126 | }, 127 | "graceful-fs": { 128 | "version": "4.1.15", 129 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 130 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" 131 | }, 132 | "has-flag": { 133 | "version": "3.0.0", 134 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 135 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 136 | }, 137 | "iconv-lite": { 138 | "version": "0.4.24", 139 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 140 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 141 | "requires": { 142 | "safer-buffer": ">= 2.1.2 < 3" 143 | } 144 | }, 145 | "inquirer": { 146 | "version": "6.3.1", 147 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", 148 | "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", 149 | "requires": { 150 | "ansi-escapes": "^3.2.0", 151 | "chalk": "^2.4.2", 152 | "cli-cursor": "^2.1.0", 153 | "cli-width": "^2.0.0", 154 | "external-editor": "^3.0.3", 155 | "figures": "^2.0.0", 156 | "lodash": "^4.17.11", 157 | "mute-stream": "0.0.7", 158 | "run-async": "^2.2.0", 159 | "rxjs": "^6.4.0", 160 | "string-width": "^2.1.0", 161 | "strip-ansi": "^5.1.0", 162 | "through": "^2.3.6" 163 | } 164 | }, 165 | "is-fullwidth-code-point": { 166 | "version": "2.0.0", 167 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 168 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 169 | }, 170 | "is-promise": { 171 | "version": "2.1.0", 172 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 173 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 174 | }, 175 | "jsonfile": { 176 | "version": "4.0.0", 177 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 178 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 179 | "requires": { 180 | "graceful-fs": "^4.1.6" 181 | } 182 | }, 183 | "lodash": { 184 | "version": "4.17.11", 185 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 186 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 187 | }, 188 | "lodash.toarray": { 189 | "version": "4.4.0", 190 | "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", 191 | "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" 192 | }, 193 | "log-symbols": { 194 | "version": "2.2.0", 195 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", 196 | "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", 197 | "requires": { 198 | "chalk": "^2.0.1" 199 | } 200 | }, 201 | "mimic-fn": { 202 | "version": "1.2.0", 203 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 204 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" 205 | }, 206 | "mute-stream": { 207 | "version": "0.0.7", 208 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 209 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" 210 | }, 211 | "node-emoji": { 212 | "version": "1.10.0", 213 | "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", 214 | "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", 215 | "requires": { 216 | "lodash.toarray": "^4.4.0" 217 | } 218 | }, 219 | "onetime": { 220 | "version": "2.0.1", 221 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 222 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 223 | "requires": { 224 | "mimic-fn": "^1.0.0" 225 | } 226 | }, 227 | "ora": { 228 | "version": "3.4.0", 229 | "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", 230 | "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", 231 | "requires": { 232 | "chalk": "^2.4.2", 233 | "cli-cursor": "^2.1.0", 234 | "cli-spinners": "^2.0.0", 235 | "log-symbols": "^2.2.0", 236 | "strip-ansi": "^5.2.0", 237 | "wcwidth": "^1.0.1" 238 | } 239 | }, 240 | "os-tmpdir": { 241 | "version": "1.0.2", 242 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 243 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 244 | }, 245 | "restore-cursor": { 246 | "version": "2.0.0", 247 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 248 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 249 | "requires": { 250 | "onetime": "^2.0.0", 251 | "signal-exit": "^3.0.2" 252 | } 253 | }, 254 | "run-async": { 255 | "version": "2.3.0", 256 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 257 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 258 | "requires": { 259 | "is-promise": "^2.1.0" 260 | } 261 | }, 262 | "rxjs": { 263 | "version": "6.5.2", 264 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", 265 | "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", 266 | "requires": { 267 | "tslib": "^1.9.0" 268 | } 269 | }, 270 | "safer-buffer": { 271 | "version": "2.1.2", 272 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 273 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 274 | }, 275 | "signal-exit": { 276 | "version": "3.0.2", 277 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 278 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 279 | }, 280 | "string-width": { 281 | "version": "2.1.1", 282 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 283 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 284 | "requires": { 285 | "is-fullwidth-code-point": "^2.0.0", 286 | "strip-ansi": "^4.0.0" 287 | }, 288 | "dependencies": { 289 | "strip-ansi": { 290 | "version": "4.0.0", 291 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 292 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 293 | "requires": { 294 | "ansi-regex": "^3.0.0" 295 | } 296 | } 297 | } 298 | }, 299 | "strip-ansi": { 300 | "version": "5.2.0", 301 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 302 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 303 | "requires": { 304 | "ansi-regex": "^4.1.0" 305 | }, 306 | "dependencies": { 307 | "ansi-regex": { 308 | "version": "4.1.0", 309 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 310 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 311 | } 312 | } 313 | }, 314 | "supports-color": { 315 | "version": "5.5.0", 316 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 317 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 318 | "requires": { 319 | "has-flag": "^3.0.0" 320 | } 321 | }, 322 | "through": { 323 | "version": "2.3.8", 324 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 325 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 326 | }, 327 | "tmp": { 328 | "version": "0.0.33", 329 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 330 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 331 | "requires": { 332 | "os-tmpdir": "~1.0.2" 333 | } 334 | }, 335 | "tslib": { 336 | "version": "1.9.3", 337 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", 338 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" 339 | }, 340 | "universalify": { 341 | "version": "0.1.2", 342 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 343 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" 344 | }, 345 | "wcwidth": { 346 | "version": "1.0.1", 347 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 348 | "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", 349 | "requires": { 350 | "defaults": "^1.0.3" 351 | } 352 | } 353 | } 354 | } 355 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser3-cli", 3 | "version": "0.2.5", 4 | "description": "A CLI for Phaser 3", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/gammafp/phaser3-cli.git" 12 | }, 13 | "keywords": [ 14 | "phaser3", 15 | "cli", 16 | "phaser3-cli", 17 | "games", 18 | "javascript" 19 | ], 20 | "author": "Francisco Pereira Alvarado", 21 | "bin": { 22 | "phaser": "./index.js" 23 | }, 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/gammafp/phaser3-cli/issues" 27 | }, 28 | "homepage": "https://github.com/gammafp/phaser3-cli#readme", 29 | "dependencies": { 30 | "chalk": "^2.4.2", 31 | "commander": "^2.20.0", 32 | "figlet": "^1.2.1", 33 | "fs-extra": "^8.0.1", 34 | "inquirer": "^6.3.1", 35 | "node-emoji": "^1.10.0", 36 | "ora": "^3.4.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /questions/newProject.js: -------------------------------------------------------------------------------- 1 | const inquirer = require('inquirer'); 2 | 3 | const validNumber = (age) => { 4 | var isValid = !isNaN(parseFloat(age)); 5 | return isValid || 'Please enter a number'; 6 | } 7 | 8 | /** Nos ayudará a crear las preguntsa de inquirer */ 9 | module.exports = { 10 | askPhaserConfig: () => { 11 | const questions = [{ 12 | type: 'input', 13 | name: 'title', 14 | default: 'My Game', 15 | message: 'Enter the name of the game' 16 | }, 17 | { 18 | type: 'list', 19 | name: 'type', 20 | message: 'Select type of canvas?', 21 | choices: [ 22 | 'Phaser.AUTO', 23 | 'Phaser.CANVAS', 24 | 'Phaser.WEBGL' 25 | ] 26 | }, 27 | { 28 | type: 'number', 29 | name: 'width', 30 | default: 640, 31 | message: 'width of project', 32 | validate: validNumber 33 | }, 34 | { 35 | type: 'number', 36 | name: 'height', 37 | default: 360, 38 | message: 'heigth of project', 39 | validate: validNumber 40 | }, 41 | { 42 | type: 'list', 43 | name: 'pixelArt', 44 | message: 'Is it a pixel art game?', 45 | choices: [ 46 | 'true', 47 | 'false' 48 | ] 49 | }, { 50 | type: 'list', 51 | name: 'physics', 52 | message: 'What physics system do you use?', 53 | choices: [ 54 | 'arcade', 55 | 'matter', 56 | 'none' 57 | ] 58 | } 59 | ]; 60 | return inquirer.prompt(questions); 61 | } 62 | }; -------------------------------------------------------------------------------- /repos.json: -------------------------------------------------------------------------------- 1 | { 2 | "phaser": "https://raw.githubusercontent.com/photonstorm/phaser/master/dist/phaser.min.js", 3 | "phaserdef": "https://raw.githubusercontent.com/photonstorm/phaser/master/types/phaser.d.ts" 4 | } 5 | -------------------------------------------------------------------------------- /scaffolding/android/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "com.gamma.game", 3 | "appName": "{{app_name}}", 4 | "bundledWebRuntime": false, 5 | "npmClient": "npm", 6 | "webDir": "dist" 7 | } 8 | -------------------------------------------------------------------------------- /scaffolding/files/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = crlf 7 | charset = utf-8 8 | trim_trailing_whitespace = false 9 | insert_final_newline = false -------------------------------------------------------------------------------- /scaffolding/files/.phaser_cli: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gammafp/phaser3-cli/ab76be5c2e501bd27e0144048b45b38303b6cc97/scaffolding/files/.phaser_cli -------------------------------------------------------------------------------- /scaffolding/files/def/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare const BUILD_TARGET: string; -------------------------------------------------------------------------------- /scaffolding/files/game/assets/phaser3_cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gammafp/phaser3-cli/ab76be5c2e501bd27e0144048b45b38303b6cc97/scaffolding/files/game/assets/phaser3_cli.png -------------------------------------------------------------------------------- /scaffolding/files/game/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} -------------------------------------------------------------------------------- /scaffolding/files/game/gamma/core.ts: -------------------------------------------------------------------------------- 1 | import { info_drag } from './templates'; 2 | 3 | /** 4 | * A callback method that is invoked immediately after the 5 | * DOM is it change. 6 | */ 7 | export function pgOnInit( 8 | target: any, 9 | propertyName: string, 10 | propertyDesciptor: PropertyDescriptor 11 | ) { 12 | window.addEventListener('load', propertyDesciptor.value()); 13 | } 14 | 15 | /** 16 | * A callback method that is invoked immediately after the 17 | * window is resize 18 | */ 19 | export function pgOnResize( 20 | target: any, 21 | propertyName: string, 22 | propertyDesciptor: PropertyDescriptor 23 | ) { 24 | window.addEventListener('resize', () => { 25 | propertyDesciptor.value(); 26 | }); 27 | } 28 | 29 | /** 30 | * Ayuda a obtener la mitad del viewport 31 | */ 32 | export const canvasSize = { 33 | w: (scene) => scene.scale.width, 34 | h: (scene) => scene.scale.height, 35 | mw: (scene) => scene.scale.width / 2, 36 | mh: (scene) => scene.scale.height / 2 37 | }; 38 | 39 | 40 | // Variable para agrupar el dragGameObject UI 41 | let uIDrag = null; 42 | /** 43 | * Herramienta que ayuda a posicionar un elemento en el canvas. 44 | */ 45 | declare interface PathConfig { 46 | path: string; 47 | } 48 | 49 | // pathConfig: {path: scenes/MainScene.ts} 50 | export function dragGameObject(pathConfig: PathConfig) { 51 | 52 | // Objeto a enviar al servidor 53 | const configToSend: any = { 54 | path: pathConfig.path 55 | }; 56 | return (target: any, key: string | symbol) => { 57 | 58 | let val = target[key]; 59 | const setter = (gameObject) => { 60 | 61 | val = gameObject; 62 | val.setInteractive(); 63 | val.nameGammaCore = key; 64 | val.scene.input.setDraggable(val); 65 | 66 | 67 | const fix_UIDrag_pos = (game_object) => { 68 | // Corrección de la sobreposición de uIDrag de la derecha 69 | if ( 70 | (game_object.x + (game_object.width * game_object.originX)) > uIDrag.x - 50 71 | && 72 | (game_object.y - (game_object.height * game_object.originY)) < uIDrag.y + 70 / 2 73 | ) { 74 | uIDrag.x = 50; 75 | uIDrag.y = 70 / 2; 76 | } 77 | if ( 78 | (game_object.x - (game_object.width * game_object.originX)) < uIDrag.x + 50 79 | && 80 | (game_object.y - (game_object.height * game_object.originY)) < uIDrag.y + 70 / 2 81 | ) { 82 | uIDrag.x = val.scene.scale.width - 50; 83 | uIDrag.y = 70 / 2; 84 | } 85 | }; 86 | 87 | val.scene.input.on('dragstart', (pointer, game_object) => { 88 | console.log(val); 89 | game_object.setTint(0xff0000); 90 | // Crea y destruye la información de posición 91 | if (uIDrag !== null) { 92 | uIDrag.destroy(); 93 | uIDrag.removeListener('click'); 94 | } 95 | // nombre variable de referencia para enviar al servidor 96 | configToSend.variableKey = game_object.nameGammaCore; 97 | 98 | uIDrag = val.scene.add.dom(val.scene.scale.width - 50, 70 / 2).createFromHTML(info_drag); 99 | uIDrag.getChildByID('x_pos_drag_info').innerHTML = game_object.x; 100 | uIDrag.getChildByID('y_pos_drag_info').innerHTML = game_object.y; 101 | fix_UIDrag_pos(game_object); 102 | 103 | uIDrag.getChildByID('drag_info_button_send').addEventListener('click', () => { 104 | // TODO: Change alert to config 105 | if (confirm('Are you sure?')) { 106 | fetch('http://localhost:43010/update', { 107 | method: 'POST', 108 | body: JSON.stringify(configToSend), 109 | mode: 'no-cors', 110 | headers: { 111 | Accept: 'application/json', 112 | 'Content-Type': 'application/json' 113 | } 114 | }).then(res => { 115 | return res.text(); 116 | }) 117 | .then(response => { 118 | console.log('Success:', response) 119 | }) 120 | .catch(error => { 121 | console.error('Error:', error) 122 | }); 123 | 124 | console.log('Esto es lo que se va a enviar ', configToSend); 125 | } 126 | }); 127 | }); 128 | 129 | val.scene.input.on('drag', (pointer, game_object, dragX, dragY) => { 130 | game_object.x = Math.round(dragX); 131 | game_object.y = Math.round(dragY); 132 | uIDrag.getChildByID('x_pos_drag_info').innerHTML = game_object.x; 133 | uIDrag.getChildByID('y_pos_drag_info').innerHTML = game_object.y; 134 | fix_UIDrag_pos(game_object); 135 | }); 136 | 137 | val.scene.input.on('dragend', (pointer, game_object) => { 138 | game_object.clearTint(); 139 | configToSend.x = game_object.x; 140 | configToSend.y = game_object.y; 141 | 142 | 143 | }); 144 | }; 145 | 146 | Object.defineProperty(target, key, { 147 | set: setter, 148 | enumerable: true, 149 | configurable: true 150 | }); 151 | }; 152 | } 153 | -------------------------------------------------------------------------------- /scaffolding/files/game/gamma/templates.ts: -------------------------------------------------------------------------------- 1 | export const info_drag = ` 2 | 76 | 77 |
78 |
79 |
80 | X: 81 | 0 82 |
83 |
84 | Y: 85 | 0 86 |
87 |
88 | 91 |
92 | `; -------------------------------------------------------------------------------- /scaffolding/files/game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {title} 9 | 10 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /scaffolding/files/game/src/Bootloader.ts: -------------------------------------------------------------------------------- 1 | export class Bootloader extends Phaser.Scene { 2 | constructor() { 3 | super({ 4 | key: 'Bootloader' 5 | }); 6 | console.log('Scene Bootloader'); 7 | } 8 | 9 | preload(): void { 10 | this.load.setPath('assets/'); 11 | this.load.image('phaser3_cli'); 12 | 13 | this.load.on('complete', () => { 14 | this.scene.start('MainScene'); 15 | }); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /scaffolding/files/game/src/config.ts: -------------------------------------------------------------------------------- 1 | import { Bootloader } from './Bootloader'; 2 | import { MainScene } from './scenes/MainScene'; 3 | 4 | export const CONFIG: any = { 5 | title: '{title}', 6 | version: '0.0.1', 7 | type: {type}, 8 | backgroundColor: '#22a6b3', 9 | scale: { 10 | parent: 'phaser_container', 11 | width: {width}, 12 | height: {height}, 13 | mode: Phaser.Scale.FIT, 14 | autoCenter: Phaser.Scale.CENTER_BOTH 15 | }, 16 | dom: { 17 | createContainer: true 18 | }, 19 | render: { 20 | pixelArt: {pixelart}, 21 | },{physics} 22 | scene: [ 23 | Bootloader, 24 | MainScene 25 | ] 26 | }; 27 | -------------------------------------------------------------------------------- /scaffolding/files/game/src/constants.ts: -------------------------------------------------------------------------------- 1 | export enum buildTargets { 2 | 'web' = 'web', 3 | 'ios' = 'ios', 4 | 'android' = 'android', 5 | 'electron' = 'electron' 6 | } 7 | -------------------------------------------------------------------------------- /scaffolding/files/game/src/main.ts: -------------------------------------------------------------------------------- 1 | import 'phaser'; 2 | import { CONFIG } from './config'; 3 | declare const BUILD_TARGET: string; 4 | 5 | class Game extends Phaser.Game { 6 | constructor(config: Phaser.Types.Core.GameConfig) { 7 | super(config); 8 | } 9 | } 10 | 11 | const game = new Game(CONFIG); -------------------------------------------------------------------------------- /scaffolding/files/game/src/scenes/MainScene.ts: -------------------------------------------------------------------------------- 1 | import { buildTargets } from '../constants'; 2 | 3 | export class MainScene extends Phaser.Scene { 4 | image: Phaser.GameObjects.Image; 5 | constructor() { 6 | super({ 7 | key: 'MainScene' 8 | }); 9 | } 10 | 11 | init() { 12 | console.log('MainScene'); 13 | } 14 | 15 | create(): void { 16 | this.image = this.add.image(this.scale.width / 2, this.scale.height / 2, 'phaser3_cli'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scaffolding/files/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{name}", 3 | "version": "0.0.1", 4 | "description": "Game created with Phaser3 cli", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack-dev-server --mode development --open", 8 | "dev-android": "webpack-dev-server --mode development --open --env.android", 9 | "build": "webpack --mode production", 10 | "build-install-android": "webpack --mode production --env.android", 11 | "build-android": "webpack --mode production --env.android && npx cap copy android && npx cap open android", 12 | "build-ios": "webpack --mode production --env.ios && npx cap copy ios && npx cap open ios", 13 | "build-electron": "webpack --mode production --env.electron && npx cap copy electron" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC", 18 | "devDependencies": { 19 | "copy-webpack-plugin": "^5.0.3", 20 | "expose-loader": "^0.7.5", 21 | "html-webpack-plugin": "^3.2.0", 22 | "ts-loader": "^6.0.1", 23 | "tslint": "^5.16.0", 24 | "typescript": "^3.6.2", 25 | "webpack": "^4.31.0", 26 | "webpack-cli": "^3.3.2", 27 | "webpack-dev-server": "^3.4.1" 28 | }, 29 | "dependencies": {} 30 | } -------------------------------------------------------------------------------- /scaffolding/files/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "importHelpers": true, 6 | "target": "ES2016", 7 | "module": "CommonJS", 8 | "sourceMap": false, 9 | "noImplicitAny": false, 10 | "strict": false, 11 | "typeRoots": [ 12 | "def" 13 | ], 14 | } 15 | } -------------------------------------------------------------------------------- /scaffolding/files/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "variable-name": [ 5 | true, 6 | "check-format", 7 | "ban-keywords", 8 | "allow-snake-case", 9 | "allow-trailing-underscore" 10 | ], 11 | "array-type": false, 12 | "arrow-parens": false, 13 | "max-line-length": { 14 | "options": [140] 15 | }, 16 | "deprecation": { 17 | "severity": "warn" 18 | }, 19 | "interface-name": false, 20 | "max-classes-per-file": false, 21 | "member-access": false, 22 | "member-ordering": [ 23 | true, 24 | { 25 | "order": [ 26 | "static-field", 27 | "instance-field", 28 | "static-method", 29 | "instance-method" 30 | ] 31 | } 32 | ], 33 | "no-consecutive-blank-lines": false, 34 | "no-empty": false, 35 | "no-inferrable-types": [ 36 | true, 37 | "ignore-params" 38 | ], 39 | "no-non-null-assertion": true, 40 | "no-redundant-jsdoc": true, 41 | "no-switch-case-fall-through": true, 42 | "no-use-before-declare": true, 43 | "no-var-requires": false, 44 | "object-literal-key-quotes": [ 45 | true, 46 | "as-needed" 47 | ], 48 | "object-literal-sort-keys": false, 49 | "ordered-imports": false, 50 | "quotemark": [ 51 | true, 52 | "single" 53 | ], 54 | "trailing-comma": false, 55 | "new-parens": true, 56 | "no-arg": true, 57 | "no-bitwise": true, 58 | "no-conditional-assignment": true, 59 | "no-console": false 60 | }, 61 | "exclude": [], 62 | "linterOptions": { 63 | "exclude": [ 64 | "node_modules" 65 | ] 66 | }, 67 | "jsRules": { 68 | "max-line-length": { 69 | "options": [1] 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /scaffolding/files/vendor/phaser/phaser.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gammafp/phaser3-cli/ab76be5c2e501bd27e0144048b45b38303b6cc97/scaffolding/files/vendor/phaser/phaser.min.js -------------------------------------------------------------------------------- /scaffolding/files/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin') 3 | const CopyWebpackPlugin = require('copy-webpack-plugin') 4 | const webpack = require('webpack'); 5 | 6 | const pathToPhaser = path.join(__dirname, '/vendor/phaser/'); 7 | const phaser = path.join(pathToPhaser, 'phaser.min.js'); 8 | const routeApp = './game'; 9 | 10 | module.exports = (env) => { 11 | let target; 12 | 13 | if (!env) { 14 | target = "web" 15 | } else if (env.android) { 16 | target = "android" 17 | } else if (env.ios) { 18 | target = "ios" 19 | } else if (env.electron) { 20 | target = "electron" 21 | } 22 | 23 | return { 24 | entry: { 25 | index: `${routeApp}/src/main.ts` 26 | }, 27 | output: { 28 | path: path.resolve(__dirname, 'dist'), 29 | filename: 'bundle.js', 30 | }, 31 | module: { 32 | rules: [{ 33 | test: /\.ts$/, 34 | loader: 'ts-loader', 35 | exclude: '/node_modules/' 36 | }, 37 | { 38 | test: /phaser\.js$/, 39 | loader: 'expose-loader?Phaser' 40 | } 41 | ] 42 | }, 43 | devServer: { 44 | contentBase: path.resolve(__dirname, `./${routeApp}`), 45 | port: 4300 46 | }, 47 | resolve: { 48 | extensions: ['.ts', '.js'], 49 | alias: { 50 | phaser: phaser 51 | } 52 | }, 53 | plugins: [ 54 | new HtmlWebpackPlugin({ 55 | template: `${routeApp}/index.html` 56 | }), 57 | new CopyWebpackPlugin([{ 58 | from: `${routeApp}/assets`, 59 | to: 'assets' 60 | }, 61 | { 62 | from: `${routeApp}/css`, 63 | to: 'css' 64 | }, 65 | ]), 66 | new webpack.DefinePlugin({ 67 | BUILD_TARGET: JSON.stringify(target) 68 | }) 69 | ] 70 | }; 71 | } -------------------------------------------------------------------------------- /scaffolding/scene.ts: -------------------------------------------------------------------------------- 1 | export class {sceneName} extends Phaser.Scene { 2 | constructor() { 3 | super({ 4 | key: '{sceneName}' 5 | }); 6 | } 7 | 8 | init() { 9 | console.log('{sceneName}'); 10 | } 11 | 12 | preload(): void { 13 | 14 | } 15 | 16 | create(): void { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server_gamma_core/controller.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const path = require('path'); 3 | const url = require('url'); 4 | const files = require('../lib/files'); 5 | const config = require('../config.json'); 6 | 7 | module.exports = http.createServer((req, res) => { 8 | 9 | const reqUrl = url.parse(req.url, true); 10 | if (reqUrl.pathname === '/update' && (req.headers['access-control-request-method'] === 'POST' || req.method === 'POST')) { 11 | 12 | console.log('Trata de acceder al data\n------------ '); 13 | 14 | let body = ''; 15 | req.on('data', function (data) { 16 | body = JSON.parse(data.toString()); 17 | 18 | console.log('Esto es el body del data: ', body); 19 | 20 | if (files.fileExists(path.normalize(`./${config.route_base_project}/src/${body.path}`))) { 21 | let sceneText = files.readFile(`./${config.route_base_project}/src/${path.normalize(body.path)}`); 22 | 23 | const regexReplaceVariable = new RegExp("[a-zA-Z]{0,}." + body.variableKey + " *= *[a-zA-Z]{0,}.add.(sprite|image)\\([a-zA-Z /0-9\\+\\(\\),'_\\-.\\)\\t\\n]{0,}\\)"); 24 | const regexReplacePositionImage = /\([\(\)\+a-zA-Z\n./ *0-9]* {0,}, {0,}[\(\)\+a-zA-Z\n./ *0-9]* {0,}/; 25 | 26 | sceneText = sceneText.replace(regexReplaceVariable, (dato) => { 27 | return dato.replace(regexReplacePositionImage, `(${body.x}, ${body.y}`); 28 | }); 29 | 30 | files.writeFile(path.normalize(`./${config.route_base_project}/src/${body.path}`), sceneText); 31 | console.log('se sobreescribe'); 32 | } else { 33 | console.log('La ruta no existe'); 34 | const datos = JSON.stringify({ 35 | "msg": "the route does not exist" 36 | }); 37 | console.log('Se trata de enviar estos datos: ', datos); 38 | // Ruta no encontrada y mandar notificación 39 | res.writeHead(200, { 40 | 'Content-Type': 'application/json' 41 | }); 42 | res.write(datos); 43 | res.end(datos); 44 | } 45 | }); 46 | 47 | } 48 | }); -------------------------------------------------------------------------------- /server_gamma_core/server.js: -------------------------------------------------------------------------------- 1 | const config = require('../config.json'); 2 | 3 | const hostname = 'localhost'; 4 | const port = config.port_server_gamma_core; 5 | 6 | const server = require('./controller.js'); 7 | 8 | module.exports = () => { 9 | server.listen(port, hostname, () => { 10 | console.log(`Server running at http://${hostname}:${port}/`); 11 | }); 12 | } --------------------------------------------------------------------------------