Convertir un entero a cadena con formato en C++

Hace un tiempo vimos cómo convertir un entero a cadena en C++.

Ahora, imaginad que queremos darle a un entero el siguiente formato: 00000x.png donde x es el número y queremos el nombre de fichero tenga longitud fija para facilitar la ordenación y visualización de los ficheros.

En este ejemplo vemos como el número 123 se convierte en 000123.png:


#include "iomanip"
#include "iostream"
#include "sstream"

int main()
{
int number = 123;

std::ostringstream ss;
ss << std::setfill('0') << std::setw(6) << number; std::string str = ss.str() + ".png"; std::cout << "str: " << str << 'n'; return 0; }

Instalar compiladores C y C++ en Ubuntu Linux

Los lenguajes de programación C y C++ son dos de los lenguajes más populares y utilizados en la actualidad. Son la base de la práctica totalidad de los sistemas operativos y de las más importantes aplicaciones como sistemas gestores de bases de datos, hojas de cálculo, procesadores de texto, etc. Para crear programas ejecutables es necesario compilar el código fuente escrito en C o C++. En Ubuntu es muy sencillo y requiere muy pocos pasos.

Para empezar abre el Centro de Software de Ubuntu. Una vez abierto busca el cuádro de búsqueda situado en el lateral superior derecho y escribe la aplicación a instalar: build-essential. En los resultados de la búsqueda puedes ver la aplicación a instalar. Si quieres obtener una descripción del programa así como una reseña de la valoración de los usuarios pulsa en el botón Más información. Si quieres directamente instalarlo pulsa en Instalar. A continuación tienes que introducir la contraseña de administrador. Esta es la que estableciste cuando instalaste Ubuntu por primera vez. Cuando la hayas escrito pulsa en Autenticar. Si no ha habido ningún problema en unos minutos tendrás instalado el programa solicitado. También puedes entrar en la terminal y ejecutar el comando: sudo apt-get install build-essential.

Para comprobar que funciona abre un editor de texto y escribe lo siguiente:

#include <stdio.h>

int main(int argc, char *argv[])

{

printf("Hola, mundo.\n");

return 0;

}

Guarda el archivo como ejemplo.c y otro como ejemplo.cpp. Para compilarlo en C entra en la terminal, busca el directorio donde está guardado el archivo, ejecuta gcc ejemplo.c y después ./a.out. Para compilarlo en C++ entra en la terminal, busca el directorio donde está guardado el archivo, ejecuta g++ ejemplo.c y después ./a.out.

Arrays asociativos en PHP: crear, editar, añadir, eliminar, extraer y eliminar elementos

Los arrays asociativos en PHP, son una de las herramientas más útiles para manejar información. A diferente de los arrays secuenciales, equivalentes a los vectores de C, el acceso no se hace al elemento iésimo, si no que lo hacemos a una clave, al estilo de las tablas hash.

Veamos un ejemplo con personas a las que se les referencia a través de su NIF. Como podéis imaginar, el acceso a través de ese dato es inmediato.

Creación

La creación es inmediata, nos limitamos a llamar a la función array seguida de los parámetros que serán sus elementos. Escribimos los elementos con esta forma: "clave" => "valor".

 $personas = array('30303030A' => 'Javier Carazo', 
'31313131B' => 'Francisco Gil');

Añadir o editar elementos

Para añadir elementos no necesitaremos otra cosa que hacer una asignación, es decir, ni siquiera deberemos indicar que el elemento es nuevo. Será la misma operación la de añadir y la de editar.

 $personas['12345678Z'] = 'Alberto Hornero';

Eliminar elementos

Usaremos la función unset():.

 unset($personas['12345678Z']);

Acceder a elementos

Accederemos a elementos usando la fórmula siguiente:

echo "La persona con NIF: $nif es: " . $personas[$dni];

Una herramienta muy útil para nuestro día a día sin lugar a dudas.

C es el lenguaje de programación más popular según TIOBE

Personalmente, siempre me ha gustado comentar la evolución de la popularidad de los diferentes lenguajes de programación según el índice TIOBE. Tanto en 2010 como en 2011 hice un pequeño análisis y ahora me gustaría anunciar un cambio importante en esta lista: la subida de C al número uno.

