Windows [SOLVED] Surface moves with camera?

D

DigitalCaffeine

Guest
I took a small break from working on my game when I did some traveling over the summer, and when I opened it for the first time in a month, the surface I'm using to draw lighting on is semi-broken. When the room starts, everything is in the correct place, but when I start walking to the right and the view moves, the surface the lights are being drawn on suddenly start moving to the left. When the character walks left again and I return the view to it's initial position, everything is correct again. Everything was working perfectly fine a month ago, and after changing nothing it's now all messed up. Did an update happen that changed the way surfaces work or is there something else that could be causing this? I make backups of the project every couple of weeks and this is now broken in old versions too when I KNOW it was fine.

What the problem looks like: https://imgur.com/a/VTagv1c

When it was working fine: https://imgur.com/4vzswin


Create Event:

light_layer = layer_get_id("Lights");
light_surface = surface_create(400,240);
layer_script_begin(light_layer,lights_begin);
layer_script_end(light_layer,lights_end);


When the script for layer_surface_begin is called:

if (event_type == ev_draw) and (event_number == 0)
{
if (!surface_exists(iLight.light_surface))
{
iLight.light_surface = surface_create(400,240);
}

var cam = view_camera[view_current];
surface_set_target(iLight.light_surface);
camera_apply(cam);
draw_clear_alpha(col,1.0);
gpu_set_blendmode(bm_add);
}
 
Last edited by a moderator:

Azenris

Member
I dunno if it will help, but have you tried replacing view_current with 0, i swear there was a bug once with it. so var cam = view_camera[0];
Maybe not, just a thought :p
 

GMWolf

aka fel666
If you are looking for a method that will work with any camera (scaling, rotation, etc) then have a look at this tutorial:

You don't really need all the layer things, but the part about resetting the camera using surface_set_target is what you want.


[Edit]
Ah wait! Just read your code again, seems like you are already using my tutorial :)

Make sure you have views enabled so you can get the camera using view_current

[Re-edit]
It could be a new change broke the project.bi will have to test my version tomorrow...
 
Last edited:
D

DigitalCaffeine

Guest
I dunno if it will help, but have you tried replacing view_current with 0, i swear there was a bug once with it. so var cam = view_camera[0];
Thanks for suggestion, no changes unfortunately...

[Re-edit] It could be a new change broke the project.bi will have to test my version tomorrow...
That would be awesome if you could figure out what's going on with it. It was a great tutorial by the way!

Had the same problem with a surface not following my in-game view. The code in the link solved my problem.

https://forum.yoyogames.com/index.p...reating-a-surface-lighting.49660/#post-304860
Thanks, I'm picking through it now to see if I can find a solution.
 

GMWolf

aka fel666
The project is broken for me too. I think its because setting the surface to the app surface will no longer reset the camera.
working on a fix now.
 

GMWolf

aka fel666
Ok, Got a fix Working!
Update the Lights_end script so it looks like this:
Code:
if (event_type == ev_draw) and (event_number == 0 ) {
   
    surface_reset_target();
    gpu_set_blendmode(bm_normal);
   
   
    //surface_set_target(application_surface);
   
        camera_apply(camera_create_view(0,0, view_wport[view_current], view_hport[view_current]));
   
        gpu_set_blendmode_ext(bm_dest_color, bm_zero);
        draw_surface(iLight.light_surface, 0, 0);
        gpu_set_blendmode(bm_normal);
       
    //surface_reset_target();
   
}
I left the parts to remove in comments.
 
D

DigitalCaffeine

Guest
I’m at work right now, so I’ll have to test it when I get home, but I really appreciate you taking the time to find a solution. This must have happened with a recent update to the program.
 

GMWolf

aka fel666
Oh, just one thing to keep in mind:
before applying the camera, you may want to grab the current active camera, in order to re-apply it after the surface has been drawn. That's just to make sure anything drawn afterwards doesnt get messed up by our camera change.
 
D

DigitalCaffeine

Guest
Oh, just one thing to keep in mind:
before applying the camera, you may want to grab the current active camera, in order to re-apply it after the surface has been drawn. That's just to make sure anything drawn afterwards doesnt get messed up by our camera change.
Everything is working perfectly now. I can't even think about how long it would have taken me to fix on my own. Again, really appreciate the help!
 
I know this thread is old, but I hope someone can still help.

I'm using GMWOLF's lighting system, and I'm impressed with what you get for it's simplicity and easy implementation. However I've come across two problems, which I can't seem to figure out how to solve:

#1 Anything place above the Asset_layer where the sprites are drawn, will be hidden.
This is a problem for GUI elements, like textboxes. I guess it has something to do with depth system, and the draw order in GM Studio 2?

I've found a video by Stefan Randa called "Depth / Fake 3D - Game Maker Studio 2 Tutorial" (I'm new, so I cant link to anything yet) where he, as far as I can tell, renders everything manually, to create the depth he wants. Would this solve the problem, or does anyone have good example to follow?

#2 Animated sprites are sloooow
I've tried implementing animated sprites for the lights, but they animate very slowly. I can't figure out the cause of this, or how to prevent it.

Thanks for the patience - I'm still new to GM Studio 2.
 

GMWolf

aka fel666
Which lighting system are you using? Is the the GMS2 system using layers? Because that should not change anything drawn after those asset layers.

As for the animation that is probably unrelated.
 
Which lighting system are you using? Is the the GMS2 system using layers? Because that should not change anything drawn after those asset layers.

As for the animation that is probably unrelated.
Thanks for the reply!

