Cinco programas para la creación de aventuras gráficas.

Sin dejar el tema de la programación, pero acerándonos a un terreno más lúdico hoy hablaremos de programas para la creación de aventuras gráficas. Si como yo eras de los que flipaban con Monkey Island, Day of the Tentacle, Maniac Mansion, Full Throttle… y tienes alguna noción de programación podrás, con este software, dar forma a tu aventura gráfica deseada. Eso sí, necesitarás también a alguien con nociones de diseño gráfico para que te haga los fondos, personajes y demás diseños.

WinterMute Engine: Se trata de un motor muy potente para crear aventuras gráficas. Es un proyecto GNU que os permitirá crear tanto aventuras comerciales como gratuítas, que permite el uso de gráficos 3D, alta definición, gran cantidad de recursos multimedia y un scripting con una sintaxis similar a PHP, por lo que si tienes nociones de este lenguaje o de C++ no te costará mucho trabajar con él.

En su página oficial podrás descargar el programa y encontrar ejemplos, ayuda, hacer donaciones…

Open SLUDGE: Basado en SLUDGE, de HungrySoftware, se trata de una alternativa abierta muy simple e intuitivo. Existe para Windows, Linux y MacOS. Gráficamente no es tan potente como WinterMute, pero tiene una gran cantidad de características que implementar. En su página de sourceforge podéis encontrar todas sus características, juegos creados con este software y el programa en si.

Javascript Graphic Adventure Maker: Bueno, el nombre ya dice bastante. Se trata de un programa que nos permitirá crear aventuras gráficas en javascript. JSGAM se trata de un proyecto libre y proporciona la ventaja de que el juega pueda ser incrustado en una página y jugado desde un navegador. De nuevo en sourceforge podéis encontrar la página del proyecto con el programa para descargar. También podéis jugar a este juego de ejemplo

DAGE: Un editor de aventuras complejo y muy potente, orientado sobre todo a la realización de aventuras con gráficos en 3D. Existen versiones para Windows y Linux y soporta OpenGL, el motor de física open source Newton Game Dynamic y usa scripting Lua. En su portal podrás no sólo descargar el editor, sino también varias aventuras subidas por otros creadores.

ALPACA: Finalmente un editor para diseñadores en Flash. Dudé si incluirlo o no, ya que todos sabéis que no soy muy partidario de esta tecnología, pero la gran cantidad de desarrolladores flash que hay por el mundo supongo que hará de ALPACA una opción interesante para ellos. Su nombre es un acrónimo de ActionScript LDU Point-And-Click Adventure. Al igual que JSGAM nos permite hacer juegos ejecutables en un navegador. En la página del proyecto tenéis juegos de ejemplo, documentación y el propio editor.

Estos cinco ejemplos no son los únicos. Tenéis también Adventure Game Studio, potente, fácile de usar pero privativo. Y si sois fans de los juegos old school podéis encontrar SCIStudio, basado en el mítico motor de Sierra (Larry2, Kings Quest IV); o NAGI, basado en el motor AGI que usaban, por ejemplo, los tres primeros King’s Quest o Larry I, y además permite hacer juegos compatibles con el motor SCUMM o con Sarien (que pemite modo multijudaor on-line).

En fin, con todo este montón malo será que no encontréis una opción que os convenza. Ahora sólo necesitáis tener una buena idea y trabajarla bien…

Detectando navegadores de móviles (PHP y Javascript)

Es habitual en los tiempos que correr desarrollar una página web para navegadores de escritorio y otras optimizadas para el uso en navegadores móviles (smartphone, tablet). Una maquetación puede parecer cojonuda para una pantalla grande, de un sobremesa, pero ser incómoda en una pantalla de cuatro pulgadas.

En ese caso tenéis dos posibilidades: detectar el dispositivo móvil en el servidor (PHP) o en el cliente (javascript). El ejemplo para PHP sería el siguiente:

<?php
$mobile_browser = ’0';

//$_SERVER['HTTP_USER_AGENT'] -> el agente de usuario que está accediendo a la página.
//preg_match -> Realizar una comparación de expresión regular
if(preg_match(‘/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone)/i’,strtolower($_SERVER['HTTP_USER_AGENT']))){
	$mobile_browser++;
}

//$_SERVER['HTTP_ACCEPT'] -> Indica los tipos MIME que el cliente puede recibir.
if((strpos(strtolower($_SERVER['HTTP_ACCEPT']),’application/vnd.wap.xhtml+xml’)>0) or
((isset($_SERVER['HTTP_X_WAP_PROFILE']) or isset($_SERVER['HTTP_PROFILE'])))){

	$mobile_browser++;
}

$mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));
$mobile_agents = array(
‘w3c ‘,’acs-’,'alav’,'alca’,'amoi’,'audi’,'avan’,'benq’,'bird’,'blac’,
‘blaz’,'brew’,'cell’,'cldc’,'cmd-’,'dang’,'doco’,'eric’,'hipt’,'inno’,
‘ipaq’,'java’,'jigs’,'kddi’,'keji’,'leno’,'lg-c’,'lg-d’,'lg-g’,'lge-’,
‘maui’,'maxo’,'midp’,'mits’,'mmef’,'mobi’,'mot-’,'moto’,'mwbp’,'nec-’,
‘newt’,'noki’,'oper’,'palm’,'pana’,'pant’,'phil’,'play’,'port’,'prox’,
‘qwap’,'sage’,'sams’,'sany’,'sch-’,'sec-’,'send’,'seri’,'sgh-’,'shar’,
‘sie-’,'siem’,'smal’,'smar’,'sony’,'sph-’,'symb’,'t-mo’,'teli’,'tim-’,
‘tosh’,'tsm-’,'upg1',’upsi’,'vk-v’,'voda’,'wap-’,'wapa’,'wapi’,'wapp’,
‘wapr’,'webc’,'winw’,'winw’,'xda’,'xda-’);
//buscar agentes en el array de agentes
if(in_array($mobile_ua,$mobile_agents)){
	$mobile_browser++;
}

//$_SERVER['ALL_HTTP'] -> Todas las cabeceras HTTP
//strpos -> Primera aparición de una cadena dentro de otra

if(strpos(strtolower($_SERVER['ALL_HTTP']),’OperaMini’)>0) {
	$mobile_browser++;
}

if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']),’windows’)>0) {
	$mobile_browser=0;
}

if($mobile_browser>0){
//Aquí redireccionamos hacia la aplicación móvil
}else{
//Aquí nos vamos a la versión para escritorio
}
?>

Se trata de una vieja función que econtré hace tiempo y detecta todo tipo de navegadores. La utilicé en mi proyecto de fin de curso y funcionaba. Utiliza un array con referencias a muchos navegadores de dispositivos móviles. La función de javascript por su parte es más sencillita y detectará el SO:

 var ua = navigator.userAgent.toLowerCase();
 var isAndroid = ua.indexOf("android") > -1; // && ua.indexOf("mobile");
 var isiPhone = ua.indexOf("iphone") > -1;
 var isiPod = ua.indexOf("ipod") > -1;
 var isiPad = ua.indexOf("ipad") > -1;
 if(!isiPad) isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);
 var isWPx = ua.indexOf("windows phone") > -1;

En este caso detecta si se trata de Android, un dispositivo Apple o WindowsPhone.

En último caso, en el siguiente enlace tenéis ejemplos de código actualizados para varios lenguajes. Os puede servir de mucha ayuda.

Ordenando un array multidimensional por un campo en PHP

Aunque había pensado publicar «como hacer una encuesta en la que no pueda votar ni dios para así poder inventarte el resultado tranquilo» no lo haré porque se me han adelantado los del diario ABC. En lugar de eso he pensado que a alguien podría interesarle una función que ordene un array multidimensional por un campo en concreto.

La función en si recibirá tres parámetros: el array, el nombre del campo y un valor booleano que indique si se querrá en orden inverso o no. Podéis ver este ejemplo de código:

function orderMultiDimensionalArray ($array, $campo, $invertir) {
    $posicion = array();
    $newRow = array();
    foreach ($array as $key => $row) {
            $posicion[$key]  = $row[$campo];
            $newRow[$key] = $row;
    }
    if ($invertir) {
        arsort($posicion);
    }
    else {
        asort($posicion);
    }
    $arrayRetorno = array();
    foreach ($posicion as $key => $pos) {
        $arrayRetorno[] = $newRow[$key];
    }
    return $arrayRetorno;
}

La función asort ordena un array por los valores que contiene en orden de menor a mayor (si hay valores numéricos los pondrá antes que los alfabéticos). El caso de arsort es el mismo sólo que inverso, ordena de mayor a menor.

Ya véis que es sencillo y no tiene mucha ciencia. Existe también la función ksort (con su versión «reverse», la función krsort) que también ordena, pero en lugar de ordenenar por el valor lo hace por el índice.

Consultas parametrizadas con PHP y MySQL

ESTA ENTRADA ESTÁ ANTICUADA. EL USO DE LA LIBRERÍA mysql YA NO SE RECOMIENDA EN PHP POR OBSOLETO. EN ESTE ENLACE TIENES UNA OPCIÓN MEJOR, CON MySQLi. PARA VER COMO HACERLO CON PDO PRUEBA CON ESTE.

Sigo con mi desarrollo freelance en PHP (para matar estos tiempos de desempleo), y hoy me he visto en la situación de tener que usar consultas parametrizadas. ¿Por qué usar consultas parametrizadas? Básicamente por seguridad, dado que las consultas parametrizadas son la mejor opción, a día de hoy, para evitar la inyección SQL (siempre y cuando estén bien implementadas). Lo habitual en las consultas MySQL en PHP es chuzarle tal cual los parámetros, concatenando cadenas de texto, lo que es muy inseguro, como en este ejemplo:

