lunes, 19 de noviembre de 2007

Progreso lento, planes interesantes.

La vida es lo que te interrumpe mientras codeas.
Ya se ha superado el tema de pinchar en los sprites.
Ahora tengo que implementar las llamadas a los eventos-acciones. No creo que me cueste mucho. Seguramente haré un par de escenas de ejemplo.
Ahora estoy pensando en construir el sistema de interfaz, que serán dos bandas negras para convertir el juego en una especie de película "cinemascope". En estas bandas aparecerá la puntuación, los mensajes y las descripciones, los diálogos, etc.
Para las escenas de lucha tengo grandes planes y una colaboración. El engine contará con una característica muy interesante.

Más noticias pronto.

miércoles, 7 de noviembre de 2007

ping?

pong!

lunes, 22 de octubre de 2007

Píxeles de SDL_Surface y eventos de sprite.

Al final era más fácil de lo que yo creía. Hay un ejemplo en la documentación de libSDL que explicaba perfectamente cómo hacerlo. Copiaré el código con muy pocos cambios. Así, la detección de sprites pinchados se queda de la siguiente manera:

1.- Crear propiedad privada del sprite que sea un SDL_Surface con tamaño igual al de la superficie de la pantalla y 8 bits de profundidad con flag SWSURFACE. Esta superficie será la máscara.
2.- Cuando se cree un frame del sprite, crear una copia del frame a 8 bits como "sombra", también con flag SWSURFACE
3.- cuando se pida un tick del sprite (actualización de animación y frame para hacer blitting a la pantalla), rellenar la superficie máscara de un color concreto (¿rosa? ¿verde fosforito? ¿azul puro?) y hacer blit de la sombra del frame actual sobre la superficie máscara.
4.- para saber si el ratón ha pinchado sobre nuestro sprite, sacamos el color del pixel donde está el ratón de la máscara. Si no es el color de fondo asignado, hemos pinchado en nuestro sprite y disparamos evento de usuario de SDL, que a su vez disparará una o varias acciones de la lista de acciones de la escena.

A ver si esta tarde o mañana lo programo.

viernes, 19 de octubre de 2007

No he avanzado mucho...

... desde el último post. Pero tengo una buena excusa; he estado con Ubuntu 7.10 probando, reprobando y poniendo más a prueba. Y sólo tiene dos problemas para mí:

  • El controlador de intel para las Xorg detecta el DPI demasiado grande que no concuerda con los ajustes de Gnome. Así, las barras de ventana, a cargo de compiz, salen con letras muy grandes respecto del resto del apartado gráfico, a cargo de Gnome. Es molesto, pero no es importante. Se arregla añadiendo la opción "-dpi 96" en el menú Sistema ==> Administración ==> Ventana de entrada ==> Seguridad ==> Configurar Servidor X ==> Comando.
  • Se agota la batería de mi portátil en tres horas escasas. Claro, que no tengo un portátil muy bueno, pero creo que es poco tiempo. Deben mejorar bastante en el consumo de energía.

El resto del sistema simplemente funciona como debe.

domingo, 14 de octubre de 2007

Máscaras de sprites

Me están costando más de lo que suponía.
Leer un pixel de una superficie SDL tiene su miga, ya que la información de los pixeles sólo es accesible directamente desde la memoria. Y además, si la superficie es de tipo "HWSURFACE", está en la memoria de la tarjeta gráfica, lo que hace las lecturas lentas. Y no podría leer pixeles fuera de rango sin hacer costosas comprobaciones antes.
Ahora mismo estoy creando un sistema de "sombra" de los sprites, en la que creo una superficie "SWSURFACE" de acceso rápido equivalente a la superficie de la pantalla, pero en la que sólo "bliteo" una copia del sprite que también es "SWSURFACE". Todo esto con sólo 8 bits de profundidad para hacer el bliteo lo más rapido posible.
Cuando quiera leer el pixel donde se encuentra el ratón, tengo que bloquear la superficie "sombra", haciendo una lectura de este estilo:


