Más sobre animaciones y parpadeos molestos

01/02/2005 - 15:53 por Zephryn Xirdal | Informe spam
Hola otra vez.

He estado probando el asunto del doble buffer para realizar una animación,
pero me sigue parpadeando la pantalla (bastante menos, pero parpadea,
incluso cuando invalido sólo el área de la animación).

El mapa de bits ocupa 400x400 píxeles (de los cuales animo un rectángulo de
unos 40x400), no creo que sea un tamaño excesivo para que todo parpadee...
sobre todo viendo a otros programas que van de muerte...

Ya sé que tengo la opción del directx, pero lo veo como matar moscas a
cañonazos...

El código encargado de componer el mapa de bits es:



m_gameAnimatrix++;

if(m_gameAnimatrix>15)

m_gameAnimatrix=0;

m_dblBuffGraphic=Graphics.FromImage(m_dblBuffBitmap);

for(int i=0;i<m_config.HorzBalls;i++)

for(int j=0;j<m_config.VertBalls;j++)

{

Rectangle r=new Rectangle(m_gameAnimatrix*40,m_gameMatrix[i,j]*40,40,40);

m_dblBuffGraphic.DrawImage(m_bitmap,i*40,j*40,r,GraphicsUnit.Pixel);

}

m_dblBuffGraphic.Dispose();

m_pnlGame.Invalidate(false);

Luego, en el método de pintado, ejecuto:

if(m_gameStarted)

e.Graphics.DrawImage(m_dblBuffBitmap,0,0);


EL código real está dentro de los dos for, que componen una tesela de 10x10
mapas de bits dependiendo del índice de m_gameAnimatrix. m_bitmap contiene
los frames de las animaciones, de modo que es de ahí de donde se saca cada
pedazo de bitmap, y m_gameMatrix es la matriz que me indica qué tesela va en
cada sitio.

La cuestión es que el parpadeo sigue apareciendo, pero esta vez en lugar de
ver barrido del pintado, se ve como un molesto parpadeo (al estilo de una
lámpara estroboscópica).

Lo curioso del asunto es que el efecto estroboscópico sigue apareciendo
incluso si se invalida un área de 10x10 pixeles (claro está, efecto aparece
"dentro" de ese área, fuera de ella todo está normal).

Supongo que estoy haciendo algo mal, porque hace tiempo tuve que hacer algo
parecido con el GDI (sin plus y en c++) y no tenía esos efectos tan malos, y
no utilizaba ni doble buffer ni nada, y antes de pintar tenía que hacer un
buen número de operaciones antes de dibujar cada uno de los posibles 256
elementos, en un área de 1600x1200.

Todo avaro tiene un hijo gastador.
**** Powered by zxFortunes: http://sourceforge.net/projects/zxfortune

Preguntas similare

Leer las respuestas

#1 Marino Posadas
03/02/2005 - 01:43 | Informe spam
Hola

Hasta el fin de semana no puedo ayudarte más (estoy de viaje), pero echate
un vistazo al funcionamiento del API BitBlt()

Saludos cordiales,
Marino Posadas
MVP - Visual C#
MCSD, MCAD, MCT
Alhambra-Eidos

"Zephryn Xirdal" escribió en el
mensaje news:%
Hola otra vez.

He estado probando el asunto del doble buffer para realizar una animación,
pero me sigue parpadeando la pantalla (bastante menos, pero parpadea,
incluso cuando invalido sólo el área de la animación).

El mapa de bits ocupa 400x400 píxeles (de los cuales animo un rectángulo
de
unos 40x400), no creo que sea un tamaño excesivo para que todo parpadee...
sobre todo viendo a otros programas que van de muerte...

Ya sé que tengo la opción del directx, pero lo veo como matar moscas a
cañonazos...

El código encargado de componer el mapa de bits es:



m_gameAnimatrix++;

if(m_gameAnimatrix>15)

m_gameAnimatrix=0;

m_dblBuffGraphic=Graphics.FromImage(m_dblBuffBitmap);

