Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Parpadeo En Movimiento

Iniciado por J_F_NASH, 09 de Agosto de 2005, 02:13:21 PM

« anterior - próximo »

J_F_NASH

 He revisado tutoriales en la red y todos ellos terminan explicando el método de animación con las clases CSprite y CFrame. Esto, me parece muy bien como "metodo final" pero necesito saber los pasos básicos.

Yo me he creado 3 funciones (carga, borra y dibuja) que luego llamo en un bucle para mover un grafico:
Citar
MAIN
int x = player.setX(0);
grafico = player.cargaGrafico("player.bmp");

while(salir ==  0){
  ResetTimeBase();
  x += 5;
  player.borrarGrafico(pantalla, negro); //Borro TODA la pantalla.
  player.dibujaGrafico(pantalla, grafico, x, 0);// Dibujo sprite en la nueva posición.
  SDL_Flip(pantalla);//Muestro lo que hay en el buffer (Si, puse DOBLE_BUFFER)

En la animación se produce un casi imperceptible parpadeo ya que borro la pantalla.
Imagino que todo lo que tengo que hacer es borrar el sprite que está en la posición anterior, pero antes de ello mostrar el sprite en la nueva posición (cosa que todavia no he logrado).

Tampoco entiendo por qué al sustituir:
player.borrarGrafico(pantalla, negro); //Borro TODA la pantalla.
Por:
player.borrarGrafico(grafico, negro); //Borro SOLO el gráfico.

No me imprime (o no veo) absolutamente nada. Debería obtener el mismo resultado ¿no?

En fin, ¿sabeis de algún tutorial que explique un movimiento básico con código básico?.


S2.

zupervaca

 para evitar el parpadeo debes de dibujar en otro sitio que no sea directo sobre la memoria de video, no se si al final estas con gdi+ pues por eso te lo digo tan generico, no obstante en todos los sistemas al sistema de evitar el parpadeo se le llama doble buffer (double buffer o double buffering) que consiste en renderizar la escena en una imagen (backbuffer llamado normalmente) y luego pasarlo a la memoria de video (frontbuffer)

sobre la duda que tienes pintar sobre la pantalla y el grafico son cosas diferentes, la pantalla en esta caso creo que es la memoria de video y el grafico es un dibujo que te gustaria pintar en pantalla, si pintas sobre grafico estas borrando en grafico y no en pantalla

si estas co gdi+ te dire que te resultara mas dificil de aprender que opengl o sdl, en principio te recomiendo sdl que es un api que te permitira dibujar sin preocuparte de ciertas cosas que en principio te pueden liar

saludos

seryu

 Dos curiosidades, tienes un TFT? comprueba primero que el haz que dices que deja no sea de tu monitor

y.. grafico supongo que es una superficie SDL que contiene el bitmap del sprite no? si la pintas toda de negro, luego estaras pintando negros sobre la pantalla, y si la pantalla es negra, se vera todo negro  :P


CitarImagino que todo lo que tengo que hacer es borrar el sprite que está en la posición anterior, pero antes de ello mostrar el sprite en la nueva posición (cosa que todavia no he logrado).

Eso esta mal pensado. PRIMERO se borra siempre el sprite, si no habra un momento en el que se vean dos sprites.

Pero como dice zupervaca, se trabaja con un buffer que no es la pantalla directamente, para asi a la pantalla hacerla un volcado directo, envez de ir añadiendo cosas que van a producir efectos graficos indeseados. Lo que pasa es que zupervaca no debe conocer o recordar que esto ya no es msdos y como funciona SDL. No pintas en la pantalla, lo que tienes es una superficie con las caracteristicas de la pantalla, y cuando utilizas el SDL_Flip es cuando se procede a volcar el contenido de esa superficie en la vga. Por lo que en SDL es posible tener un doble buffer y lo que decia zupervaca seria ya un triple buffer, que por otro lado es aun mejor.

Buscate un tutorial de SDL mas decente.

J_F_NASH

 
Cita de: "seryu"Buscate un tutorial de SDL mas decente.
Buscar, busco pero parece que es lo que hay.

Si, estoy con SDL, he dejado aparcado GDI+,... al menos de momento (no me parecía tan chungo como comentas).

Lo del TFT:
Si, en la pantalla del portatil el paradeo es mas evidente que en el monitor (apenas perceptible).


Si explicais un poco mas detalladamente eso de NO dibujar directamente en el buffer de pantalla mejor.
en realidad solo tengo 2 superficies:
1- pantalla (donde le indico la resolucion, buffer,...)
2- grafico



S2.

zupervaca

 efectivamente SDL no lo conozco con lo que no puedo ayudarte

Mandelbrot

 Lo de guardar solo la zona donde se dibujaba un sprite para luego recuperarla y volver a dibujar en la nueva posicion se hacia antiguamente porque el borrar todo el fondo costaba un tiempo valiosisimo con las vga antiguas,  ahora ya no es necesario meterse en ese embolao. Es mejor borrar toda la pantalla de un color o con otra imagen y dibujar los sprites en sus nuevas posiciones.

Si el proceso de borrado y los dibujos se hicieran directamente sobre el buffer que vemos, se notarian los parpadeos y otros efectos odiosos, para evitar esto lo que se hace es que se crean dos buffers identicos paralelos, mientras uno de ellos es mostrado, en el otro se dibuja.  Cuando se llama a SDL_fllip lo que se hace es intercambiar los buffers tan rapido que el ojo ni lo ve, de modo que lo que se habia dibujado en el buffer que permacia oculto ahora es mostrado, y el buffer que veiamos ahora queda oculto y listo para ser borrado y dibujado de nuevo.

Todo esto es trasparente para el programador, porque todas las operaciones de dibujo se efectuan sobre el buffer oculto, que viene determinado por la llamada a SDL_flip.

TheAzazel

 Lo q te dije en otro post... si tienes muchos sprites en pantalla, lo mejor es borrar todo el fondo(o volcar todo el fondo entero que tengas) y luego volver a pintar sprites.

El efecto de parpadeo es normal si no utilizas el doublebuffer... para activarlo en SDL tienes que hacer la llamada a SDL_VideoInit() con SDL_HWSURFACE, SDL_FULLSCREEN y SDL_DOUBLEBUF. Es decir, solo tendras el double buffer en modo pantalla completa y cuando utilices superficies hardware :).

Mas adelante, cuando pilotes mas...decirte que si utilizas glSDL podras tener double buffer tambien en modo ventana :).

Y de todos modos, creo q mi lib te podria ser util, quizas no para programar con ella puesto que quieres aprender pero si para aclarar ideas :)

si tienes cualquier otra cosa, tiralo por aqui... que de SDL y demas...estoy muy puesto jejeje

ah y luego para volcar a screen...debes usar el SDL_Flip!!! (en modo doublebuf)

J_F_NASH

Cita de: "Mandelbrot"si tienes cualquier otra cosa, tiralo por aqui... que de SDL y demas...estoy muy puesto jejeje
Una simple animación que carga el fichero "player.bmp" que se mueve de izquierda a derecha.
Es como la tenía originalmente. ¿Es correcta la forma en que animo el sprite?. Es que ya no se si son mis ojos o que. Porque yo diría que hay un parpadeo aunque muy leve.

No se, gracias en cualquier caso.


Aquí el código (ya se que no es el metodo correcto a seguir, esto simplemente son pruebas):




#ifndef TIEMPO_H_
#define TIEMPO_H_

Uint32 ini_miliSeg, fin_miliSeg, frameTime;

void ResetTimeBase(){
ini_miliSeg = SDL_GetTicks();
}

int CurrentTime(){
fin_miliSeg = SDL_GetTicks();
return fin_miliSeg - ini_miliSeg;
}

#endif


#ifndef INICIASDL_H_
#define INICIASDL_H_

SDL_Surface *pantalla;

int IniciaSDL(int ancho, int alto){

if(SDL_Init(SDL_INIT_VIDEO) < 0){
 printf("No puedo inicializar las SDL: %s\n", SDL_GetError());
 return 1;
}

pantalla = SDL_SetVideoMode(ancho, alto, 24, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN);

if(pantalla == NULL){
 printf("El modo video no lo puedo inicializar, Miguel: %s\n", SDL_GetError());
 return 1;
}

if(TTF_Init() < 0){
 printf("Tio, no se ha podido inicializar las TTF: %s\n", SDL_GetError());
 return 1;
}

atexit(SDL_Quit);
atexit(TTF_Quit);

return 0;
}