Uint8 *bufp;//Avanzamos en bloques de 8 bits en vez de 1 byte
SDL_LockSurface(superficie);
bufp = (Uint8 *)superficie->pixels + y*superficie->pitch/2 + x;
// realizamos comparación de bufp con un valor generado por la función
// SDL_MapRGB para saber si hemos tocado nuestro sprite
SDL_UnlockSurface(superficie);


Siendo "superficie" un SDL_Surface.

Más noticias pronto :)

sábado, 6 de octubre de 2007

Punteros de ratón.

El ratón tiene punteros que indican la acción activa en ese momento.
Para "usar", un par de engranajes. Para "ver", una lupa. Para "coger", una mano. Para "disparar", una mirilla. Y por supuesto, un puntero normal.

Lo siguiente serán eventos disparados por los sprites. Pero antes debo decidir cómo gestiono las máscaras de los sprites... Esto me va a costar un poco más, pero una vez resuelto este tema, ya se podrán crear juegos simples.

sábado, 29 de septiembre de 2007

Música en las escenas y futuro

He programado un pequeño gestor de sonido y ahora las escenas tienen música de fondo. Pronto código y binario.
Lo siguiente va a ser los modos de interacción (ver, usar, coger) con el ratón, eventos generados por los sprites, presentación de texto, efectos de sonido...

miércoles, 19 de septiembre de 2007

Temas pendientes

Ahora que ya tengo una base funcionando, tengo pendientes un montón de cosas:

- Sonido en las escenas. Listas de sonidos, eventos de reproducción.
- Máscaras en los sprites. ¿Autogeneradas?
- Los sprites deben generar eventos al ser pinchados con el ratón.
- Las escenas interactivas deben comprobar la lista de objetivos cumplidos y generar las acciones oportunas. Esto sirve para que los objetos cambiados en el juego tengan persistencia.
- Hay que ir pensando en una forma de representar texto en la pantalla dinámicamente para diálogos y descripciones.
- Un sistema de inventario también estaría bien.

martes, 18 de septiembre de 2007

Primer ejecutable

Ya he conseguido implementar las listas de sprites y su presentación en la pantalla. La librería SDL funciona muy bien. Incluso puedo dar unas especificaciones mínimas para el engine: Procesador pentium a 800 MHz, Windows 2000, una tarjeta gráfica que soporte directX 7 y 256 Mb de ram.

Aberrant Engine. Código fuente.
Ejemplo de Aberrant Engine. Binario Win32.

Intrucciones para el Binario de ejemplo: descomprimir y ejecutar "theaberrant.exe" de la carpeta "theaberrant". Para salir del programa, pulsar la tecla F10.

Ahora queda implementar eventos disparados desde los sprites y ya se podrá hacer un juego tipo "Exmortis"

sábado, 8 de septiembre de 2007

Creación de Sprites comprobada

Ahora tengo que idear un sistema para asignar a cada sprite una función de posición que dependa del tiempo y que sea individual para cada Sprite.
Será una función de la librería de datos a la que se le pasará toda la información importante por referencia.
Por cierto, seguramente me llevaré el ordenador portátil a mis vacaciones, bajo el benepácito de mi novia, por lo que el desarrollo no se detendrá. Creo.

viernes, 7 de septiembre de 2007

Se acercan las vacaciones...

Ya tengo escrito todo el sistema de métodos que cargarán los frames de cada sprite de una escena en memoria. Leer estos frames será tan sencillo como devolver el puntero SDL_Surface para hacer blitting directamente a la pantalla. Tengo que hacer unas cuantas pruebas para ver si no me dejo ningún puntero por borrar.
¿Sería posible reproducir una animación de "Loading" mientras se carga? Tengo que investigarlo.
Están las vacaciones a la vuelta de la esquina, por lo que el proyecto se quedará parado entre una y dos semanas a partir de este domingo. Publicaré lo que llevo hecho por si alguien quiere echarle un vistazo. Pero vista la increíble audiencia de este blog :P no creo que nadie me mande parches.

jueves, 6 de septiembre de 2007

Codeando voy, codeando vengo...

