Match objects with drawing lines (Bingo! Solved)

Started by Amir, Mon 06/06/2022 07:43:06

Previous topic - Next topic

Amir

Hello,

I still have my last puzzle in the game where you have to match objects (or hotspots), with an OK button you have to click on it when you have matched to see if it's wrong or right. I have a complicated idea how to do this, using lines as objects. But it's complicated and takes a lot of work and time. I thought differently, I could maybe do it with drawing lines. when the left mouse button is pressed the mouse moves while the button is still down, a line is drawn between where you clicked and you let go the mouse button.

Something like that here: (this is not my puzzle ;-D)
Spoiler
[close]

I found this ancient code in this thread, since 2004. It looks like it's right for my puzzle but it doesn't work anymore. https://www.adventuregamestudio.co.uk/forums/index.php?topic=12390.msg148534#msg148534

I tried to fix it but the commands are from the Jurassic period.
Has anyone written or used some similar code before, or maybe there's a module I haven't discovered yet?
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Pogwizd

#1
Not sure if this helps, but if you are going to have the pictures as objects in the room, I would, on mouse button click, loop through the objects and check their coordinates and dimensions of their sprites. Knowing the coordinates and dimensions, you can check if the click happened within the boundaries of one of the objects/sprites. If yes, you store the object's id and wait for the release of the mouse button. When the mouse button is released you do the same thing - check where the mouse button was released. If it was released within the boundaries of one of the images you grab its id. Then you can check what two objects/images have been linked (of course you would need to have an array of correct matches to compare against).

As for the drawing the line, once the mouse is pressed, you start drawing a line using dynamic sprites. As far as I remember, you do it by capturing the background before you start drawing the line, and every pixel the mouse is moved, you redraw the background and the new line (starting from the point where the mouse was pressed, and finishing at the current position of the mouse). Once the mouse button is released, you stop redrawing the background and the line.

I can't write the actual code at the moment, but I would probably try doing something along these lines.   

Amir

It doesn't matter if it's hotsopts or objects, I can change it.

thanks for explaining the method, I understand it but i think I wouldn't be able to do it because i've never handled this Drawing functions before, so I asked if anyone has any code already and that's why I tried Rick's code . This would take me longer and require more work than the complicated lines-as-objects method. I can't find any modules with drawings at all, I might set them up faster so that I can draw lines from mouse.x to mouse.y. I will look again today.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Pogwizd

#3
I see. If you don't mind waiting, I will try to fish out my old code from my game in the evening and share it with you. This is a clip from my game, which also draws lines: https://youtu.be/9pksmHxbXnc?t (go to 48:00) If I am not mistaken, this is something similar you want to achieve?

Amir

Oh cool, yes, exactly, but with free moving mouse cursor. I see you have limited mouse x and y in this room. I think this is not difficult to change in your code. Take your time, I can wait. Now I have a worse problem with changing the translation. (I posted it in Beginners' Technical section)

Cool game, I like the graphics. I will definitely play it at some point.

Thank u  :)
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Pogwizd

#5
Right. I found the code and managed to pull out the bits that will hopefully shed some light. I haven't tested this particular code, so there might be some imperfections. But, in essence, this is the same logic that worked for me. It's possible you will have to tweak it here and there, though.

Code: ags

bool accept_input = true;
bool draw = false;
int line_count = 0;
int LINE_WIDTH = 5;
int start_x;
int start_y;
DrawingSurface *surface;
DynamicSprite *sprite;

function room_RepExec(){

  //if the left mouse button is down and the game accepts input, 
  //store x and y of the current mouse position
  //as well as copy the current view of the screen to sprite (so already drawn lines will stay)  
  if(Mouse.IsButtonDown(eMouseLeft) && accept_input){  
      accept_input = false;
      start_x = mouse.x;
      start_y = mouse.y;     
      sprite = sprite.CreateFromScreenShot();  
      line_count++;      
  }

  //if the mouse button is released and input set to false, reset accept_input and stop drawing lines
  if(!Mouse.IsButtonDown(eMouseLeft) && !accept_input ){
    accept_input = true;    
  }
  
  //if accept_input is false, this means the button is pressed, so draw the lines
  if(!accept_input){
    surface = Room.GetDrawingSurfaceForBackground();
    
    //if this is the first line/match to be drawn, draw the background from the 'clean' sprite
    //otherwise draw the background with already drawn lines
    if(line_count == 0) sprite = sprite.CreateFromExistingSprite(id_of_background_image);      
    
    //draw the sprite variable on the screen
    surface.DrawImage(0, 0,  sprite.Graphic);  
    
    //draw line from the place where the mouse was pressed to the current position of the mouse
    surface.DrawLine(start_x, start_y,  mouse.x, mouse.y, LINE_WIDTH);
    surface.DrawingColor = number_of_colour;   
    surface.Release();     
  }
}


Note that once you are finished, you should delete the sprite variable with
Code: ags
sprite.Delete();


Hope this helps, if not, give ma a shout.




Amir

Ok, thank you so much  ;-D I'll test it right away in my puzzle room.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

#7
I've only tested drawing so far, but there's a problem or two. Whenever I click to draw, the music stutters annoyingly and I have 2 buttons there, whenever I click to draw, the sprites of buttons become more pixelated and look aliased. Do u know why?  :-\  I doubted the width, I tried int LINE_WIDTH = 1; but that didn't help. My resolution is 1280 x 720.
I also doubt the mouse cursor because it stays there after you draw. Is there any way to prevent it?

And I cannt change the color surface.DrawingColor = 53248; I want it red but it's always black, but that doesn't matter, that's no problem.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Pogwizd

