Submit Your Article


 
RPG Maker

Welcome Guest ( Log In | Register )


  Games Resources RPG Maker VX RPG Maker XP Scripts Tutorials Downloads

> [Scripting][Series]RGSS: Windows - Lesson 2b: Simple Menu Remodel
ccoa
post Jan 17 2008, 07:28 AM
Post #1


Storm Goddess
Group Icon

Group: Revolutionary
Posts: 989
Type: Scripter
RM Skill: Masterful




Today we're going to talk about doing some very simple remodeling on an existing scene. We're going to take the default menu and change it up a little.

What I want to do:
  • Replace the Play Time window with a Location window
  • Move the command window, playtime window, and gold window to the right side of the menu
  • Replace the character sprites with faces


Not a very big remodel, but it would be enough for a first project looking to be a little less "RTP."

To start, we're going to create a new window for the Location window.

CODE
class Window_Location < Window_Base
  def initialize
    super(0, 0, 160, 96)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
end


So far, so good. However, I just ran into one teensy little problem. By default, you can't access a map's name easily. Don't worry, that easy enough to fix. First, we need a way to get the name from the $game_map global variable. Head over to Game_Map, and add this line under the attributes (attrs).

CODE
  attr_reader   :name                     # the name of the current map


Remember what we said about attributes?

Attributes are "hooks" into the internal data of an object. Normally, if I define an instance variable @name inside a class, no other object can see it! That's useful if the variable is only used internally, but not so great if you wanted to look at it or set it from outside that object.

Now, you could do this to make that instance variable readable:

CODE
class Something
  def name
    return @name
  end
end
[code]

[code]t = Something.new
print t.name


The return statement tells the interpreter to exit the method, remember? However, if you follow the return statement with a value, it "returns" that value from the method. Thus, someone outside class Something can "read" the instance variable @name.

To make it writeable, you could do this:

CODE
class Something
  def name=(nm)
    @name = nm;
  end
end
[code]

[code]t = Something.new
t.name = "hello"


This allows you to "write" to the @name variable from outside the Something class.

However, writing all that out every single time is something of a pain. So Ruby gave us 3 shortcuts.

CODE
class Something
  attr_reader :name
end


is the same as

CODE
class Something
  def name
    return @name
  end
end
[code]

[code]class Something
  attr_writer:name
end


is the same as

CODE
class Something
  def name=(nm)
    @name = nm
  end
end
[code]

and

[code]class Something
  attr_accessor :name
end


is the same as

CODE
class Something
  def name
    return @name
  end
  def name=(nm)
    @name = nm
  end
end
[code]

Make sense?  Feel free to ask questions if it doesn't.

Okay, back to the code.  We need to get the map name from the stored database data.  Fortunately for us, there's a way to load that data easily.

[code]# load the name of the map
    @name = load_data("Data/MapInfos.rxdata")[@map_id].name


load_data is a global function that is provided as part of RGSS. It reads rxdata files. In this case, we're asking it to read the MapInfos file, which will return an array of MapInfo objects. You can see the specs for the MapInfo class in the help file under Game Library -> RPGXP Data Structure.

The array is indexed by map id. So map 7 in your editor is at index 7 in the array you get back. Thus, load_data("Data/MapInfos.rxdata")[@map_id] gives you the MapInfo object for the current map. Now we have the name of the map in a convenient location.

Back to the Window in progress.

CODE
class Window_Location < Window_Base
  def initialize
    super(0, 0, 160, 96)
    self.contents = Bitmap.new(width - 32, height - 32)
    refresh
  end
  
  # clear and redraw the contents
  def refresh
    self.contents.clear
    
    # draw the word "location" in blue
    self.contents.font.color = system_color
    self.contents.draw_text(4, 0, 120, 32, "Location")
    
    # draw the name of the map in white
    self.contents.font.color = normal_color
    self.contents.draw_text(4, 32, 120, 32, $game_map.name, 2)
  end
