Saludos !
He estado muy ocupado ultimamente y tenía mi proyecto bastante abandonado, ahora tengo unos dias y quiero meterle muchas horas, el caso es que llevaba tiempo pensando en como hacer una room sin iluminación y usar el tipico efecto linterna con SURFACES.
El jugador se me ilumina sin problemas, pero el problema viene cuando quiero que las balas también tengan su luz propia.
Como cada bala se llamará igual, en este caso "ob_player_bullet", supongo que no puedo dar las coordenadas del objeto en sí, si no su ID, pero nunca he usado ID´s, así que no se como funciona, y menos si el objeto no se ha creado aún.
De momento expongo mi código del objeto que controla la surface:
EVENTO CREATE:
[gml]///PROPIEDADES
// CREA LA OSCURIDAD
oscuridad=surface_create(room_width,room_height)[/gml]
EVENTO STEP
[gml]///PROPIEDADES
// DIBUJA LA OSCURIDAD
surface_set_target(oscuridad) // llama a la surface
draw_set_color(c_black) // establece el color negro
draw_set_alpha(0.8) // nivel de transparencia en la oscuridad
draw_rectangle(0,0,room_width,room_height,0) // dibuja el rectangulo negro que ocupa toda la room
draw_set_alpha(1) // establece el nivel de transparencia al normal
// CREA LA LUZ SOBRE EL JUGADOR
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
if instance_exists(ob_player_in_room){ // Lo coloca sobre el jugador entrando en la room
draw_sprite(spr_luz_1,0,ob_player_in_room.x,ob_player_in_room.y)
}else{ // lo coloca sobre el jugador
draw_sprite(spr_luz_1,0,ob_player.x,ob_player.y)
}
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
// CREA LUZ SOBRE LAS BALAS
if instance_exists(ob_player_bullet){
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite(spr_luz_1,0,ob_player_bullet.x,ob_player_bullet.y)// Lo coloca sobre las balas
}
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface[/gml]
EVENTO DRAW
[gml]/// PROPIEDADES
// DIBUJARSE A SI MISMA
draw_self()
// DIBUJAR LA OSCURIDAD
draw_surface(oscuridad,0,0)[/gml]
Lo dicho, con el personaje del jugador funciona todo bien, no funciona con las balas, supongo que por que todas se llaman OB_PLAYER_BULLET, aún que si disparo sólo una, tampoco sale la luz.
Alguien que me pueda ayudar con este código ?.
Gracias como siempre.
Un Saludo.
La parte que dibujas la luz de las balas tenes que colocarlo cuando llamas a la surface surface_set_target(oscuridad), asi como todo lo que quieras que afecte la surface
[gml]
surface_set_target(oscuridad)
///todos lo que quieras que se dibuje en la surface
surface_reset_target()
[/gml]
El caso es que van a ser muchos los objetos que tienen que usar el substract, y no estan en pantalla aun, como por ejemplo la bala, items, magias, etc.
he intentado poner esto al objeto bala en su evento STEP, pero no funciona, no se por que:
[gml]/// LUZ EN SURFACE
// CREA LA LUZ SOBRE EL ATAQUE
if room == lvl_4 {
surface_set_target(global.oscuridad) // llama a la surface
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite_ext(spr_luz_1,0,x,y,1,1,0,1,1) // dibuja el sprite de luz
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
}
[/gml]
En realidad es muy curioso por que parece que funcionar funciona, pero es apenas apreciable.
Alguna ayuda ?.
Gracias.
Se ve mal el sprite o no se ve ?
Practicamente no hay efecto de substact, es como si no existiera, no se que hacer.
Será que no puede hacer nada sobre la surface otro objeto mas que el que la creó ?.
Con la surface creada podes modificarla desde cualquier objeto.
Intenta quitarle el sprite desde las propiedades del objeto y solo dibujar el sprite en el evento STEP cuando uses la surface.
Lo probaré y te cuento, gracias 3Dgeminis
Cita de: Yuzo en Noviembre 07, 2017, 04:33:21 PM
...
EVENTO STEP
[gml]///PROPIEDADES
// DIBUJA LA OSCURIDAD
surface_set_target(oscuridad) // llama a la surface
draw_set_color(c_black) // establece el color negro
draw_set_alpha(0.8) // nivel de transparencia en la oscuridad
draw_rectangle(0,0,room_width,room_height,0) // dibuja el rectangulo negro que ocupa toda la room
draw_set_alpha(1) // establece el nivel de transparencia al normal
// CREA LA LUZ SOBRE EL JUGADOR
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
if instance_exists(ob_player_in_room){ // Lo coloca sobre el jugador entrando en la room
draw_sprite(spr_luz_1,0,ob_player_in_room.x,ob_player_in_room.y)
}else{ // lo coloca sobre el jugador
draw_sprite(spr_luz_1,0,ob_player.x,ob_player.y)
}
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
// CREA LUZ SOBRE LAS BALAS
if instance_exists(ob_player_bullet){
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite(spr_luz_1,0,ob_player_bullet.x,ob_player_bullet.y)// Lo coloca sobre las balas
}
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface[/gml]
...
Sólo tienes que reemplazar esto:
[gml]
// CREA LUZ SOBRE LAS BALAS
if instance_exists(ob_player_bullet){
[/gml]
Por esto:
[gml]
// CREA LUZ SOBRE LAS BALAS
with(ob_player_bullet){
[/gml]
3DGeminis, sigue sin funcionar.
Markus, así funciona, pero sólo funciona en un objeto por room, es decir, si hay dos balas o más, sólo la primera que se creó tiene el efecto de luz.
No hay algo que se le pueda poner al objeto bala para que el efecto se haga desde el propio objeto ?, creo que sería mejor, y que usaría menos recursos, no ?.
En un fallido intento de hacerlo de dicha manera puse esto en el evento STEP del objeto bala:
[gml]/// LUZ EN SURFACE
// CREA LA LUZ SOBRE EL ATAQUE
if room == lvl_4 {
surface_set_target(global.oscuridad) // llama a la surface
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite_ext(spr_luz_1,0,x,y,1,1,0,1,1) // dibuja el sprite de luz
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
}[/gml]
Pero nada, así tampoco funciona, ya no se que hacer .....
Te dejo un ejemplo, con linterna y balas como fuentes de luz. El codigo esta en el objeto o_superficie, ademas fijate en el objeto o_bala.
(https://i.imgur.com/hVspdnL.png)
Cita de: Yuzo en Noviembre 18, 2017, 10:34:26 AM
3DGeminis, sigue sin funcionar.
Markus, así funciona, pero sólo funciona en un objeto por room, es decir, si hay dos balas o más, sólo la primera que se creó tiene el efecto de luz.
No hay algo que se le pueda poner al objeto bala para que el efecto se haga desde el propio objeto ?, creo que sería mejor, y que usaría menos recursos, no ?.
En un fallido intento de hacerlo de dicha manera puse esto en el evento STEP del objeto bala:
[gml]/// LUZ EN SURFACE
// CREA LA LUZ SOBRE EL ATAQUE
if room == lvl_4 {
surface_set_target(global.oscuridad) // llama a la surface
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite_ext(spr_luz_1,0,x,y,1,1,0,1,1) // dibuja el sprite de luz
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
}[/gml]
Pero nada, así tampoco funciona, ya no se que hacer .....
¿Pero hiciste el cambio que te indiqué? Porque con WITH haces que todas las balas ejecuten su código, justamente lo que están diciendo que necesitas hacer.
Prueba poniendo el objecto que controla el draw de las luces en el ultimo orden de carga de la room.
Suerte!!! ;)
Gracias 3DGeminis, mirando tu codigo no entiendo que es lo que me funciona mal.
Sí, Markus, esta tal que así:
[gml]// CREA LUZ SOBRE LAS BALAS
with(ob_player_bullet){
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite(spr_luz_1,0,ob_player_bullet.x,ob_player_bullet.y)// Lo coloca sobre las balas
}[/gml]
NONOROMAN, como se hace eso ?, suena interesante, aun que no se si lo resolverá.
Estoy dandole vueltas y vueltas y he pensado que tal vez se trate de que tengo un objeto en la room que tambien modifica una surface, tal vez sea que entra en conflico con este.
Tiene lo siguiente:
OBJETO LUCIERNAGA:
CREATE:
[gml]/// PROPIEDADES
escala_x = 0; // variable que controla la escala X (tamaño del sprite)
escala_y = 0; // variable que controla la escala Y (tamaño del sprite)
tamano_luz_x = 0; // variable que controla el tamaño de la luz en X
tamano_luz_y = 0; // variable que controla el tamaño de la luz en Y
// PROFUNDIDAD
depth = choose(-2,-1,0,1,2,3);
// DIRECCION
direction = irandom_range(0,360);[/gml]
STEP
[gml]
/// LUZ EN SURFACE
// CREA LA LUZ SOBRE LA LUCIERNAGA
surface_set_target(global.oscuridad) // llama a la surface
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite_ext(spr_luz_1,0,x,y,tamano_luz_x,tamano_luz_y,0,1,1) // dibuja el sprite de luz
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
[/gml]
DRAW
[gml]
/// PROPIEDADES
// DIBUJA EL SPRITE ORIGINAL
draw_sprite_ext(spr_luciernaga,0,x,y,escala_x,escala_y,0,c_white,1)
// LO HACE BORROSO
draw_set_blend_mode(bm_add)
// DIBUJA EL SPRITE DIFUMINADO
if global.pause == false and global.magia_on == false{
draw_sprite_ext(spr_luciernaga_des,0,x,y,escala_x,escala_y,0,c_white,alpha_level)}
// ESTABLECE EL MODO DE BLEND EN NORMAL
draw_set_blend_mode(bm_normal);
[/gml]
En las propiedades de la room hay un boton que pone instance orden o algo asi. Te sale la.lista de todos los objectos que hay en la room y puedes cambiar su orden. Ponlo el ultimo.
Cita de: Yuzo en Noviembre 24, 2017, 11:37:06 AM
Gracias 3DGeminis, mirando tu codigo no entiendo que es lo que me funciona mal.
Sí, Markus, esta tal que así:
[gml]// CREA LUZ SOBRE LAS BALAS
with(ob_player_bullet){
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite(spr_luz_1,0,ob_player_bullet.x,ob_player_bullet.y)// Lo coloca sobre las balas
}[/gml]
NONOROMAN, como se hace eso ?, suena interesante, aun que no se si lo resolverá.
Estoy dandole vueltas y vueltas y he pensado que tal vez se trate de que tengo un objeto en la room que tambien modifica una surface, tal vez sea que entra en conflico con este.
Tiene lo siguiente:
OBJETO LUCIERNAGA:
CREATE:
[gml]/// PROPIEDADES
escala_x = 0; // variable que controla la escala X (tamaño del sprite)
escala_y = 0; // variable que controla la escala Y (tamaño del sprite)
tamano_luz_x = 0; // variable que controla el tamaño de la luz en X
tamano_luz_y = 0; // variable que controla el tamaño de la luz en Y
// PROFUNDIDAD
depth = choose(-2,-1,0,1,2,3);
// DIRECCION
direction = irandom_range(0,360);[/gml]
STEP
[gml]
/// LUZ EN SURFACE
// CREA LA LUZ SOBRE LA LUCIERNAGA
surface_set_target(global.oscuridad) // llama a la surface
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite_ext(spr_luz_1,0,x,y,tamano_luz_x,tamano_luz_y,0,1,1) // dibuja el sprite de luz
draw_set_blend_mode(bm_normal) // deja el modo de dibujo en normal
surface_reset_target() // cierra la surface
[/gml]
DRAW
[gml]
/// PROPIEDADES
// DIBUJA EL SPRITE ORIGINAL
draw_sprite_ext(spr_luciernaga,0,x,y,escala_x,escala_y,0,c_white,1)
// LO HACE BORROSO
draw_set_blend_mode(bm_add)
// DIBUJA EL SPRITE DIFUMINADO
if global.pause == false and global.magia_on == false{
draw_sprite_ext(spr_luciernaga_des,0,x,y,escala_x,escala_y,0,c_white,alpha_level)}
// ESTABLECE EL MODO DE BLEND EN NORMAL
draw_set_blend_mode(bm_normal);
[/gml]
Nada, que no sale, lo he probado todo chicos, todas vuestras ideas, y más cosas que se me iban ocurriendo.
No tengo ni idea de por que me pasa esto.
Comparto el proyecto a ver si alguien sabe donde está el error.
Cambiale el tamaño horizontal del room a 8000
Cambiado, sigue sin funcionar.....
De todos modos gracias por la ayuda.
A ver si alguien es capaz de resolverlo.....
Gracias de antemano a los que vengan y gracias a los que lo han intentado tambien.
Por fin entendí lo que faltaba en la recomendación que te di. Así que vamos de nuevo:
Esto que tienes aquí:
EVENTO STEP
[gml]
...
// CREA LUZ SOBRE LAS BALAS
if instance_exists(ob_player_bullet){
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
draw_sprite(spr_luz_1,0,ob_player_bullet.x,ob_player_bullet.y)// Lo coloca sobre las balas
}
...
[/gml]
Por esto:
[gml]
// CREA LUZ SOBRE LAS BALAS
draw_set_blend_mode(bm_subtract) // modo de dibujar "EXTRAER"
with(ob_player_bullet){
draw_sprite(spr_luz_1,0,x,y)// Lo coloca sobre las balas
}[/gml]
[gml]with(ob_player_bullet)[/gml]
hace que todo el código que viene después, dentro de los {} lo ejecute cada instancia del objeto ob_player_bullet, entonces, lo que faltaba era reemplazar las coordenadas que tenías
[gml](ob_player_bullet.x,ob_player_bullet.y)[/gml]
por las coordenadas de la instancia que ejecuta el código
[gml](x, y)[/gml]
¿Por qué? Porque cuando escribes objeto.x, usa la coordenada de la primera instancia existente en ese momento del objeto.
Lo probé y funciona.
Saludos.
Sííííííííí !!!!, por fin funciona !!!!!.
Dios santo, no sabes como te lo agradezco, te debo una cerveza !!!!.
y también he puesto esto al eliminar el objeto:
[gml]/// ELIMINA LA SURFACE
surface_free(global.oscuridad)[/gml]
Que en el ejemplo de 3DGeminis he visto que está y parece ser por lo que he leido por ahí que es algo necesario, por el tema de consumo de recuersos.
Lo que no entiendo es por que todo el mundo usa END STEP para el tema de las surfaces, yo uso el evento STEP y funciona, a que se debe ?, a decir verdad ni si quiera se muy bien como funciona el END STEP.
De todos modos, muchisimas gracias a todos por la ayuda y disculpad que haya tardado tanto en contestar, pero ultimamente ando extremadamente justo de tiempo.
GRACIAS !!!!
Cita de: Yuzo en Diciembre 03, 2017, 11:13:17 AM
Sííííííííí !!!!, por fin funciona !!!!!.
Dios santo, no sabes como te lo agradezco, te debo una cerveza !!!!.
Te la cobraré ;D
Cita de: Yuzo en Diciembre 03, 2017, 11:13:17 AM
...
Lo que no entiendo es por que todo el mundo usa END STEP para el tema de las surfaces, yo uso el evento STEP y funciona, a que se debe ?, a decir verdad ni si quiera se muy bien como funciona el END STEP.
...
END STEP se usa generalmente para asegurarse de que todas las instancias ya se hayan movido en STEP actual, antes de trabajar con la surface. Así evitas tener que crear la instancia controladora del surface en el orden correcto para ejecutar su código después de que todo el resto lo haga.