Quote from: Amir on Wed 08/06/2022 15:40:55
I also doubt the mouse cursor because it stays there after you draw. Is there any way to prevent it?
The mouse stays because the game captures whatever is displayed on the screen. I didn't have that problem because the cursor was hidden in my room. I guess you could try hiding the cursor right before this line:
Code: ags
sprite = sprite.CreateFromScreenShot();

...and then showing it again afterwards.



Quote from: Amir on Wed 08/06/2022 15:40:55
And I cannt change the color surface.DrawingColor = 53248; I want it red but it's always black, but that doesn't matter, that's no problem.
Are you sure your colour code is correct? In my game it had the value of 13 and it worked fine. Have you tried any other colour numbers?


Quote from: Amir on Wed 08/06/2022 15:40:55
Whenever I click to draw, the music stutters annoyingly.
I didn't have that issue. Are you doing anything with the audio clips in the same room_RepExec() function?



Quote from: Amir on Wed 08/06/2022 15:40:55
the sprites of buttons become more pixelated and look aliased.
Are these buttons the only GUI elements shown in this puzzle room? I am not an expert, and I am not sure what may be the cause of that. I wonder if the same would happen if you hid the buttons for the time of capturing the screenshot from the background (just like with the cursor)?




Amir

#9
QuoteThe mouse stays because the game captures whatever is displayed on the screen. I didn't have that problem because the cursor was hidden in my room. I guess you could try hiding the cursor right before this line

I had tried this and Changemode of the mouse as well, in the code and in on_mouse_click but it dosn't work, it would work if you just click once, the mouse cursor disappears but you can no longer see where you draw the line. It doesn't matter, that's no problem, it doesn't look that bad.

QuoteAre you sure your colour code is correct? In my game it had the value of 13 and it worked fine. Have you tried any other colour numbers?
Yes and I tried many codes, it stays black  ;-D that's also no problem. I like black metal.

QuoteI didn't have that issue. Are you doing anything with the audio clips in the same room_RepExec() function?
No nothing, by the way it's in the Global script because of the buttons "OK" and "Reset" I have 3 Buttons there, ok reset and exit room, it won't look pretty if they keep disappearing and reappearing when you draw and finish drawing.  ;-D

I think I know now why this is happening, because of the screenshot the code takes. When I take a screenshot in the game, the music stutters the same as in this room. I don't think it's a good idea to draw with a screenshot at my resolution 1280 x 720. I think a Gui as BackgroundGraphic would be better in my case. Look at this link https://www.adventuregamestudio.co.uk/forums/index.php?topic=54958.0

I will try to mix your codes and do it with Gui, like I said, I have never written any code using Drawing Surface. If you can help with that, that would be very nice. (or someone else who reads and knows)
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#10
You don't really need a screenshot here, as you may save the finished lines on a separate sprite.

Idea for this is:
Draw on a dynamic sprite, cleared to transparency.
Remember line coordinates, then on each "drawing" step clear the old line by drawing it with transparent color, and draw a new one with updated coordinates.

Assign that sprite to a room object or GUI, so that you don't have to repaint the background all the time either.

Since you have multiple lines, save them on a second sprite, and only paste finished lines there as soon as they are completed. Assign that sprite to another object or gui.

Amir

Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Regarding color not working, I noticed that in the above script example DrawingColor is set after DrawLine. You need to swap these two commands.

Amir

Quote from: Crimson Wizard on Thu 09/06/2022 09:02:59
Regarding color not working, I noticed that in the above script example DrawingColor is set after DrawLine. You need to swap these two commands.

(laugh) your right, now it's red.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Snarky

Quote from: Crimson Wizard on Thu 09/06/2022 08:30:53
on each "drawing" step clear the old line by drawing it with transparent color

Surely it's easier and probably more efficient to just wipe the whole sprite by calling DrawingSurface.Clear(COLOR_TRANSPARENT)?

Crimson Wizard

#15
Quote from: Snarky on Thu 09/06/2022 09:19:37
Quote from: Crimson Wizard on Thu 09/06/2022 08:30:53
on each "drawing" step clear the old line by drawing it with transparent color

Surely it's easier and probably more efficient to just wipe the whole sprite by calling DrawingSurface.Clear(COLOR_TRANSPARENT)?

Clear() sets every pixel on a sprite to certain value. DrawLine sets only necessary pixels, but does extra math to calculate how line is going. A speed test would be required to see the actual difference, which may also depend on the sprite resolution and average line length.

Crimson Wizard

Here's the working script, created by adjusting the above script by Pogwizd.
You only need 2 GUIs to make it work, called gGuiLine and gGuiAllLines.

Code: ags


bool accept_input = true;
bool draw = false;
int LINE_WIDTH = 5;
int sx, sy, ex, ey;
DynamicSprite *spriteForLine;
DynamicSprite *spriteForAll;
int line_color = 53248;

function room_Load()
{
  spriteForAll = DynamicSprite.Create(Room.Width, Room.Height);
  gGuiAllLines.BackgroundGraphic = spriteForAll.Graphic;
}

function room_Leave()
{
  if (spriteForLine) {
    spriteForLine.Delete();
  }
  if (spriteForAll) {
    spriteForAll.Delete();
  }
}
 
