Marzo 17, 2016, 10:10:12 PM Ultima modificación: Marzo 19, 2016, 01:52:00 PM por ian12
Hola nuevamente!

Tengo un problemita. Es que quisiera saber como podría hacer para lograr un efecto de desenfoque alrededor del personaje, como simulando su campo de visión.


Para dar un ejemplo, como tiene el juego LIMBO (no en el fondo, sino alrededor de la view sería). Si lo han jugado lo entenderán sin problemas..




Que se centra el personaje y se mueve con el.

He buscado y solo encuentro efectos de pantalla completa o para simular un efecto de velocidad.. Y no me sirven  :-X


Y bueno, ese es el asunto.. Gracias de antemano  :-[

Por un momento pensé en sugerirte un shader, pero me di cuenta de que utilizas GM8. El efecto se puede lograr con superficies. En este caso el proceso se complica un poco porque la escena se debe dibujar a la superficie y no directamente a la pantalla; el dibujo de las instancias se debe hacer previo al evento Draw y en Draw sólo se debe dibujar la superficie para no dibujar dos veces lo mismo.
En resumen, el procedimiento es este: Primero se crean superficies de diferentes tamaños, pero con la misma relación aspecto, y se activa la interpolación de textura. En cada Step se dibuja la escena a una superficie que tiene un tamaño igual a la view, y se usa una imagen con degradado para hacer transparentes algunas zonas de la superficie. Después la superficie con transparencia se dibuja a escala sobre otras superficies.
[gml]
surface_set_target( sf1 );
draw_background( bg0, 0,0 );
draw_set_blend_mode_ext( bm_zero, bm_src_color );
draw_background( bgGradBlanco, 0,0 );
draw_set_blend_mode( bm_normal );
surface_reset_target();

surface_set_target( sf2 );
draw_surface_ext( sf1, 0,0, 1/2, 1/2, 0,c_white,1 );
surface_reset_target();

surface_set_target( sf4 );
draw_surface_ext( sf2, 0,0, 1/2, 1/2, 0,c_white,1 );
surface_reset_target();
[/gml]
En cada evento Draw se dibuja la superficie con la escena original y encima se dibujan las superficies con transparencia, estiradas para que cubran toda el área de la view. Al final se dibuja un degradado oscuro.
[gml]
if surface_exists( sf2 )
draw_surface_ext( sf2, 0,0, 2,2, 0,c_white,1 );

if surface_exists( sf4 )
draw_surface_ext( sf4, 0,0, 4,4, 0,c_white,1 );

draw_background( bgGradNegro, 0,0 );
[/gml]
El resultado es este

Adjunto el editable

El grado de desenfoque y la cantidad de oscuridad se puede modificar cambiando los degradados, usando más supeficies o dibujando con diferentes niveles de opacidad. Además en Limbo parece que hay una capa extra de ruido, para tener ese efecto granulado.

Cita de: Clamud en Marzo 18, 2016, 04:26:57 PM
Por un momento pensé en sugerirte un shader, pero me di cuenta de que utilizas GM8. El efecto se puede lograr con superficies. En este caso el proceso se complica un poco porque la escena se debe dibujar a la superficie y no directamente a la pantalla; el dibujo de las instancias se debe hacer previo al evento Draw y en Draw sólo se debe dibujar la superficie para no dibujar dos veces lo mismo.
En resumen, el procedimiento es este: Primero se crean superficies de diferentes tamaños, pero con la misma relación aspecto, y se activa la interpolación de textura. En cada Step se dibuja la escena a una superficie que tiene un tamaño igual a la view, y se usa una imagen con degradado para hacer transparentes algunas zonas de la superficie. Después la superficie con transparencia se dibuja a escala sobre otras superficies.
[gml]
surface_set_target( sf1 );
draw_background( bg0, 0,0 );
draw_set_blend_mode_ext( bm_zero, bm_src_color );
draw_background( bgGradBlanco, 0,0 );
draw_set_blend_mode( bm_normal );
surface_reset_target();

surface_set_target( sf2 );
draw_surface_ext( sf1, 0,0, 1/2, 1/2, 0,c_white,1 );
surface_reset_target();

surface_set_target( sf4 );
draw_surface_ext( sf2, 0,0, 1/2, 1/2, 0,c_white,1 );
surface_reset_target();
[/gml]
En cada evento Draw se dibuja la superficie con la escena original y encima se dibujan las superficies con transparencia, estiradas para que cubran toda el área de la view. Al final se dibuja un degradado oscuro.
[gml]
if surface_exists( sf2 )
draw_surface_ext( sf2, 0,0, 2,2, 0,c_white,1 );

if surface_exists( sf4 )
draw_surface_ext( sf4, 0,0, 4,4, 0,c_white,1 );

draw_background( bgGradNegro, 0,0 );
[/gml]
El resultado es este

Adjunto el editable

El grado de desenfoque y la cantidad de oscuridad se puede modificar cambiando los degradados, usando más supeficies o dibujando con diferentes niveles de opacidad. Además en Limbo parece que hay una capa extra de ruido, para tener ese efecto granulado.





Genial, es lo que andaba necesitando.. Muchas gracias!

Aunque, no habrá manera de reemplazar..

Citardraw_background( bg0, 0,0 );

por una función que dibuje lo que se muestra en pantalla en lugar de una imagen fija? Probé de varias formas, incluso con "background_create_from_screen" y "background_create_from_surface"  y lo me muestra todo muy oscuro o me sale es este error..

CitarERROR in
action number 1
of Create Event
for object obj_bloom:

Trying to draw non-existing background.

:(

#3 Marzo 19, 2016, 03:02:40 PM Ultima modificación: Marzo 19, 2016, 03:23:12 PM por elviskelley
Oh usan surface, eso ralentiza el juego, bueno al menos en mi PC, yo solo uso
draw_set_blend_mode( bm_blend);
draw_sprite_ext.... el sprite mancha blanca
draw_set_blend_mode( bm_normal);
detph=10000

luego creo un object con un sprite de cuadro negro de 32x32
y coloco en su End step si usa view o create si no la usa.
image_xscale=(room_width/32);
image_yscale=(room_height/32);
detph=-9999; image_alpha=.7;

Listo el circulo anterior teñira el cuadro negro...
Te lo dejo adjunto...
Atentamente.-
Elvis Kelley
Mi Manual.
Mi canal de Youtube Youtube click aqui
Video tutoriales Game maker

Cita de: elviskelley en Marzo 19, 2016, 03:02:40 PM
Oh usan surface, eso ralentiza el juego, bueno al menos en mi PC, yo solo uso
draw_set_blend_mode( bm_blend);
draw_sprite_ext.... el sprite mancha blanca
draw_set_blend_mode( bm_normal);
detph=10000

luego creo un object con un sprite de cuadro negro de 32x32
y coloco en su End step si usa view o create si no la usa.
image_xscale=(room_width/32);
image_yscale=(room_height/32);
detph=-9999; image_alpha=.7;

Listo el circulo anterior teñira el cuadro negro...
Te lo dejo adjunto...



Gracias, pero la cuestión es, que yo no quiero dibujar la iluminación, eso sería talvez más facil incluso. El asunto es el desefoque alrededor, que si bien se logra con el ejemplo de Clamud, el mismo es para una imagen fija y yo necesito que se vea sin importar la escena, ahora estoy viendo si encuentro la vuelta para que quede..

Es cierto Elvis, usar superficies causa ralentización en algunas máquinas. Para que el juego funcione bien en la mayoría de computadoras, sería bueno poner una opción que desactive los efectos.

Logré hacerlo funcionar con el juego en movimiento, pero estoy haciendo algo que el manual no recomienda: estoy cambiando los lienzos de dibujo dentro del evento Draw, lo bueno es que no parece afectar, el único problema que he encontrado es que si se usa un "foreground" a veces no se ve. El ejemplo está adjunto, el efecto se controla con obBlur, que tiene una profundidad menor a las demás instancias. Creo que exageré con el desenfoque, eso se puede arreglar cambiando los degradados.

#6 Marzo 19, 2016, 11:30:10 PM Ultima modificación: Marzo 19, 2016, 11:33:54 PM por ian12
Cita de: Clamud en Marzo 19, 2016, 05:16:49 PM
Es cierto Elvis, usar superficies causa ralentización en algunas máquinas. Para que el juego funcione bien en la mayoría de computadoras, sería bueno poner una opción que desactive los efectos.

Logré hacerlo funcionar con el juego en movimiento, pero estoy haciendo algo que el manual no recomienda: estoy cambiando los lienzos de dibujo dentro del evento Draw, lo bueno es que no parece afectar, el único problema que he encontrado es que si se usa un "foreground" a veces no se ve. El ejemplo está adjunto, el efecto se controla con obBlur, que tiene una profundidad menor a las demás instancias. Creo que exageré con el desenfoque, eso se puede arreglar cambiando los degradados.



Ah gracias, ahí con ese sí queda genial, lo de los foreground igual ya tenía otro objeto encargado de eso y me corre a 60fps sin problemas, igual es buena idea la opcion de desactivar. Lo único que no me queda claro es porque a pesar de que le cambie los parametros sigue utilizando la view[0]? Es que me gustaría centrarlo en el personaje y no en la view (supongo que tendría que usar otra ya que la view[0] tiene la camara y eso) porque cuando llega al borde se ve borroso y tapa al personaje.. jeje

Usar otra view no es recomendable porque el código se va a complicar mucho.
Hice unas modificaciones al ejemplo para que el desenfoque siempre esté centrado en el personaje. Los degradados se dibujan de acuerdo a la posición relativa del personaje y la vista, y por supuesto, es necesario usar unas imágenes más grandes.

Cita de: Clamud en Marzo 20, 2016, 05:37:23 AM
Usar otra view no es recomendable porque el código se va a complicar mucho.
Hice unas modificaciones al ejemplo para que el desenfoque siempre esté centrado en el personaje. Los degradados se dibujan de acuerdo a la posición relativa del personaje y la vista, y por supuesto, es necesario usar unas imágenes más grandes.

Ahora si, con unos ajustes queda perfecto :3

   Saludos Makeros:


  Muy interesante el tema.
  De hecho tengo pronblemas con una funcionalidad similar que quiero implementar, pero la eficiencia cayó al piso.

  Es una lástima que no pueda ver el código de esos ejemplos por no tener GM 8.1, si alguien pudiera ayudarme...

  Gracias...


Ya lo pasé a gmk, espero que funcione.

Cita de: Clamud en Marzo 29, 2016, 08:37:16 PM
Ya lo pasé a gmk, espero que funcione.

  Muchas gracias makero Clamud. Revisaré el código para compararlo con el mío...  ;D


Oye Clamud, porque será que luego de unos 2 minutos el juego empieza a bajar sus FPS de repente? :-X ¿Será que se acumula algo del efecto que agota la memoria?

Es extraño, lo ejecuté por más de 5 minutos y en ningún momento bajaron los fps, el uso de memoria se mantuvo constante (20 MB aprox.) y el uso de procesador fluctuó un poco, pero nunca se usó demasiado.

Hice otra prueba y encontré un error: Cuando se reinicia la room las surfaces se mantienen en memoria y se crean otras nuevas, el uso de memoria no incrementa mucho, pero de todas formas es un desperdicio. Es necesario borrar esas surfaces, al cambiar de room o al reiniciar, y también sería conveniente al finalizar el juego.
[gml]
//Previo a room_restart
if surface_exists( sf0 )
surface_free( sf0 );

if surface_exists( sf1 )
surface_free( sf1 );

// ...
[/gml]

#14 Abril 03, 2016, 02:51:15 AM Ultima modificación: Abril 03, 2016, 07:05:49 PM por ian12
Cita de: Clamud en Abril 02, 2016, 02:34:10 PM
Es extraño, lo ejecuté por más de 5 minutos y en ningún momento bajaron los fps, el uso de memoria se mantuvo constante (20 MB aprox.) y el uso de procesador fluctuó un poco, pero nunca se usó demasiado.

Hice otra prueba y encontré un error: Cuando se reinicia la room las surfaces se mantienen en memoria y se crean otras nuevas, el uso de memoria no incrementa mucho, pero de todas formas es un desperdicio. Es necesario borrar esas surfaces, al cambiar de room o al reiniciar, y también sería conveniente al finalizar el juego.
[gml]
//Previo a room_restart
if surface_exists( sf0 )
surface_free( sf0 );

if surface_exists( sf1 )
surface_free( sf1 );

// ...
[/gml]


Si, con el ejemplo funciona todo bien, el asunto es en mi juego(adjunto captura). Pero talvez sea por que tiene más elementos en pantalla y resolucion que el ejemplo, aunque yo adapté todo bien.. Igual voy a probar crear una partición con windows 7 y probar, ya que sé que GMK 8.1 no es del todo compatible con el windows 8 que yo tengo y ya me ha dado error "out of memory" cuando lo ejecuto y tengo abierto el photoshop al mismo tiempo. Ojalá sea solo eso, porque este efecto es lo unico que me falta para dejar el motor de mi juego como me gusta  :-[