Escribo código allá donde puedo; en el trabajo medio a escondidas, en casa después de limpiar, cocinar y hacer compra. La implementación de los sprites avanza lentamente.
Serán animados, pero no tendrán máscaras todavía. Estoy pensando en crear un sistema automático de creación de máscaras para ahorrar espacio en disco pero no creo que lo haga.
Los sprites podrán ser animados. Cada objeto sprite tiene una lista de frames que irán rotando automáticamente.
Todavía no tengo código enseñable. Pronto más.

viernes, 31 de agosto de 2007

¿Y dónde pongo los sprites?

He retrasado todo lo que he podido la implementación de la escena interactiva por que quería estar completamente seguro del diseño.
Tengo dos clases que manejan el comportamiento del programa. La clase juego, gestiona las llamadas a la librería SDL, guarda los datos persistentes del juego y manda eventos a la clase escena. La clase escena se instancia para cada escena, y modifica los datos de la clase juego en respuesta a los eventos recibidos.
Cada vez que se crea una escena nueva, hay que cargar los sprites, sonidos, reglas, y todo lo relacionado con la escena. Pero, ¿dónde se cargan?. Parece que lo lógico sería que todo lo de la escena fuera propiedad privada de la clase escena. Pero eso son datos que va a utilizar SDL en realidad. Los sprites serán pngs que se "blitearán" a la pantalla. Y los sonidos lo mismo. Así que he decidido que todo lo que tenga relación con SDL estará en la clase juego. Crearé los arrays de sprites y sonidos como propiedad privada de la clase juego. Como los punteros de cada instancia son conocidos, haré que en el constructor de la escena se carguen los sprites en la clase juego.

Código fuente

Vamos a publicar lo que llevamos hecho:

http://www.arrakis.es/~cesrodmo/theaberrant_20070831.zip

Si alguien lo pide, publicaré un binario con un par de escenas de ejemplo.

martes, 21 de agosto de 2007

ping?

pong!

miércoles, 15 de agosto de 2007

Nueva versión de Work Logger

Ya se graba la hora correctamente en los log.

martes, 14 de agosto de 2007

Reproductor de vídeo terminado.

El engine ya tiene una funcionalidad mínima como secuenciador de vídeo :) Ahora soy capaz de ordenar escenas de vídeo, definir la siguiente escena, salir del juego con una tecla determinada y responder al teclado. He implementado un sistema simple de eventos que servirá de base para las escenas interactivas.
Empieza la parte realmente interesante; crear las listas de sprites y sonidos, reproducirlos en orden, crear los eventos adecuados y hacerlo todo orientado a un desarrollo del juego rápido y sencillo dentro de lo que cabe.

En otro orden de cosas, me he dado cuenta que el Work Logger pone los "timestamps" con dos horas de retraso. Luego lo arreglo.

viernes, 10 de agosto de 2007

Work Logger

Esto no esta relacionado con el juego, pero creo que merece la pena ponerlo aquí. A lo mejor a alguien le resulta útil...
He hecho una pequeña utilidad para windows que sirve para llevar un registro de lo que haces. Abres el programa, escribes lo que has hecho y lo cierras. Nada más. El programa te deja un registro en tu escritorio con la hora de la entrada y la entrada.
Luego si alguien te pregunta, o tienes que decirle a otra persona lo que llevas hecho, sólo tienes que pasarle el log.

Código fuente: worklogger.zip
Binario: worklogger.exe

jueves, 2 de agosto de 2007

Eventos, condiciones y acciones

Este fin de semana voy a tratar de solucionar un problema que, cada vez que lo pienso, se vuelve más complicado dentro de mi cabeza.
Necesito crear un sistema para cambiar las propiedades del objeto juego y el objeto escena, que se configure en cada escena, que reaccione a los clicks del ratón o a temporizadores ajustados y que dependa de cualquier propiedad del objeto juego o del objeto escena.
Ya contaré más sobre el tema.

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.

domingo, 24 de junio de 2007

Sigo vivo...

Pronto más posts...

sábado, 16 de junio de 2007

Conclusión sobre las licencias.

Para el motor del juego y un pequeño módulo de ejemplo, utilizaré la licencia BSD, en la que permitiré la libre distribución del código y crear trabajos derivados tanto en forma de código como en binarios siempre y cuando se me nombre explícitamente en créditos y publicidad.
Para el juego completo utilizaré "Licencia Reconocimiento-No comercial-Sin obras derivadas 2.5 España License de Creative Commons" en la que no permito el uso comercial del juego ni permito modificarlo. Me reservo el derecho de cambiar de opinión más adelante :P

