Problema con generacion de mascaras

Si tienes alguna duda y crees que alguien podría resolverla, ponla aquí. || If you have any doubt about programming, post it here.

Moderador: CEZ

Responder
Avatar de Usuario
santoto
8 bits
8 bits
Mensajes: 13
Registrado: 23 Jun 2007 15:26

Problema con generacion de mascaras

Mensaje por santoto »

Hola estoy haciendo una pequeña libreria para manejar los sprites con SDL y dev-c++, pero al tratar de implementar el codigo para generar una mascara de bits del sprite el programa no anda, he mirado y re mirado el codigo pero no se q pasa aca les dejo el codigo:

main.cpp

Código: Seleccionar todo

/***************************************************************************
 Ejemplo5_1
 (C) 2003 by Alberto Garcia Serrano
 Programación de videojuegos con SDL
 ***************************************************************************/

#include <stdio>
#include <stdlib>
#include <SDL>
#include <SDL>
#include "sprite.h"


SDL_Surface *screen;
Frame fnave;
Frame fmalo;
Sprite nave(1);
Sprite malo(1);
SDL_Rect rectangulo;
int done=0;


// estructura que contiene la información
// de nuestro avión
struct minave {
	int x,y;
} jugador;


// Estructura que contiene información
// del avión enemigo
struct naveenemiga {
	int x,y;		
} enemigo;




// Dibuja los esprites en la pantalla
void DrawScene(SDL_Surface *screen) {

	// borramos el avión dibujado
	// en el frame anterior
	rectangulo.x=nave.VerX();
	rectangulo.y=nave.VerY();
	rectangulo.w=nave.VerAncho();
	rectangulo.h=nave.VerAlto();
	SDL_FillRect(screen,&rectangulo,SDL_MapRGB(screen->format,0,0,0));

	// dibuja avión
	nave.CargarX(jugador.x);
	nave.CargarY(jugador.y);
	nave.Dibujar(screen);


	// Dibuja enemigo
	malo.CargarX(enemigo.x);
	malo.CargarY(enemigo.y);
	malo.Dibujar(screen);
				
	// ¿ha colisionado con la nave?
	if (malo.ColisionCajas(nave) == TRUE) {
		done=1;
	}

	// Mostramos todo el frame
	SDL_Flip(screen);
}


// Inicializamos estados
void inicializa() {
	jugador.x=300;
	jugador.y=300;
	enemigo.x=100;
	enemigo.y=100;
}


void finaliza() {

	// finalizamos los sprites
	nave.Finalizar();
	malo.Finalizar();
	
}



// Preparamos los esprites
int InitSprites() {

	fnave.Cargar("cuadro2.png");
	//fnave.Mascara(); // Aqui se genera el error
	nave.AgregarFrame(fnave);

	fmalo.Cargar("cuadro1.png");
	malo.AgregarFrame(fmalo);

	return 0;
}



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

SDL_Event event;
Uint8 *keys;


	if (SDL_Init(SDL_INIT_VIDEO) <0> 0)) {jugador.y=jugador.y-(1);}
		if ((keys[SDLK_DOWN]) && (jugador.y <460> 0)) {jugador.x=jugador.x-(1);}
		if ((keys[SDLK_RIGHT]) && (jugador.x < 620)) {jugador.x=jugador.x+(1);}


		while (SDL_PollEvent(&event)) {
					
			if (event.type == SDL_QUIT) {done=1;}
					
			if (event.type == SDL_KEYDOWN) {
						
				if (event.key.keysym.sym == SDLK_ESCAPE) {
					done=1;
				} 
					
			}
									
		}
	}
			

	finaliza();

	return 0;
}

sprite.h

Código: Seleccionar todo

/*----------------------------------------------------------------
|  Autor: Exequiel Lares                                          |
|  Fecha: 26-06-2007                              Versión: 1.0    |
|-----------------------------------------------------------------|
|  Descripción del Programa:  libreria para manejo de sprites     |
|                             Archivo de cabecera                 |
| ----------------------------------------------------------------*/


#ifndef SPRITE_H_
#define SPRITE_H_

#define TRUE 1
#define FALSE 0

#include <SDL>



typedef unsigned long word;

