• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Dialogue

C

Charliebailey03

Guest
Okay, so I watched this guy's tutorial on how to make dialogue boxes, and for the first time ever it it worked first try! But I don't know how to make it into a dialogue for an NPC, or make it changeable for different objects in the creation code or anything. He also uploaded a video of dialogue for NPC's and signs, ETC, but he did something with a destroy object which i don't have in my game because there's no fighting. Also when I start the room with the dialogue in it displays automatically, but I want it to appear when I press a key near an NPC and the have a different dialogue to when I press a key near a different NPC. I can answer any questions needed, I don't mind. However I only started coding in around March so you may have to explain a few things to me a begginer wouldn't understand. Thanks :p



Code:
Ob_Dialog

 - Create Event
-/// Initialize the dialog object
text = noone;
text_visible = "";
text_page = 0;
text_count = 0;
spd = .5;
display_scale = display_get_gui_width()/view_wview[0];
width = sprite_width*display_scale;
margin = 8;

- Draw GUI event
/// Draw the dialog
text_count += spd;
text_visible = string_copy(text[text_ppage], 0, text_count);
var xx = (x-view_xview[0])*display_scale;
var yy = (y-view_yview[0])*display_scale;
draw_text_ext(xx+margin, yy+margin, text_visible, -1, width-(margin*2));



Ob_Speaker
- Create Event
/// Initialize the speaker
dialog = noone;
dialog_page = 0;
xoffset = -32;
yoffset = -40;
text[0] = "FKJSDHFKSJ"
text[1] = "23827328"
text[2] = "FASDFSDHJF"

-Step Event
/// Update the depth
depth = -y;
 
D

dannyjenn

Guest
or make it changeable for different objects in the creation code or anything.
To make it changeable, you need to change text[0], text[1], text[2], etc. You need a different Ob_Speaker (with different text) for every NPC.

As for your code, it makes no sense to me. It seems that Ob_Dialog is using Ob_Speaker's text variable, but nowhere in the code do I see anything indicating that the text variable is in Ob_Speaker rather than in Ob_Dialog. Also, I see that your text_page variable is misspelled. Does the code even run?


Regardless, it should be something more along the lines of this:
Code:
// Ob_Dialog

// Create Event
// Initialize the dialog object
speaker = noone;
text_visible = "";
text_count = 0;
spd = .5;
display_scale = display_get_gui_width()/view_wview[0];
width = sprite_width*display_scale;
margin = 8;

// Draw GUI event
// Draw the dialog
if(speaker!=noone){
    text_count += spd;
    text_visible = string_copy(speaker.text[speaker.dialog_page], 1, 1+floor(text_count));
    var xx = (x-view_xview[0])*display_scale;
    var yy = (y-view_yview[0])*display_scale;
    draw_text_ext(xx+margin, yy+margin, text_visible, -1, width-(margin*2));
}
Code:
// Ob_Speaker1 - This is your first NPC or sign or whatever

// Create Event
// Initialize the speaker
dialog_page = 0;
text[0] = "The quick brown fox";
text[1] = "jumps over the lazy";
text[2] = "dog.";
number_of_lines = 3;

// Step Event
// Update the depth
depth = -y;
Code:
// Ob_Speaker2 - This is your second NPC. You'll need a separate object for each NPC.

// Create Event
// Initialize the speaker
dialog_page = 0;
text[0] = "Hello. I am the second";
text[1] = "NPC.";
number_of_lines = 2;

// Step Event
// Update the depth
depth = -y;

but I want it to appear when I press a key near an NPC and the have a different dialogue to when I press a key near a different NPC.
For this, you need to give your Ob_Speaker1 (and Ob_Speaker2, et al.) a key down event for whatever key, and in it you do this:
Code:
if(point_distance(x, y, player.x, player.y)<30){
    Ob_Dialog.speaker = id;
    if(Ob_Dialog.text_visible==text[dialog_page]){
        dialog_page += 1;
        if(dialog_page==number_of_lines){
            dialog_page = 0;
            Ob_Dialog.text_visible = "";
            Ob_Dialog.text_count = 0;
            Ob_Dialog.speaker = noone;
        }
    }
}
And don't just copy and paste that into your project. Make sure you understand it first. And there are a few things in it that you'll probably need to change.

Also note, ideally you would not be using a separate object for each NPC. But if you're new then this is probably the easiest way for you for now.
 
Last edited by a moderator:
C

Charliebailey03

Guest
To make it changeable, you need to change text[0], text[1], text[2], etc. You need a different Ob_Speaker (with different text) for every NPC.

