domingo, 29 de julio de 2007

Librería SMPEG

Me bajé un devpak con el DEV-C++ para la librería SMPEG. La librería, compilada como estática, proporciona funciones para cargar y reprodcir videos en formato mpeg1. Tiene un buen rendimiento pero esta abandonada.
Este devpak reproduce correctamente los vídeos, pero no los paraba hasta el final. He tenido que bajarme el último cvs, importar el proyecto de visual C a DEV-C++ y recompilar la librería. El resultado es un archivo con extension ".a" que se sustituye por la que venía con el devpak.
Ahora los vídeos se reproducen, se pausan y se paran sin ningún problema.

La página del SMEPG es http://icculus.org/smpeg/

sábado, 28 de julio de 2007

Vamos avanzando

El engine empieza a tomar forma, aunque todavía no hace nada interesante en realidad. El esqueleto con la relación juego<-->escena esta hecho. Se inicia el juego, el juego inicia la primera escena, que es un video y lo reproduce. Esto es todo de momento.
Ahora tengo que añadir a la escena el sistema de eventos-acciones que modifica el juego y asi pasar a la siguiente escena de una forma programada.
Lo siguiente será crear el sistema de escena interactiva. Será lo que me lleve más tiempo en realidad, ya que va a ser un sistema un poco complicado. Habrá listas de sprites animados, animaciones programadas mediante funciones, transparencias, eventos generados por el ratón y el teclado...
Estaba pensando en hacer otro programa que gererase el código de la librería de datos. Algo así como un editor del engine para crear juegos. Eso lo dejaremos para lo último.

lunes, 23 de julio de 2007

Nueva versión de SDL

SDL 1.2.12

y de SDL_mixer y de SDL_image y de SDL_gfx... toca rehacer las librerías y el sistema de compilado.

viernes, 20 de julio de 2007

ping idaho^j idaho is alive

Mucho trabajo y mucho cansancio últimamente. El proyecto esta un poco parado. Pronto más. :)

domingo, 8 de julio de 2007

Referencias cruzadas entre dos clases

En mi diseño, los métodos de una clase tienen que poder llamar a los métodos de una segunda. Los métodos de la segunda clase tienen que poder llamar a los métodos de la primera.
La solución para este problema que se me ha ocurrido es poner un puntero a la clase que queremos llamar como parte privada. Uno de los métodos públicos de la clase se encargará de darle el valor adecuado a ese puntero. Supongamos una cabecera “clasejuego.h”:

#include "claseescena.h"

class claseJuego
{
private:
claseEscena * punteroEscena;
[...]
public:
// class constructor
claseJuego();
// class destructor
~claseJuego();

// Asigna la dirección del objeto Escena en el Juego
void asignaEscena(claseEscena * nuevoPunteroEscena);

// Con este método cambio propiedades del objeto Escena
void cambiaEscena(int a, int b);
[...]
};

En “claseescena.h” el código sería muy parecido.
Nosotros crearíamos las instancias de los objetos e inmediatamente después llamaríamos a asignaEscena y a asignaJuego tal que así:

#include "clasejuego.h"
#include "claseescena.h"

int main(int argc, char *argv[])
{
claseJuego * punteroJuego;
claseEscena * punteroEscena;

punteroJuego = new claseJuego;
punteroEscena = new claseEscena;

punteroJuego->asignaEscena(punteroEscena);
punteroEscena->asignaJuego(punteroJuego);
[...]
}

Parece correcto, ¿verdad? Pues esto no compila. No se pueden hacer includes cruzados por que no se pueden declarar dos tipos a la vez. Por muchos includes que se pongan en las cabeceras, el compilador recibe las declaraciones de una en una. Siempre se encotrará con que se hace referencia a un tipo todavía no declarado. Así que investigando sobre este problema he encontrado que se pueden hacer declaraciones de tipos por adelantado. Así en “clasejuego.h”:

#include "claseescena.h"

class claseEscena; // referencia por adelantado de un tipo
class claseJuego

{

private:
claseEscena * punteroEscena;
[...]

Igual en la otra cabecera.
Hay otra soluciones para este problema, pero esta me parece la más fácil. Ahora, a otra cosa :)

Estilo de código

Utilizaré estilo de notación de camello y todas las variables tendrán su tipo como prefijo excepto los de tipo obvio que necesite para contar o guardar cadenas de caracteres. Creo que este estilo se llama notación Húngara. Ejemplos:

claseJuego: Estructura de la clase para el juego.
puntJuego: Puntero de una instacia de claseJuego
i: variable entero que utilizo para un bucle o algo así
boolCheckSprite: booleando de una comprobación.

Las constantes irán en mayúsculas. Los bloques de código dentro de bucles y funciones añadirán cuatro espacios o un tabulador antes de cada línea. Los comentarios podrán ir detrás de cada línea con doble barra o en bloques de barra asterisco.

viernes, 6 de julio de 2007

Cambiar de opinión (licencias, la venganza)

Dicen que es de sabios.
He hablado con Fabi. Me ha convencido. Liberaré el Aberrant Engine bajo GPLv3 y el Juego bajo CC sin permiso para modificar.
No es una contradicción, ya que como autor, puedo considerar el juego como arte derivado. Una obra separada. Que yo diga que ese arte derivado tiene parte GPL no implica que deba liberarlo también.

Hablando de otros temas, tengo el diseño casi terminado. Pronto más.

jueves, 5 de julio de 2007

La criatura se va a llamar:

Tras pensarmelo mucho, el engine del juego se va a llamar:

Aberrant engine


domingo, 1 de julio de 2007

Listas en c++

Las clases que voy a utilizar en el programa van a hacer un uso intensivo de listas de datos que se recorrerán para realizar alguna función.
Por ejemplo, la clase "escena" tendrá una lista de "sprites". "sprite" será a su vez otra clase que contendrá más listas.
¿Cómo implemento una lista? La opción más académica es crear un sistema de punteros con una clase que gestiona la creación de nodos, su inserción y su recorrido. Es un sistema eficiente en la gestión de memoria pero es un poco pesado de implementar. Además, no tengo claro la forma en que gestionaria los diferentes tipos de punteros. ¿Tengo que hacer una clase lista para cada tipo? ¿o hago una clase genérica y luego voy heredando y sobrecargando los metodos para cada una? Un coñazo.
La opción vaga es hacer arrays de objetos de esta forma:
    laClase *arrayClase;

arrayClase = new laClase[TAMANIO_LISTA];

[...]

delete[] arrayClase;

Así, todas las clases se instancian por que "new" llama a todos los constructores de cada elemento del array. Al principio, estos objetos tendrán la menor cantidad de datos posible e iremos "llenando" de datos cada nodo de la lista según lo vayamos necesitando. El comando "delete[]" llama a todos los destructores de las clases, que a su vez se encargarán de "deletear" sus arrays-listas. Es un sistema poco eficiente en el uso de memoria, pero seguro y fácil de implementar.
La memoria no me preocupa mucho. Todos los ordenadores modernos tienen bastante memoria.