typedef struct {
        int LongX;
        int LongY;
        int Words;
        word** MaskData;} mask;



class Frame{
      public:
             
             mask *m;
             SDL_Surface *img;
             void Cargar(char *path);
             void Liberar();
             int DestrMascara (mask *Mascara);
             void Mascara();
             void InitMascara (SDL_Surface *BitMap, mask *Mascara);
             mask * CreaMascara (SDL_Surface *BitMap);
             };
             
class Sprite{
      private:
              int x , y, estado, nframes, cont;
      public:
             Frame *sprite;
             Sprite();
             Sprite(int nf);
             void Finalizar();
             void AgregarFrame(Frame frame);
             void ElegirFrame(int nf);
             int CantFrames(){return cont;}
             void CargarX(int xx){x=xx;}
             void CargarY(int yy){y=yy;}
             void IncrementaX(int c){x+=c;}
             void IncrementaY(int c){y+=c;}
             int VerX(){return x;}
             int VerY(){return y;}
             int VerAncho(){return sprite[estado].img->w;}
             int VerAlto(){return sprite[estado].img->h;}
             void Dibujar(SDL_Surface *Superficie);
             bool ColisionCajas(Sprite sp);
             bool ColisionPixel(Sprite sp);
             
             
};

SDL_Color getPixel(SDL_Surface *screen, int x, int y);


#endif /* SPRITE_H_ */

sprite.cpp

Código: Seleccionar todo

/*----------------------------------------------------------------
|  Autor: Exequiel Lares                                          |
|  Fecha: 26-06-2007                              Versión: 1.0    |
|-----------------------------------------------------------------|
|  Descripción del Programa:  libreria para manejo de sprites     |
|                             con SDL                             |
| ----------------------------------------------------------------*/

#include <SDL>
#include <SDL>
#include "sprite.h"


//Metodos de la clase Frame

void Frame::Cargar(char *path)
{
     img=IMG_Load(path); //Cargamos la imagen
     
     SDL_SetColorKey(img, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB(img->format,255,0,0)); // Seleccionamos el color transparente = ROJO 
     
     img=SDL_DisplayFormat(img); //Cambia el formato de la imagen por el formato de la pantalla (Ahorra tiempo) 

     
}

void Frame::Liberar()
{
     SDL_FreeSurface(img); //Libera la memoria, borra la superficie
}


mask * Frame::CreaMascara (SDL_Surface *BitMap)
{   
      int Tamano=sizeof(word)*8; 
      mask *Retorno;
      int b1;
      Retorno = new mask;
      Retorno->LongX = BitMap->w;
      Retorno->LongY = BitMap->h;
      Retorno->Words = Retorno->LongX / Tamano;
      if (Retorno->LongX % Tamano != 0) Retorno->Words += 1;
      Retorno->MaskData = new word*[Retorno->LongY];
      for (b1 = 0; b1 <Retorno>LongY; b1++)
      Retorno->MaskData[b1] = new word [Retorno->LongX];
          
      return Retorno;
}

void Frame::InitMascara (SDL_Surface *BitMap, mask *Mascara)
 {
    int Tamano=sizeof(word)*8; 
    int b1,b2,b3;
    
    for (b1 = 0; b1 <Mascara>LongY; b1++)
        for (b2 = 0; b2 <Mascara>Words; b2++)
            Mascara->MaskData[b1][b2] = 0;
            
    for (b1 = 0; b1 <Mascara>LongY; b1++)
        for (b2 = 0; b2 <Mascara>Words; b2++)
            for (b3 = 0; b3 <Tamano>MaskData[b1][b2]+= ( 1 <<Mascara>LongX - b2));
                }
}


int Frame::DestrMascara (mask *Mascara) 
{
    int b1;
    if (!Mascara) return -1;
    for (b1 = 0; b1 <Mascara>LongY; b1++)
        delete[] Mascara->MaskData[b1];
    delete[] Mascara->MaskData;
    delete Mascara;
    if (Mascara) return 1;
    return 0;
}

void Frame::Mascara()
{
     InitMascara(img, m);
     m=CreaMascara(img);
}
     



//Metodos de la clase Sprite

Sprite::Sprite(int nf)
{
     sprite=new Frame[nf];
     nframes=nf;
     cont=0;
}
     