I'm using the one you give a tutorial on in the video "Simple lighting system for GMS2 - GMWolf", with the *fix* implementation a few posts above in this thread. I have a lot of layers, and using the standard GMS2 depth system. I don't set any depth in any object manually however, which I would guess could be a problem, but since I don't I'm pretty stumped as to why this is happening. It happens in any layer that is moved above the asset_layer where the lighting sprites are placed.

Heres the code:

Code:
oLight - Create Event
Placed on "InstancesLights" position 2 in the layers tab

light_layer = layer_get_id("AssetsLights");
light_surface = surface_create(384, 216);

layer_script_begin(light_layer, lights_begin);
layer_script_end(light_layer, lights_end);
Code:
Lights Begin script

if (event_type == ev_draw) and (event_number == 0) {
    if (!surface_exists(iLight.light_surface)) {
        iLight.light_surface = surface_create(384, 216);
    }
    
    var cam = view_camera[view_current];
    
    surface_set_target(iLight.light_surface);
    
    camera_apply(cam);
    
    draw_clear_alpha(c_gray, 1.0);
    gpu_set_blendmode(bm_add);
}
Code:
Lights_end script

if (event_type == ev_draw) and (event_number == 0 ) {
  
    surface_reset_target();
    gpu_set_blendmode(bm_normal);
  
  
    //surface_set_target(application_surface);
  
        camera_apply(camera_create_view(0,0, view_wport[view_current], view_hport[view_current]));
  
        gpu_set_blendmode_ext(bm_dest_color, bm_zero);
        draw_surface(iLight.light_surface, 0, 0);
        gpu_set_blendmode(bm_normal);
      
    //surface_reset_target();
  
}
 
Last edited:

GMWolf

aka fel666
Tbh I don't 100% remember how it all works but I seem to recall that the surface gets draw on the layer end script.
So any layer after than should get drawn on top.

Perhaps try to change when that surface gets draw using some more explicit code to figure out where the issue lies.
 
T

Tayoyo

Guest
Tbh I don't 100% remember how it all works but I seem to recall that the surface gets draw on the layer end script.
So any layer after than should get drawn on top.

Perhaps try to change when that surface gets draw using some more explicit code to figure out where the issue lies.
Do you have any good ideas on how I can make the lights move, for example having a light follow the player around?

EDIT: I figured it out nvm. Just changed it to an instance layer
 
Last edited by a moderator:
Ok, Got a fix Working!
Update the Lights_end script so it looks like this:
Code:
if (event_type == ev_draw) and (event_number == 0 ) {

    surface_reset_target();
    gpu_set_blendmode(bm_normal);


    //surface_set_target(application_surface);

        camera_apply(camera_create_view(0,0, view_wport[view_current], view_hport[view_current]));

        gpu_set_blendmode_ext(bm_dest_color, bm_zero);
        draw_surface(iLight.light_surface, 0, 0);
        gpu_set_blendmode(bm_normal);
   
    //surface_reset_target();

}
I left the parts to remove in comments.

Just finished your tutorial. I love it. BUT it doesn't follow my camera. I am using my own camera. and "view_camera[view_current]" doesn't work for me. My camera is called simply "Camera". Forgive me I am quite new.

(edit: I tried your fix, but that broke it worse for me) This is what I have....

object: oLight (instance named iLight inside the room)
GML:
light_layer = layer_get_id("Lights");
light_surface = surface_create(1280, 720);

layer_script_begin(light_layer, sc_lights_begin);
layer_script_end(light_layer, sc_lights_end);
sc_lights_begin
GML:
if (event_type == ev_draw) and (event_number == 0) {
   
    if (!surface_exists(iLight.light_surface)) {
        iLight.light_surface = surface_create(1280, 720);
    }
   
    var cam = Camera;
   
    surface_set_target(iLight.light_surface);
   
    camera_apply(cam);
   
    draw_clear_alpha(c_black, 1);
    gpu_set_blendmode(bm_add);
   
}
sc_lights_end
GML:
if (event_type == ev_draw) and (event_number == 0 ) {
 
    surface_reset_target();
    gpu_set_blendmode(bm_normal);
 
 
    //surface_set_target(application_surface);
    var _uc_pw = uc_get_port_width();
    var _uc_ph = uc_get_port_height();
 
        camera_apply(camera_create_view(0,0, _uc_pw, _uc_ph));
 
        gpu_set_blendmode_ext(bm_dest_color, bm_zero);
        draw_surface(iLight.light_surface, 0, 0);
        gpu_set_blendmode(bm_normal);
     
    //surface_reset_target();
 
}

The game runs fine and the lights apply. But it (the lights/surface) follows the camera. Instead of staying where they should stay.
 
Last edited:

GMWolf

aka fel666
What do you mean by your own camera?
Is it a camera created with the camera functions? Is it an instance?

How is it not working? Instead of it following the camera, what do you see?
 
What do you mean by your own camera?
Is it a camera created with the camera functions? Is it an instance?

How is it not working? Instead of it following the camera, what do you see?
Im not using the built in GML camera. I am using Ultimate Camera. Which has plenty option get port width or view width options etc. I just dont know what to put there. Essentially whats happening is the surface is following the camera/player instead of sticking to the ground or where they are suppose to light. I hope that makes sense.
 
Im not using the built in GML camera. I am using Ultimate Camera. Which has plenty option get port width or view width options etc. I just dont know what to put there. Essentially whats happening is the surface is following the camera/player instead of sticking to the ground or where they are suppose to light. I hope that makes sense.
Disregard. I found a different solution. Thank you
 
Seems like that the Lighting System makes so every object above it will be on the wrong position (e.g. Particles aren't correctly displaying where they should be.)

Edit: I Attached a Screenshot when the Lights Layer is above my Sword Layer while others are above the Lights Layer.
1627403524069.png
 
Top