function room_RepExec(){
 
  bool mouse_down = Mouse.IsButtonDown(eMouseLeft);
  //if the left mouse button is down and the game accepts input, 
  //store x and y of the current mouse position
  if (mouse_down && accept_input){
    accept_input = false;
    draw = true;
    sx = mouse.x;
    sy = mouse.y;
    ex = sx;
    ey = sy;
    spriteForLine = DynamicSprite.Create(Room.Width, Room.Height);
    gGuiLine.BackgroundGraphic = spriteForLine.Graphic;
  //draw line from the place where the mouse was pressed to the current position of the mouse
  } else if (mouse_down && draw) {
    DrawingSurface *surface = spriteForLine.GetDrawingSurface();
    // first erase old line by repainting it with a transparent color
    surface.DrawingColor = COLOR_TRANSPARENT;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    ex = mouse.x;
    ey = mouse.y;
    surface.DrawingColor = line_color;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    surface.Release();
  // if the mouse button is released and input set to false, reset accept_input and stop drawing lines
  } else if (!mouse_down && !accept_input) {
    accept_input = true;
    draw = false;
    // paste resulting line onto the final sprite with many lines
    DrawingSurface *surface = spriteForAll.GetDrawingSurface();
    surface.DrawImage(0, 0, spriteForLine.Graphic);
    surface.Release();
    // don't display single-line sprite anymore
    gGuiLine.BackgroundGraphic = 0;
    spriteForLine.Delete();
  }
}

Amir

Oh cool, I'm trying to do it now with sprite.CreateFromExistingSprite(object[2].Graphic); but when you've already done it with guis, I'll take your code. (not yet tested)

But shouldn't it be in the Global Script? As I said, I have an OK button that the player has to click on if all the lines are correct. And the button is always in Global Script. It won't see the lines like that in the room 19.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Thu 09/06/2022 09:51:26
But shouldn't it be in the Global Script? As I said, I have an OK button that the player has to click on if all the lines are correct. And the button is always in Global Script. It won't see the lines like that in the room 19.

You can put that anywhere you like. For example you may create a separate script module for that, and add functions that turn the line drawing on and off.

But it does not have to be in the global script only to let button do something. You may pass a "signal" into the room script using CallRoomScript command:
https://adventuregamestudio.github.io/ags-manual/Globalfunctions_General.html#callroomscript

Amir

Quote from: Crimson Wizard on Thu 09/06/2022 09:55:27
Quote from: Amir on Thu 09/06/2022 09:51:26
But shouldn't it be in the Global Script? As I said, I have an OK button that the player has to click on if all the lines are correct. And the button is always in Global Script. It won't see the lines like that in the room 19.

You can put that anywhere you like. For example you may create a separate script module for that, and add functions that turn the line drawing on and off.

But it does not have to be in the global script only to let button do something. You may pass a "signal" into the room script using CallRoomScript command:
https://adventuregamestudio.github.io/ags-manual/Globalfunctions_General.html#callroomscript


Thank u so much. It works like a charm. But I can't make this on_call. what am I doing wrong?
this is the reset button. All lines should be deleted.

Global scrip
Code: ags

function gReset_OnClick(GUI *theGui, MouseButton button)
{
if (cBerny.Room == 19)  
CallRoomScript(1);
}


Room 19
Code: ags

function on_call (int Lines)
{
  
if (Lines == 1)
{
  if (spriteForLine) {
    spriteForLine.Delete();
  }
  if (spriteForAll) {
    spriteForAll.Delete();
  }  
}
}


Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#20
Quote from: Amir on Thu 09/06/2022 11:27:40But I can't make this on_call. what am I doing wrong?
this is the reset button. All lines should be deleted.

Your on_call code works for me.

I may only suggest begin with checking if the button script is called, on_call is called, and the conditions work correctly. This may be tested for instance with "Display" command, or placing breakpoints in the editor and running game with F5.

Also:
- is the button clickable;
- is the button covered by any clickable guis.

Amir

Oh, I probably clicked wrong.

Code: ags

function gReset_OnClick(GUI *theGui, MouseButton button)
{
if (cBerny.Room == 19)  
CallRoomScript(1);
}
 


That was the gui, not the button  (laugh)

They get deleted but when you want to draw again, it gets drawed then disappears because we deleted spriteForAll.Delete(); . Something is probably missing in else if
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Thu 09/06/2022 13:44:35
They get deleted but when you want to draw again, it gets drawed then disappears because we deleted spriteForAll.Delete(); . Something is probably missing in else if

Well, the solution is to not just delete spriteForAll when you click on button, but to clear it instead. Or delete it and recreate again.

Code: ags

function on_call (int Lines)
{
  if (Lines == 1)
  {
     if (spriteForLine) {
       spriteForLine.Delete();
     }

     DrawingSurface *surface = spriteForAll.GetDrawingSurface();
     surface.Clear();
     surface.Release();
  }
}


This will preserve the main sprite, but clear it with transparent color

Amir

Aaah I understood the principle now of these DrawingSurface. Thank u  :)
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

Part 2 of the puzzle that is killing me. check if all lines are correct. I'm trying to do somthing like that with global variables.
according to CW's code. (I use the picture in the first post as an example)

Code: ags

   if ((draw == false) && (ex == mouse.x && ey == mouse.y))
  {
  if ((Hotspot.GetAtScreenXY(sx, sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(ex, ey) == hotspot[2]))
  AnchorBoat = true;
  
  else if ((Hotspot.GetAtScreenXY(sx, sy) == hotspot[3]) && (Hotspot.GetAtScreenXY(ex, ey) == hotspot[4]))
  ColaHotdog = true; 
  } 


Button OK

Code: ags

function Button58_OnClick(GUIControl *control, MouseButton button)
{
if ((AnchorBoat == true)  &&  (ColaHotdog == true) )
cBerny.Say("Bingo."); 

}


That dosn't work of course.
It occurred to me that this is for just one line, not multiple, am I right? how do I do this way for multiple lines? Does anyone have an idea.


Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Thu 09/06/2022 19:15:56
It occurred to me that this is for just one line, not multiple, am I right? how do I do this way for multiple lines? Does anyone have an idea.

There are two approaches, either:

1) Make a test when player finishes drawing line and save the test result.
2) Save final line coordinates (sx,sy,ex,ey) and test later (on button press?).

Since you have multiple lines you will have to make an array of final line coordinates or test results.

for a quick example:
Code: ags

