Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

custom menu

Jking

Member

i want to learn to make a custom menu for my game welcome to Endarium. i don't now how i would go about this. would some one be interested in helping me learn it, or point me in the right direction. (if this is in the wrong place please move it)
 

Jking

Member

my own background and custom buttons......
kind of basic but i want to learn to do it witch is why im asking for instructions i also want an extra button for extras
 

khmp

Sponsor

I wouldn't recommend any CMS that is either poorly documented or the comments are in a different language like Mr. Arbiter said. Especially from a learning point of view. But I'm feeling generous tonight.

*Teacher's Cap On*

What you ask isn't terribly hard to implement so how about we start with the question of getting your own picture in the background. But I'm going to take you through it step by step with little FYI's intermixed. First we are going to create a class to hold constants called Scene_Shared. I use something like this to hold strings and information I want to be able to grab which are often more times that not inside a Scene. Open your script editor(F11) right click Main and insert an empty section right above it. Then in this section paste in the code below.

Code:
#==============================================================================
# ** Scene_Shared
#------------------------------------------------------------------------------
#  Constants that are shared across Scenes can be placed here.
#==============================================================================

module Scene_Shared
  BACKGROUND_TEX = 'dir/imagename'
end

Set that constant BACKGROUND_TEX to the name of the image you want in the background. We will load the image through the Cache, so place the image in 'Graphics/Pictures/' directory. Go down a few lines below our module and use the code below:

Code:
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs menu screen processing.
#==============================================================================

class Scene_Menu

end

From now on we're going to be editing the class Scene_Menu so don't just keep pasting the code I present or something bad might happen.

In Ruby you can do some pretty nifty things in code like extending a class definition without overwriting it. We can create new methods inside Scene_Menu without ever having to edit the default script directly. However if we need to mess with the inner workings of how a method works. We most likely will override the method. Overriding is accomplished by simply redefining the method. But the cool thing is with our picture thing is that we don't need to mess with the inner workings... Anyway we instead can just alias the method we need to alter. And this way we preserve the old code that was defined. To get our picture into this scene we will alias 'main'.
Code:
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs menu screen processing.
#==============================================================================

class Scene_Menu
  #--------------------------------------------------------------------------
  # * Alias Methods
  #--------------------------------------------------------------------------
  alias_method :jkin_learning_main, :main
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    jkin_learning_main
  end
end

If you run the game right now nothing will be changed. The old code is still being used. Neat huh. Now we will add code. First we need a Sprite object. I'm naming it back. Notice it isn't proceeded by a '@' or a '$'. In this case because this variable in this case a Sprite is not being used over multiple methods he can stay as a local variable. Local variables begin with a lower case letter and have no prefix character.
Code:
back = Sprite.new
back.bitmap = RPG::Cache.picture(Scene_Shared::BACKGROUND_TEX)

We also will need to dispose of these objects. We release them in the reverse order of their instantiation. First the bitmap then the sprite.
Code:
if !back.bitmap.disposed?
  back.bitmap.dispose
end
back.dispose unless back.disposed?

I throw the checks in on every case of resource disposal just to avoid any unnecessary crashes. Also take note of the various ways you can arrange conditional statements. 'if !(not)' equates to the same as 'unless'. So where are we at in the Scene?
Code:
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs menu screen processing.
#==============================================================================

class Scene_Menu
  #--------------------------------------------------------------------------
  # * Alias Methods
  #--------------------------------------------------------------------------
  alias_method :jkin_learning_main, :main
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    back = Sprite.new
    back.bitmap = RPG::Cache.picture(Scene_Shared::BACKGROUND_TEX)
    jkin_learning_main
    back.bitmap.dispose unless back.bitmap.disposed?
    back.dispose unless back.disposed?
  end
end

