Spherical forums

Sphere Development => Sphere Support => Script Support => Topic started by: Xenso on August 01, 2013, 06:15:08 am

Title: How can I add Choice Selection in Messages?
Post by: Xenso on August 01, 2013, 06:15:08 am
 :D So far my MsgBox works perfect.

How can I add choice selection into the interface?
Like when an NPC says something you can select Yes or No to respond
depending on your response a resulting message will show

e.g NPC >> txt("I'm a Psycho",face_magus);
      Choice1 = Yes you are!
      Choice2 = No I am
      Choice3 = I always knew

if Choice1 then NPC >> txt("exactly!",face_magus_normal);
if Choice2 then NPC >> txt("We are psychopath-friends",face_magus_happy)
if Choice1 then NPC >> txt("Yes it's obvious",face_magus_aloof)

Title: Re: How can I add Choice Selection in Messages?
Post by: Radnen on August 01, 2013, 06:37:44 am
By using the exact logic you described.

Code: (javascript) [Select]

this.drawChoice = function(choices) {
    var done = false;
    var choice = 0;

    while (!done)
    {
        RenderMap();

        // ... draw the textboxes and text and stuff ...

        this.arrow.blit(this.x, this.y + choice * 16);
        for (var i = 0; i < choices.length; ++i) {
            this.font.drawText(this.x + 16, this.y + i * 16, choices[i]);
        }

        FlipScreen();

        while (AreKeysLeft()) {
            switch (GetKey()) {
                case KEY_X: done = true; break;
                case KEY_DOWN: if (choice < choices.length-1) choice++; break;
                case KEY_UP: if (choice > 0) choice--; break;
                case KEY_ENTER: done = true;
            }
        }
    }

    return choice; // this is important!
}


To use such a piece of code:
Code: (javascript) [Select]

switch (textbox.showChoice(["Hi.", "Who are you?", "Go away fool!"]))
{
    case 0: break; // maps to choice 0
    case 1: break; // maps to choice 1
    case 2: break; // maps to choice 2
}


The above is just a sample, I'm sure with very slight modification you can get it into your own code. :) I hope to ta least show you the process.

What it does: block the map engine until a user has selected a choice and then quit out with X or ENTER. the choice is then returned and you can store it into a variable or as I did above, put it into a switch. A switch is cool because you can easily map the choice to further text boxes or actions.

You would need an arrow graphic of some kind for the selector, and make sure it's positioned where the text lines start and not where the textbox itself starts since those are in two different placed (as evidenced by the fact you are inserting a portrait, which is cool). You might also need to change the 16 to 8 if it better suits your smaller font size. :)
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 01, 2013, 09:02:04 am
Instead of using an arrow can I use color?
How would I set the color for one line of text in a string and not the entire string or do I have to draw each choice on its own then manage its position?

e.g txt("Choice1 \nChoice2",face_player_thinking);
I want Choice1 to be color_2 which is CreatColor(0,255,255,255);
color_1  is CreatColor(255,255,255,255); ( no ColorMask )

when the player presses KEY_DOWN then Choice2 is set to setColorMask(color_2); Choice1 is set to setColorMask(color_1);

when the player presses KEY_UP then Choice1 is set to setColorMask(color_2); Choice2 is set to setColorMask(color_1);
Title: Re: How can I add Choice Selection in Messages?
Post by: Radnen on August 01, 2013, 01:51:26 pm
It's really not that hard, it's what if statements were invented for.

Code: (javascript) [Select]

    for (var i = 0; i < choices.length; ++i) {
        if (i == choice) {
            this.font.setColorMask(yellow);
        }
        this.font.drawText(this.x + 16, this.y + i * 16, choices[i]);
        this.font.setColorMask(white);
    }


If the i'th position in the choice list is equal to the selected choice turn that particular item yellow, draw the item and reset the color to white.
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 01, 2013, 04:21:42 pm
And thus choice was born 8)

Tomorrow I am going to make a separate window just for choices so you can still see what was said. right now I'm tired.

I learned how to use switch case statements from looking at your code. I made a function that faces the npc towards the player.
Code: (javascript) [Select]

function faceplayer(){
var player_direction = GetPersonDirection(player);
                switch (player_direction) {
                case "north": return "south" ; break;
                case "east" : return "west" ; break;
                case "south": return "north" ; break;
                case "west" : return "east" ; break;
                }
}


then in the Person, On Talk

Code: (javascript) [Select]
SetPersonDirection("seishin",faceplayer());


Thanks dude ;). Tell me if that's not how to use case statements because this was learned from pure speculation of your code.
I think it works perfect though. If statements for this sort of thing are..uh...chunky (<_<)
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 02, 2013, 05:19:34 am
How can I draw the 5th choice in a new position set screen width/2 and 20 pixels

I tried this if statement to change the position but it does it for all the choices
Code: (javascript) [Select]
 if (this.y + i*12 > h && i==4){this.y = 4; this.x = sw/2 + 20}


Please see the attachment to get an idea of what I wanted to do ( Its a mock-up )

The white line in the middle represents screen width/2
I want to continue the drawing like in the picture
Title: Re: How can I add Choice Selection in Messages?
Post by: Radnen on August 02, 2013, 06:09:31 am
That's not too bad,

The for loop would look something like this:
Code: (javascript) [Select]

    var column = 0;
    for (var i = 0; i < choices.length; ++i) {
        if (i == 4) column = 1;

        var x = this.x + column*100;
        var y = this.y + i * 16;

        if (i == choice) {
            arrow.blit(x, y);
            this.font.setColorMask(yellow);
        }
        this.font.drawText(16 + x, y, choices[i]);
        this.font.setColorMask(white);
    }