end


The only real surprises there are the font colors, so let's take a look at those.

self.contents.font contains the font properties for the drawing pane of the window. If you'd like to know more about the Font class, look in the Help file under Game Library -> RGSS Built-In Classes. By setting the font properties for a bitmap, you can change the look of the text drawn on the window. In this case, the color.

system_color and normal_color are methods defined in Window_Base (remember, anything Window_Base can do! wink.gif )

Here are all the "color" methods defined in Window_Base:

CODE
#--------------------------------------------------------------------------
  # * Get Normal Text Color
  #--------------------------------------------------------------------------
  def normal_color
    return Color.new(255, 255, 255, 255)
  end
  #--------------------------------------------------------------------------
  # * Get Disabled Text Color
  #--------------------------------------------------------------------------
  def disabled_color
    return Color.new(255, 255, 255, 128)
  end
  #--------------------------------------------------------------------------
  # * Get System Text Color
  #--------------------------------------------------------------------------
  def system_color
    return Color.new(192, 224, 255, 255)
  end
  #--------------------------------------------------------------------------
  # * Get Crisis Text Color
  #--------------------------------------------------------------------------
  def crisis_color
    return Color.new(255, 255, 64, 255)
  end
  #--------------------------------------------------------------------------
  # * Get Knockout Text Color
  #--------------------------------------------------------------------------
  def knockout_color
    return Color.new(255, 64, 0)
  end


You can change them here, if you like, and they'll change all across your game. The Color class's initialize method takes 4 arguments. They are the red, blue, green, and alpha transparency values of the color. Each should be a value from 0 to 255. Alpha is optional, if you omit it is assumed to be 255. So:

Color.new(0, 0, 0, 255) is a completely opaque black, Color.new(255, 255, 255, 160) is a partially transparent white, and Color.new(90, 100, 140) is a completely opaque blue.

Okay, now that the window is complete, we need to add it to the scene. Since it's the same height and width of the steps window, all we need to do is replace the steps window with the location window.

Find this line in Scene_Menu:

CODE
@steps_window = Window_Steps.new


And rewrite it to look like this:

CODE
@location_window = Window_Location.new


Now all we need to do is a search and replace on @steps_window and replace it with @location_window. Hit Ctrl+H and do so.

Now run your menu. It should look like this:



Not too bad so far, right?

Now let's shift the windows on the left to the right side of the menu, shall we? The first thing we need to know is: how wide in pixels is that status window, exactly?

Go to Window_MenuStatus. Looks like it's 480 pixels wide:

CODE
  def initialize
    super(0, 0, 480, 480)


The RMXP screen is 640 pixels wide, and 480 pixels tall. The upper left pixel is at 0, 0. So to put something 480 pixels to the right, we'll need to put it at x coordinate 480. Simple enough, right?

Head back to Scene_Menu and look at the main method:

CODE
  def main
    # Make command window
    s1 = $data_system.words.item
    s2 = $data_system.words.skill
    s3 = $data_system.words.equip
    s4 = "Status"
    s5 = "Save"
    s6 = "End Game"
    @command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6])
    @command_window.index = @menu_index
    # If number of party members is 0
    if $game_party.actors.size == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(0)
      @command_window.disable_item(1)
      @command_window.disable_item(2)
      @command_window.disable_item(3)
    end
    # If save is forbidden
    if $game_system.save_disabled
      # Disable save
      @command_window.disable_item(4)
    end
    # Make play time window
    @playtime_window = Window_PlayTime.new
    @playtime_window.x = 0
    @playtime_window.y = 224
    # Make steps window
    
    @location_window = Window_Location.new
    @location_window.x = 0
    @location_window.y = 320
    
    # Make gold window
    @gold_window = Window_Gold.new
    @gold_window.x = 0
    @gold_window.y = 416
    # Make status window
    @status_window = Window_MenuStatus.new
    @status_window.x = 160
    @status_window.y = 0
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @command_window.dispose
    @playtime_window.dispose
    @location_window.dispose
    @gold_window.dispose
    @status_window.dispose
  end


