No es fácil diseñar juegos con software de gestión, como es el caso de PHPRunner.
El desarrollo de juegos requieren un uso muy especial del interface de usuario, pero yo entiendo que puede ser un buen ejemplo para aquellos que se están formando en la herramienta de desarrollo (PHPRunner), pues con muy poco código se puede apreciar características de la herramienta y es una buena alternativa para modificar/ampliar la funcionalidad del ejercicio.
Uno de los juegos que casi siempre programo en los lenguajes en los que me estoy formando es el de «MasterMind«, en la variante de utilización de números en vez de colores, y ese es un de los juegos que he desarrollado.
Otro, que puede ser una variante del mismo es el de «Wordle«, adivinanza de una palabra de 5 letras. También lo he desarrollado (palabras en español).
Objetivo
A través del desarrollo de un juego mostrar un conjunto de características de un desarrollo hecho en PHPRunner:
- Mostrar cómo en la definición de las tablas o vistas podemos utilizar querys complejas e incluso actualizar los campos de una tabla que participa en la query compleja.
- Utilización de plugins e instalación de plugins.
- Utilización del API de JavaScript de PHPRunner.
- Utilización de JQuery, para modificar aspectos y funcionalidad en JavaScript.
- Presentación de información con aspectos especiales, creando HTML dinámico.
- Cambio de lógica en el flujo de las páginas del aplicativo.
- Modificaciones de aspectos con CSS.
- Validaciones en ADD inline con mostrado de mensajes de error en «alert» o cualquier otra forma clara para el usuario.
- Cuidar los aspectos para que los ejemplos sean funcionales en la ejecución en el móvil
DEMO: https://fhumanes.com/masterMind/
DEMO: https://fhumanes.com/wordPlay/
Solución técnica
Los plugins utilizados son:
- TouchSpin
- Toggle
Los puedes descargar desde la página de Plugines. Y para instalarlos puedes seguir estas indicaciones.
A modo de ejemplo de definición de querys complejas muestro esta:
select id_masterM_game, title, date1, `key` ,`help`, successes , position from ( SELECT id_masterM_game, title, date1, `key` ,`help`, (SELECT max(id_masterM_line) FROM masterM_line WHERE masterM_game_id = id_masterM_game ) id_l FROM masterM_game ) t1 left join masterM_line on (id_masterM_line = id_l)
Que corresponde a la tabla «masterM_game» , además de los datos de la tabla se obtienen los datos resumen de resultados posicionados y acertados, de la última jugada.
En el caso de la tabla «masterM_line», el query es:
SELECT id_masterM_line, masterM_game_id, game, successes, position, SUBSTRING(game,1,1) n0, SUBSTRING(game,2,1) n1, SUBSTRING(game,3,1) n2, SUBSTRING(game,4,1) n3, SUBSTRING(game,5,1) n4 FROM masterM_line order by id_masterM_line desc
En este caso los datos de entrada y salida se realizará en los campos «n0″…»n4» y para guardar los valores en el evento «before record Add», escribo:
$values['game'] = $values['n0'].$values['n1'].$values['n2'].$values['n3'].$values['n4']; // Value // Eliminación de campos falsos | Removal of false fields unset($values['n0']); unset($values['n1']); unset($values['n2']); unset($values['n3']); unset($values['n4']);
Creo el campo y el contenido del campo real «game» y elimino los campos ficticios de «n0″…»n4».
Espero que hayáis podido comprender que las posibilidades de definir nuevos campos a presentar en los formularios pueden ser ficticios y que podéis agrupar la información a los campos reales de las tablas.
Cómo ejemplo de utilización del Api de JavaScript y de la utilización de JQuery os muestro este ejemplo de WordPlay en la tabla «wordplay_line»:
var ctrl_n0 = Runner.getControl(pageid, 'n0'); var ctrl_n1 = Runner.getControl(pageid, 'n1'); var ctrl_n2 = Runner.getControl(pageid, 'n2'); var ctrl_n3 = Runner.getControl(pageid, 'n3'); var ctrl_n4 = Runner.getControl(pageid, 'n4'); ctrl_n0.setFocus(); $('#'+ctrl_n0.valContId).select(); // Change witn JQUERY $('#'+ctrl_n0.valContId).css({"height": "30px", "font-size": "24px","width": "30px","min-width": "50px"}); // Change to field "n0" $('#'+ctrl_n1.valContId).css({"height": "30px", "font-size": "24px","width": "30px","min-width": "50px"}); // Change to field "n1" $('#'+ctrl_n2.valContId).css({"height": "30px", "font-size": "24px","width": "30px","min-width": "50px"}); // Change to field "n2" $('#'+ctrl_n3.valContId).css({"height": "30px", "font-size": "24px","width": "30px","min-width": "50px"}); // Change to field "n3" $('#'+ctrl_n4.valContId).css({"height": "30px", "font-size": "24px","width": "30px","min-width": "50px"}); // Change to field "n4" ctrl_n0.on('onkeyup', function() { // Control para cuando cambia de valor var local_value = this.getValue(); local_value = local_value.toLowerCase(); // Pasa a minúscula la letra this.setValue(local_value); // Put value in lowerCase ctrl_n1.setFocus(); // Fix focus next field $('#'+ctrl_n1.valContId).select(); // Select content of next field }); ctrl_n1.on('onkeyup', function() { var local_value = this.getValue(); local_value = local_value.toLowerCase(); this.setValue(local_value); ctrl_n2.setFocus(); $('#'+ctrl_n2.valContId).select(); }); ctrl_n2.on('onkeyup', function() { var local_value = this.getValue(); local_value = local_value.toLowerCase(); this.setValue(local_value); ctrl_n3.setFocus(); $('#'+ctrl_n3.valContId).select(); }); ctrl_n3.on('onkeyup', function() { var local_value = this.getValue(); local_value = local_value.toLowerCase(); this.setValue(local_value); ctrl_n4.setFocus(); $('#'+ctrl_n4.valContId).select(); }); ctrl_n4.on('onkeyup', function() { var local_value = this.getValue(); local_value = local_value.toLowerCase(); this.setValue(local_value); ctrl_n0.setFocus(); $('#'+ctrl_n0.valContId).select(); }); if(inlineRow){ var rowId = row.recordId(); $('#saveLink'+rowId).hide(); // Hide button Save $('#revertLink'+rowId).hide(); // Hide Button Cancel console.log('estamos en: '+ rowId); };
Aún estando en el caso más complejo de ADD inline, se puede utilizar el Api de JavaScript y JQuery (no todo se puede hacer con el API y de ahí, utilizar la potencia increíble de JQuery).
En el ejemplo se hace:
- Cambiar por JQuery aspectos/presentación de los campos de entrada de datos.
- Detectar cuando se ha introducido un carácter en el campo y se mueve al siguiente campo seleccionado el contenido del mismo para sustituir el contenido con lo tecleado.
- Desactivar los botones de «Save» y de «Revert», que son estándares en PHPrunner. Esto se hace porque se crea un «custom buttom» para aplicar una nueva lógica en la orden de salvado del contenido.
Este botón de «Save» especial tiene esta lógica aplicada.
* «Before Client»
function Validation(game){ var v_game = game; var v_msg; $.ajax({ async: false, cache: false, type: 'POST', // SEND with POST method url: 'MyCode/validate_game_ajax.php', // Destination file (the PHP that manages the data) data: { keys: v_game } // Data that are sent }).done(function( msg ) { // Function that runs if everything has gone well console.log("Response the Function Validation: "+msg ); v_msg = msg; }).fail(function (jqXHR, textStatus, errorThrown){ // Function that runs if something has gone wrong // We show the message with the error that has been produced console.log("The following error occured: "+ textStatus +" "+ errorThrown); }); return v_msg; } // Put your code here. var rowId = row.recordId(); params["rowId"] = rowId; var game = row.getFieldValue('n0')+row.getFieldValue('n1')+row.getFieldValue('n2')+row.getFieldValue('n3')+row.getFieldValue('n4'); console.log("Word is: "+game); var result = Validation(game); // Validation "game" in WordList console.log("Response is: "+result); if ( result != 'OK' ) { alert(game + ' - Is not valid in WordList'); return false; }
Se utiliza la función «Validation» para consultar en el server si la nueva palabra introducida está en la lista de las «WordList». Si está sigue los siguientes pasos y si no está , muestra en un «alert» que esa palabra no es válida.
* «After Client»
var rowId = result['rowId']; $('a[id^="ok_line_"]').hide(); // Hide button Custom $('#saveLink'+rowId).click(); // Click button Save console.log('hemos hecho SAVE en: '+ rowId);
Si todo está bien, llega hasta esta parte del código que lo que hace es ocultar el botón «custom buttom» y hace «click» en el botón oculto de «Save» que genera PHPrunner.
Para visualizar «las pelotas» de colores en «MasterMind» he utilizado la visualización «custom» y he puesto es código:
include_once __DIR__.'/../MyCode/functions.php'; $dataMaster = $_SESSION['dataMaster']; // Acceso a información del Máster $key = $dataMaster['key']; $help = $dataMaster['help']; $game = $data['game']; // Las listas de números las pasamos a un array $key_arr = str_split($key); $game_arr = str_split($game); $i = 0; if ( $key_arr[$i] == $game_arr[$i] ) { // Position OK $value = "<span class='badge' style='background-color:darkgreen;'><b>$value</b></span>"; } else { $success_arr = success_array($game); if ( $success_arr[$i] == 1 and $help == 1 ) { $value = "<span class='badge' style='background-color:darkorange;'><b>$value</b></span>"; } else { $value = "<span class='badge' style='background-color:gray;'><b>$value</b></span>"; } }
Para que después de dar de alta un nuevo juego se pase a la pantalla de «maestro» y «detalle» de las jugadas, he hace la redirección en el evento «After ADD» con:
$id = $values['id_wordplay_game']; // Close page and new page $html = <<<EOT <html> <head> <meta charset='utf-8' /> </head> <body> <div> <p>New updated request</p> </div> <script> window.open("wordplay_line_list.php?mastertable=wordplay_game&masterkey1=$id","_top"); </script> </body> </html> EOT; echo $html; exit();
Son pequeños pedazos de código que se pueden utilizar en muchos otros sitios y creo que os puede ayudar a vuestros desarrollos.
Os dejo los fuentes de los 2 ejemplos/ejercicios para que lo instaléis en vuestros PC’s y podáis revisar y modificar lo que consideréis oportuno.
Para cualquier duda o explicación, hacedme llegar vuestras dudas a mi email: [email protected]