Windows Text keeps piling up on top of itself when I exit and enter a room repeatedly.

M

Master_of_Balls

Guest
A set of textures and some text underneath them is drawn whenever I enter a room. This worked without a hitch when I was drawing to the application surface, but in this case I'm drawing the surfaces as well, and now the text, which is randomized every time the room is entered, piles up on top of the text which was supposed to be discarded once I left the room previously.

Create event:



Code:
//declare surface
surfEjobs = surface_create(720, 480);

(((A whole lot of declaring randomized variables, will post them if you think it helps. 
Ex: randImg1 = irandom(2);)))
Draw event:

Code:
 //draws 3 characters with randomised features
//side by side on surface

if surface_exists(surfEjobs)
{
image_xscale = 4;
image_yscale = 4;
surface_set_target(surfEjobs);
//draws left composite applicant
draw_sprite_ext(spr_apBody, randImg1, 120, 160, 4, 4, 0, c_white, 1);
draw_sprite_ext(spr_apClothes, randImg2, 120, 160, 4, 4, 0, c_white, 1);
draw_sprite_ext(spr_apHair, randImg3, 120, 160, 4, 4, 0, c_white, 1);
//draws middle composite applicant
draw_sprite_ext(spr_apBody, randImg4, 360, 160, 4, 4, 0, c_white, 1);
draw_sprite_ext(spr_apClothes, randImg5, 360, 160, 4, 4, 0, c_white, 1);
draw_sprite_ext(spr_apHair, randImg6, 360, 160, 4, 4, 0, c_white, 1);
//draws right composite applicant
draw_sprite_ext(spr_apBody, randImg7, 600, 160, 4, 4, 0, c_white, 1);
draw_sprite_ext(spr_apClothes, randImg8, 600, 160, 4, 4, 0, c_white, 1);
draw_sprite_ext(spr_apHair, randImg9, 600, 160, 4, 4, 0, c_white, 1);
//Draws random names roughly below each character image
draw_text(120, 320, string(name[randN1]));
draw_text(360, 320, string(name[randN2]));
draw_text(600, 320, string(name[randN3]));
//Draws random wage demands below character img and name
draw_text(120, 340, "$" + string(randWage1));
draw_text(360, 340, "$" + string(randWage2));
draw_text(600, 340, "$" + string(randWage3));
//Draws random fortiture attribute below each applicant
draw_text(120, 360, "fort:" + string(randFort1));
draw_text(360, 360, "fort:" + string(randFort2));
draw_text(600, 360, "fort:" + string(randFort3));
//Draws random constitution below each applicant
draw_text(120, 380, "const" + string(randConst1));
draw_text(360, 380, "const" + string(randConst2));
draw_text(600, 380, "const" + string(randConst3));
//Draws random charisma below each applicant
draw_text(120, 400, "char" + string(randCha1));
draw_text(360, 400, "char" + string(randCha2));
draw_text(600, 400, "char" + string(randCha3));
surface_reset_target();
draw_clear_alpha(c_aqua, 0);
draw_surface(surfEjobs, 0, 0); //Draws the surface
}
else
{
surfEjobs = surface_create(720, 480);
surface_set_target(surfEjobs);
draw_clear_alpha(c_aqua, 0);
surface_reset_target();
}
Room end event

Code:
 if surface_exists(surfEjobs);
{
surface_free(surfEjobs);
}
If I put the code the draws the surface before the code that draws onto the surface then, when I exit and enter the room again, I can see the previous sprites being drawn for a split second before they are replaced with the sprites that are supposed to be drawn in the current room pass, so I'm guessing the same thing that happens to the text also happens to them, except that they all have the same shape and size and so anything underneath them isn't visible, whereas the text and numbers being drawn get visibly scrambled.
 

TheouAegis

Member
Are you cleaning the surface every time before you draw on it? I see that you clear it when you first create it, but I don't see you clean it before you draw on it again.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Are you cleaning the surface every time before you draw on it? I see that you clear it when you first create it, but I don't see you clean it before you draw on it again.
Apart from that (which is almost certainly the issue, tbh) I would also move the surface creation and stuff into the DRAW event, which is where it should be and is recommended to be by YYG and the Manual... so simply change the create event to this, as you have the draw event already creating the surface if it doesn't exist:

Code:
// CREATE EVENT
surfEjobs = -1;
Not using the draw event has been proven to cause some issues with how surfaces are drawn and cleared...
 

TheouAegis

Member
Not using the draw event has been proven to cause some issues with how surfaces are drawn and cleared...
On what platforms, for reference? I haven't worked extensively with the surfaces in Studio, but so far on Win10 it seems to function the same as GM8's surfaces in XP. I haven't delved into the iOS, Android, HTML5 side of GMS.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
On what platforms, for reference? I haven't worked extensively with the surfaces in Studio, but so far on Win10 it seems to function the same as GM8's surfaces in XP. I haven't delved into the iOS, Android, HTML5 side of GMS.
I honestly can't say... I have seen at least two topics saying this on the GMC (don't ask me where though!) and I know that YYG are always stressing how important it is to keep everything related to surfaces in the draw event.
 