See how the x coordinates of the windows are defined for most of them? It's just a matter of changing them.

CODE
def main
    # Make command window
    s1 = $data_system.words.item
    s2 = $data_system.words.skill
    s3 = $data_system.words.equip
    s4 = "Status"
    s5 = "Save"
    s6 = "End Game"
    @command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6])
    @command_window.index = @menu_index
    # If number of party members is 0
    if $game_party.actors.size == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(0)
      @command_window.disable_item(1)
      @command_window.disable_item(2)
      @command_window.disable_item(3)
    end
    # If save is forbidden
    if $game_system.save_disabled
      # Disable save
      @command_window.disable_item(4)
    end
    # Make play time window
    @playtime_window = Window_PlayTime.new
    @playtime_window.x = 480
    @playtime_window.y = 224
    # Make steps window
    
    @location_window = Window_Location.new
    @location_window.x = 480
    @location_window.y = 320
    
    # Make gold window
    @gold_window = Window_Gold.new
    @gold_window.x = 480
    @gold_window.y = 416
    # Make status window
    @status_window = Window_MenuStatus.new
    @status_window.x = 0
    @status_window.y = 0
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @command_window.dispose
    @playtime_window.dispose
    @location_window.dispose
    @gold_window.dispose
    @status_window.dispose
  end


I've set the x coordinate of the playtime, location, and gold windows to 480, and the x coordinate of the status window to 0. But wait, we forgot the command window! No problem, we just add a line:

@command_window.x = 480

Like so:

CODE
def main
    # Make command window
    s1 = $data_system.words.item
    s2 = $data_system.words.skill
    s3 = $data_system.words.equip
    s4 = "Status"
    s5 = "Save"
    s6 = "End Game"
    @command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6])
    @command_window.index = @menu_index
    @command_window.x = 480
    # If number of party members is 0
    if $game_party.actors.size == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(0)
      @command_window.disable_item(1)
      @command_window.disable_item(2)
      @command_window.disable_item(3)
    end
    # If save is forbidden
    if $game_system.save_disabled
      # Disable save
      @command_window.disable_item(4)
    end
    # Make play time window
    @playtime_window = Window_PlayTime.new
    @playtime_window.x = 480
    @playtime_window.y = 224
    # Make steps window
    
    @location_window = Window_Location.new
    @location_window.x = 480
    @location_window.y = 320
    
    # Make gold window
    @gold_window = Window_Gold.new
    @gold_window.x = 480
    @gold_window.y = 416
    # Make status window
    @status_window = Window_MenuStatus.new
    @status_window.x = 0
    @status_window.y = 0
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @command_window.dispose
    @playtime_window.dispose
    @location_window.dispose
    @gold_window.dispose
    @status_window.dispose
  end


Check out your menu now:



One last thing. We're going to add faces instead of character sprites to the Status Window. First, let's add a method to Window_Base to draw face graphics. Why to Window_Base? Because we might want to use it in another window some day, and it's better not to duplicate code. That way, if you want to change how it works someday you only have to change it in one place.

CODE
  #--------------------------------------------------------------------------
  # * Draw Face Graphic
  #     actor : actor
  #     x     : draw spot x-coordinate
  #     y     : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_actor_face_graphic(actor, x, y)
    bitmap = RPG::Cache.picture(actor.name)
    self.contents.blt(x, y, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height))
  end


This is pretty similar to the way we drew icons on the screen for the HUD. In this case, I have imported a picture that has the same name as the actor (Cecilia.png). Thus the actor.name, the name of the image will be the same as the name of the actor.

Now we head over to Window_MenuStatus. Notice this line:

CODE
      draw_actor_graphic(actor, x - 40, y + 80)


This is the line that draws the character sprite on the window. If you're curious about it, head over to Window_Base and check it out.

