Help - Search - Members - Calendar
Full Version: [Series][Scripting]Selectable Windows
RPG RPG Revolution Forums > Scripting > Script Tutorials > RGSS
Night_Runner
The Script Builders' Tutorials:
----Lesson 2: Selectable Windows----


I. Introduction
II. The Window Creation Story
III. Set-Up
IV. Making Our Window
V. Showing Our Window
VI. Conclusion
VII. Homework


I. Introduction

Greetings! Welcome to the second lesson by the Script Builders (the first being found here).
By this stage, you should have an idea of how to make a window with text, and if you did the homework you'll know how to reposition (& resize) the window smile.gif

We'll start off slowly, and make plenty of references to the last tutorial to help you process it all, but today we're looking at Selectable Windows!


II. The Window Creation Story

You may recall, Window_Selectable is the son of Window_Base. Window_Selectable shares many traits with his father (Window_Base) such as the draw_text command that we used last time. He also has an awesome sense of personal hygiene : D However, Window_Selectable can also have selectable items; such as New Game, Continue, Items, Equipment, Status, Save etc which was why he was kicked out of his family.

III. Setup

Okey dokey, I believe the stage has been set, so like last time, we're going to save the outline of a normal window that is inherited from Window_Selectable into Notepad and call it Window Selectable Outline. Here it is:

CODE
#==============================================================================
# **
#------------------------------------------------------------------------------
#  
#==============================================================================

class
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(x, y, width, height)
    self.index = 0 # Initial Option
    @item_max = 2 # Number of options
    self.contents = Bitmap.new(width - 32, height - 32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
  end
end


You may notice, it looks much like the same guy that was on last week, unfortunately though, we have a no refunds policy ; )
Windows all share the same basic structure, Ruby was kind in its original creation, and had consistency. But if you look closely, you'll see two new items added under the initialize method.

Window_Selectable, much like a nice restaurant, needs to know how many seats you would like, and where the birthday boy would like to sit.
Except in programming, the number of seats is how many choices you would like in your list (@item_max; the amount of choices), and the birthday boy, the one in the spotlight, is representative of the highlighted object, it's index if you will (self.index; the highlighted object).

For this introduction tutorial, we will have two choices (@item_max = 2), and when you first load it up, have the first item in the list highlighted (self.index = 0).


Now onto the fun bit, adding in new stuff smile.gif


IV. Making Our Window

First, let's start off by naming our window in the second line of code next to the comment symbol. Write this: Window_Pet.

Then two lines down, write a brief description like we did last time. Something like: This window allows you to make selections between two different items.

Now, let's look at the line of code that starts with Class.

We remember from last time that we can name our class whatever we want (provided it's not already in use!) and it needs to take its inheritance from our subject of the week.
I plan on calling my window Window_Pet since we already named it like that in our comment line and it's taking its inheritance from Window_selectable:

CODE
Class Window_Pet < Window_Selectable


Let's face it, when it comes to pets, there are only real two options, a Puppy Dog, or a Ninja Turtle cool.gif

So down in the refresh area, we need to do a draw_text for our two options, but Window_Selectable assumes a couple things about its options.
Firstly, it assumes that option #1 is in the top left corner (coordinates 0,0), and secondly that the options are lined up vertically going down, spaced 32 pixels apart.
It's not that restricting, and it can easily be changed, but for the moment our text is only 32 pixels anyway, so we'll work with it smile.gif

Keeping all this in mind, and the stuff that you learnt with The Law, if I were to ask you to come up with a window, hopefully you would come back with something like this:


CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  This window allows you to make selections between two different items.
#===============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(100, 100, 640-200, 480-200)
    self.index = 0 # This is what item is selected when the window is first made
    @item_max = 2 # Number of selections available.
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear

    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.draw_text(0,0,100,32,"Puppy Dog")
    self.contents.draw_text(0,32,100,32,"Ninja Turtle")

  end
end


Now, if we make an event the same as last time, we get: (open up your game maker and take a look!)


The same as last time, a static window wink.gif
This is where Window_Selectable differs from Window_Base.
Window_Base you could make a window, it doesn't need to respond to inputs, so after it's made, you can leave it smile.gif
Window_Selectable needs to be updated, to check if it should move the cursor up or down, and if it should select the highlighted item.

By default, Window_Selectable has the scripts to check if up or down is pressed, but it is up to us to tell it what to do if your player presses enter smile.gif

This will require a new method (a method being the thing that starts with def), and I plan on calling mine: check_input.

CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  Based on the Script Builder's Guide, this is a selectable window :)
#==============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(100, 100, 640-200, 480-200)
    self.index = 0 # This is what item is selected when the window is first made
    @item_max = 2
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.draw_text(0,0,100,32,"Puppy Dog")
    self.contents.draw_text(0,32,100,32,"Ninja Turtle")
  end
  #--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        $window = Window_Text.new
      elsif self.index == 1
        print "You have selected option two"
        $window = Window_Text.new
        $window.y = 0
        $window.back_opacity = 0
      end
    end
  end
end


You should all be familiar with the refresh; it's the same as The Law G14's one, but the check_input I will explain though.

CODE
    if Input.trigger?(Input::C)
This checks if the the "C" input is pressed, if it is, continue : )