La llegada de C al primer puesto de popularidad era inminente. Cada mes C aventajaba paso a paso a Java en pequeños porcentajes hasta que este mes lo ha superado. C es la base de la programación actual: sistemas operativos, bases de datos e incluso intérpretes de otros lenguajes de programación están escritos en C. Según mi opinión, las razones del descenso de Java son dos. Primero, Java está estancado y sigue siendo muy pesado, y hasta que aparezca la versión 8 esto no va a cambiar. Y segundo, aunque no haya ganado popularidad, C# es más completo y rápido que Java, sólo hay que ver la comparativa. De todas maneras, la plataforma Java creada es tan grande que es complicado que quede relegado a un tercer puesto.

En esta lista hay que destacar la increíble escalada de Objective-C, el lenguaje de programación preferente en el sistema operativo iOS. Es obvio que Apple está consiguiendo un nutrido grupo de programadores para sus productos. Y es normal, cada vez las ventas de sus dispositivos aumentan más y más lo que conlleva a una mayor demanda. También hay que recalcar las subidas de PL/SQL, Visual Basic .NET y NXT-G. Éste último lenguaje es el utilizado para los robots de LEGO Mindstorms NXT, resulta curioso saber cómo ha llegado al vigésimo puesto.

Comprobar de qué tipo es una variable u objeto en C#

Cuando tenemos un objeto de tipo genérico Object en C#, podemos hacer con él las operaciones básicas de cada objeto pero en ocasiones, necesitaremos convertirlo en un objeto menos abstracto para poder hacer operaciones más concretas.

Aunque esta entrada no forma parte del curso de Mono, sí está muy relacionada con esta entrega dedicada a tipos de datos.

Si tenemos una variable u objeto y no sabemos su tipo con seguridad, disponemos de dos métodos que usaremos para ver cuál es realmente el tipo del mismo. Veamos:

Por ejemplo, ¿cómo saber si el objeto "auxiliar" es un entero con signo de 32 bits (el entero más estándar, el que usamos al poner int simplemente)?

if(auxiliar.GetType() == Type.GetType("System.Int32"))
   return true;
else
   return false;

Al igual que con enteros, podemos hacer la comprobación para cualquier tipo:

  • Boolean: valor booleano
  • Byte: ocho bits sin signo
  • Char: carácter UNICODE
  • DateTime: fecha con tiempo
  • Decimal: número decimal
  • Double: pnto flotante de precisión doble
  • Int16: entero con signo de 16 bits
  • Int32: ídem pero de 32 bits
  • Int64: ídem pero de 64 bits
  • SByte:  8 bits con signo
  • Single: punto flotante de precisión simple
  • UInt16: entero sin signo de 16 bits
  • UInt32: ídem pero de 32 bits
  • UInt64: ídem pero de 64 bits
Aspecto interfaz MonoDevelop

Curso ADO.NET con Mono y MySQL – Creación del proyecto

Nos dirigimos a MonoDevelop y creamos una solución nueva, en C#, para consola. Elegís el nombre, el que le he puesto para el ejemplo es: ejemplo_mono_ado. Os aparecerá en pantalla un fichero de nombre: Main.cs junto a un árbol a la izquierda con características de la solución. Una de ellas, las referencias es donde importaremos el ensamblado.

Antes de seguir sería conveniente que copiarais al directorio del proyecto el fichero “mysql.data.dll” que venía dentro del paquete comprimido del conector. Os dirigís a referencias y haciendo clic sobre el mismo título “Referencias”, elegís “Editar referencias...”. De las tres pestañas que aparecen en el diálogo elegís “Ensamblado .NET” y os dirigís al directorio del proyecto o donde tengáis guardado el fichero. Lo elegís y lo añadís.

Aspecto interfaz MonoDevelop

Desde este momento tenéis referenciado el conector dentro de vuestro programa. Ahora el siguiente paso es importarlo al fichero Main.cs. Para ello escribís debajo de “using System; ”, “using MySql.Data.MySqlClient;”. El archivo quedaría así:

using System;
using MySql.Data.MySqlClient; 