#endif



#ifndef SPRITE_H_
#define SPRITE_H_

class SPRITE{
private:
 int posX, posY, veloc;
public:
 int setVeloc(int v){veloc = v;return veloc;};
 int setX(int x){posX = x;return posX;};
 int setY(int y){posY = y;return posY;};
 int teclado(SDL_Event _evento);
 SDL_Surface* cargaGrafico(const char *fichero);
 void borrarGrafico(SDL_Surface *screen, SDL_Color color);
 void dibujaGrafico(SDL_Surface *screen, SDL_Surface *sprite, int x, int y);
};

SDL_Surface* SPRITE::cargaGrafico(const char *fichero){
   SDL_Surface *tmp, *bmp;
Uint32 colorKey;

tmp = SDL_LoadBMP(fichero);

colorKey = SDL_MapRGB(tmp->format, 255, 255, 255);
SDL_SetColorKey(tmp, SDL_SRCCOLORKEY|SDL_RLEACCEL, colorKey);
bmp = SDL_DisplayFormat(tmp);//Transforma la superficie bmp en el formato de pantalla tmp.
SDL_FreeSurface(tmp);

return bmp;
}
void SPRITE::borrarGrafico(SDL_Surface *screen, SDL_Color color){
Uint32 col = SDL_MapRGB(screen->format, color.r, color.g, color.b);
SDL_FillRect(screen, 0, col);
}
void SPRITE::dibujaGrafico(SDL_Surface *screen, SDL_Surface *sprite, int x, int y){
SDL_Rect rect;
rect.x = x;
rect.y = y;
SDL_BlitSurface(sprite, 0, screen, &rect);
}
int SPRITE::teclado(SDL_Event _evento){
if(_evento.type == SDL_KEYDOWN){
 switch(_evento.key.keysym.sym){
  case SDLK_ESCAPE:
   return 1;
   break;
  case SDLK_RIGHT:
   //mover(-1);
   break;
 }
}
return 0;
}

#endif



//MAIN.cpp

//C++ estándar
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//SDL
#include <SDL.h>
#include <SDL_ttf.h>
//Propias
#include "cabeceras\IniciaSDL.h"
#include "cabeceras\tiempo.h"
#include "cabeceras\sprite.h"
#include "cabeceras\tipografia.h"
#include "setup.txt"

//Objetos
SPRITE player;
SDL_Event evento;

SDL_Surface *grafico;
SDL_Color negro;

int velocPlayer = 5;

int main(int argc, char *argv[]){
IniciaSDL(RESOLUCION_X, RESOLUCION_Y);

int x = player.setX(0);
grafico = player.cargaGrafico("player.bmp");

while(player.teclado(evento) == 0){
 ResetTimeBase();
 x += player.setVeloc(velocPlayer);

 player.borrarGrafico(pantalla, negro);
 player.dibujaGrafico(pantalla, grafico, x, 0);
 SDL_Flip(pantalla);

 while(SDL_PollEvent(&evento)){
           player.teclado(evento);
 }

 do{
  frameTime = CurrentTime();
 }while(frameTime < 30);
}

return 0;
}





S2.

J_F_NASH

 Se me olvidaba. otra cosa que noto son "titoncillos" en la velocidad. Como si leyese del HDD o algo asi.


S2.

J_F_NASH

 "titon..."  :D  tironcillos, parones queria decir.



S2.

TheAzazel

 Uhmm....estoy vago :), zipeame todo el codigo y mandamelo a mi email(esta aki abajo indicado) y te lo pruebo a ver q pasa....

he visto una cosa que no debes hacer je, no utilices el modo 24bits en cualquier resolucion...es LENTISIMO!!! o te pones con 16bit(en makinas antiguas) o a 32bits que es mas rapido q 24bits.

y los tironcillos puede ser pq tu mismo has puesto un limitador de velocidad....

do{
 frameTime = CurrentTime();
}while(frameTime < 30);


espero tu code..... si es q con estas dos cosillas no se te soluciona el problemilla...

J_F_NASH

 Efectivamente.