for(int i=0;i<m_config.HorzBalls;i++)

for(int j=0;j<m_config.VertBalls;j++)

{

Rectangle r=new Rectangle(m_gameAnimatrix*40,m_gameMatrix[i,j]*40,40,40);

m_dblBuffGraphic.DrawImage(m_bitmap,i*40,j*40,r,GraphicsUnit.Pixel);

}

m_dblBuffGraphic.Dispose();

m_pnlGame.Invalidate(false);

Luego, en el método de pintado, ejecuto:

if(m_gameStarted)

e.Graphics.DrawImage(m_dblBuffBitmap,0,0);


EL código real está dentro de los dos for, que componen una tesela de
10x10 mapas de bits dependiendo del índice de m_gameAnimatrix. m_bitmap
contiene los frames de las animaciones, de modo que es de ahí de donde se
saca cada pedazo de bitmap, y m_gameMatrix es la matriz que me indica qué
tesela va en cada sitio.

La cuestión es que el parpadeo sigue apareciendo, pero esta vez en lugar
de ver barrido del pintado, se ve como un molesto parpadeo (al estilo de
una lámpara estroboscópica).

Lo curioso del asunto es que el efecto estroboscópico sigue apareciendo
incluso si se invalida un área de 10x10 pixeles (claro está, efecto
aparece "dentro" de ese área, fuera de ella todo está normal).

Supongo que estoy haciendo algo mal, porque hace tiempo tuve que hacer
algo parecido con el GDI (sin plus y en c++) y no tenía esos efectos tan
malos, y no utilizaba ni doble buffer ni nada, y antes de pintar tenía que
hacer un buen número de operaciones antes de dibujar cada uno de los
posibles 256 elementos, en un área de 1600x1200.

Todo avaro tiene un hijo gastador.
**** Powered by zxFortunes: http://sourceforge.net/projects/zxfortune



Respuesta Responder a este mensaje
#2 Zephryn Xirdal
03/02/2005 - 15:33 | Informe spam
Lo acabo de resolver gracias a una búsqueda en los grupos de c# en inglés
relativa a otra cosa...

Es mucho más fácil:

El parpadeo con el doble buffer se debe a que el control pinta primero en
fondo y luego el gráfico. Parece ser que hay un evento conocido como
OnPaintBackground que se encarga de pintar primero el fondo... El problema
es que en la documentación no está nada claro, o al menos yo no he podido
encontrarlo de forma clara (Ahora que lo sé, me aparece en todos lados)...

Pensando en cómo hacerlo mejor, decidí pintar en un panel de modo que si
añado algo a la ficha, pues puedo hacerlo con un nuevo panel y así no
interfiero en nada... Al parecer, cuando se invalida el panel, se pinta
primero el fondo del mismo, y luego se dispara el OnPaint.

Pero lo bueno del asunto no es eso, lo interesante ¡es que las propias
funciones de pintado del GDI+ soportan internamente el doble buffer! Y
también puedes desactivar el pintado automático del fondo. Las dos cosas
juntas se pueden hacer mediante una llamada al método

SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint,true);

El problema es que ese método está oculto en un panel, pero no en la propia
ficha, por lo que he quitado el panel y ahora pinto directamente en la
ficha... sin parpadeos, sin efecto estroboscópico y a una velocidad
medianamente aceptable (menos de 50 ms de timer impiden el pintado).

Simplemente genial.

De todas formas, si necesitase pintar en un panel supongo que podría heredar
un nuevo control del Panel original y modificar esas propiedades...

PS: huys huys, todo esto es un candidato directo para un articulillo en
panoramabox o en codeproject... Me pido la exclusiva.

La página que lee el autor cuando recibe su libro tiene el error más
garrafal.
**** Powered by zxFortunes: http://sourceforge.net/projects/zxfortune
"Marino Posadas" escribió en el mensaje
news:%
Hola

Hasta el fin de semana no puedo ayudarte más (estoy de viaje), pero echate
un vistazo al funcionamiento del API BitBlt()