namespace ejemplo_mono_ado
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			Console.WriteLine("¡Hola Mundo!");
// Hola Mundo inicial creado por el IDE
		}
	}
}

Con ésto ya tendríamos el espacio de nombres del conector MySQL disponible en nuestro código por lo que a partir de ahora sí que podríamos tratar con las clases del mismo.

Curso ADO.NET con Mono y MySQL – Preparación e instalación

Pasado más de un mes desde la entrada que anunciaba este curso, volvemos a la carga, veamos.

Antes de nada, de forma básica, vamos a revisar qué necesitamos, cómo obtenerlo y en caso necesario, cómo configurarlo. En este momento ,creo conveniente señalar que utilizaremos MonoDevelop,el entorno de desarrollo integrado para Mono más popular, en lugar de utilizar directamente el compilador, mcs; para centrarnos directamente en el desarrollo con ADO y dejar de lado los detalles que no son necesarios.

Logo MonoDevelop

Mono y MonoDevelop

En función de la distribución que utilicéis, las circunstancias particulares cambiaran, pero básicamente os comento dos alternativas que probablemente os sirvan prácticamente a todos. La primera es dirigiros a vuestro gestor de paquetes y buscar los paquetes correspondientes. Como monodevelop, que será más o menos así el nombre del paquete, depende de Mono, si elegís éste se os seleccionaran los demás paquetes necesarios para desarrollar y ejecutar programas con Mono. Es decir, básicamente instalando MonoDevelop a través del paquete homónimo, tendréis todo preparado. Además, es más que probable que tengáis instalado Mono en vuestro equipo por defecto. Por ejemplo, el entorno de escritorio Gnome utiliza esta tecnología ampliamente.

La segunda solución, la más larga y menos recomendable es instalar Mono compilando el código fuente. Necesitaremos tener instalados: cmpilador de C (gcc), Bison y las librerías de desarrollo para glib. Descargaremos el código fuente desde la sección de descargas del Proyecto Mono (pondrá algo así como Mono el número de la versión seguido de “sources”). Utilizaremos el directorio “/opt” para evitar problemas. Más o menos el proceso de instalación sería:

  1. Descomprimimos y desempaquetamos el código fuente, gráficamente o mediante la consola: $ tar zxvf mono-X.XX.tar.gz
  2. Configuramos los archivos para realizar el make: $ ./configure --prefix=/opt/mono
  3. Ejecutamos make para ejecutar el código fuente: $ make
  4. Finalmente instalamos: $ sudo make install

Tras la instalación deberemos configurar debidamente las variables de entorno. Para ello ejecutamos desde la terminal:

$ export PATH=$PATH:/opt/mono/bin
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/mono/lib
$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/mono/lib/pkgconfig
$ export MONO_PATH=/opt/mono/lib

Una vez ya tenemos instalado Mono, pasamos a instalar MonoDevelop de una forma análoga. Accedemos al sitio de MonoDevelop, descargamos el código fuente y:

  1. Desempaquetamos el código fuente y lo descomprimimos: $ tar zxvf monodevelop-X.X.tar.bz2
  2. Configuramos para crear el make: ./configure --prefix=`pkg-config --variable=prefix mono`
  3. Compilamos: $ make
  4. Instalamos: $ make install

Ya tendríamos esta parte lista, pero como dije antes, mucho mejor utilizar el sistema gestor de paquetes para evitar problemas derivados de no poder actualizar tan fácilmente o por ejemplo, las dependencias insatisfechas.

Logo MySQL

MySQL

De igual manera instalaremos el servidor MySQL al que nos conectaremos desde nuestra aplicación con C#. Dado que hay gran cantidad de tutoriales y manuales en la red, voy a ser bastante breve. Básicamente deberéis buscar en vuestro gestor de repositorios el paquete mysql-server y ya tendréis el servidor de base de datos instalado.

Conector