$sql = "SELECT * FROM tabla WHERE condicion1 = ".parametro1." and condicion2 = ".parametro2."";

En Java tenemos la función PreparedStatement como una gran ayuda, pero en PHP en principio no (aunque con PDO creo que hay algo similar, pero no he trabajado con dicho framework), así que lo que haremos será crear nuestro propio método para crear consultas parametrizadas y otro para tratar los parámetros.

Pero lo primero es crear la consulta sql tal que así:

$sql = "SELECT * FROM tabla WHERE condicion1 = ? and condicion2= ?";

Este es el formato de consulta parametrizada típico de Java, utilizando interrogaciones en lugar de los valores.

Bien, una vez tenemos así la idea es generar dos funciones. La primera comprobará el tipo de parámetro, si es cadena, array, número o nulo. Si es de cadena lo devolverá entre comillas y con los caracteres especiales ya escapados. Si es un array lo devolverá como una cadena de valores separados por comas, si es un nulo devolverá la cadena NULL y si no es ninguno de esos tres dará por hecho que se trata de un número y lo devolverá tal cual. El código sería el siguiente:

function prepareParam($parametro)
{
if(is_string($parametro))
{
// Si el parámetro es una cadena retorna cadena
return "'".mysql_scape_string($parametro)."'";
}
else if(is_array($parametro))
{
// Si es un array devolvemos una lista de los parámetros
// separados por comas.
$devolver = '';
foreach($parametro as $par)
{
// Cuando retorno es vacio ('') quiere decir que no
// tenemos que añadir la coma.
if($devolver == '')
{
$devolver .= prepararParametro($par);
}
else
{
$devolver .= ','.prepararParametro($par);
}
}
return $devolver;
}
else if($parametro == NULL)
{
// Si es nulo devolvemos la cadena 'NULL'
return 'NULL';
}
else
{
// Devolvemos el parametro.
return $parametro;
}

En fin, me disculpo por enésima vez por el sangrado. En fin, Pilarín, continuamos. Ya tenemos nuestro tratamiento de parámetros, ahora nos queda hacer la función que inserte los parámetros dentro de la consulta, y esta será la siguiente. Una función que recibe la cadena con la consulta y una lista de parámetros, parte la consulta por las interrogaciones, procesa los parámetros y se los chuza dentro:

function preparedStatement($cons_sql, $param = array())
{
// Partimos la consulta por los símbolos de interrogación
$partes = explode("?", $cons_sql);

$devolver = '';
$num_parametros = count($param);

// Recorremos los parametros
for($i = 0; $i < $num_parametros; $i++)
{
// Juntamos cada parte con el parametro correspondiente preparado
//con la función antes creada.
$devolver .= $partes[$i].prepareParam($param[$i]);
}

$num_partes = count($partes);
// Si hay más partes que parametros quiere decir que hay una parte final que hay que concatenar
if($num_partes > $num_parametros)
{
$devolver.= $partes[$num_partes -1];
}

// Devolvemos la consulta preparada
return $devolver;
}

Con esto ya tenemos nuestro PreparedStatement, casero y mejorable (podríamos, por seguridad, hacer que comprobara si el número de parámetros pasado coincide con el número requerido en la consulta, por ejemplo).

Existe otra forma de parametrizar utilizando una función nativa de PHP, sin tener que recurrir a bibliotecas externas, que era la que nos enseñaban en el San Clemente cuando hice allí el ciclo (idea de Rafa Veiga, que era el profesor que daba Proyecto Integrado): La idea es utilizar la función sprintf, que funciona como un printf (si has programado en C seguro que conoces dicha función) pero no imprime en pantalla, simplemente almacena en la variable la cadena construída de forma parametrizada. Dicho así suena un poco rollo, pero con este ejemplo lo entenderás:

$sql = sprintf("SELECT * FROM pi_usuarios WHERE nick = '%s' and password = '%s'", $_POST['nick'],$_POST['passwd']);

Bueno, esto era un fragmento de código de mi proyecto de curso de PHP. Básicamente la consulta recupera todos los registros de la tabla pi_usuarios cuyos valores nick y password coincidan con los que se han pasado por un método post (si hubiera más de uno, devolvería un error, si hubiera menos también, pero eso es tema para otro día que hablemos de tratamiento de errores en php). En cualquier caso os explico: la función sprintf (al igual que printf) sustituirá los %s por valores de cadena de texto que vendrán especificados tras la coma (en este caso las variables $_POST[‘nick] y $_POST[‘passwd’]). Dichos %s van entre comillas porque van a ser tratados en la consulta sql como cadenas, la idea es que paséis entre comillas todo lo que en la consulta, de forma nativa, iría entre comillas, y sin ellas lo que no las necesite (valores numéricos, mismamente). Lo que no se es si este sistema ayuda a evitar la inyección sql de forma efectiva o no, pero al menos se ve más claro que construyendo la consulta a base de concatenar cadenas.

En fin, espero que os haya sido útil.