Cambiando de 24 a 16, incluso a 32 bits. La animación ya no pega "tironcillos", tambien va mas rápida.
El limitador de velocidad lo he cambiado a 10 en lugar de a 30. Ya no hay parpadeo alguno.

Buf! que alivio.
Bueno, ya postearé mas problemas.



S2.

TheAzazel

 De todos modos...ese limitador de tiempo no me gusta mucho... buscate por ahi alguno otro o "fabrica" tu uno mejor y de paso q te de medidas de fps, q puedes limitar por fps o por tiempo y demas cosillas....

pos na, q siga la cosa bien :P

Mandelbrot

 Bueno..., realmente el SDL es bastante lento,  se pasa de un movimiento suave al dibujar solo un sprite a uno a saltos al hacer el blit de toda la pantalla, no quiero ni pensar como ira de lento cuando empiecen a rular mogollon de bichos por ahi.

pues nada, mi consejo para todo el mundo es pasar definitivamente ya de GDIs, SDLs, SVGAs y otros apaños que aunque para empezar a probar o como ayuda puntual de alguna funcion en un momento dado estan bien, pero que casi siempre conducen a callejones sin salida si se usa como contexto principal.

Lo mejor es empezar ya a usar OpenGL o DirectX aunque no se tenga mucha idea, eso si... apoyado en librerias y utilidades preparadas para facilitar el uso de estas APIS, solo asi (que yo sepa) se puede aprovechar toda la potencia grafica de los ordenadores actuales.

Podemos usarlo solo para 2D (si queremos evitar el tema del algebra, matrices y demas) y nos beneficiaremos de filtros para difuminar los pixels, mezclas de color para todo tipo de efectos, sombras, rotaciones de sprites, crear zonas donde se permita dibujar o no, z buffer para que queden ocultos los dibujos a partir de su distancia sin tener que dibujar primero los mas alejados,  y un monton de cosas mas que nos permitira hacer practicamente todo lo que se nos ocurra sin limite alguno, mas facilmente de lo que parece y todo ello sin preocuparse de perder velocidad, y con la ventaja de poder añadir objetos 3D facilmente en un futuro.

Asi se hizo commandos, es un juego en 2D usando la tecnologia 3D de las tarjetas, por eso tiene esos graficos tan buenos (aparte de los grafistas claro esta).

Yo personalmente recomiendo para empezar, por su facilidad, OpenGL con la libreria GLUT que trae funciones para simplificar la iniciacion y gestion de la ventana, teclado, timer, etc.. y crear unas sencillas clases de sprites y a partir de ahi ya se puede empezar a hacer muchas cosas al tiempo que se aprenden otras nuevas.

Tambien se puede usar SDL+OpenGL aunque no se como va ni que resultados tiene puesto que no lo he probado. Otra opcion es usar DirectX 9 y las librerias de apoyo D3DX que incluye, da lo mismo, de lo que se trata es de programar la tarjeta grafica como dios manda y todo ello pasa por DirectX o OpenGL.

un saludo a todos y espero haber animado a alguien.

TheAzazel

 
CitarBueno..., realmente el SDL es bastante lento, se pasa de un movimiento suave al dibujar solo un sprite a uno a saltos al hacer el blit de toda la pantalla, no quiero ni pensar como ira de lento cuando empiecen a rular mogollon de bichos por ahi.

Seguimos con los mismos mitos de siempre :P. Te recomiendo que busques un thread en este mismo foro llamado glSDL Benchmark... y veas los resultados y veas lo que puede hacer SDL en comparacion con otras APIs y la utilizacion del glSDL.... vamos, creo que te aclarara un poco la mente.

No es mala idea lo de empezar con opengl+glut pero es mucho mas pesado y sin embargo, SDL tiene mil librerias para hacer todo, multiplataforma y mas que probado... y eso de q es lento... sigue siendo un mito, lo siento.

Los blitters de SDL si es cierto que si lo compilas con Visual C no utiliza muchas mejoras MMX y aun compilandolo con mingw32 por ejemplo, algunas cosillas son mejorables. En mi libreria que es una capa por encima de SDL he retocado todo esto y el volcado via software he conseguido optimizarlo muy mucho dependiendo de la plataforma que utilices(pentium3,pentiumM,pentium4,pentiummmx,k6,k7 y k8) Pero vamos....glSDL rulez!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.