As for your code, it makes no sense to me. It seems that Ob_Dialog is using Ob_Speaker's text variable, but nowhere in the code do I see anything indicating that the text variable is in Ob_Speaker rather than in Ob_Dialog. Also, I see that your text_page variable is misspelled. Does the code even run?


Regardless, it should be something more along the lines of this:
Code:
// Ob_Dialog

// Create Event
// Initialize the dialog object
speaker = noone;
text_visible = "";
text_count = 0;
spd = .5;
display_scale = display_get_gui_width()/view_wview[0];
width = sprite_width*display_scale;
margin = 8;

// Draw GUI event
// Draw the dialog
if(speaker!=noone){
    text_count += spd;
    text_visible = string_copy(speaker.text[speaker.dialog_page], 1, 1+floor(text_count));
    var xx = (x-view_xview[0])*display_scale;
    var yy = (y-view_yview[0])*display_scale;
    draw_text_ext(xx+margin, yy+margin, text_visible, -1, width-(margin*2));
}
Code:
// Ob_Speaker1 - This is your first NPC or sign or whatever

// Create Event
// Initialize the speaker
dialog_page = 0;
text[0] = "The quick brown fox";
text[1] = "jumps over the lazy";
text[2] = "dog.";
number_of_lines = 3;

// Step Event
// Update the depth
depth = -y;
Code:
// Ob_Speaker2 - This is your second NPC. You'll need a separate object for each NPC.

// Create Event
// Initialize the speaker
dialog_page = 0;
text[0] = "Hello. I am the second";
text[1] = "NPC.";
number_of_lines = 2;

// Step Event
// Update the depth
depth = -y;

For this, you need to give your Ob_Speaker1 (and Ob_Speaker2, et al.) a key down event for whatever key, and in it you do this:
Code:
if(point_distance(x, y, player.x, player.y)<30){
    Ob_Dialog.speaker = id;
    if(Ob_Dialog.text_visible==text[dialog_page]){
        dialog_page += 1;
        if(dialog_page==number_of_lines){
            dialog_page = 0;
            Ob_Dialog.text_visible = "";
            Ob_Dialog.text_count = 0;
            Ob_Dialog.speaker = noone;
        }
    }
}
And don't just copy and paste that into your project. Make sure you understand it first. And there are a few things in it that you'll probably need to change.

Also note, ideally you would not be using a separate object for each NPC. But if you're new then this is probably the easiest way for you for now.
Thanks for your help, ill try it out now
 
C

Charliebailey03

Guest
To make it changeable, you need to change text[0], text[1], text[2], etc. You need a different Ob_Speaker (with different text) for every NPC.

As for your code, it makes no sense to me. It seems that Ob_Dialog is using Ob_Speaker's text variable, but nowhere in the code do I see anything indicating that the text variable is in Ob_Speaker rather than in Ob_Dialog. Also, I see that your text_page variable is misspelled. Does the code even run?


Regardless, it should be something more along the lines of this:
Code:
// Ob_Dialog

// Create Event
// Initialize the dialog object
speaker = noone;
text_visible = "";
text_count = 0;
spd = .5;
display_scale = display_get_gui_width()/view_wview[0];
width = sprite_width*display_scale;
margin = 8;

// Draw GUI event
// Draw the dialog
if(speaker!=noone){
    text_count += spd;
    text_visible = string_copy(speaker.text[speaker.dialog_page], 1, 1+floor(text_count));
    var xx = (x-view_xview[0])*display_scale;
    var yy = (y-view_yview[0])*display_scale;
    draw_text_ext(xx+margin, yy+margin, text_visible, -1, width-(margin*2));
}
Code:
// Ob_Speaker1 - This is your first NPC or sign or whatever

// Create Event
// Initialize the speaker
dialog_page = 0;
text[0] = "The quick brown fox";
text[1] = "jumps over the lazy";
text[2] = "dog.";
number_of_lines = 3;

// Step Event
// Update the depth
depth = -y;
Code:
// Ob_Speaker2 - This is your second NPC. You'll need a separate object for each NPC.

// Create Event
// Initialize the speaker
dialog_page = 0;
text[0] = "Hello. I am the second";
text[1] = "NPC.";
number_of_lines = 2;

// Step Event
// Update the depth
depth = -y;