We want to replace this line with one of our own, so we delete it. Then we add

CODE
draw_actor_face_graphic(actor, x - 64, y)


The x value will always be 0 (since x is 64). The y value will be 0 for the first actor, 116 for the second, etc. You may need to do some experimentation with placing objects on windows. Remember, higher x values are farther right, higher y values are farther down.

That's not too bad, but the text is overlapping the face:



So I move the name, level, and state over 40 pixels.

CODE
def refresh
    self.contents.clear
    @item_max = $game_party.actors.size
    for i in 0...$game_party.actors.size
      x = 64
      y = i * 116
      actor = $game_party.actors[i]
      draw_actor_face_graphic(actor, x - 64, y)
      draw_actor_name(actor, x + 40, y)
      draw_actor_class(actor, x + 144, y)
      draw_actor_level(actor, x + 40, y + 32)
      draw_actor_state(actor, x + 90, y + 32)
      draw_actor_exp(actor, x + 40, y + 64)
      draw_actor_hp(actor, x + 236, y + 32)
      draw_actor_sp(actor, x + 236, y + 64)
    end
  end


Well, that took care of the image overlap, but now status is overlapping level!



Let's move it up by actor class, shall we?

CODE
      draw_actor_state(actor, x + 236, y)


I got the 236 from the HP and SP drawing methods. Again, experimentation is the key.



Other possible solution would have been to remove unnecessary data or to make the font size smaller. Be creative when you remodel. If you're doing something big, make a mock-up in a graphics program first to be sure everything will fit first!

Be sure to download the latest version of the Window Demo and check it out!

http://www.pcis-studios.com/ccoa/Window%20Demo.exe

Homework

Try a very simple remodel on a scene of your choice. Try remodeling the internal contents of at least one window. Do it in a new project, and don't be afraid of breaking things! That's how you learn. Post any questions or problems here.


__________________________
Go to the top of the page
 
+Quote Post
   
 
Start new topic
Replies
Dark Dragon
post Jan 20 2008, 12:50 AM
Post #2


Level 8
Group Icon

Group: Revolutionary
Posts: 116
Type: Event Designer
RM Skill: Skilled




Oh yeah yeah, sure..
I'll try making a tutorial as soon as I can. And that's not going to be soon xD
I have a script I'm working on and I'm studying for my SAT, but I'll try, and do my best happy.gif
Edit : That depends on what you mean by a transition, a transition is changing from a state to another, even if you make a message window with an event it's called a transition >_>
But my guess is that you mean a transition like the one when you start up a battle ? Yes it can be done, but I still don't know how, I'll try to search it up and include it in the tutorial though tongue.gif

This post has been edited by Dark Dragon: Jan 20 2008, 12:53 AM


__________________________
وَلَقَدْ يَسَّرْنَا الْقُرْآنَ لِلذِّكْرِ فَهَلْ مِن مُّدَّكِرٍ



I have noticed that kewlness is mainly based on the behaviour of the kewl person, it doesnt matter wether u kewl or u nt kewl lol omg
I smell n00by, but is me ?
Go to the top of the page
 
+Quote Post
   
Heavyblues
post Jan 20 2008, 12:59 AM
Post #3


Level 11
Group Icon

Group: Revolutionary
Posts: 188
Type: Artist
RM Skill: Beginner




QUOTE (Dark Dragon @ Jan 19 2008, 11:57 PM) *
Oh yeah yeah, sure..
I'll try making a tutorial as soon as I can. And that's not going to be soon xD
I have a script I'm working on and I'm studying for my SAT, but I'll try, and do my best happy.gif
Edit : That depends on what you mean by a transition, a transition is changing from a state to another, even if you make a message window with an event it's called a transition >_>
But my guess is that you mean a transition like the one when you start up a battle ? Yes it can be done, but I still don't know how, I'll try to search it up and include it in the tutorial though tongue.gif

good luck biggrin.gif
Go to the top of the page
 