Sprite::Sprite()
{
     int nf=1;
     sprite=new Frame[nf];
     nframes=nf;
     cont=0;
}

void Sprite::Finalizar()
{
     int i;
     for(i=0; i<=nframes-1; i++)
              sprite[i].Liberar();              
}
          
void Sprite::AgregarFrame(Frame frame)
{
     if(cont<nframes){
                      sprite[cont]=frame;
                      cont++;
                      }
}

void Sprite::ElegirFrame(int nf)
{
     if(nf<nframes>x2) && ((y1+h1)>y2) && ((x2+w2)>x1) && ((y2+h2)>y1))
        return true;
        else
        return false;
}             
     
/*bool Sprite::ColisionPixel(Sprite sp)
{
    
      
                         
}

*/    


SDL_Color getPixel(SDL_Surface *screen, int x, int y)
{

SDL_Color color;
Uint32 col;

char *buffer=(char *) screen->pixels;       // Determinamos posición de inicio
buffer+=screen->pitch*y;                    // Calculamos offset para y
buffer+=screen->format->BytesPerPixel*x;    // Calculamos offset para x
memcpy(&col, buffer, screen->format->BytesPerPixel);      // Obtenemos el pixel
SDL_GetRGB(col, screen->format, &color.r, &color.g, &color.b);         // Descomponemos el color

return color;                   
}     

el problema surge cuando llamo al metodo Mascara de la clase Frame, espero q puedan ver q es lo q pasa.

Saludos y espero ansiosamente respuestas 8)
Avatar de Usuario
na_th_an
256 bits
256 bits
Mensajes: 11874
Registrado: 22 Abr 2005 13:25
Contactar:

Mensaje por na_th_an »

Ufff, es que a mí con el C++ me entran sarpullidos :lol: a ver si viene Ben y te echa un cable (o a ver si aprendo el "++" de C de una @#!! vez :lol:)
Avatar de Usuario
santoto
8 bits
8 bits
Mensajes: 13
Registrado: 23 Jun 2007 15:26

Mensaje por santoto »

he estado probando el codigo de a trozos y he descubierto que el problema se origina cuando se ejecuta el siguiente codigo:

Código: Seleccionar todo

SDL_Color color;
color=getPixel(BitMap, b2, b1);
if(!((color.r==255)&&(color.g==0)&&(color.b==0)))
 // color transparente es rojo
    Mascara->MaskData[b1][b2]+= ( 1 <<Mascara>LongX - b2));
Y creo q se origina en la funcion getPixel():

Código: Seleccionar todo

SDL_Color getPixel(SDL_Surface *screen, int x, int y)
{

SDL_Color color;
Uint32 col;

char *buffer=(char *) screen->pixels;       // Determinamos posición de inicio
buffer+=screen->pitch*y;                    // Calculamos offset para y
buffer+=screen->format->BytesPerPixel*x;    // Calculamos offset para x
memcpy(&col, buffer, screen->format->BytesPerPixel);      // Obtenemos el pixel
SDL_GetRGB(col, screen->format, &color.r, &color.g, &color.b);         // Descomponemos el color

return color;                   
} 
Asi que si alguien tiene una idea de porque no anda se lo agradeceria mucho. 8)
Avatar de Usuario
AugustoRuiz
128 bits
128 bits
Mensajes: 1726
Registrado: 24 May 2006 08:35
Ubicación: Madrid
Contactar:

Mensaje por AugustoRuiz »

Asegúrate de que b1 y b2 están dentro de valores correctos. Es decir, si b1 son las filas y b2 son las columnas, comprueba que b1 va de 0 a filas -1 y b2 va de 0 a columnas -1. Y que estás siendo consistente en su uso (es decir, b1 siempre para filas y b2 siempre para columnas).

Saludos,
Avatar de Usuario
santoto
8 bits
8 bits
Mensajes: 13
Registrado: 23 Jun 2007 15:26

Mensaje por santoto »

:D :D :D :D :D Lo he resuelto habia cometido un grave error miren puse esto:

Código: Seleccionar todo

void Frame::Mascara()
{
     InitMascara(img, m);
     m=CreaMascara(img);
}
y tenia q ponerlo asi:

Código: Seleccionar todo