TheouAegis

Member
Just seems like a queer thing for them to keep stressing, since even NES games used to draw outside the normal periods using interrupts and such. It was probably a tad slower, but sometimes the draw event is slow enough as it is and sometimes you wouldn't want to slow it down any more so unnecessarily.
 
M

Master_of_Balls

Guest
Are you cleaning the surface every time before you draw on it? I see that you clear it when you first create it, but I don't see you clean it before you draw on it again.
I thought that's what freeing the surface in the end room event did? I'm sorry, I should have mentioned I'm completely new at this, like a few weeks of scripting, I'm going to need a bit of spoon feeding here:) Where should I put the free_surface(); function? If I put it in the draw event at the end of where it's created and drawn ie:
else
Code:
{
surfEjobs = surface_create(720, 480);
surface_set_target(surfEjobs);
draw_clear_alpha(c_aqua, 0);
surface_reset_target();
<<<here>>>
....then the game crashes when I enter the room...

Apart from that (which is almost certainly the issue, tbh) I would also move the surface creation and stuff into the DRAW event, which is where it should be and is recommended to be by YYG and the Manual... so simply change the create event to this, as you have the draw event already creating the surface if it doesn't exist:

Code:
// CREATE EVENT
surfEjobs = -1;
Not using the draw event has been proven to cause some issues with how surfaces are drawn and cleared...
Is that the same as putting the 'noone' value in it?
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Okay, you need to clear the surface contents, not clear the surface from memory... so keep the surface_free in the room end event as you had it, and instead change your draw event to:

Code:
if surface_exists(surfEjobs)
{
image_xscale = 4;
image_yscale = 4;
surface_set_target(surfEjobs);
draw_clear_alpha(c_black, 0);
// THE REST OF YOUR DRAW CODE HERE AS NORMAL
surface_reset_target();
draw_clear_alpha(c_aqua, 0); // This can probably be removed?
draw_surface(surfEjobs, 0, 0); //Draws the surface
}
As for using "noone", that's only for use with instances. In reality it evaluates to -4, so you CAN use it in this instance since all surface ID's are positive integers, but I try to keep reserved keywords to their specific uses. Noone mught evaluate to -4 now, but in the future it could evaluate to something different if the devs decide to change it...
 
M

Master_of_Balls

Guest
Okay, you need to clear the surface contents, not clear the surface from memory... so keep the surface_free in the room end event as you had it, and instead change your draw event to:

Code:
if surface_exists(surfEjobs)
{
image_xscale = 4;
image_yscale = 4;
surface_set_target(surfEjobs);
draw_clear_alpha(c_black, 0);
// THE REST OF YOUR DRAW CODE HERE AS NORMAL
surface_reset_target();
draw_clear_alpha(c_aqua, 0); // This can probably be removed?
draw_surface(surfEjobs, 0, 0); //Draws the surface
}
As for using "noone", that's only for use with instances. In reality it evaluates to -4, so you CAN use it in this instance since all surface ID's are positive integers, but I try to keep reserved keywords to their specific uses. Noone mught evaluate to -4 now, but in the future it could evaluate to something different if the devs decide to change it...
Ok it works great now. But I'm still unclear as to why the surface contents are cleared from memory only if I declare the surface with -1 in the create event instead of with a create event. Also, what you're saying is that surface_free doesn't delete the surface, but just clears it of stuff instead?

Thanks, by the way :)
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Nonono... surface_free DOES clear the surface from memory. Which is why you were right to call it in the room end event. The difference between surface_free and calling draw_clear_alpha is simply that surface_free clears the surface from memory, and draw_clear_alpha clears what's ON the surface, but keeps it in memory.

As for declaing the variable as -1 in the create event, you don't have to do that and can create the surface there first, it's just that YYG recommend that all surface operations be done in the draw event. Setting it to -1 in the Create event simply forces the surface_exists check in the draw event to be false the first game frame and so the surface is created using your failsafe code. ;)
 

TheouAegis

Member
Think of it this way:

There is a piece of paper on a table with a pencil.
You right a message on the paper with the pencil.
Later, someone else comes by and writes a message on the paper with the pencil.
Your message is still there because the other person didn't erase the message (draw_clear_alpha).
Later you come back and write another message on the paper.
Later someone else comes in and writes a message on the paper.
This goes on throughout the day.
By the next morning, the paper will be a garbled mess because everyone was writing on the paper without erasing the previous messages.
 
M

Master_of_Balls

Guest
The overlapping text is fixed, but I managed to bump into another one. Whenever I enter the room what'd drawn isn't any of the sutff I want drawn on the surface, but it draws the whatever was in the view before I entered the room/building, ie. it draws the city hub in the previously drawn room. The only thing that tells me I entered another room is that the menu buttons which are visible objects with their own sprites show up in the correct positions. Basically it doesn't look like I entered anything, just that the menu buttons appear in the city hub view.

create:

Code:
surfEjobs = -1;
draw

Code:
if surface_exists(surfEjobs)
    {
    image_xscale = 4;
    image_yscale = 4;
   
    surface_set_target(surfEjobs);
    draw_clear_alpha(c_aqua, 0);

    draw_sprite_ext(spr_apBody, global.randImg1, 120, 160, 4, 4, 0, c_white, 1);
    draw_sprite_ext(spr_apClothes, global.randImg2, 120, 160, 4, 4, 0, c_white, 1);
    draw_sprite_ext(spr_apHair, global.randImg3, 120, 160, 4, 4, 0, c_white, 1);
   
    draw_sprite_ext(spr_apBody, global.randImg4, 360, 160, 4, 4, 0, c_white, 1);
    draw_sprite_ext(spr_apClothes, global.randImg5, 360, 160, 4, 4, 0, c_white, 1);
    draw_sprite_ext(spr_apHair, global.randImg6, 360, 160, 4, 4, 0, c_white, 1);
    
    draw_sprite_ext(spr_apBody, global.randImg7, 600, 160, 4, 4, 0, c_white, 1);
    draw_sprite_ext(spr_apClothes, global.randImg8, 600, 160, 4, 4, 0, c_white, 1);
    draw_sprite_ext(spr_apHair, global.randImg9, 600, 160, 4, 4, 0, c_white, 1);
    
    draw_text(120, 320, string(global.name[global.randN1]));
    draw_text(360, 320, string(global.name[global.randN2]));
    draw_text(600, 320, string(global.name[global.randN3]));
    
    draw_text(120, 340, "$" + string(global.randWage1));
    draw_text(360, 340, "$" + string(global.randWage2));
    draw_text(600, 340, "$" + string(global.randWage3));
   
    draw_text(120, 360, "end:" + string(global.randEnd1));
    draw_text(360, 360, "end:" + string(global.randEnd2));
    draw_text(600, 360, "end:" + string(global.randEnd3));
   
    draw_text(120, 380, "const" + string(global.randConst1));
    draw_text(360, 380, "const" + string(global.randConst2));
    draw_text(600, 380, "const" + string(global.randConst3));
    
    draw_text(120, 400, "char" + string(global.randChar1));
    draw_text(360, 400, "char" + string(global.randChar2));
    draw_text(600, 400, "char" + string(global.randChar3));
   
    surface_reset_target();
   
    draw_clear_alpha(c_aqua, 0);
    draw_surface(surfEjobs, 0, 0); //Draws the surface
    }
else
    {
    surfEjobs = surface_create(720, 480);
    surface_set_target(surfEjobs);
    draw_clear_alpha(c_aqua, 0);
    surface_reset_target();
    }
room end

Code:
if surface_exists(surfEjobs)
  {
  surface_free(surfEjobs);
  }
 

TheouAegis

Member
Huh. Do you have anything else drawing the surface? Because the code you posted should be clearing the surface every step from what I can see.
 
M

Master_of_Balls

Guest
Huh. Do you have anything else drawing the surface? Because the code you posted should be clearing the surface every step from what I can see.
I don't think so. If it helps, I'll post the code that draws the main city hub background since that's what is also being drawn in the next room
Alos, slight update, I made a mistake which I now fixed and I am able to see the sprites that are supposed to be drawn in the next room, but the background is still the same background as the one in the city hub instead of the aqua colored background that I want it to draw:

room rm_city
creation event:

Code:
// background is 1280*720 while room and surface are 1440p
background_xscale[0] = 2;
background_yscale[0] = 2;

//declare surface
surfPavement = surface_create(2560, 1440);;

//draws bk on surface, but checks if surface exists because volatile
if surface_exists(surfPavement)
    {
    surface_set_target(surfPavement);
    draw_clear_alpha(c_white, 0);
    draw_background_ext(bk_city, 0, 0, background_xscale[0], background_xscale[0], 0, -1, 1);
   
    surface_reset_target();
    }
    else
    {
    surfPavement = surface_create(2560, 1440);
    surface_set_target(surfPavement);
    draw_clear_alpha(c_white, 0);
    surface_reset_target();
    }

draw event:


Code:
draw_clear_alpha(c_white, 0);
draw_surface(surfPavement, 0, 0);
room end event:

Code:
surface_free(surfPavement);
 

TheouAegis

Member
draw_background_ext(bk_city, 0, 0, background_xscale[0], background_xscale[0], 0, -1, 1);

Minor typo there.

Is bk_city a variable or the background name? Are you sure the background resources are actually different?
 
Top