struct Line {
    int sx,sy,ex,ey;
};

#define MAX_LINES 100
Line Lines[MAX_LINES];


Remember the line count in a integer variable, increase each time a line was finished, and reset to 0 when lines are cleared.

Then in the end, you may do a check:
Code: ags

    for (int i = 0; i < line_count; i++) {
        // test Lines[i] values:
        if (Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == ...) { // where line starts
        }
        if (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == ...) { // where line ends
        }
    }

Amir

Ah right Pogwizd was talking about array, I totally forgot about that. I'll try that after dinner.

// where line starts and // where line ends = where the hotspots are? x and y of the hotspots? because I don't know where exactly the player will draw the line to the hotspot, up from the hotspot down, right or left.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

Hi CW,

could you check please, because Berny doesn't say bingo. (Im trying first only for 2 lines, 4 hotspots)

In room_RepExec

Code: ags

 for (int i = 0; i < line_count; i++)   // that's for loop for each line the player will draw, right?
 {
        // test Lines[i] values:
        if (Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == hotspot[1]) { // where line starts
        }
        if (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[2]) { // where line ends
        }
        if (Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == hotspot[3]) { // where line starts
        }
        if (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[4]) { // where line ends
        }
  }


In Button

Code: ags

if ((Hotspot.GetAtScreenXY(sx, sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(ex, ey) == hotspot[2])
&& (Hotspot.GetAtScreenXY(sx, sy) == hotspot[3]) && (Hotspot.GetAtScreenXY(ex, ey) == hotspot[4])
)

cBerny.SayBubble("Bingo.");


I tried also in Button with if (draw == false) but it doesn't work.

I have a second problem with on_call. I want to make 2 calls for Reset and OK button.

Code: ags

function on_call (int LinesReset, int LinesOK) 
{
  
if (LinesReset == 1)
{
     if (spriteForLine) {
       spriteForLine.Delete();
     }
 
     DrawingSurface *surface = spriteForAll.GetDrawingSurface();
     surface.Clear();
     surface.Release();
}

if (LinesOK == 2)
{
if ((Hotspot.GetAtScreenXY(sx, sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(ex, ey) == hotspot[2]))
cBerny.SayBubble("Bingo.");
}
}


In global script

Code: ags

function Button59_OnClick(GUIControl *control, MouseButton button)
{
if (cBerny.Room == 19)  
CallRoomScript(1);
}

function Button58_OnClick(GUIControl *control, MouseButton button)
{ 
if (cBerny.Room == 19)  // OK button
CallRoomScript(2);
}


I'm getting an error message .... function on_call (expected 2, supplied 1). what am I doing wrong?  :-\
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#28
I think you misunderstood my examples. The "room_RepExec" code you posted does nothing, it's just "if" condition with nothing inside. My code was a placeholder that should be filled with something. For instance, you could remember which items are connected, similar to the code you posted yesterday:
https://www.adventuregamestudio.co.uk/forums/index.php?topic=60037.msg636646898#msg636646898

The code "In Button" makes more sense, but I don't know where did you get "sx,sy" etc variables from. The idea was to use the stored variables from Lines instead.

So, the code called from the button press could look like:
Code: ags

  // test all lines to see what do they connect
  for (int i = 0; i < line_count; i++)
 {
     if ((Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[2]))
          AnchorBoat = true;
     else if ((Hotspot.GetAtScreenXY((Lines[i].sx, Lines[i].sy) == hotspot[3]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[4]))
          ColaHotdog = true;
     // and so on -- other variants here
  }


afterwards, when you found and remembered which combinations are correct, you could display results, for example:
Code: ags

  if (AnchorBoat && ColaHotdog)
    cBerny.SayBubble("Bingo.");




In regards to the on_call problem, the on_call can take only 1 argument, as shown in the manual. You should compare that 1 argument with all possible values.
Code: ags

function on_call (int event) 
{
  
  if (event == 1) // lines reset
  {
     // do something for lines reset
  }
  else if (event == 2) // lines ok
  {
     // do something for lines check
  }
}


If you don't like using simple numbers, and prefer some text instead, you may create a enum. For example you may put this in the global header:
Code: ags

enum LinePuzzleEvents {
    LinePuzz_Reset,
    LinePuzz_Check
};


And then just do
Code: ags

function on_call (int event) 
{
  if (event == LinePuzz_Reset) // lines reset
  {
     // do something for lines reset
  }
  else if (event == LinePuzz_Check) // lines ok
  {
     // do something for lines check
  }
}


And similarly when doing CallRoomScript:
Code: ags

CallRoomScript(LinePuzz_Reset); // and so on

Amir

#29
Oh did you mean with the boolean variables. Yes I got it totally wrong.

Quotebut I don't know where did you get "sx,sy" etc variables from.

lol

I don't know why I like it that way  ;-D
Code: ags

  if ((AnchorBoat == true) && (ColaHotdog == true))
    cBerny.SayBubble("Bingo.");



Thanks for the information. I'll try it.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

#30
It doesn't work  :-\ Maybe something else is missing?

I'm trying with just one line and bool. AnchorBoat = true;

I don't think it makes any difference.
Code: ags

//hotspot[1].Enabled = false;  
//hotspot[2].Enabled = false; 
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Fri 10/06/2022 11:39:42
It doesn't work  :-\ Maybe something else is missing?

I'm trying with just one line and bool. AnchorBoat = true;

Please post your current code?

Amir

Ok,

in room_RepExec (under the code of drawing)

Code: ags

for (int i = 0; i < line_count; i++)
 {
        // test Lines[i] values:
     if ((Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[2]))
          VBaer = true;
     //else if ((Hotspot.GetAtScreenXY((Lines[i].sx, Lines[i].sy) == hotspot[3]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[4]))
         // ColaHotdog = true;
  }


Button

Code: ags

function on_call (int LinesOK) 
{

if (LinesOK == 2)
{
if (VBaer == true) cBerny.SayBubble("Bingo");
}
}


Global

Code: ags


function Button58_OnClick(GUIControl *control, MouseButton button)
{
if (cBerny.Room == 19)  // OK button
CallRoomScript(2);
}
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Fri 10/06/2022 12:19:19
Ok,

in room_RepExec (under the code of drawing)


What else is in room_RepExec? how do you fill Lines array?

Crimson Wizard

Actually,.... if you are using Lines array, then you should not be checking hotspots in RepExec. Or, if you check hotspots in RepExec, then you do not need Lines array at all.

There are 2 approaches:
1) Save Lines array in rep exec. Test both the line results and final results after button is pressed (in on_call).
2) Don't use Lines array at all. Test line results in rep exec and save booleans (VBaer and others) there. Then test these booleans in on_call.

Amir

Quote from: Crimson Wizard on Fri 10/06/2022 17:18:14
Quote from: Amir on Fri 10/06/2022 12:19:19
Ok,

in room_RepExec (under the code of drawing)


What else is in room_RepExec? how do you fill Lines array?

No nothing, Lines array just like you wrote me. I didn't change anything. Take a look please, there is everything. It's not much in this room.

Code: ags


struct Line {
    int sx,sy,ex,ey;
};
 
#define MAX_LINES 100
Line Lines[MAX_LINES];

int line_count;

bool accept_input = true;
bool draw = false;
int LINE_WIDTH = 5;
int sx, sy, ex, ey;
DynamicSprite *spriteForLine;
DynamicSprite *spriteForAll;
int line_color = 53248;

function room_Load()
{
hotspot[1].Enabled = false;  
hotspot[2].Enabled = false;  
hotspot[3].Enabled = false;  
hotspot[4].Enabled = false; 
  
gSchliessen.Visible = true;
gSchliessen.SetPosition(1140, 16);


 gInventoryBar.Visible = false;
 gInventoryBar.Transparency = 100;
 
 if (Game.TranslationFilename == "English") object[1].Visible = true;
 
 gverbinden.Visible = true;
 gReset.Visible = true;
 
  spriteForAll = DynamicSprite.Create(Room.Width, Room.Height);
  gGuiAllLines.BackgroundGraphic = spriteForAll.Graphic;
 
 gGuiLine.Visible = true;
 gGuiAllLines.Visible = true;
}


/*
function on_call (int event) 
{
  
  if (event == 1) // lines reset
  {
       if (spriteForLine) {
       spriteForLine.Delete();
     }
 
     DrawingSurface *surface = spriteForAll.GetDrawingSurface();
     surface.Clear();
     surface.Release();  
    
  }
  else if (event == 2) // lines ok
  {
   if (VBaer == true) cBerny.SayBubble("Bingo"); 
     
  }
}
*/

function on_call (int LinesOK) 
{

if (LinesOK == 2)
{
if (VBaer == true) cBerny.SayBubble("Bingo");
}

}


function room_Leave()
{
  
  if (spriteForLine) {
    spriteForLine.Delete();
  }
  if (spriteForAll) {
    spriteForAll.Delete();
  }
 
 gGuiLine.Visible = false;
 gGuiAllLines.Visible = false;
 
  
}


function room_RepExec()
{ 
  
  bool mouse_down = Mouse.IsButtonDown(eMouseLeft);
  //if the left mouse button is down and the game accepts input, 
  //store x and y of the current mouse position
  if (mouse_down && accept_input)
  {
    accept_input = false;
    draw = true;
    sx = mouse.x;
    sy = mouse.y;
    ex = sx;
    ey = sy;
    spriteForLine = DynamicSprite.Create(Room.Width, Room.Height);
    gGuiLine.BackgroundGraphic = spriteForLine.Graphic;
  //draw line from the place where the mouse was pressed to the current position of the mouse
  } 
  else if (mouse_down && draw)
  { 
    DrawingSurface *surface = spriteForLine.GetDrawingSurface();
    // first erase old line by repainting it with a transparent color
    surface.DrawingColor = COLOR_TRANSPARENT;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    ex = mouse.x;
    ey = mouse.y;
    surface.DrawingColor = line_color;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    surface.Release();
  // if the mouse button is released and input set to false, reset accept_input and stop drawing lines
  } 
  else if (!mouse_down && !accept_input)
  {
    accept_input = true;
    draw = false;
    // paste resulting line onto the final sprite with many lines
    DrawingSurface *surface = spriteForAll.GetDrawingSurface();
    surface.DrawImage(0, 0, spriteForLine.Graphic);
    surface.Release();
    // don't display single-line sprite anymore
    gGuiLine.BackgroundGraphic = 0;
    spriteForLine.Delete();
    
  }
  
  
  /////////
  
 
 for (int i = 0; i < line_count; i++)
 {
        // test Lines[i] values:
      
     if ((Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[2]))
          VBaer = true;
       
     //else if ((Hotspot.GetAtScreenXY((Lines[i].sx, Lines[i].sy) == hotspot[3]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[4]))
         // ColaHotdog = true;
  }
 
  
}


Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

Quote from: Crimson Wizard on Fri 10/06/2022 17:38:39
Actually,.... if you are using Lines array, then you should not be checking hotspots in RepExec. Or, if you check hotspots in RepExec, then you do not need Lines array at all.

There are 2 approaches:
1) Save Lines array in rep exec. Test both the line results and final results after button is pressed (in on_call).
2) Don't use Lines array at all. Test line results in rep exec and save booleans (VBaer and others) there. Then test these booleans in on_call.