void Frame::Mascara()
{
    m=CreaMascara(img);     
    InitMascara(img, m); 
}
pasaba que creaba la mascara sin haberla iniciado antes :oops: :oops: :oops: , lo mas extraño de todo es que no me daba ningun error, simplemente no arrancaba.

Bueno ahora podre continuar con el desarrollo, lastima q tendre q esperar una semana :(. Tengo que estudiar para los parciales de la Uni :x pero bueno q va a ser. Saludos y gracias por su ayuda, pronto estare consultando por nuevos problemas. Nos estamos leyendo 8).
Avatar de Usuario
santoto
8 bits
8 bits
Mensajes: 13
Registrado: 23 Jun 2007 15:26

Mensaje por santoto »

Bueno la alegria duro poco, ahora directamente no detecta la colision o la detecta mal o en algunos lugares si y otros no, debe haber un problema con la creacion de la mascara o en la comparacion de los bits, les dejo el archivo con las imagenes q uso y si tienen tiempo mirenlo (es el mismo q esta aca cambiando la funcion Mascara()), ahora tengo q estudiar :( pero estare pendiente de sus respuestas.

Necesitan tener instalada la SDL.
No tienes los permisos requeridos para ver los archivos adjuntos a este mensaje.
Avatar de Usuario
Benway
Site Admin
Site Admin
Mensajes: 9241
Registrado: 24 Dic 2005 10:18
Ubicación: Madrid
Contactar:

Mensaje por Benway »

A ver si tengo un rato y lo miro, que ando fatal de tiempo (y eso que estoy en paro :lol: que a partir de julio no quiero ni imaginarlo :lol:) y de SDL controlo Nada / muy poco...

Pero vamos, no te desesperes... que el gustito que te va a dar cuando lo consigas... ;) (Yo con el Horacio Esquiador me tiré más de un mes para esto de las colisiones :?)
Un saludo.
Imagen - Imagen - Imagen
Avatar de Usuario
santoto
8 bits
8 bits
Mensajes: 13
Registrado: 23 Jun 2007 15:26

Mensaje por santoto »

No hay problema, estuve buscando toda la noche y me encontre con una libreria para allegro que maneja los sprites y controla las colisiones por los metodos de bounding box y pixel perfect, es por eso que como recien me iniciaba conla SDL he decidido usar Allegro en lugar de la otra, y estoy mirando la libreria para crear a partir de ella una libreria propia, pero por ahora con eso me basta.

Por si la quieren, la pueden descargar de aqui http://ibaldo.codigolibre.net/ppcol.php?setLenguaje=ES

eso si tienen que cambiarle algunas cosillas para q sea compatible con allegro 4.2 y bue ya que estamos se la dejo aca corregida y compilando perfectamente (al menos con el dev-c++).

Y tambien aprovecho para decirles si pueden pasarme links con tutoriales de allegro en español.

Nos Leemos 8)

PD: Si descubris cual es el problema avisame asi me saco las dudas, pero si no tenes tiempo deja no te preocupes.
No tienes los permisos requeridos para ver los archivos adjuntos a este mensaje.
Avatar de Usuario
Benway
Site Admin
Site Admin
Mensajes: 9241
Registrado: 24 Dic 2005 10:18
Ubicación: Madrid
Contactar:

Mensaje por Benway »

Una cosita que puedes hacer es una prueba de la máscara para ver si está bien hecha, y así sabes si el error lo tienes al hacerla o al compararla.

Mira cómo lo hago yo:

Código: Seleccionar todo

/* //  ******************************************************* Prueba de máscara
     mask *Prueba;
     Prueba = MSprites [43][0][0][0];

     for (n = 0; n < Prueba->LongY; n++)
         for (m = 0; m < Prueba->Words; m++)
             for (o = 0; o < Tamano; o++)
                 if (Prueba->MaskData[n][m] & 0x0001 << o)
                    textout_ex (screen, font, "*",(m * Tamano + o)* 4, 4 * n, 
                               makecol(255,255,255),0);

Si te sale bien dibujada, entonces ya miro con lupa el código de las colisiones ;) (échale un ojo al post que he puesto en el hilo del tutorial, porque quizá pueda ayudarte ;))
Un saludo.
Imagen - Imagen - Imagen
Responder