+Quote Post
   

Posts in this topic
- ccoa   [Scripting][Series]RGSS: Windows - Lesson 2b: Simple Menu Remodel   Jan 17 2008, 07:28 AM
- - rock_yusuf_lee   One problem here.... So for the making the comman...   Jan 18 2008, 04:03 PM
|- - ccoa   QUOTE (rock_yusuf_lee @ Jan 18 2008, 04:1...   Jan 19 2008, 06:46 AM
|- - Heavyblues   erm... where do I put this? should I start another...   Jan 19 2008, 10:11 AM
- - ccoa   You spelled "update" wrong.   Jan 18 2008, 04:08 PM
|- - rock_yusuf_lee   QUOTE (ccoa @ Jan 19 2008, 06:15 AM) You ...   Jan 18 2008, 05:02 PM
- - kyle1234lee   Can I ask a basic question? hehe, i'm just new...   Jan 18 2008, 10:58 PM
- - Synthesize   QUOTE (kyle1234lee @ Jan 18 2008, 11:05 P...   Jan 18 2008, 11:05 PM
|- - kyle1234lee   Thanks a lot synthezis   Jan 18 2008, 11:24 PM
- - SeeYouAlways   There are more scripting tutorials for RGSS here: ...   Jan 19 2008, 12:08 AM
- - ccoa   You'd replace actor.name with actor.id.to_s in...   Jan 19 2008, 03:55 PM
|- - Heavyblues   QUOTE (ccoa @ Jan 19 2008, 03:02 PM) You...   Jan 19 2008, 05:17 PM
- - ccoa   Ah, sorry, I thought it was in reference to my las...   Jan 19 2008, 05:21 PM
|- - Heavyblues   heehee, nope ^-^; but I'm sure that'll hel...   Jan 20 2008, 12:31 AM
- - Vicener   Thanks for this tutorial Ccoa! It helped me u...   Jan 19 2008, 07:24 PM
- - Dark Dragon   Erm you mean like the windows move ? All you have ...   Jan 20 2008, 12:37 AM
|- - Heavyblues   QUOTE (Dark Dragon @ Jan 19 2008, 11:44 P...   Jan 20 2008, 12:40 AM
- - Dark Dragon   Ah... let me put this in another way : You mean li...   Jan 20 2008, 12:44 AM
|- - Heavyblues   that, and, say, you choose an option, make the cur...   Jan 20 2008, 12:47 AM
- - Kinnison   Oh, cool. Another tutorial I learned how to make ...   Jan 20 2008, 05:56 AM
- - ccoa   I'll be making a tutorial on windows that move...   Jan 20 2008, 06:15 AM
- - KiteDXX   I never knew you could format your images to searc...   Jan 20 2008, 06:24 AM
- - rock_yusuf_lee   QUOTE (ccoa @ Jan 19 2008, 08:53 PM) QUOT...   Jan 20 2008, 11:28 PM
- - KyoRen   Here's a screenshot of my menu system. I used ...   Feb 10 2008, 08:58 PM
- - danny_warfield   @ CCOA How the way we change character sprite in s...   Apr 8 2008, 09:32 PM
- - Urborg   how can i show a variable to the menu window i me...   Apr 13 2008, 04:24 PM
- - BillSekowsky   I tried doing the location part of the tutorial bu...   Apr 16 2008, 03:56 PM
- - JoRu   I know this is a quite old topic but I get the sam...   Jun 3 2008, 06:01 AM
- - woratana   You may forget to add this. CODEclass Game_Map a...   Jun 3 2008, 02:51 PM
- - BillSekowsky   What do you mean when you say CODEOkay, back to t...   Aug 15 2008, 04:42 AM
- - LoLawes   I have learnt alot in the 3 tutorials by ccoa but ...   Feb 11 2009, 12:57 PM


Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 24th May 2013 - 02:15 AM
RPG RPG Revolution is an Privacy Policy and Legal
eXTReMe Tracker