Our image is loaded into the scene. And if you run the game right now you will see absolutely nothing but the original code. This is because of those dang windows. Their opacity by default is 255, which is full opacity. How can we go about this. We do have justifiable reasons to override main now. If we do we can just manually adjust every windows opacity to a certain value. Plus you want to also eventually add buttons right? So lets just override main. And add in this bit:
Code:
    # Alter the transparency of the windows.
    @command_window.opacity =
    @playtime_window.opacity =
    @steps_window.opacity =
    @gold_window.opacity =
    @status_window.opacity = 128

That doesn't look right does it? I'm only assigning that last window an opacity of 128. Well in Ruby lines carry over if there is an operand on the previous line suggesting that that line is not yet complete. Like:
Code:
a = 8 +
2

'a' will still be ten. Let's put the code into our overridden main method.
Code:
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs menu screen processing.
#==============================================================================

class Scene_Menu
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    back = Sprite.new
    back.bitmap = RPG::Cache.picture(Scene_Shared::BACKGROUND_TEX)
        # 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
    @steps_window = Window_Steps.new
    @steps_window.x = 0
    @steps_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

    # Alter the transparency of the windows.
    @command_window.opacity =
    @playtime_window.opacity =
    @steps_window.opacity =
    @gold_window.opacity =
    @status_window.opacity = 128

    # 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
    @steps_window.dispose
    @gold_window.dispose
    @status_window.dispose
    back.bitmap.dispose unless back.bitmap.disposed?
    back.dispose unless back.disposed?
  end
end

Now the picture is in the back and we can somewhat see it. Cool huh. Don't forget though you will need to do this Scene_Save, Status, Items, Skills etc. The SDK and VX picked up this mess with inheritance but that's another discussion.

Alright second part adding in options into Scene_Menu. This is quite obvious to edit if you've looked. There's a bunch of strings declared at the top of 'Scene_Menu.main'. So let's continue to edit our 'Scene_Menu.main' override, ok? You said you wanted to add an 'Extras' right? I'm going to just add it just before the 'End Game' just to limit the number of edits we have to do elsewhere. Plus we won't break the 'Save' button code or anything but 'End Game' temporarily.

Code:
    s1 = $data_system.words.item
    s2 = $data_system.words.skill
    s3 = $data_system.words.equip
    s4 = "Status"
    s5 = "Save"
    s6 = 'Extras'
    s7 = "End Game"
    @command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6, s7])

Sweet, so Extra's are in there right? Well when you run the game. 'Extras' will have the behavior 'End Game' had and 'End Game' will do nothing. Oh noes! In the script editor go back to the default 'Scene_Menu' script and copy the update method. Just the update method. We are going to override this guy just like we did to main.
Code:
  #--------------------------------------------------------------------------
  # * Frame Update (when command window is active)
  #--------------------------------------------------------------------------
  def update_command
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to map screen
      $scene = Scene_Map.new
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # If command other than save or end game, and party members = 0
      if $game_party.actors.size == 0 and @command_window.index < 4
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # Branch by command window cursor position
      case @command_window.index
      when 0  # item
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to item screen
        $scene = Scene_Item.new
      when 1  # skill
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Make status window active
        @command_window.active = false
        @status_window.active = true
        @status_window.index = 0
      when 2  # equipment
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Make status window active
        @command_window.active = false
        @status_window.active = true
        @status_window.index = 0
      when 3  # status
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Make status window active
        @command_window.active = false
        @status_window.active = true
        @status_window.index = 0
      when 4  # save
        # If saving is forbidden
        if $game_system.save_disabled
          # Play buzzer SE
          $game_system.se_play($data_system.buzzer_se)
          return
        end
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to save screen
        $scene = Scene_Save.new
      when 5  # end game
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to end game screen
        $scene = Scene_End.new
      end
      return
    end
  end

Inside update is a case statement that checks for which option we are on in the command window when we hit the C button. We need to add an additional case because we added an additional option right? This case that we are adding now will be case 5 and the one that was case 5 will become case 6. Remember that we pushed 'End Game' down one? That's what we are correcting right now.
Code:
      when 5  # extras
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to end game screen
        $scene = Scene_Extras.new

All together now:
Code:
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs menu screen processing.
#==============================================================================