For this, you need to give your Ob_Speaker1 (and Ob_Speaker2, et al.) a key down event for whatever key, and in it you do this:
Code:
if(point_distance(x, y, player.x, player.y)<30){
    Ob_Dialog.speaker = id;
    if(Ob_Dialog.text_visible==text[dialog_page]){
        dialog_page += 1;
        if(dialog_page==number_of_lines){
            dialog_page = 0;
            Ob_Dialog.text_visible = "";
            Ob_Dialog.text_count = 0;
            Ob_Dialog.speaker = noone;
        }
    }
}
And don't just copy and paste that into your project. Make sure you understand it first. And there are a few things in it that you'll probably need to change.

Also note, ideally you would not be using a separate object for each NPC. But if you're new then this is probably the easiest way for you for now.
############################################################################################
FATAL ERROR in
action number 1
of Key Release Event for <Space> Key
for object ob_speaker:

Variable ob_speaker.player(100045, -2147483648) not set before reading it.
at gml_Object_ob_speaker_KeyReleased_SPACE_1 (line 1) - if(point_distance(x, y, player.x, player.y)<30){
############################################################################################
 

Simon Gust

Member
############################################################################################
FATAL ERROR in
action number 1
of Key Release Event for <Space> Key
for object ob_speaker:

Variable ob_speaker.player(100045, -2147483648) not set before reading it.
at gml_Object_ob_speaker_KeyReleased_SPACE_1 (line 1) - if(point_distance(x, y, player.x, player.y)<30){
############################################################################################
player is most likely supposed to be the player object.
 
D

dannyjenn

Guest
Yeah, this is what I meant by "there are a few things in it that you'll probably need to change". If you understand the code, you'll know what to change. But in particular,
- player needs to be changed to the player object
- 30 probably needs to be changed to some other number depending on how sensitive you want it to be
- you may also want to add additional code so that the dialog only happens when the player is facing the NPC/sign/whatever (right now it happens whenever he's within 30 pixels, regardless)
- if your game is grid-based, then you may want to count the tiles rather than using point_distance
 
C

Charliebailey03

Guest
Yeah, this is what I meant by "there are a few things in it that you'll probably need to change". If you understand the code, you'll know what to change. But in particular,
- player needs to be changed to the player object
- 30 probably needs to be changed to some other number depending on how sensitive you want it to be
- you may also want to add additional code so that the dialog only happens when the player is facing the NPC/sign/whatever (right now it happens whenever he's within 30 pixels, regardless)
- if your game is grid-based, then you may want to count the tiles rather than using point_distance
and how do i write it instead of point_distance?
 

Simon Gust

Member
Um, what does that mean? :(
If your game is based on a grid or array you don't have to use point_distance. So they asked if you do, but you probably don't right. in that case check distance between two objects by either
Code:
point_distance(x, y, objectB.x, objectB.y);
or
distance_to_point(objectB.x, objectB.y);
or
distance_to_object(objectB);
 
C

Charliebailey03

Guest
If your game is based on a grid or array you don't have to use point_distance. So they asked if you do, but you probably don't right. in that case check distance between two objects by either
Code:
point_distance(x, y, objectB.x, objectB.y);
or
distance_to_point(objectB.x, objectB.y);
or
distance_to_object(objectB);
so how much of it do i replace with that?
 

Simon Gust

Member
so how much of it do i replace with that?
according to this code somewhere in this thread
Code:
if(point_distance(x, y, player.x, player.y)<30){
    Ob_Dialog.speaker = id;
    if(Ob_Dialog.text_visible==text[dialog_page]){
        dialog_page += 1;
        if(dialog_page==number_of_lines){
            dialog_page = 0;
            Ob_Dialog.text_visible = "";
            Ob_Dialog.text_count = 0;
            Ob_Dialog.speaker = noone;
        }
    }
}
You already have it. Replace player with the object of the player (probably obj_player).
 
D

dannyjenn

Guest
The overall idea is that you need some way of checking whether the player is close enough to the NPC. (In my example, 30 is furthest the distance. The NPC will only say stuff when the player is within 30 pixels of the NPC.)

What I was saying was, the point_distance() in my example is a very crude way of doing this. The NPC will speak whenever the player is within a 30-pixel radius of him. This may be what you want, but most games (especially grid-based games) don't do it this way. Still, this is the simplest way, so you should start here.

What @Simon Gust was saying is that there are two other built-in functions which make this even easier. They are distance_to_point and distance_to_object... both do the exact same thing but they require less arguments (the former only requires the player's x and y, while the latter only requires the player's id). I think distance_to_object probably runs slightly faster, though the difference is negligible. Just use whichever you're most comfortable with (I personally only ever use point_distance()...)

Now if you haven't got the code running yet, the part you need to change is this line:
if(point_distance(x, y, player.x, player.y)<30){
You need to replace the word "player" with whatever your player object's name is. That's what's causing your error. The rest of the code should run, though I have not tested any of it.

edit - Ninja'd

edit - Sorry, I was wrong about distance_to_point() and distance_to_object(). See Simon Gust's post below.
 
Last edited by a moderator:

Simon Gust

Member
The overall idea is that you need some way of checking whether the player is close enough to the NPC. (In my example, 30 is furthest the distance. The NPC will only say stuff when the player is within 30 pixels of the NPC.)

What I was saying was, the point_distance() in my example is a very crude way of doing this. The NPC will speak whenever the player is within a 30-pixel radius of him. This may be what you want, but most games (especially grid-based games) don't do it this way. Still, this is the simplest way, so you should start here.

What @Simon Gust was saying is that there are two other built-in functions which make this even easier. They are distance_to_point and distance_to_object... both do the exact same thing but they require less arguments (the former only requires the player's x and y, while the latter only requires the player's id). I think distance_to_object probably runs slightly faster, though the difference is negligible. Just use whichever you're most comfortable with (I personally only ever use point_distance()...)

Now if you haven't got the code running yet, the part you need to change is this line:
if(point_distance(x, y, player.x, player.y)<30){
You need to replace the word "player" with whatever your player object's name is. That's what's causing your error. The rest of the code should run, though I have not tested any of it.

edit - Ninja'd
The 3 functions are for distance checking but they are not the same.
distance_to_object gets you the shortest distance from the bounding boxes of both objects.
distance_to_point gets you the distance between the shortest bounding box of one instance and the xy coordinates of the other instance.
point_distance has nothing to do with objects and simply gets you the vector length of point A to point B, hence them being useful in stuff like arrays or grids.

point_distance is by itself the fastest function.
 
C

Charliebailey03

Guest
thanks but what i was saying was how much of
if(point_distance(x, y, player.x, player.y)<30){
do i replace with the better stuff because although theres no errors right now nothing pops up.

so is it all the stuff in brackets or what?
 

Simon Gust

Member
thanks but what i was saying was how much of
if(point_distance(x, y, player.x, player.y)<30){
do i replace with the better stuff because although theres no errors right now nothing pops up.

so is it all the stuff in brackets or what?
Well, the problem could be anywere, we're just trying to make you understand what is supposed to happen.
 
D

dannyjenn

Guest
The 3 functions are for distance checking but they are not the same.
distance_to_object gets you the shortest distance from the bounding boxes of both objects.
distance_to_point gets you the distance between the shortest bounding box of one instance and the xy coordinates of the other instance.
point_distance has nothing to do with objects and simply gets you the vector length of point A to point B, hence them being useful in stuff like arrays or grids.

point_distance is by itself the fastest function.
Oh, oops, I forgot that those other two used the bounding box rather than the origin. Thanks for pointing that out.

thanks but what i was saying was how much of
if(point_distance(x, y, player.x, player.y)<30){
do i replace with the better stuff because although theres no errors right now nothing pops up.

so is it all the stuff in brackets or what?
Hmmm, I don't know. I'll test the code on my computer and get back to you.
 
D

dannyjenn

Guest
Ok, I figured it out. The problem is that 30 is too small a number. Try 100 or 150. Or just use distance_to_object instead.

Also, I forgot a couple lines of code...
Code:
if(point_distance(x, y, Ob_Player.x, Ob_Player.y)<100){
   Ob_Dialog.speaker = id;
   if(Ob_Dialog.text_visible==text[dialog_page]){
       dialog_page += 1;
       Ob_Dialog.text_visible = ""; // <-- You need this...
       Ob_Dialog.text_count = 0; // <-- and this.
       if(dialog_page==number_of_lines){
           dialog_page = 0;
           Ob_Dialog.text_visible = "";
           Ob_Dialog.text_count = 0;
           Ob_Dialog.speaker = noone;
       }
   }
}
Additionally, you'll probably want to put your player's movement code in an if statement, so that the player does not move when the text is on the screen:
Code:
if(Ob_Dialog.speaker = noone){
     // movement code here
}
 
C

Charliebailey03

Guest
Ok, I figured it out. The problem is that 30 is too small a number. Try 100 or 150. Or just use distance_to_object instead.

Also, I forgot a couple lines of code...
Code:
if(point_distance(x, y, Ob_Player.x, Ob_Player.y)<100){
   Ob_Dialog.speaker = id;
   if(Ob_Dialog.text_visible==text[dialog_page]){
       dialog_page += 1;
       Ob_Dialog.text_visible = ""; // <-- You need this...
       Ob_Dialog.text_count = 0; // <-- and this.
       if(dialog_page==number_of_lines){
           dialog_page = 0;
           Ob_Dialog.text_visible = "";
           Ob_Dialog.text_count = 0;
           Ob_Dialog.speaker = noone;
       }
   }
}
Additionally, you'll probably want to put your player's movement code in an if statement, so that the player does not move when the text is on the screen:
Code:
if(Ob_Dialog.speaker = noone){
     // movement code here
}
if(point_distance(x, y, ob_Manacili.x, ob_Manacili.y)<30){
ob_dialog.speaker = id;
ob_dialog.text_visible = "";
ob_dialog.text_count = 0;
ob_dialog.text_page = dialog_page;
if(ob_dialog.text_visible==text[dialog_page]){
if(dialog_page==number_of_lines){
dialog_page = 0;
ob_dialog.speaker = noone;
}
else{
dialog_page += 1;
}
}
this is my code, so do i need to replace or did you forget a bit?
 
C

Charliebailey03

Guest
k ive got this now and it still doesnt work

if(point_distance(x, y, ob_Manacili.x, ob_Manacili.y)<30){
ob_dialog.speaker = id;
if(ob_dialog.text_visible==text[dialog_page]){
dialog_page += 1;
ob_dialog.text_visible = ""; // <-- You need this...
ob_dialog.text_count = 0; // <-- and this.
if(dialog_page==number_of_lines){
dialog_page = 0;
ob_dialog.text_visible = "";
ob_dialog.text_count = 0;
ob_dialog.speaker = noone;
}
}
}
 
C

Charliebailey03

Guest
Code:
if(point_distance(x, y, ob_Manacili.x, ob_Manacili.y)<30){
    ob_dialog.speaker = id;
    if(ob_dialog.text_visible==text[dialog_page]){
        dialog_page += 1;
        ob_dialog.text_visible = ""; // <-- You need this...
        ob_dialog.text_count = 0; // <-- and this.
        if(dialog_page==number_of_lines){
            dialog_page = 0;
            ob_dialog.text_visible = "";
            ob_dialog.text_count = 0;
            ob_dialog.speaker = noone;
        }
    }
}
sorry
 
D

dannyjenn

Guest
You need to change the 30 to some other number. Because 30 is the distance between the origin of both sprites. Depending upon how wide your sprites are, 30 probably isn't going to be enough. Maybe try 100 and if that still doesn't work then 150 or 200 or 300 or whatever.
 
C

Charliebailey03

Guest
my player is 32x32 and it not working still. are you sure my code is right?
 
C

Charliebailey03

Guest
  • Arrays?
  • ds_grid?
  • move_snap()?
  • Room editor's grid and everything moves in increments of the grid size but they're not 'really' aligned to a grid?
  • None of the above?
  • All of the above?
im not sure if this is asking me if i have them, telling me to put them in or asking me if i know what they are ( i dont)
 

Yal

🐧 *penguin noises*
GMC Elder
Asking whether you're handling the grid you mentioned by any of those methods. I'll assume you aren't using either of them if you don't know what any of them are, but that just leads me back to my original "how are you handling the grid?" question... :p
 
D

dannyjenn

Guest
Strictly speaking, he never explicitly said he was using a grid, lol. I'm the one who brought up the grid.
All I was originally saying was that if he was using a grid then he'd probably want to do it a lot differently than a simple point_distance() check.

my player is 32x32 and it not working still. are you sure my code is right?
Did you try changing the number to 100?
The code works fine. I have it all in a test file, though I am unable to upload it at the moment.
 
C

Charliebailey03

Guest
Asking whether you're handling the grid you mentioned by any of those methods. I'll assume you aren't using either of them if you don't know what any of them are, but that just leads me back to my original "how are you handling the grid?" question... :p
Strictly speaking, he never explicitly said he was using a grid, lol. I'm the one who brought up the grid.
All I was originally saying was that if he was using a grid then he'd probably want to do it a lot differently than a simple point_distance() check.

Did you try changing the number to 100?
The code works fine. I have it all in a test file, though I am unable to upload it at the moment.
In my room i uses tiles 0f 16 x 16 and i usually use the determine distance i guess, but only with the block code option of 'if distance_to_object(ob_Manacili) is less than 16
 
D

dannyjenn

Guest
Then try that.
Code:
if(distance_to_object(ob_Manacili)<16){
    // put the rest of the code in here
}
 
Top