Ok, all right.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#37
Quote from: Amir on Fri 10/06/2022 17:39:22
No nothing, Lines array just like you wrote me. I didn't change anything.

The thing is, what I wrote about Lines was just a starting example + tips of how you may approach this, it was not a complete code.
I am not explaining this well.

Let's discuss the logic first.

1) Each time the player finishes drawing the line, the line should be remembered.
2) When player presses the button to check the puzzle, two things should be performed:
2.1) first we check all the remembered lines, and find out what hotspots they connect. Each time there's a good connection, we save that result in corresponding bool.
2.2) second we check the resulting bools, to find out the actual state of the puzzle, and do something about it (display the message, and so on).
3) When we reset the line sprites we should also reset the line counter.


Now, let's look at the RepExec where we draw the line. The code responsible for finishing the line is this:
Code: ags

  else if (!mouse_down && !accept_input)
  {
    accept_input = true;
    draw = false;
    // paste resulting line onto the final sprite with many lines
    DrawingSurface *surface = spriteForAll.GetDrawingSurface();
    surface.DrawImage(0, 0, spriteForLine.Graphic);
    surface.Release();
    // don't display single-line sprite anymore
    gGuiLine.BackgroundGraphic = 0;
    spriteForLine.Delete();
  }


We need to save the line coordinates right there, under this "if", and increase the line counter to know how many lines are drawn:
Code: ags

     ..............
     // don't display single-line sprite anymore
     gGuiLine.BackgroundGraphic = 0;
     spriteForLine.Delete();
     // save line
     Lines[line_count].sx = sx;
     Lines[line_count].sy = sy;
     Lines[line_count].ex = ex;
     Lines[line_count].ey = ey;
     line_count++; // increase line counter