Saludos cordiales,
Marino Posadas
MVP - Visual C#
MCSD, MCAD, MCT
Alhambra-Eidos

"Zephryn Xirdal" escribió en el
mensaje news:%
Hola otra vez.

He estado probando el asunto del doble buffer para realizar una
animación,
pero me sigue parpadeando la pantalla (bastante menos, pero parpadea,
incluso cuando invalido sólo el área de la animación).

El mapa de bits ocupa 400x400 píxeles (de los cuales animo un rectángulo
de
unos 40x400), no creo que sea un tamaño excesivo para que todo
parpadee...
sobre todo viendo a otros programas que van de muerte...

Ya sé que tengo la opción del directx, pero lo veo como matar moscas a
cañonazos...

El código encargado de componer el mapa de bits es:



m_gameAnimatrix++;

if(m_gameAnimatrix>15)

m_gameAnimatrix=0;

m_dblBuffGraphic=Graphics.FromImage(m_dblBuffBitmap);

for(int i=0;i<m_config.HorzBalls;i++)

for(int j=0;j<m_config.VertBalls;j++)

{

Rectangle r=new Rectangle(m_gameAnimatrix*40,m_gameMatrix[i,j]*40,40,40);

m_dblBuffGraphic.DrawImage(m_bitmap,i*40,j*40,r,GraphicsUnit.Pixel);

}

m_dblBuffGraphic.Dispose();

m_pnlGame.Invalidate(false);

Luego, en el método de pintado, ejecuto:

if(m_gameStarted)

e.Graphics.DrawImage(m_dblBuffBitmap,0,0);


EL código real está dentro de los dos for, que componen una tesela de
10x10 mapas de bits dependiendo del índice de m_gameAnimatrix. m_bitmap
contiene los frames de las animaciones, de modo que es de ahí de donde se
saca cada pedazo de bitmap, y m_gameMatrix es la matriz que me indica qué
tesela va en cada sitio.

La cuestión es que el parpadeo sigue apareciendo, pero esta vez en lugar
de ver barrido del pintado, se ve como un molesto parpadeo (al estilo de
una lámpara estroboscópica).

Lo curioso del asunto es que el efecto estroboscópico sigue apareciendo
incluso si se invalida un área de 10x10 pixeles (claro está, efecto
aparece "dentro" de ese área, fuera de ella todo está normal).

Supongo que estoy haciendo algo mal, porque hace tiempo tuve que hacer
algo parecido con el GDI (sin plus y en c++) y no tenía esos efectos tan
malos, y no utilizaba ni doble buffer ni nada, y antes de pintar tenía
que hacer un buen número de operaciones antes de dibujar cada uno de los
posibles 256 elementos, en un área de 1600x1200.

Todo avaro tiene un hijo gastador.
**** Powered by zxFortunes: http://sourceforge.net/projects/zxfortune







Respuesta Responder a este mensaje
#3 Marino Posadas
04/02/2005 - 19:35 | Informe spam
Ah! pues muy interesante, ¡sí señor!.
Gracias por la info.


Saludos cordiales
Marino Posadas
MVP Visual C#

www.ElAveFenix.net

"Zephryn Xirdal" escribió en el
mensaje news:
Lo acabo de resolver gracias a una búsqueda en los grupos de c# en inglés
relativa a otra cosa...

Es mucho más fácil:

El parpadeo con el doble buffer se debe a que el control pinta primero en
fondo y luego el gráfico. Parece ser que hay un evento conocido como
OnPaintBackground que se encarga de pintar primero el fondo... El problema
es que en la documentación no está nada claro, o al menos yo no he podido
encontrarlo de forma clara (Ahora que lo sé, me aparece en todos lados)...

Pensando en cómo hacerlo mejor, decidí pintar en un panel de modo que si
añado algo a la ficha, pues puedo hacerlo con un nuevo panel y así no
interfiero en nada... Al parecer, cuando se invalida el panel, se pinta
primero el fondo del mismo, y luego se dispara el OnPaint.