Finalmente, descargaremos el fichero con el conector de MySQL para .NET y Mono. Es un fichero con extensión .dll, que es la extensión con que suelen ser almacenados los ensamblados, como es el caso de .NET/Mono. Si queréis saber más sobre ensamblados, el CLI, o cualquier otro detalle más técnico propio de .NET/Mono, podéis visitar la Wikipedia (preferiblemente en inglés) o la MSDN (antes también Mono-Hispano pero ahora mismo parece que no está accesible). Aunque no sea el objetivo de este artículo definiré brevemente dichos conceptos para que quede algo más claro. Podríamos decir que un ensamblado en Mono es un conjunto de clases implementadas junto con sus metadatos correspondientes para ser utilizados, recogidos en un fichero que puede ser llamado desde un proyecto Mono.

En el caso que nos ocupa utilizaremos una implementación de la arquitectura ADO.NET creada por el propio proyecto MySQL para posibilitar una comunicación lo más nativa e integrada posible entre aplicaciones desarrolladas con .NET/Mono y MySQL. El conector, que así se llama, podéis encontrarlo en la web de MySQL (http://dev.mysql.com/downloads/connector/net/).

Una vez nos encontremos en el sitio, descargamos los ficheros para Windows sin instalador (un fichero .zip con varios ensamblados), lo descomprimimos y ya tendremos todo preparado para comenzar el proyecto.

Antes de continuar un detalle importante. Microsoft Windows no es case sensitive, sensible a mayúsculas/minúsculas, en cuanto a rutas, pero GNU/Linux sí lo es, por lo que deberéis renombrar los ficheros dll que utilicemos conforme se llaman en el programa que será: “MySql.Data” en lugar de “mysql.data” como vienen nombrados por defectos (los demás también de manera análoga).

 

Tributo a Dennis M. Ritchie

La informática es un constante cambio de tecnologías, apenas los sistemas aguantan el peso de los años porque son reemplazados por otros nuevos, muchos más eficientes y potentes. Sin embargo, sólo las más insólitas herramientas aguantan el paso de los años y se convierten en la base de la informática contemporánea y del futuro. Sólo mentes brillantes y personas extraordinarias serían capaz de concebir tecnologías atemporales, y una de ellas es Dennis M. Ritchie.

Dennis MacAlistair Ritchie ha muerto a los 70 años de edad tras una larga enfermedad el 8 de octubre de 2011. Su muerte ha sido tan discreta que ha tenido que ser Rob Pike quien lo anunciase varios días después en su muro de Google+.

Mi compañero y amigo Alberto, ya anunció la noticia, sin embargo, he querido yo también hacer una excepción, anunciarlo y homenajearle, a continuación, personalmente.

Las aportaciones de Dennis M. Ritchie a la informática abarcan multitud de campos. Sin embargo, si hay que destacar dos es la creación del lenguaje de programación C y la cocreación del sistema operativo UNIX.

El primero, C, es el lenguaje base de todos los sistemas operativos actuales. Y no sólo los sistemas operativos, también multitud de aplicaciones como sistemas gestores de bases de datos, gestores de procesos, etc. Si contamos C con clases, extensión creada por Bjarne Stroustrup, la lista se alargaría hasta el infinito. También es el referente de muchos lenguajes de programación, como PHP o Java, que se nutren bastante de la sintaxis y semántica de C.

La segunda aportación es UNIX, el sistema operativo del cual se basan tanto Linux como Mac OS. Si bien el mérito no es totalmente suyo, sí que contribuyó enormemente junto con Ken Thompson en su creación.

Personalmente, Dennis M. Ritchie ha sido el mejor ingeniero informático de la historia. Si bien Dennis es licenciado en física y matemáticas aplicadas, su aporte a la informática ha sido tanta que, para mí, lo considero como un verdadero ingeniero informático. Su aporte como ingeniero ha sido mayor, en mi opinión, que otras personas como Linus Torvalds o Richard Stallman. Si bien éstos últimos concebieron elementos imprescindibles como, por ejemplo, un núcleo y un compilador libres y ayudaron a hacer una informática abierta, Dennis M. Ritchie fue el que diseñó, junto con otros genios, la mejor estructura de un sistema operativo y la creación del mejor lenguaje de progración de la historia.

Sólo me queda decir gracias, gracias a Dennis por haber contribuido tanto a este mundo y, a la vez, ser la persona más discreta y humilde que, viendo esta entrevista y ante tales creaciones, no haya querido hacerse notar.

Gracias por todo, y descansa en paz.

Dennis Ritchie ha muerto

A sus 70 años de edad (1941-2011), Dennis Ritchie, co-fundador del lenguaje C falleció el pasado 9 de Octubre. Parece que no ha tenido demasiada relevancia en la red, mientras que la muerte de archiconocido (y multimillonario) Steve Jobs sí la tuvo, y lo ha eclipsado.

Hemos de tener en cuenta que C es el segundo lenguaje de programación más usado, por detrás de Java y con una cuota de mercado del 17.7% (0.2% menos que el primero y más de un 8% respecto a C++, su seguidor inmediato).

Creo que merece una mención especial y nuestro más profundo respecto a uno de los que, a mi aparecer, ha sido uno de los que más a aportado al mundo de la informática.

Descanse en paz.

Curso ADO.NET con Mono y MySQL – Introducción

El desarrollo de software es una labor en la que intervienen tal cantidad de variables que debemos siempre conocer el mayor número de tecnologías distintas para poder dar siempre la mejor respuesta en cada caso. Muy frecuentemente, es necesario desarrollar un sistema software que sea multiplataforma, a la vez que trate con muchos datos situados en un servidor de datos ajeno. Para estos casos es idóneo utilizar el binomio Mono y MySQL.

Las facilidades que provee una tecnología multiplataforma de alto nivel como Mono, unido a la integración en el mismo de MySQL a través de un conector nativo para ADO.NET, hacen que tengamos al alcance de nuestra mano un binomio de software libre con una potencia envidiable. Siempre tenemos otras opciones también libres, como Java en el caso de tecnología de desarrollo multiplataforma; y otras bases de datos como PostgreSQL para arquitecturas cliente-servidor, o SQLite para máquinas locales, que gozan de muy buena salud.

A lo largo de este curso explicaremos de una manera introductoria el uso de ADO.NET; y lo utilizaremos a través de un interfaz en modo texto. Sin lugar a dudas, las personas que hayan programado anteriormente para la .NET Framework de Microsoft en Windows, conocerán bastantes de los detalles que aquí relatamos y es que como ya muchos sabréis, Mono es una implementación libre de esta plataforma.

Mono, MySQL y ADO.NET

Vamos a ser breves en la presentación de las herramientas con las que vamos a tratar, pero siempre considero útil situar al lector, para que en caso de que no conozca las herramientas sepa situarse en un contexto apropiado.

Mono es un proyecto libre, creado por Ximian en su día y actualmente impulsado por Novell tras la compra de la primera por parte de la segunda, que ofrece una serie de herramientas libres que cumplen las especificaciones de .NET. La figura más destacada del Proyecto Mono es Miguel de Icaza, cofundador de Gnome, hombre fuerte en Novell y una persona un tanto polémica dentro del software libre por sus aportaciones a la vez que sus acercamientos a Microsoft.

MySQL como sabréis, es el sistema gestor de base de datos creado por una empresa del mismo nombre y que posteriormente ha sido adquirido por Sun Microsystems, y recientemente por Oracle. Su popularidad en la red gracias al binomio que forma con PHP la han llevado a convertirse en la base de datos más conocidas del mundo web y una de las alternativas libres más eficaces en este tema.

Finalmente, ADO.NET, es un conjunto de componentes que permiten acceder a datos y a servicios de datos, a través de un arquitectura completa que facilita enormemente ciertas labores al desarrollador. Está integrado dentro de Mono y existe un conector creado ex profeso para ligar a MySQL con Mono/.NET a través de esta arquitectura. Existen otras alternativas similares como Hibernate que nunca está de más conocer.

Curso programación de videojuegos con SDL – Conclusiones. ¿Quién usa SDL?

El resultado no es en absoluto profesional, pero espero que este ejemplo os haya demostrado lo fácil (o al menos no tan difícil) que puede llegar a ser desarrollar un juego. Existen otras muchas maneras de hacerlo, pero SDL es quizás la alternativa más potente en dos dimensiones de las que existen en el universo del software libre. Recordando siempre que podemos usarla conjuntamente con OpenGL para conseguir gráficos tridimensionales.

Otras opciones además de Allegro y ClanLib de las que he hablado, son por ejemplo plataformas destinadas expresamente al desarrollo de videojuegos, como el Proyecto Fénix (el compilador alternativo al famoso DIV propietario). Sin embargo, como ya comenté anteriormente, estas opciones pueden parecer más fáciles pero son menos potentes que SDL.

En cuanto al juego que hemos creado, no sería difícil incluirle un sistema de puntuación, un sistema de vidas, un cálculo de la distancia crítica mejorado, distintos tipos de fases... un universo que se nos abre delante de nosotros de creaciones posibles con cada juego que creamos. El código en sí tampoco está demasiado depurado, pero el propósito era intentar realizar un código con la mayor legibilidad posible.

Otro punto importante a tener en cuenta es que SDL no sirve sólo para desarrollar videojuegos. Hemos usado SDL para hacer un juego, pero las mismas funciones que sirven para mostrar el avión por ejemplo, pueden servir para una aplicación multimedia de otra clase, además por supuesto del resto de funciones multimedia que nos proporciona.

En definitiva, espero que este artículo os haya introducido en un mundo al que antes de comenzar a conocerlo puede parecer más complejo de lo que es. Recordad también que SDL es multiplataforma y el código que compiláis para vuestro juego en Linux os sirve sin cambiar nada para Windows, sólo tenéis que compilarlo para dicho sistema operativo. Con entornos de desarrollo integrados como Dev-Cpp puede resultar realmente fácil compilarlo para el sistema de Microsoft.

¿Quién usa SDL?

Antes de finalizar el curso es buen momento para recordar ejemplos reales de juegos que han usado SDL y han conseguido (y consiguen) resultados realmente buenos. Algunos comerciales, otros muchos libres, engrosan una lista en la que nombres de gran fama saltan a la vista de todos los que hemos jugado alguna vez en nuestro sistema operativo GNU/Linux.

Como representante comercial podemos nombrar a Civilization Call To Power”. En cuanto a ejemplos libres hay muchísimo, aquí os dejo algunos de los títulos más importantes:

Estos son sólo un ejemplo de un total de miles de juegos que han sido (y serán) programados con SDL. Con esto quiero daros sólo una visión de la potencia y de los resultados que se pueden llegar a conseguir haciendo uso sólo de esta librería.

Curso programación de videojuegos con SDL – Creando continuidad

Finalmente, sólo nos queda darle continuidad a nuestro juego. En función de los objetivos que nos habíamos propuesto, es que los aviones vuelvan a aparecer por la parte superior de la pantalla una vez lleguen al final. Esto es bastante simple ya que solamente tenemos que copiar y pegar la inicialización de los aviones enemigos dentro de una condición que compruebe si ha llegado ya al final de la pantalla por la parte inferior.

for(i=0;i<numeroEnemigos;i++)
{
	if(posicionesEnemigos[i].y>=480)
	{
		posicionesEnemigos[i].x=rand()%590+1;
		posicionesEnemigos[i].y=60-rand()%40+1;

	}
	posicion.x=posicionesEnemigos[i].x;
	posicion.y=posicionesEnemigos[i].y;
	SDL_BlitSurface(enemigos[i], NULL, buffer, &posicion);
}

Como podéis apreciar dentro del bucle principal, incluimos la condición y en caso de ser cierta, la inicialización de nuevo de la posición.

Curso programación de videojuegos con SDL – Colisiones

Una vez ya tenemos los enemigos moviéndose, el doble búfer implementado e incluso si queremos la pantalla completa pasemos a establecer algún objetivo en el juego. Para este ejemplo el objetivo será evitar que nuestro avión se choque con los aviones enemigos. Una vez se choquen terminaremos el juego. Aunque esto en un juego real no pasaría dado que es un ejemplo didáctico, es la opción que tomamos. Podríamos también poner un número de vidas por ejemplo, pero esto ya alargaría demasiado el ejemplo (tened en cuenta que tendríamos entonces que escribir con letras y números en nuestra pantalla de SDL, lo que no es tan fácil). Lo que si haremos será que cada vez que desaparezcan los enemigos posicionarlos de nuevo en el comienzo para que vuelvan a aparecer.

Comprobando si existe colisión

Para comprobar si existe colisión calcularemos la distancia entre el jugador y cada uno de los enemigos. Para calcular la distancia, primero hallaremos el centro de cada uno de los enemigos y del jugador para posteriormente calcular la distancia euclidea entre ambos puntos.

Ya que las dimensiones son:

  • Jugador: 59x42
  • Enemigo: 50x40

El centro de cada uno de ellos debe estar desplazado de la posición en la que están dibujados (teniendo en cuenta que SDL dibuja desde la posición superior izquierda del objeto):

  •  Jugador: (30,21)
  • Enemigo: (25,20)

Veamos cuál es la distancia límite a la que pueden estar el jugador y un enemigo (si la distancia es menor se considerará que ha habido una colisión y por lo tanto el juego se termina):

  • Distancia crítica=(30²+21²)^(1/2)+(25²+20²)^(1/2) aproximadamente 69.

Es decir el punto en el que se tocan los extremos de las superficie enemigo con la superficie jugador. Este modo de calcular la distancia no es el más exacto, pero es bastante orientativo. Si quisiéramos calcular la distancia de manera más exacta deberíamos estudiar mejor la geometría y las dimensiones reales de nuestro dibujo (despreciando la parte con transparencia en los extremos).

La función que hace esta comprobación sería la siguiente:

int existeColision(int x, int y, int numeroEnemigos,
   struct posicion* posicionesEnemigos)
{
   int i;

   int centroJugador[2]={x+30,y+21};
   struct posicion* centroEnemigos;
   double distancia;

   centroEnemigos=(struct posicion*)malloc
(sizeof(struct posicion)*numeroEnemigos);

   for(i=0; i < numeroEnemigos; i++)
   {
	centroEnemigos[i].x=posicionesEnemigos[i].x+25;
	centroEnemigos[i].y=posicionesEnemigos[i].y+20;
	distancia=sqrt(pow((double)centroJugador[0]-
centroEnemigos[i].x,2)+pow((double)centroJugador[1]-centroEnemigos[i].y,2));
	if(distancia <= 69)
		return 1;
   }

   return 0;
}

Una vez tenemos la distancia crítica pasemos a ver como ha quedado la función (devuelve 1 si existe colisión, 0 en caso contrario).

Tened en cuenta la diferencia entre centro y posición. El centro es el centro de la superficie y la posición su extremo superior izquierdo.

Paso por paso:

  1. ¿Qué recibe?
  • int x: entero con coodenada X de la posición del jugador.
  • int y: entero con coordenada Y de la posición del jugador.
  • int numeroEnemigos: número de enemigos.
  • struct posicion* posicionesEnemigos: vector con las posiciones de los enemigos.
  1.  Cálculo del centro (30 y 21, por las dimensiones de la superficie del jugador 59 y 42):
  • int centroJugador[2]={x+30,y+21};
  1. Declaración del vector con las coordenadas del centro de los enemigos. Aprovechamos la estructura de datos posición, ya que nos sirve para almacenar las coordenadas X e Y del centro:
  • struct posicion* centroEnemigos;
  • centroEnemigos=(struct posicion*)malloc(sizeof(struct posicion)*numeroEnemigos);

Para cada enemigo además:

  1. Calculamos las coordenadas de su centro:
  • centroEnemigos[i].x=posicionesEnemigos[i].x+25;
  • centroEnemigos[i].y=posicionesEnemigos[i].y+20;
  1. La distancia euclídea entre el centro del jugador y el centro que acabamos de calcular (la expresión no se ve demasiado bien pero es simplemente aplicar la raíz a la suma de los cuadrados de las diferencias de las coordenadas X e Y).
  • distancia=sqrt(pow((double)centroJugador[0]-centroEnemigos[i].x,2)+pow((double)centroJugador[1]-centroEnemigos[i].y,2));
  1. Vemos si la distancia es menor o igual que la distancia crítica:
  • if(distancia<=68) return 1;

Para que el juego terminase en caso de que existiera colisión haríamos una llamada dentro del bucle

while(!terminar)
{
  ...
  if(existeColision(posicionJugadorX,posicionJugadorY,
numeroEnemigos,posicionesEnemigos))

    terminar=1;
  ...
}

Guardar un entero en cuatro char sin signo en C

En ocasiones, por motivos del protocolo utilizado en una comunicación, por la forma de acceder a la capa física o por cualquier otra razón similar, no podemos manejar directamente enteros de 4 bytes en nuestro programa, sino que debemos manejar valores de 1 sólo byte. No debemos preocuparnos, al fin y al cabo, podemos enviar un vector de 4 elementos de un tipo de dato que tenga 1 byte, por ejemplo, un carácter sin signo.

Gracias a la operación de desplazamiento de bits y al producto binario, la operación es casi inmediata. Veamos, la idea es guardar un entero de 4 bytes en un vector de 4 elementos de un byte de la siguiente manera:

  • Vector[0]: bits del 24 al 31 (parte más significativa)
  • Vector[1]: bits del 16 al 23
  • Vector[2]: bits del 8 al 15
  • Vector[3]: bits del 0 al 7 (parte menos significativa)

Por lo tanto, para almacenar el entero en dicho vector nos limitaremos a hacer lo siguiente:

unsigned char v[4];
v[0] = (n >> 24) & 0xFF;
v[1] = (n >> 16) & 0xFF;
v[2] = (n >> 8 ) & 0xFF;
v[3] = n & 0xFF;

Como véis, además de desplazar, multiplico por todo unos (FF) para asegurarnos de que el entero resultante se queda sólo con el byte que nos importa.

Ahora tenemos en base 256 un número de 4 bytes guardado en 4 cifras. ¿Cómo hacer la operación inversa? Muy simple, si en base 10 hacemos: unidades + decenas x 10 + centenas  * 100... en nuestro caso tendríamos:

resultado = v[0] * 16777216 + v[1] * 65536 + v[2] * 256 + v[3];

Curso programación de videojuegos con SDL – Mejorando aspectos gráficos

Habréis podido observar que los aviones parpadean al moverse por la pantalla. Esto se produce porque dibujamos directamente sobre la pantalla, es decir sobre lo que hemos llamado screen, de manera que dibujamos antes unos objetos y luego otros. Este problema es bien sencillo de solucionar con SDL gracias a la llamada técnica del doble búfer que nos ofrece. Mediante esta técnica dibujaremos sobre un búfer en el que una vez dibujados todos lo necesario, pasaremos a dibujar sobre el screen, de esta manera eliminaremos el parpadeo que creaba la técnica anterior.

Expliquemos la implementación de esta técnica sobre nuestro ejemplo:

  1. Declamos un puntero a una variable del tipo SDL_Surface sobre la que “dibujaremos” y despues volcaremos sobre el screen:
    SDL_Surface *buffer;
  2. Creamos este buffer:
    buffer = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480, 16,0,0,0,0);
  3. Le indicamos al screen que vamos a usar la técnica de doble búfer:screen = SDL_SetVideoMode( 640, 480, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
  4. Dibujamos los componentes del juego, fondo, jugador y enemigos sobre el búfer:
    SDL_BlitSurface(fondo, NULL, buffer, &posicion);
    SDL_BlitSurface(jugador, NULL, buffer, &posicion);
    SDL_BlitSurface(enemigos[i], NULL, buffer, &posicion);
  5. Volcamos sobre la pantalla:
    posicion.x=0;
    posicion.y=0;
    SDL_BlitSurface(buffer, NULL, screen, &posicion);
    SDL_Flip(screen);

No mostramos el código completo, porque como estos cambios han sido menores y son fácilmente identificables. Para terminar esta entrada del curso sólo comentar cómo sería el caso de que quisiéramos hacer que el juego se ejecutase en pantalla completa en lugar de en una ventana. Con SDL solamente tendríamos que incluir en el último parámetro SDL_FULLSCREEN:

screen = SDL_SetVideoMode( 640, 480, 16, SDL_FULLSCREEN | 
SDL_HWSURFACE | SDL_DOUBLEBUF);

Como podéis observar los valores se incluyen con OR lógicos (|).