Now, we may go to on_call and put line tests there; but on another thought, it may be more convenient to write a separate function for that, to keep code tidy. So we create our own function that just test lines and saves bools:
Code: ags

function TestLines() {
    for (int i = 0; i < line_count; i++) {
        if ((Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy) == hotspot[1]) && (Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey) == hotspot[2]))
          VBaer = true;
        // ..... and more pair tests here
    }
}


And then in on_call we just call TestLines and perform final test:
Code: ags

function on_call (int event) 
{
    // LinesOk event
    if (event== 2) {
         // test all lines and save bools
         TestLines(); 
         // now final test(s)
         if (VBaer == true) cBerny.SayBubble("Bingo");
    }
}


We also may need to reset line counter along with the sprites. We need to do this in both room_Leave() and on_call where you reset the lines.
E.g. in on_call:
Code: ags

  if (event == 1) // lines reset
  {
     if (spriteForLine) {
       spriteForLine.Delete();
     }
 
     DrawingSurface *surface = spriteForAll.GetDrawingSurface();
     surface.Clear();
     surface.Release();

     line_count = 0; // <---- reset lines counter
  }

Amir

Yes, I completely understand the logic. But don't ask me why I didn't save the line coordinates after drawing them. I didn't think of that  :-\  I don't have your experience  :) moreover the code is not a simple code. but yes, now it looks a lot more logical. But... it still doesn't work. Now my wish of my life is to see him say this F. Bingo.

QuoteActually,.... if you are using Lines array, then you should not be checking hotspots in RepExec. Or, if you check hotspots in RepExec, then you do not need Lines array at all.

There are 2 approaches:
1) Save Lines array in rep exec. Test both the line results and final results after button is pressed (in on_call).
2) Don't use Lines array at all. Test line results in rep exec and save booleans (VBaer and others) there. Then test these booleans in on_call.

Is that correct after u saw the error in the code?

I think without the Lines array will not work.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#39
This is my room code that works:

Note that when making tests, I check both directions, because player could draw line from hotspot 2 to 1 too.

Code: ags

// room script file

bool accept_input = true;
bool draw = false;
int LINE_WIDTH = 5;
int sx, sy, ex, ey;
DynamicSprite *spriteForLine;
DynamicSprite *spriteForAll;
int line_color = 53248;

struct Line {
    int sx,sy,ex,ey;
};
 
#define MAX_LINES 100
Line Lines[MAX_LINES];
int line_count;

// Line linking results
bool VBaer;


function room_Load()
{
  spriteForAll = DynamicSprite.Create(Room.Width, Room.Height);
  gGuiAllLines.BackgroundGraphic = spriteForAll.Graphic;
}

// ResetLines function clears lines up, clears results too.
// pass "true" if you want to delete full sprite, or only clear it
function ResetLines(bool delete_all)
{
  if (spriteForLine) {
    spriteForLine.Delete();
    spriteForLine = null;
  }

  // delete full lines sprite or only clear it
  if (delete_all) {
    spriteForAll.Delete();
    spriteForAll = null;
  } else {
    DrawingSurface *surface = spriteForAll.GetDrawingSurface();
    surface.Clear();
    surface.Release();
  }
  
  // Reset saved lines and results
  line_count = 0;
  VBaer = false;
}

function room_Leave()
{
  ResetLines(true);
}
 
function room_RepExec()
{ 
  bool mouse_down = Mouse.IsButtonDown(eMouseLeft);
  //if the left mouse button is down and the game accepts input, 
  //store x and y of the current mouse position
  if (mouse_down && accept_input){  
    accept_input = false;
    draw = true;
    sx = mouse.x;
    sy = mouse.y;
    ex = sx;
    ey = sy;
    spriteForLine = DynamicSprite.Create(Room.Width, Room.Height);
    gGuiLine.BackgroundGraphic = spriteForLine.Graphic;
  } else if (mouse_down && draw) {
    DrawingSurface *surface = spriteForLine.GetDrawingSurface();
    // first erase old line by repainting it with a transparent color
    surface.DrawingColor = COLOR_TRANSPARENT;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    //draw line from the place where the mouse was pressed to the current position of the mouse
    ex = mouse.x;
    ey = mouse.y;
    surface.DrawingColor = line_color;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    surface.Release();
  } else if (!mouse_down && !accept_input) {
    //if the mouse button is released and input set to false, reset accept_input and stop drawing lines
    accept_input = true;
    draw = false;
    // paste resulting line onto the final sprite with many lines
    DrawingSurface *surface = spriteForAll.GetDrawingSurface();
    surface.DrawImage(0, 0, spriteForLine.Graphic);
    surface.Release();
    // don't display single-line sprite anymore
    gGuiLine.BackgroundGraphic = 0;
    spriteForLine.Delete();
    // save line
    Lines[line_count].sx = sx;
    Lines[line_count].sy = sy;
    Lines[line_count].ex = ex;
    Lines[line_count].ey = ey;
    line_count++; // increase line counter
  }
}

// Perform line link tests and save results in boolean variables
function TestLines()
{
  for (int i = 0; i < line_count; i++) {
    Hotspot* h1 = Hotspot.GetAtScreenXY(Lines[i].sx, Lines[i].sy);
    Hotspot* h2 = Hotspot.GetAtScreenXY(Lines[i].ex, Lines[i].ey);
    if ((h1 == hotspot[1]) && (h2 == hotspot[2]) ||
        (h1 == hotspot[2]) && (h2 == hotspot[1]))
      VBaer = true;
    // ..... and more pair tests here
  }
}

function on_call(int event)
{
  // reset lines
  if (event == 1) {
    ResetLines(false);
  }
  // check lines
  else if (event == 2) {
    // test all lines and save bools
    TestLines();
    // now final test(s)
    if (VBaer == true)
      player.Say("Bingo");
    ResetLines(false);
  }
}

Amir

Aha this TestLines(); function probably makes a big difference but it doesn't work for me  ???
I have to import the 2 new functions, right?
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#41
Quote from: Amir on Fri 10/06/2022 20:39:33
Aha this TestLines(); function probably makes a big difference but it doesn't work for me  ???
I have to import the 2 new functions, right?

It's not only 2 new functions, there are other differences, compared to the last code you posted above. I guess you could compare the code side by side to see what is different. Or simply paste full code over, and then adjust to your needs.

Amir

#42
Quote from: Crimson Wizard on Fri 10/06/2022 20:56:08
Quote from: Amir on Fri 10/06/2022 20:39:33
Aha this TestLines(); function probably makes a big difference but it doesn't work for me  ???
I have to import the 2 new functions, right?

It's not only 2 new functions, there are other differences, compared to the last code you posted above. I guess you could compare the code side by side to see what is different. Or simply paste full code over, and then adjust to your needs.

Yes it works now. Thank u so much.  ;-D
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

Quote from: Crimson Wizard on Fri 10/06/2022 20:56:08
Quote from: Amir on Fri 10/06/2022 20:39:33
Aha this TestLines(); function probably makes a big difference but it doesn't work for me  ???
I have to import the 2 new functions, right?

It's not only 2 new functions, there are other differences, compared to the last code you posted above. I guess you could compare the code side by side to see what is different. Or simply paste full code over, and then adjust to your needs.

Please forgive me, I have one last question since you have the code. I want to make it so that if you click the OK button and haven't dragged anything yet, nothing happens. I mean if there are no lines there nothing happens when you click OK. It doesn't work like that

Code: ags

else if (event == 2) // lines ok
  {
  // test all lines and save bools
    TestLines();
    // now final test(s)
    
   if ((line_count == 0) && (VBaer == false) && (Grim == false) && (Fenster == false) && (Vase == false))
    {}  // do nothing
    
   else if ((VBaer == true) && (Grim == true) && (Fenster == true) && (Vase == true))
   {
     // Bingo
     
   } 
   
  else
{
 // wrong answer
}

Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Sat 11/06/2022 00:49:40I want to make it so that if you click the OK button and haven't dragged anything yet, nothing happens. I mean if there are no lines there nothing happens when you click OK.

I think it might work if you simply move the "line_count" check up and merge with "if (event == 2)":
Code: ags
if (event == 2 && line_count > 0)

as if there are no lines drawn, then no need to also call TestLines and other things.

Amir

#45
Quote from: Crimson Wizard on Sat 11/06/2022 01:34:54
Quote from: Amir on Sat 11/06/2022 00:49:40I want to make it so that if you click the OK button and haven't dragged anything yet, nothing happens. I mean if there are no lines there nothing happens when you click OK.

I think it might work if you simply move the "line_count" check up and merge with "if (event == 2)":
Code: ags
if (event == 2 && line_count > 0)

as if there are no lines drawn, then no need to also call TestLines and other things.

Good morning, it doesn't work, I've tried many things, like this for example.
Code: ags

  else if (event == 2) // lines ok
  {
  // test all lines and save bools
    TestLines();
    // now final test(s)
  if (line_count == 0) {} // do nothing

  else if ((line_count > 0) && (VBaer == true) && (Grim == true) && (Fenster == true) && (Vase == true))
  {
    // Bingo
  }  
  else
{
 // wrong answer
}    
  }


The result is wrong answer. Something doesn't let it be. The loop? for (int i = 0; i < line_count; i++)

Edit: I'll try to do it with gverbinden.Clickable = false; That is the Gui of the OK button.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

#46
Quote from: Amir on Sat 11/06/2022 08:20:09
Good morning, it doesn't work, I've tried many things, like this for example.

This may be because the line drawing code draws lines even when you click on buttons. So when you click on a button, it draws a small line anyway.
The solution may be to either restrict drawing to certain coordinates, or coordinates of gui that you put sprites on, if you make it not cover whole screen but only area where it is allowed to draw.
Or use ZOrder to put gGuiLine below other controls and test GUI.GetAtScreenXY to see if the mouse is above it before starting to draw.

Code: ags

  bool mouse_down = Mouse.IsButtonDown(eMouseLeft);
  //if the left mouse button is down and the game accepts input, 
  //store x and y of the current mouse position
  if (mouse_down && accept_input){
    if (GUI.GetAtScreenXY(mouse.x, mouse.y) != gGuiLine) // <--------- add this
      return;// <--------- 
   <...>

Amir

QuoteThe solution may be to either restrict drawing to certain coordinates, or coordinates of gui that you put sprites on, if you make it not cover whole screen but only area where it is allowed to draw.

It's not on the whole screen, otherwise the buttons would not be clickable. It's there where the hotspots are. But apparently it still draws invisible lines outside the gui.

Quoteuse ZOrder to put gGuiLine below other controls and test GUI.GetAtScreenXY to see if the mouse is above it before starting to draw.

Ok, i'll test it.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

Yes with if (GUI.GetAtScreenXY(mouse.x, mouse.y) != gGuiLine) return;// I can click on OK gui but not gGuiline, gGuiline is gone. That's good, but when I change ZOrder and put gGuiline behind the other and click on OK gui, wrong answer, like I said, like I'm drawing an invisible line outside of the gui and that's why it doesn't work.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Sat 11/06/2022 13:12:18
Yes with if (GUI.GetAtScreenXY(mouse.x, mouse.y) != gGuiLine) return;// I can click on OK gui but not gGuiline, gGuiline is gone. That's good, but when I change ZOrder and put gGuiline behind the other and click on OK gui, wrong answer, like I said, like I'm drawing an invisible line outside of the gui and that's why it doesn't work.

That should not happen. What are zorder values of these guis?
There's also gGuiAllLines, it should perhaps be made non-clickable to not interfere with anything.

Amir

#50
Quote from: Crimson Wizard on Sat 11/06/2022 14:02:34
Quote from: Amir on Sat 11/06/2022 13:12:18
Yes with if (GUI.GetAtScreenXY(mouse.x, mouse.y) != gGuiLine) return;// I can click on OK gui but not gGuiline, gGuiline is gone. That's good, but when I change ZOrder and put gGuiline behind the other and click on OK gui, wrong answer, like I said, like I'm drawing an invisible line outside of the gui and that's why it doesn't work.

That should not happen. What are zorder values of these guis?
There's also gGuiAllLines, it should perhaps be made non-clickable to not interfere with anything.

They are already both unclickable.

Code: ags

  gGuiLine.ZOrder = -100;
 gGuiAllLines.ZOrder = -100;
 
  gverbinden.ZOrder = 100;  // Ok button
 gReset.ZOrder = 100;    // Reset Button


Both Guis left 0 and width 540 and the button OK width 100 and left 700. I tried moving the Gui OK to the far right edge 1100 left but // wrong answer, as if it were inside the gGuiline.

Is it really only drawn in GUI and not outside?
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Amir

I added if (mouse.x < 505) and it seems to be working now.

Code: ags

if (mouse.x < 505)
  {
  
  if ((object[0].Visible == true) || (object[3].Visible == true)) {}  // nicht malen
  
  else if (mouse_down && accept_input) 
  {
    accept_input = false;
    draw = true;
    sx = mouse.x;
    sy = mouse.y;
    ex = sx;
    ey = sy;
    spriteForLine = DynamicSprite.Create(Room.Width, Room.Height);
    gGuiLine.BackgroundGraphic = spriteForLine.Graphic;
  //draw line from the place where the mouse was pressed to the current position of the mouse
  } 
  else if (mouse_down && draw)
  { 
    DrawingSurface *surface = spriteForLine.GetDrawingSurface();
    // first erase old line by repainting it with a transparent color
    surface.DrawingColor = COLOR_TRANSPARENT;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    ex = mouse.x;
    ey = mouse.y;
    surface.DrawingColor = line_color;
    surface.DrawLine(sx, sy, ex, ey, LINE_WIDTH);
    surface.Release();
    
  // if the mouse button is released and input set to false, reset accept_input and stop drawing lines
  } 
  else if (!mouse_down && !accept_input)
  {
    accept_input = true;
    draw = false;
    // paste resulting line onto the final sprite with many lines
    DrawingSurface *surface = spriteForAll.GetDrawingSurface();
    surface.DrawImage(0, 0, spriteForLine.Graphic);
    surface.Release();
    // don't display single-line sprite anymore
    gGuiLine.BackgroundGraphic = 0;
    spriteForLine.Delete();
         // save line
     Lines[line_count].sx = sx;
     Lines[line_count].sy = sy;
     Lines[line_count].ex = ex;
     Lines[line_count].ey = ey;
     line_count++; // increase line counter 
  }
  
  } 
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

Crimson Wizard

Quote from: Amir on Sat 11/06/2022 15:27:37
They are already both unclickable.

Note that if gGuiLine is also unclickable, then " if (GUI.GetAtScreenXY(mouse.x, mouse.y) != gGuiLine)" won't work, as GUI.GetAtScreenXY only looks for clickable guis.

Amir

Quote from: Crimson Wizard on Sat 11/06/2022 20:10:32
Quote from: Amir on Sat 11/06/2022 15:27:37
They are already both unclickable.

Note that if gGuiLine is also unclickable, then " if (GUI.GetAtScreenXY(mouse.x, mouse.y) != gGuiLine)" won't work, as GUI.GetAtScreenXY only looks for clickable guis.

Yes, you're right. That's why it didn't work. I forgot that I made both Guis unclickable. No matter now. It works now after I restricted mouse activation. Thank u.
Truly, truly, I say to you, blessed are those who play adventure games, for theirs is the kingdom of heaven.

SMF spam blocked by CleanTalk