Pero lo bueno del asunto no es eso, lo interesante ¡es que las propias
funciones de pintado del GDI+ soportan internamente el doble buffer! Y
también puedes desactivar el pintado automático del fondo. Las dos cosas
juntas se pueden hacer mediante una llamada al método

SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint,true);

El problema es que ese método está oculto en un panel, pero no en la
propia ficha, por lo que he quitado el panel y ahora pinto directamente en
la ficha... sin parpadeos, sin efecto estroboscópico y a una velocidad
medianamente aceptable (menos de 50 ms de timer impiden el pintado).

Simplemente genial.

De todas formas, si necesitase pintar en un panel supongo que podría
heredar un nuevo control del Panel original y modificar esas
propiedades...

PS: huys huys, todo esto es un candidato directo para un articulillo en
panoramabox o en codeproject... Me pido la exclusiva.

La página que lee el autor cuando recibe su libro tiene el error más
garrafal.
**** Powered by zxFortunes: http://sourceforge.net/projects/zxfortune
"Marino Posadas" escribió en el mensaje
news:%
Hola

Hasta el fin de semana no puedo ayudarte más (estoy de viaje), pero
echate un vistazo al funcionamiento del API BitBlt()

Saludos cordiales,
Marino Posadas
MVP - Visual C#
MCSD, MCAD, MCT
Alhambra-Eidos

"Zephryn Xirdal" escribió en el
mensaje news:%
Hola otra vez.

He estado probando el asunto del doble buffer para realizar una
animación,
pero me sigue parpadeando la pantalla (bastante menos, pero parpadea,
incluso cuando invalido sólo el área de la animación).

El mapa de bits ocupa 400x400 píxeles (de los cuales animo un rectángulo
de
unos 40x400), no creo que sea un tamaño excesivo para que todo
parpadee...
sobre todo viendo a otros programas que van de muerte...

Ya sé que tengo la opción del directx, pero lo veo como matar moscas a
cañonazos...

El código encargado de componer el mapa de bits es:



m_gameAnimatrix++;

if(m_gameAnimatrix>15)

m_gameAnimatrix=0;

m_dblBuffGraphic=Graphics.FromImage(m_dblBuffBitmap);

for(int i=0;i<m_config.HorzBalls;i++)

for(int j=0;j<m_config.VertBalls;j++)

{

Rectangle r=new
Rectangle(m_gameAnimatrix*40,m_gameMatrix[i,j]*40,40,40);

m_dblBuffGraphic.DrawImage(m_bitmap,i*40,j*40,r,GraphicsUnit.Pixel);

}

m_dblBuffGraphic.Dispose();

m_pnlGame.Invalidate(false);

Luego, en el método de pintado, ejecuto:

if(m_gameStarted)

e.Graphics.DrawImage(m_dblBuffBitmap,0,0);


EL código real está dentro de los dos for, que componen una tesela de
10x10 mapas de bits dependiendo del índice de m_gameAnimatrix. m_bitmap
contiene los frames de las animaciones, de modo que es de ahí de donde
se saca cada pedazo de bitmap, y m_gameMatrix es la matriz que me indica
qué tesela va en cada sitio.

La cuestión es que el parpadeo sigue apareciendo, pero esta vez en lugar
de ver barrido del pintado, se ve como un molesto parpadeo (al estilo de
una lámpara estroboscópica).

Lo curioso del asunto es que el efecto estroboscópico sigue apareciendo
incluso si se invalida un área de 10x10 pixeles (claro está, efecto
aparece "dentro" de ese área, fuera de ella todo está normal).

Supongo que estoy haciendo algo mal, porque hace tiempo tuve que hacer
algo parecido con el GDI (sin plus y en c++) y no tenía esos efectos tan
malos, y no utilizaba ni doble buffer ni nada, y antes de pintar tenía
que hacer un buen número de operaciones antes de dibujar cada uno de los
posibles 256 elementos, en un área de 1600x1200.

Todo avaro tiene un hijo gastador.
**** Powered by zxFortunes: http://sourceforge.net/projects/zxfortune











email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida