¿Imagenes dentro del juego, sin cargarlas?

Tratamos sobre el manejo de APIs frecuentemente utilizadas en el desarrollo de videojuegos, como SDL, pygame o SFML.

¿Imagenes dentro del juego, sin cargarlas?

Notapor lacabra25 » Vie Abr 11, 2008 3:24 pm

Hola, he visto programas que uno se lo descarga y solo es un archivo .exe, y se ejecuta sin instalacion ni necesidad de ningun archivo ni imagen y me preguntaba como se podria usar SDL y tener las imagenes sin necesidad de cargarlas de ningun archivo. ¿como podria hacerlo? :roll:
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor lacabra25 » Lun Abr 14, 2008 6:15 pm

Hola, me descargue gimp para hacer los dibujos para mis juegos, y vi que la imagen se podia guardar con formato .c, de forma que define una estructura y crea una variable para guardar la imagen, supongo que cada byte del array de los pixels, se correspondera con el byte de cada canal de un pixel, pero aun asy no se como pasar la imagen a una superficie SDL, ¿dibujo pixel a pixel la superficie pasando como valores de rojo, verde y azul al color del pixel cada byte del array?, ¿como identifico en que posicion esta cada byte de cada canal de cada pixel?, para esta ultima pregunta se me ocurrio que como el array mide ancho(o alto, no se seguro) X alto(o ancho, no se seguro) X canales + 1 podria identificar la posicion del pixel en las coordenadas (x; Y) de la siguiente forma (x * 3) + (y * alto * 3) + canal pero no estoy seguro si esto funcionaria. ¿como podria pasar la imagen a una superficie SDL?

Codigo de la imagen en c:
Código: Seleccionar todo
/* GIMP RGB C-Source image dump (tierra_agrietada.c) */

static const struct {
  guint      width;
  guint      height;
  guint      bytes_per_pixel; /* 3:RGB, 4:RGBA */
  guint8     pixel_data[100 * 100 * 3 + 1];
} tierra_agrietada = {
  100, 100, 3,
  "\200U+\200U+\200U+U+\0\200U+\377\324\252\377\324\252\324\252\252\324\252"
  "\252\324\252\200\324\252\200\324\252\200\324\252\200\324\252\200\324\252"
  "\200\324\252\252\324\252\252\324\252\252\324\252\252\324\252\200\324\252"
  "\200\324\252\200\324\252\200\324\252\200\324\252\252\252\200\200\324\252"
  "\200\324\252\200\252\200\200\252\200\200\324\252\200\324\252\200\324\252"
  "\200\324\252\200\324\324\252\324\252\200\324\252\200\324\252\200\324\252"
  "\200\324\252\200\252\252\200\324\252\200\324\252\200\324\252\200\324\252"
  "\200\324\252\200\324\252\200\252\200U\324\252\200\324\252\200\252\200U\252"
[...]
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor Geo » Mar Abr 15, 2008 4:58 pm

lacabra25 escribió:Hola, me descargue gimp para hacer los dibujos para mis juegos, y vi que la imagen se podia guardar con formato .c, de forma que define una estructura y crea una variable para guardar la imagen, supongo que cada byte del array de los pixels, se correspondera con el byte de cada canal de un pixel, pero aun asy no se como pasar la imagen a una superficie SDL, ¿dibujo pixel a pixel la superficie pasando como valores de rojo, verde y azul al color del pixel cada byte del array?,

Una es crear una Surface y luego copiar pixel a pixel, pero no es nada eficiente. La alternativa sería copiar el bloque de memoria completo a una SDL_Surface o mejor utilizar SDL_CreateRGBSurfaceFrom :).

lacabra25 escribió:¿como identifico en que posicion esta cada byte de cada canal de cada pixel?, para esta ultima pregunta se me ocurrio que como el array mide ancho(o alto, no se seguro) X alto(o ancho, no se seguro) X canales + 1 podria identificar la posicion del pixel en las coordenadas (x; Y) de la siguiente forma (x * 3) + (y * alto * 3) + canal pero no estoy seguro si esto funcionaria.

Si, así se hace.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor lacabra25 » Mié Abr 16, 2008 1:56 pm

Geo escribió:Una es crear una Surface y luego copiar pixel a pixel, pero no es nada eficiente. La alternativa sería copiar el bloque de memoria completo a una SDL_Surface o mejor utilizar SDL_CreateRGBSurfaceFrom :).


Un pequeño detalle, a la funcion SDL_CreateRGBSurfaceFrom que parametros hay que pasarle y que devuelve, como funciona esa funcion, esque no la conozco y nunca la he usado. :oops:
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor Geo » Jue Abr 17, 2008 6:38 am

La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor lacabra25 » Jue Abr 17, 2008 2:40 pm

el parametro pitch, ¿que es exactamente? gracias por el enlace pero no esplica los parametros, aunque el unico que no se es el pitch ese.
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor lacabra25 » Jue Abr 17, 2008 4:22 pm

Geo, he intentado usar la funcion que me dijistes, pero no se si es que la he usado mal o que algo falla, pero aunque la superficie devuelta es diferente de NULL cuando la intento mostrar por pantalla, en la ventana no se ve nada mas que el fondo negro. Pego el codigo que use de ejemplo, aunque la matriz de la imagen la abreviare quitando la parte central:

Código: Seleccionar todo
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

static const struct {
  int      w;
  int      h;
  int      bpp; /* 3:RGB, 4:RGBA */
  Uint8     pixels[100 * 100 * 3 + 1];
} tierra_agrietada = {
  100, 100, 3,
  "\200U+\200U+\200U+U+\0\200U+\377\324\252\377\324\252\324\252\252\324\252"
  "\252\324\252\200\324\252\200\324\252\200\324\252\200\324\252\200\324\252"
   "\252\200\324\252\200\252\200U\252\200U\324\252\200\324\252\200\324\252\200"
  "\324\200U\252\200U\252U+\200U+\200U+\200U+\377\252\200\377\324\252\377\252"
  "\252\324\252\200\252\200U\200U+\200U+\200U+\252\200U\377\324\252\377\324"
  "\252\324\252\200\324\252\200\252\252\200\252\200U\252\200U\200U+\200U+\200"
  "+\0\200+\0\200U+\252\200U\324\252\200\324\252\200\324\252\200",
};

int main(int argc, char *argv[]){
SDL_Surface *pantalla, *imagen;
SDL_Rect dest;
/* Iniciando SDL*/
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("EGI - No fue posible iniciar SDL, error: %s\n",SDL_GetError());
exit(1);
}
/* Iniciando modo de video*/
pantalla = SDL_SetVideoMode(200,200,24,SDL_SWSURFACE| SDL_DOUBLEBUF);
if (pantalla == NULL) {
printf("EIV - No se puede inicializar el modo de video 457x457 24 Bits en la memoria de video con doble buffer, error: %s\n",SDL_GetError());
exit(1);
}
imagen= SDL_CreateRGBSurfaceFrom(&tierra_agrietada.pixels, 100, 100, 3, 400, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
if(imagen != NULL){
/*mostramos la imagen en la pantalla centrada si es mas pequeña que la pantalla*/
dest.x = 0;
dest.y = 0;
dest.w = 100;
dest.h = 100;
SDL_BlitSurface(imagen, NULL, pantalla, &dest);
if(SDL_Flip(pantalla) == -1){
SDL_UpdateRect(pantalla, 0, 0, pantalla->w, pantalla->h);
}
printf("Imagen mostrada\n");
}
else{
printf("Imagen NULL\n");
}
SDL_Delay(4000);
return 0;
}


¿que podria estar causando que no funcione?, ¿como puedo conseguir que funcione?
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor Geo » Vie Abr 18, 2008 4:26 am

  • El cuarto parámetro es bits por pixel, no bytes por pixel, en el caso de la imagen que muestras debería ser un 24 y no 3.
  • Algo similar para el quinto parámetro (pitch), el cual es el ancho de la imagen en pixeles por el número de bytes por pixel, en este caso sería 100 x 3.
  • En tu imagen no exportaste el canal alfa, así que no necesitas poner la máscara 0xff000000, en su lugar pon un 0.

Prueba con algo como esto:
Código: Seleccionar todo
   imagen = SDL_CreateRGBSurfaceFrom(
      &tierra_agrietada.pixels,
      tierra_agrietada.width,
      tierra_agrietada.height,
      tierra_agrietada.bytes_per_pixel * 8,   // 1 byte = 8 bits => bits por pixel = bytes por pixel * 8
      tierra_agrietada.width * tierra_agrietada.bytes_per_pixel,   // scanline = ancho * bytes por pixel
      0x000000ff, 0x0000ff00, 0x00ff0000, 0
   );

Como ves, es mejor utilizar las variables de dimensión y bytes por pixel que están en la estructura en lugar de escribir sus valores numéricos :).

Notas:
* en las máscaras, puedes eliminar el primer byte correspondiente al canal alfa, pues no se utiliza, entonces serían 0x0000ff, 0x00ff00 y 0xff0000.
* no utilicé los tipos de Glib para exportar la imagen en Gimp.

Suerte.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor lacabra25 » Vie Abr 18, 2008 2:20 pm

Gracias Geo, ahora funciona perfectamente, no estaria mal tener algun ejemplo de imagenes dentro del propio codigo del programa en la seccion de ejemplos.

¿La inversa de esto, como se hace, como de la superficie sacan el codigo en C necesario para hacer una superficie a partir de el?, se que gimp lo hace y todo eso, y no creo que haciendolo gimp me ponga yo a hacerlo, pero es por curiosidad y por aprender más sobre las superficies, c y sdl.

No entiendo la ultima linea, sobre Glib de gimp, ¿a que te refieres exactamente?, si he usado algo de Glib de Gimp, la verdad es que no me he enterado de que lo he usado.
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor Geo » Vie Abr 18, 2008 3:54 pm

lacabra25 escribió:Gracias Geo, ahora funciona perfectamente, no estaria mal tener algun ejemplo de imagenes dentro del propio codigo del programa en la seccion de ejemplos.

En eso estaba pensando, la verdad es que ya había contemplado hacer algo similar pero hasta ahora no lo había hecho :P. En fin, de lo que se trata es tener la idea de cómo hacer las cosas, no saberse de memoria los nombres de funciones para tal o cual efecto :P. Si nadie se ofrece, con gusto me hago un tiempo para escribir un ejemplo :).

lacabra25 escribió:¿La inversa de esto, como se hace, como de la superficie sacan el codigo en C necesario para hacer una superficie a partir de el?, se que gimp lo hace y todo eso, y no creo que haciendolo gimp me ponga yo a hacerlo, pero es por curiosidad y por aprender más sobre las superficies, c y sdl.

En realidad es sencillo, lo básico para representar una imagen es conocer sus dimensiones (ancho y alto), el número de bits que se utilizan para representar cada pixel de la imagen y la información de los pixeles en si. De una SDL_Surface, puedes obtener estos datos fácilmente, de allí te tocaría exportarlos a un archivo de texto organizándolo de forma que pueda ser utilizado, en el caso de Gimp, lo hace creando una estructura con los elementos básicos para representar la información de la imagen.

lacabra25 escribió:No entiendo la ultima linea, sobre Glib de gimp, ¿a que te refieres exactamente?, si he usado algo de Glib de Gimp, la verdad es que no me he enterado de que lo he usado.

Ah, es que al guardar la imagen como código en C, Gimp muestra este diálogo:
Imagen
By geomx at 2008-04-18

En el diálogo se tiene la opción "Usar tipos Glib (guint8*)", es simplemente para los tipos a usar para la estructura que se utiliza para representar la imagen. Por ejemplo, si se activa, el array de pixeles será del tipo guint8*, mientras que si no está activa se usa unsigned char*.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor lacabra25 » Sab Abr 26, 2008 9:57 am

Geo escribió: :P. Si nadie se ofrece, con gusto me hago un tiempo para escribir un ejemplo :).


Pues yo (como ya te supondras al haber contestado esta pregunta) no es que tenga demasiada experiencia manipulando imagenes pixel a pixel ni incorporando el codigo de la imagen al del propio progama, por lo que si ya te has animado a hacer el ejemplo, preferiria que lo hicieras tu en vez de ponerme yo ha hacerlo, si te sirve de ayuda te adjunto el primer programa para probar que he hecho con la funcion que me dijistes.

Código: Seleccionar todo
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