class Scene_Menu
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    back = Sprite.new
    back.bitmap = RPG::Cache.picture(Scene_Shared::BACKGROUND_TEX)
    # Make command window
    s1 = $data_system.words.item
    s2 = $data_system.words.skill
    s3 = $data_system.words.equip
    s4 = "Status"
    s5 = "Save"
    s6 = 'Extras'
    s6 = "End Game"
    @command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6, s7])
    @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
    @steps_window = Window_Steps.new
    @steps_window.x = 0
    @steps_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

    # Alter the transparency of the windows.
    @command_window.opacity =
    @playtime_window.opacity =
    @steps_window.opacity =
    @gold_window.opacity =
    @status_window.opacity = 128

    # 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
    @steps_window.dispose
    @gold_window.dispose
    @status_window.dispose
    back.bitmap.dispose unless back.bitmap.disposed?
    back.dispose unless back.disposed?
  end
  #--------------------------------------------------------------------------
  # * Frame Update (when command window is active)
  #--------------------------------------------------------------------------
  def update_command
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to map screen
      $scene = Scene_Map.new
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # If command other than save or end game, and party members = 0
      if $game_party.actors.size == 0 and @command_window.index < 4
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # Branch by command window cursor position
      case @command_window.index
      when 0  # item
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to item screen
        $scene = Scene_Item.new
      when 1  # skill
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Make status window active
        @command_window.active = false
        @status_window.active = true
        @status_window.index = 0
      when 2  # equipment
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Make status window active
        @command_window.active = false
        @status_window.active = true
        @status_window.index = 0
      when 3  # status
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Make status window active
        @command_window.active = false
        @status_window.active = true
        @status_window.index = 0
      when 4  # save
        # If saving is forbidden
        if $game_system.save_disabled
          # Play buzzer SE
          $game_system.se_play($data_system.buzzer_se)
          return
        end
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to save screen
        $scene = Scene_Save.new
      when 5  # extras
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to end game screen
        $scene = Scene_Extras.new
      when 6  # end game
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Switch to end game screen
        $scene = Scene_End.new
      end
      return
    end
  end
end

I'm not doing Scene_Extras for you but it'll follow something like the code below.
Code:
#==============================================================================
# ** Scene_Extras
#------------------------------------------------------------------------------
#  This class does extra work!
#==============================================================================

class Scene_Extras
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main

    # --Your custom code here--

    # Transition run
    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

    # --Your disposal code here--

  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    $scene = Scene_Menu.new(5) if Input.trigger?(Input::B)
  end
end

Almost forgot whenever you add to that Window_Command in Scene_Menu involving any choice that was pushed down. There's a butterfly effect. Meaning that there case was changed so now you need to edit the behavior of how the Scene that was affected. In this case we only pushed Scene_End down. So the fix for this would be:
Code:
#==============================================================================
# ** Scene_End
#------------------------------------------------------------------------------
#  This class performs game end screen processing.
#==============================================================================

class Scene_End
  #--------------------------------------------------------------------------
  # *  Process When Choosing [Cancel] Command
  #--------------------------------------------------------------------------
  def command_cancel
    # Play decision SE
    $game_system.se_play($data_system.decision_se)
    # Switch to menu screen
    $scene = Scene_Menu.new(6) # Its 6 now instead of 5
    # Just so when we return to Scene_Menu the correct option is selected.
  end
end

Good luck with it Jking! :thumb:
 

khmp

Sponsor

Yautja Arbiter":262agkb4 said:
Way to do all the work, khmp :thumb:

Don't pick on me. :down: You know that isn't all the work. There's still plenty to do. I just wanted to explain some things to help him understand the RGSS a little better. Plus this is support not academies most of these people don't come here to learn. Much to chagrin of you and me. So consider it as me giving him half a fish and a stick with a string attached to it. By the way, I want you to become a teacher! I think they still need scripting teachers. And if you become a teacher I will be your student and you can yell at me all you want. That is, if you're not... yella("yellow" for non back to future fans).
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top