CODE
      $window.dispose
Window_Selectable has served it's purpose, so we let it get back to perfecting it's new cologne.

CODE
      if self.index == 0
If the first item in the list is selected

CODE
        $window = Window_Text.new
Then make the Window_Text from the last tutorial

CODE
      elsif self.index == 1
If the first item isn't selected, but the second one is:
Then make a pop up, make the Window_Text from last time, move it around, and change it's back opacity wink.gif

CODE
      end

End looking at which item from our selection was picked
End the stuff that will happen if the input "C" was pressed
End the module ( def check_input)
End the class (class Window_Pet < Window_Selectable)

Ok done! We have made a selectable window, yay!


V. Showing Our Window

This requires a bit of thought, we need to address two things, we need to call $window.update (the default bit of script that moves the cursor up/down), and $window.check_input every frame, and we need to stop after we have selected something.



To make sure that it gets updated every frame, we use a for loop.
That code inside the conditional branch is a bit scary, but what it does is it looks at your $window, when we made it on the first line we define it as $window = Window_Pet.new, and once we select something, $window becomes a Window_Text. What the conditional branch does, is check if the $window is still a Window_Pet.
If it is a Window_Pet, then run the update method (inside Window_Selectable) to check if up/down is pressed, and then run the check_input method (inside Window_Pet) to tell the program what to do if the player has selected an option : )


VI. Conclusion

I realize that Window_Selectable isn't easy, and there are a quite a few things that will seem daunting at first, but on the flip side, if you can vaguely understand what's going on, you know A LOT about windows, and could probably do more than I could when I first started lurking around the Script_Support section : )
I hope that people have found this useful, and am looking forward to any feedback you may have smile.gif

Also, I need to stress that you will probably NOT understand this tutorial the first time through. Be sure to post any concerns you have about the tutorial because Window_Selectable is a hard concept to grasp.


VII. Homework

For your homework, try making a more interesting selectable window, something that has a few more options, starting on say the 3rd item, and for the love of God, add some colour to the text!
The Law G14
Great work Night! I'll try to show you my homework by tomorow if that's ok with you lol

Oh, and just so you know, this taught me alot of new things about window_selectable like being able to make a window_selectable window without using a scene smile.gif

EDIT:

Here it is!

[Show/Hide] Screenie




It's a little blurry because I saved it as a jpg but I think you get the picture. Oh and here's the script:

CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  Based on the Script Builder's Guide, this is a selectable window :)
#==============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(100, 100, 640-200, 480-200)
    self.index = 0
    @item_max = 3
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,0,100,32,"Red")
    self.contents.font.color = system_color
    self.contents.draw_text(0,32,100,32,"Blue")
    self.contents.font.color = crisis_color
    self.contents.draw_text(0,64,100,32,"Yellow")
  end
  #--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        print "GO RED!!"
      elsif self.index == 1
        print "GO BLUE!!!"
      elsif self.index == 2
        print "GO YELLOW!!!!"
      end
    end
  end
end
Night_Runner
Hooray! It's colourful!!!
Nice work :)
Zeffa
Great work boys!

Everyone will be scripting pro soon!

Keep it up!
thatbennyguy
Thanks Night! Here's my attempt... I mean, it's a bit stretched, and the choices don't switch every time I input key... let me know what's wrong:

[Show/Hide] screenie


CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  Based on the Script Builder's Guide, this is a selectable window :)
#==============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(200, 200, 640-200, 480-200)
    self.index = 0 # This is what item is selected when the window is first made
    @item_max = 4
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.font.color = system_color
    self.contents.draw_text(0,0,100,32,"@@@Serenity@@@")
    self.contents.font.color = crisis_color
    self.contents.draw_text(0,32,100,32,"$$$Riches$$$")
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,64,100,32,"XXXDeathXXX")
    self.contents.draw_text(0,96,100,32,"!!!Ignore!!!")
  end
  #--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        print "You meditate in the bush for a week or two..."
      elsif self.index == 1
        print "You start up a business and become a mega-buck billionaire!"
      elsif self.index == 2
        print "You drink poison and drift off into oblvion!"
      elsif self.index == 3
        print "You confess ignorance and thus discover philosophical truth!"
      end
    end
  end
end
The Law G14
Very nice Benny, I love it biggrin.gif biggrin.gif

Hopefully more people will do the homework smile.gif
thatbennyguy
Yes, I feel this topic is being mega-ignored... I still want my question answered though... what's wrong with my script? And why are my text all squashed up? Fanx Night, anyway, you put tons of time into a tutorial and this is your reception!? I wouldn't blame you if you were annoyed...
darkhalo
Well I'm certainly going through all this, as selectable windows is something Ive wanted in my games
for a long time. Now I have the weekend, I can focus more on the script side of things.
The Law G14
@Benny: Woops, completely overlooked your question. The reason Night_Runner isn't answering any questions is because he's going to be gone for a little bit. So, to make your text wider you have to change the third value in your draw_text parameters. For example, change line 26 of your code to this:

CODE
self.contents.draw_text(0,0,150,32,"@@@Serenity@@@")


Notice how I changed the third value in the parenthisis. That’s the width value of your string of text. I just changed it from 100 pixels to 150 pixels. Try changing all of your text widths to make your text more readable and then show me your results smile.gif


@D.H: Sounds good, if you manage to make something out of this tutorial, please post your results smile.gif
Night_Runner
Hooray, more people!
@> Benny, beautifully done, I love your mapping smile.gif The problem is, we're running the Loop through the event, so what the game will do, is take one command at a time from each event and run that, update the map, go back through ant take one more command from each event, and then update the map again, and so it becomes really really laggy as it tries updating the inputs...

We can fix this through scripting, change your event to run this pile of code:


There's quite a bit of code in there, but it's all exactly the same as the evented version, but in 1 massive block, so it forces the rest of the map to wait patiently while the selection is made smile.gif
crimson_plague101
here is my homework night still dont know how to do the screenshot thingy but here is the code


CODE
#==============================================================================
# *Window_Pet*
#------------------------------------------------------------------------------
#  
#==============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(0, 320, 640, 140)
    self.index = 0 # Initial Option
    @item_max = 4 # Number of options
    self.contents = Bitmap.new(width - 32, height - 32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    
    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.draw_text(0,0,100,32,"Puppy Dog")
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,32,100,32,"Ninja Turtle")
    self.contents.font.color = crisis_color
    self.contents.draw_text(0,64,100,32,"Demon")
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,96,100,32,"Devil")
    self.contents.font.color = crisis_color
#--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        $window = Window_Text.new
      elsif self.index == 1
        print "You have selected option two"
        $window = Window_Text.new
        $window.y = 0
        $window.back_opacity = 0
      elsif self.index == 2
        $window = Window_Text.new
        $window.y = 0
        $window.back_opacity = 0
      elsif self.index ==3
        print "You have selected option four"
        $window = Window_Text.new
      end
    end
  end
end
end
Holder
Your question was already answered in this topic you posted:
http://www.rpgrevolution.com/forums/index....c=36724&hl=
kikonami123
This is mine =/ its a lil messy if ya ask me tongue.gif


CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  This window allows you to make selections between two different items.
#===============================================================================

class Rokomofococo < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(100, 100, 640-100, 480-100)
    self.index = 0 # This is what item is selected when the window is first made
    @item_max = 2 # Number of selections available.
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear

    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,0,100,32,"French Fries")
    self.contents.draw_text(0,32,100,32,"Rice & Chicken")
  end
end
  #--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        print "You picked French Fries!"
      elsif self.index == 1
        print "You picked Rice & Chicken!"
        $window.back_opacity = 250
      end
    end
  end