miércoles, 13 de junio de 2007

Más acerca de las licencias.

He seguido investigando sobre los tipos de licencias que podría aplicar al juego. En general, mis conclusiones son las siguientes:
La licencia GPLv2 y posteriores me obligan a publicar TODO el código fuente del juego. Eso incluiría las funciones que definen las escenas que van en librerías a parte. No me interesa esto, ya que no podría poner a descargar el juego sin que la parte creativa quedase expuesta.
La licencia LGPLv2 y posteriores permite que el código sea enlazado desde programas privativos si obligar a esos programas a que liberen a su vez su código. Esto esta pensado para publicar librerías de tal forma que todo el mundo pueda usarlas, incluyendo los productos privativos.
La licencia BSD original permite hacer cualquier cosa con el código siempre y cuando se nombre explícitamente al autor del programa o librería incluso en la publicidad que se haga del programa. Puede que esto me interese, ya que podría liberar sólo parte del programa bajo BSD y el resto sería cerrado. Otra versión de BSD posterior no tiene la clausula de publicidad.
La licencia X11. Quizás es la más sencilla de todas. Permite hacer lo que sea con el código mientras no se nombre en otro producto como característica. Como lo que busco es que mi nombre vaya con el juego, no creo que elija esta.

De momento, creo que BSD es lo que más me gusta. Ahora quiero saber si existe un equivalente legal español a esta licencia.

martes, 29 de mayo de 2007

Librerias y licencias

Quiero diseñar el juego de tal forma que el intérprete de escenas y los descriptores de escenas se compilen independientemente. Así, la máquina principal del juego, que controlará el refresco de pantalla, el ratón, las transiciones y demás, serán el ejecutable principal en C++. Cuando se “instancie” un objeto que contenga toda la información de una escena, el constructor llamará a funciones C que devolverán los valores adecuados para esa escena. Estas funciones estarán en una DLL a parte. Así tendré separados el juego del “engine”.
El uso de DLL es más lento (sólo un poquito más lento, vamos, inapreciable) que si integrase todo en un mismo ejecutable, pero así puedo lanzar el contenido artístico con una licencia restrictiva y el código del juego con otra más abierta.
Ya he hecho mis primeras pruebas y es relativamente sencillo. Incluir código C en C++ se hace con la instrucción:

extern “C” {
#include “cabeceraC.h”
}

Así, podremos llamar a las funciones en C desde C++.

martes, 1 de mayo de 2007

Almacenamiento y otros problemas

Tengo un mac de 24 pulgadas, un pentium 4 HT, un portatil de 12 pulgadas con un core 2 duo y otro portatil viejo que hace las veces de servidor de ficheros.


Utilizaré este último como repositorio del código y del "toolkit". Será algo sencillo, un samba para almacenar ficheros comprimidos manulamente. Pondré la versión a mano en el nombre de fichero. Sé que lo ideal sería un cvs o algo así, pero no tengo tiempo para eso.


Además, no puedo postear con el widget blogger en este blog. ¿Alguien sabe de algún programa para mac os x para postear aquí?

lunes, 30 de abril de 2007

Preparación de librerías

El juego estará hecho sobre SDL, SDL_mixer, SDL_gfx, SDL_image y SMPEG. Hoy por fin he conseguido crear un entorno de programación. Voy a user DEV C++. He bajado las librerías precompiladas de todo lo que me hace falta. No he utilizado los devpaks por que no estan actualizados. Es una pena.


El método que he seguido es el siguiente:


- Bajar el devpak si lo hubiera.


- Bajar la ultima version de la librería


- Sustituir los .h, los .a y los .dll


SDL_gfx tuve que compilarlo para crear los DLL. Con SMPEG no ha habido suerte y voy a utilizar un devpak que parece que funciona bien. Más adelante intentaré compilarlo yo mismo.

¿Que es esto?

El diario de creación del proyecto "The Aberrant". Juego de terror-horror multiplataforma basado en las librerias SDL, hecho en C y C++.