static const struct {
  int      w;
  int      h;
  int      bpp; /* 3:RGB, 4:RGBA */
  Uint8     pixels[100 * 100 * 3 + 1];
} tierra_agrietada = {
  100, 100, 3,
  "\200U+\200U+\200U+U+\0\200U+\377\324\252\377\324\252\324\252\252\324\252"
  "\252\324\252\200\324\252\200\324\252\200\324\252\200\324\252\200\324\252"
  "\200\324\252\252\324\252\252\324\252\252\324\252\252\324\252\200\324\252"
  "\200\324\252\200\324\252\200\324\252\200\324\252\252\252\200\200\324\252"
  "\200\324\252\200\252\200\200\252\200\200\324\252\200\324\252\200\324\252"
  "\200\324\252\200\324\324\252\324\252\200\324\252\200\324\252\200\324\252"
  "\200\324\252\200\252\252\200\324\252\200\324\252\200\324\252\200\324\252"
  "\200\324\252\200\324\252\200\252\200U\324\252\200\324\252\200\252\200U\252"
  "\200U\324\200\200\324\252\200\324\252\200\324\252\200\324\252\200\324\252"
[...]


ADMIN edita: phpbb no soporta código tan extenso (ver la
posibilidad de subir el código a otro servidor y adjuntar aquí
un link).
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor lacabra25 » Sab Abr 26, 2008 10:02 am

Otra cosa que casi se me olvidava, en la funcion para crear la superficie con la imagen a partir de la estructura no se le indica si quiero que la cree en la memoria principal o en la memoria de video, ¿donde la crea?, ¿como podria elegir que la creara en la principal o en la de video segun me interese?

Y ¿con lo interesante que es esa funcion para no tener que distribuir junto con el programa un monton de archivos de imagen, sino todo junto en el .exe; como es que en ningun manual de SDL (o por lo menos de los que yo llevo leidos) aparece esta funcion?

Y gracias por todo. :D
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor hugoruscitti » Sab Abr 26, 2008 10:29 pm

lacabra25 escribió:Y ¿con lo interesante que es esa funcion para no tener que distribuir junto con el programa un monton de archivos de imagen, sino todo junto en el .exe; como es que en ningun manual de SDL (o por lo menos de los que yo llevo leidos) aparece esta funcion?


No se trata mucho esa función porque no es demasiado relevante,
imagina que el objetivo de usar SDL es poder hacer juegos o
emuladores, se pierde mucho tiempo tratando de ocultar recursos
de juego... y no se gana demasiado, ¿realmente importa si el
juego tiene muchos archivos .png o .txt.?, no, para nada.

En todo caso se puede usar una biblioteca para colocar todos los
recursos en un archivo bajo compresión (como hacen Quake,
Doom o similares). Usando SDL resulta sencillo usar zziplib [1]

Como programador de juegos tu principal objetivo es hacer el juego, no
me gustaría ver que abandones esto por dedicar todo tu tiempo
a detalles menores. Te recomiendo usar directamente archivos .png o
.bmp, cuando ganes confianza haciendo juegos vas a poder avanzar
en otras cosas de menos importancia. Imagina que tu juego tiene 50
imágenes, ¿vas a transladar todo eso a matrices?. ¿y si luego necesitas
actualizar alguna imagen?. Conviene usar archivos de imágenes, todos
hacen lo mismo, por algo es.

Buena suerte.

[1] - http://zziplib.sourceforge.net/
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Notapor lacabra25 » Dom Abr 27, 2008 11:14 am

hugoruscitti escribió:En todo caso se puede usar una biblioteca para colocar todos los
recursos en un archivo bajo compresión (como hacen Quake,
Doom o similares). Usando SDL resulta sencillo usar zziplib [1]

Como programador de juegos tu principal objetivo es hacer el juego, no
me gustaría ver que abandones esto por dedicar todo tu tiempo
a detalles menores.
[1] - http://zziplib.sourceforge.net/


La pagina de zziplib ya la he visto, pero esta en ingles y me preguntaba si sabes de algun manual, algun pdf, en español que explique tanto como instalarla como el modo de usarla.

Y no abandono la programacion del videojuego en si por este detalle, es la curiosidad de como hacian aplicaciones que no traian ningun archivo mas que el .exe sin ninguna imagen.
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)


Volver a Sobre las bibliotecas multimedia

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados

cron