The Law G14
Great work on this Kikonami. However, try to add more options next time as two is not too many lol. But in any event, great work on this smile.gif
Bio Wolfz
I like this. Simple but fascinating trying it out later.
Runefreak
Ah thank you for this smile.gif, I'll be trying this out later.
Legacy
Nice tutorial. Very useful.
Red Knight

This actually took longer than usual.
CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  Based on the Script Builder's Guide, this is a selectable window :)
#==============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(200, 200, 640-200, 480-200)
    self.index = 0 # This is what item is selected when the window is first made
    @item_max = 4
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.font.color = system_color
    self.contents.draw_text(0,0,150,32,"Peace")
    self.contents.font.color = crisis_color
    self.contents.draw_text(0,32,150,32,"Go to war!")
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,64,150,32,"Die a matyr!")
    self.contents.font.color = normal_color    
    self.contents.draw_text(0,96,150,32,"Suicide!")
  end
  #--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        print "You stay in your house, hiding everyday."
      elsif self.index == 1
        print "You went to war as a common soldier and died!"
      elsif self.index == 2
        print "You went to rebel but died after nearly killing the King."
      elsif self.index == 3
        print "You take out your knife and kill yourself."
      end
    end
  end
end

One slight problem with your tutorial though. When I finish the event and dispose the window, it has an error that points to line 95, with only the mere code, "super".
Redd
I'm getting an error whenever I talk to the Thief01 guy to make the selectable box pop up:

BigEd781
QUOTE (Redd @ Dec 9 2009, 12:51 PM) *
I'm getting an error whenever I talk to the Thief01 guy to make the selectable box pop up:


Looks like there is no method named 'is' defined in your Window_Pet class. Can you post the code?
Redd
CODE
#==============================================================================
# ** Window_Pet.
#------------------------------------------------------------------------------
#  Based on the Script Builder's Guide, this is a selectable window :)
#==============================================================================

class Window_Pet < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(200, 200, 640-200, 480-200)
    self.index = 0 # This is what item is selected when the window is first made
    @item_max = 4
    self.contents = Bitmap.new(width-32,height-32)
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    #self.contents.draw_text(x_position_from_edge , y_position_from_edge,
    #                         width, height, "Text", alignment)
    self.contents.font.color = system_color
    self.contents.draw_text(0,0,150,32,"Dieeee!")
    self.contents.font.color = green_color
    self.contents.draw_text(0,32,150,32,"What? I kill you!")
    self.contents.font.color = knockout_color
    self.contents.draw_text(0,64,150,32,"This is getting boring...")
    self.contents.font.color = normal_color    
    self.contents.draw_text(0,96,150,32,"METALLICA ROCKS!")
  end
  #--------------------------------------------------------------------------
  # * Check_Input
  #--------------------------------------------------------------------------
  def check_input
    if Input.trigger?(Input::C)
      $window.dispose
      if self.index == 0
        print "You want to dieeee?"
      elsif self.index == 1
        print "C'mon man I just asked you a simple question!"
      elsif self.index == 2
        print "I know.... this is really boring huh"
      elsif self.index == 3
        print "METALLICA IS THE BOMB!"
      end
    end
  end
end


Is there anything wrong with it?

EDIT: I fixed THAT problem. It was because I accidentally added a period after is inside the call script conditional branch thingy. But now I have a different problem:


in Interpreter 7 line 274, this is what is says (and a while after that)
CODE
    if result == false
      # End
      return false
    end
    # Continue
    return true
  end
end


Any help?
Redd
Ummm... bump?
Night_Runner
Sorry about that Redd.

I got the script working without running into that particular error, I think it may have something to do with your event...

Have your event run this bit of code, if it fixes your problem, let me know
CODE
$window = Window_Pet.new
loop do
Graphics.update; Input.update
$window.update
$window.check_input
break if $window.disposed?
end


And you should only run into the problem of trying to call green_color tongue.gif
All those system_color, knockout_color, normal_color etc do is try to enforce a consistent colour scheme, so there's no such thing as red_color or green_color.
Change that green_color to Color.new(0, 255, 0)
where the formatting is Color.new(red, green, blue)
so if you wanted to make a purple, it'd be
Color.new(255, 0, 255)

But otherwise it should work fine, if it isn't, please send a screen shot of your event.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2013 Invision Power Services, Inc.