You might need to fudge the numbers a bit so that it would fit on your screen 100 might be too much or too little. Anyways, this works because before each loop column is set to 0, so the first 4 items (0, 1, 2, and 3) are drawn normally (0*100 = 0). At the 4th item the column is set to 1 and the remaining items are drawn 100 pixels over (1*100 = 100). Also notice I put the arrow into the if condition that states if we are on the 'choice' item this slightly optimizes the code for us since we can leverage the loop to take care of the arrows placement. Also notice I put x and y into their own variables this makes it easier to propagate the value in other places (remember the text needs to have that 16 pixel offset for the arrow). It might seem strange to newer programmers or perhaps harder to follow but being able to track variables through code will get easier the more code you read/write. ;)

Also pay attention to my changes, none of your questions were that hard to figure out. The original loop I showed you to display choices is the backbone of 90% of menu code (the neat code is in display, but the logic is the exact same). Most things only take little changes from such a design. You had a loop that went through each element, you can ask yourself: "Okay, element 4 and onwards is on another column", how do I do another column? What is a column? Oh! It's setting the x position over to the right by some amount. So I should add some kind of change in x position. Hmm, that word "change" means I need to use a variable. Etc. The only math here is addition (and multiplication).

Good programmers ask questions like these when problem solving. Look at the problem grounds up rather than straight through it. ;)
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 02, 2013, 07:49:40 am
I changed you're code to replace i with another variable r that increments itself just like i but when i == 4 sets itself to 0 and then increments itself again.

Code: (javascript) [Select]

var column = 0;
var r = -1;
        for(var i=0;i<choices.length;++i){
          r = ++r;
         if (i == this.txt_h){column = 1;r = 0;}
//this.txt_h = Math.floor(h/12) 12 is the font height, h is the msgbox height
            var choice_x = this.x + column * 88; //var x and var y cant be used
            var choice_y = this.y + r * 12; // r is used not i
           
         if (i == choice)this.setcolor(color_2);
               this.font.drawText(x,y, choices[i]);
               this.setcolor(color_1);
                                         }


The code works but I had to change var x and var y to var choice_x and choice_y because those variable names where already in use and you get the following error message if you use var x and var y.

You're right the logic was very similar  ;)
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 02, 2013, 08:21:49 am
I changed the keys to accommodate for the additional choices using the same logic you showed me for setting the keys in the switch statement  (^_^).

Code: (javascript) [Select]

while (AreKeysLeft()) {
             switch(GetKey()) {
                case KEY_Z:done = true;break;
                case KEY_DOWN: if (choice < choices.length-1) choice++; break;
                case KEY_UP: if (choice > 0) choice--; break;
                case KEY_RIGHT: if (choice <= 3 && choices.length > 3) choice = choice + 4; break;
                case KEY_LEFT: if (choice >= 4) choice = choice - 4; break;
                }
             }

Title: Re: How can I add Choice Selection in Messages?
Post by: Radnen on August 02, 2013, 02:33:09 pm
See, now you're figuring it out! :D
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 03, 2013, 05:15:36 am
I fixed a few things to make the MsgBox more generalized so that you can make it whatever size you want and the choices will still be in the right placement.
Code: (javascript) [Select]

   //Arguments == MsgBox(x,y,w1,w2,h,xo,yo) w1 is for the window, w2 is for the text box
   this.txt_h = Math.floor(h/12);
   this.txt_w = Math.floor(w2/2);


The while loop now looks like this
Code: (javascript) [Select]

while(!done)
        {
        RenderMap();
        this.window.drawWindow(x,y,w1,h);       
        var column = 0;
        var r = -1;
        for(var i=0;i<choices.length;++i){
          r = ++r;
         if (i == this.txt_h){column = 1;r = 0;}
            var choice_x = this.x + column * this.txt_w;
            var choice_y = this.y + r * 12;
           
         if (i == choice)this.setcolor(color_2);
               this.font.drawText(choice_x,choice_y, choices[i]);
               this.setcolor(color_1);
                                         }


But I need to find a ratio between the numbers to fix the case statements for case KEY_RIGHT and case KEY_LEFT
Code: (javascript) [Select]

case KEY_RIGHT: if (choice <= 3 && choices.length > 3) choice = choice + 4; break;
case KEY_LEFT:  if (choice >= 4) choice = choice - 4; break;


choice + 4 and choice - 4 wont cut it.
For example in the attached screenshot if I press right and I am at choice == 7 it will jump to choice == 11 not choice == 22.

Is there a math formula for this sort of thing?
Title: Re: How can I add Choice Selection in Messages?
Post by: Radnen on August 03, 2013, 06:43:24 am
You have to add the height of the column, so that's something like: choice = choice + height / 16 or some other number if you don't use 16 pixel intervals.
Title: Re: How can I add Choice Selection in Messages?
Post by: Xenso on August 03, 2013, 08:09:39 am
Your right (^_^), sometimes I over complicate things.

I used
Code: (javascript) [Select]
this.txt_h = Math.floor(h/12);

h being the height of the msgbox and 12 the font size in pixels.

The while loop for the Keys is now like this
Code: (javascript) [Select]

while (AreKeysLeft()) {
             switch(GetKey()) {
                case KEY_Z:done = true;break;
                case KEY_DOWN: if (choice < choices.length-1) choice++; break;
                case KEY_UP: if (choice > 0) choice--; break;
                case KEY_RIGHT: if (choice <= this.txt_h - 1 && choices.length > this.txt_h - 1) choice = choice + this.txt_h; break;
                case KEY_LEFT:  if (choice >= this.txt_h) choice = choice - this.txt_h; break;
                }
             }