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.

How to "Show Text" in a message window using RGSS?

*Edit* I'm using RPG Maker XP!

I'm working on an introduction script for my game, and I need to be able to mimic the effect of the Event Command "Show Text" - meaning I want to display a series of messages that will introduce my game. Could somebody explain to me the best way to accomplish this?
 
I'm not quite sure what you're trying to get that you can't do with regular messages. Let's say you're in a scene outside Scene_Map, meaning there's no message window present, you could still take a look at how it's initialized and set up in that scene (along with Spriteset_Map maybe... not sure, but probably not) and mimic that setup in your custom introductional scene, being able to create a new message the regular (scripted) way.

That is pretty in-general, however you chose to keep your RPG Maker version a secret, which is why I can't help you any further here :p
 
Thanks BlueScope for your reply, sorry I forgot to mention I'm using RMXP. Let me be more specific about my script as well: As you suggested, I am creating a new scene called Scene_Intro. (Of course I could do everything I want to accomplish easily with events, but this is a learning project for me as I am trying to learn RGSS.) My script will work similar to the way the title screen works by displaying a background image, but without the command window. It will instead, display a message window to introduce the game! I would like to accomplish this completely event free. Do I need to create another class, something like class Intro_Window and call it from my Scene_Intro? Or is there another way of doing it? Preferably, I would like the intro text to be easily customizable by different users.
 
You can't use Window_Message, the window used to display text in the game.
It uses variables which will be defined only later, when the game starts.
make your own simple window, something like:
[rgss]class Mywindow < Window_Selectable
  def initialize
      super(80, 304, 480, 160)
      self.contents = Bitmap.new(width - 32, height - 32)
  end
 
  def show(text)
    @text = text
  end
 
  def update
    self.contents.clear
    self.contents.draw_text(x, y, width, height, @text, align)
    # if you wish to mimic the default message :
    # self.contents.draw_text(0, 32* line, width, 32, @text, 0)
  end
 
end
[/rgss]

Your scene should create and update the window. Its update method should check if Enter was pressed, and if so show the next message.
[rgss]class Scene_Intro
  def main
     @message_window = Mywindow.new
     # show title picture
     @sprite = Sprite.new
     @sprite.bitmap = RPG::Cache.title($data_system.title_name)
      # you probably want to store all the text in an array.
     @array = [ "message", "second message" ..]
     @i = 0
     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
    @message_window.dispose
    @sprite.bitmap.dispose
    @sprite.dispose
  end
 
  def update
    # if player hits Enter, Space or X
    if Input.trigger?(Input::C)
      @i += 1
      # if done showing all messages
      if (@i == @array.size)  
        # exit this scene and go to title screen
        $scene = Scene_Title.new
      else
        next_message = @array[@i]  
        @message_window.show(next_message)
      end
    end
    @message_window.update
  end
 
end
[/rgss]
 
I don'T see why you wouldn't be able to set these variables yourself, temporarily... creating a second window to mimic one that's already accessible seems weird to me, especially since people are likely to use CMS' and therefore might want to keep a distinct style to their game, not necessarily achieveable your way (even the default downpoint animation, for example, won't be working this way).
But yeah, other than that, it's a completely fine and clean way to do this... if it's not about perfect exactness.
 
Yeah, it's possible to use Window_Message, if you first create $game_temp, $game_variables and $game_actors, and set $game_temp.message_text to the next message.
It just seems like an overkill for a simple task of showing text and the title picture.
It's unlikely anyone will need a number input, a game variable or actor's name during the intro. Show choices, however, may come in handy- if you want to select a playable character, for example.
Do you know how to add the down animation to a window?
 
Well, while I could draw the animation manually with ease, I don't know if there's a method, flar or whatever you can assign to a window to get it. I'm pretty sure it's in Window_Message, though, if anywhere in the non-hidden scripts.
And yeah, I think setting all that (which you set later anyway, so it's not actually 'more' you do) isn't more overkilling than creating an entirely new window, and after all, you don't have to mess with anything at all either way (like I said: Custom message system that might offer a bazilion functions, or the integration of my Multiple Language script that you basically would have to recreate). All in all, I doubt having the same thing used for the same occassion can be worse than having a cloned attempt...
 
Thank you both for your replies (and your different point of views)! Your explanations have helped me to understand windows a lot better. I have only been working with RGSS for a few weeks now and this will be my first time creating windows.

silver wind":18ce8szn said:
Do you know how to add the down animation to a window?

I do not know how to add the down animation to a window yet, which is actually another question I would have asked. I would like to create a custom down animation that displays after the final word in the window, rather than at the bottom of the window.

BlueScope":18ce8szn said:
creating a second window to mimic one that's already accessible seems weird to me, especially since people are likely to use CMS' and therefore might want to keep a distinct style to their game, not necessarily achieveable your way (even the default downpoint animation, for example, won't be working this way).

When you have time, could you explain to me how you might go about this your way? Your argument on keeping a distinct style throughout the game is quite valid. In my intro, it may be optimal for the window to match the rest of the game automatically. How could I ensure that my intro window will work with someone's CMS? (Actually, I'm sure I will be writing my own CMS for this project eventually.)

Here's a bit more information about what I would like to accomplish in the Intro: At some point, the player will choose between two playable characters. Then the player will be able to name the hero. Other than that, it will just be text for the player to read through.

Thanks again for all your help!
 
XeroVolume":249vgi5p said:
At some point, the player will choose between two playable characters. Then the player will be able to name the hero. Other than that, it will just be text for the player to read through.

Thanks again for all your help!
In that case, you're better with BlueScope's way.
All you'll have to change in the script I posted earlier is:

1. @message_window = Mywindow.new

instead, use:
$game_temp = Game_Temp.new
$game_actors = Game_Actors.new
$game_variables = Game_Variables.new
@message_window = Window_Message.new

2. @message_window.show(next_message)
instead use:
$game_temp.message_text = next_message
 
oh WOW I can't believe I missed that! I thought maybe there was some hidden method called show or something but I couldn't figure it out... Anyway there are a few bugs I noticed, except this time I was able to figure them out. :biggrin: Here's your script again, slightly tweaked so that it works the way you had in mind.

Code:
class Scene_Intro

  def main

     @message_window = Window_Message.new

     # show title picture

     @sprite = Sprite.new

     @sprite.bitmap = RPG::Cache.title($data_system.title_name)

      # you probably want to store all the text in an array.

     @array = [ "message", "second message" ]

     @i = 0

     # Transition run

     Graphics.transition

     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

    @message_window.dispose

    @sprite.bitmap.dispose

    @sprite.dispose

  end

 

  def update

    next_message = @array[@i]

    $game_temp.message_text = (next_message)

    # if player hits Enter, Space or X

    if Input.trigger?(Input::C)

      @i += 1

      # if done showing all messages

      if (@i == @array.size)  

        # exit this scene and go to title screen

        $scene = Scene_Title.new

      end

    end

    @message_window.update

  end

 

end

First, you forgot the Graphics.transition before the loop. Next, it wasn't displaying the messages correctly because it was first checking if the player pressed C before it would set $game_temp.message_text = (message_next) and therefore @i was set to 1 before it even displayed the first window. I moved next_message = @array[@i] and $game_temp.message_text = (next_message) outside of the if statement and now everything works according to plan!

Oh yeah I almost forgot: I didn't need to create $game_temp, $game_variables and $game_actors because my intro script will come just after the title screen, (and only if the player selects new game) and the title screen sets those variables for me.

I never could have done this without you silver wind! Thank you so much! So... any tips on creating that custom down animation?
 
You're welcome, I'm sure you could, though :)

The help file says the down animation is controlled by:
@pause = true # show down animation
@pause = false # hide animation
The actual method to show the animation is in the hidden class Window. In other words, I don't have a clue. o.o
 
I've come across another bug that I'm having trouble correcting. It is caused by the following line:

Code:
# if Input.trigger?(Input::C)

#       @i += 1

Say someone is trying to scroll through the intro messages very fast and they just keep pressing C (Everyone does this). Well by the time the first message is displayed, they could have pressed C five (or more) times, which would set @i to 5, thus instead of displaying the remaining messages in order, it would skip to the 5th message in the array. (well, fourth when you include the zero)

I hope I've described this bug accurately enough... Any ideas on how to fix this?

I've been looking through all the window classes but I can't find how the default scripts handle this issue. How can I correct the script so that it adds 1 to @i when C is pressed but only after the current message in the array is displayed? I know some CMS' have one letter at a time features which obviously have to deal with this problem in some way. I guess I'll have a look at some of them and see if I can find something useful.
 
Ok here's what I have now. It seems to be an improvement, but still not perfect. I need some help guys!

Code:
class Scene_Intro

  def main

     # Create message window

     @message_window = Window_Message.new

     # Create background image

     @sprite = Sprite.new

     @sprite.bitmap = RPG::Cache.title($data_system.title_name)

      # Array for storing intro messages

     @array = [ "message", "second message", "third message" ]

     # The index of the message being displayed

     @i = 0

     # Initialize the first message

     $game_temp.message_text = @array[@i]

     # Transition run

     Graphics.transition

     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

    # Frreeze the Graphics

    Graphics.freeze

    # Dispose the window(s) & sprite(s)

    @message_window.dispose

    @sprite.bitmap.dispose

    @sprite.dispose

  end

 

  def update

    # Update the message window

    @message_window.update

    # If showing message window

    if $game_temp.message_window_showing

      return

    end

    @i += 1

    # If finished showing all messages in array

    if (@i == @array.size)  

      # Switch to map screen

      return $scene = Scene_Map.new

    end

    # Otherwise, set the message_text to the next item in the array

    $game_temp.message_text = @array[@i]

  end

end

Using $game_temp.message_window_showing solves my original problem, but it also creates a new one. Now the message window disappears for a split second in between each message!

The player presses C, the message window disappears, @i is updated, message_text is set to the next item in the array, and then a new message window displays showing the next message in order.

I hate to be a nuisance but this just doesn't look right. When you "Show Text" from an Event Command, the message window does not disappear between each message.

What's the secret?
 
Hmm. I don't know how it's done automatically.
This edit to window_message will stop it from 'blinking', just add this line to intro_scene: @message_window.dont_fade_out
[rgss]class Window_Message < Window_Selectable
 
  attr_accessor  :dont_fade_out
 
  def dont_fade_out
    @dont_fade = true
  end
 
  def update
    super
    # If fade in
    if @fade_in
      self.contents_opacity += 24
      if @input_number_window != nil
        @input_number_window.contents_opacity += 24
      end
      if self.contents_opacity == 255
        @fade_in = false
      end
      return
    end
    # If inputting number
    if @input_number_window != nil
      @input_number_window.update
      # Confirm
      if Input.trigger?(Input::C)
        $game_system.se_play($data_system.decision_se)
        $game_variables[$game_temp.num_input_variable_id] =
          @input_number_window.number
        $game_map.need_refresh = true
        # Dispose of number input window
        @input_number_window.dispose
        @input_number_window = nil
        terminate_message
      end
      return
    end
    # If message is being displayed
    if @contents_showing
      # If choice isn't being displayed, show pause sign
      if $game_temp.choice_max == 0
        self.pause = true
      end
      # Cancel
      if Input.trigger?(Input::B)
        if $game_temp.choice_max > 0 and $game_temp.choice_cancel_type > 0
          $game_system.se_play($data_system.cancel_se)
          $game_temp.choice_proc.call($game_temp.choice_cancel_type - 1)
          terminate_message
        end
      end
      # Confirm
      if Input.trigger?(Input::C)
        if $game_temp.choice_max > 0
          $game_system.se_play($data_system.decision_se)
          $game_temp.choice_proc.call(self.index)
        end
        terminate_message
      end
      return
    end
    # If display wait message or choice exists when not fading out
    if @fade_out == false and $game_temp.message_text != nil
      @contents_showing = true
      $game_temp.message_window_showing = true
      reset_window
      refresh
      Graphics.frame_reset
      self.visible = true
      self.contents_opacity = 0
      if @input_number_window != nil
        @input_number_window.contents_opacity = 0
      end
      @fade_in = true
      return
    end
    # If message which should be displayed is not shown, but window is visible
    if self.visible
      # --------------- my edit ----------------- #
      if @dont_fade
        @fade_out = false
        $game_temp.message_window_showing = false
        return
      end
      # --------------- my edit ----------------- #
      @fade_out = true
      self.opacity -= 48
      if self.opacity == 0
        self.visible = false
        @fade_out = false
        $game_temp.message_window_showing = false
      end
      return
    end
  end
 
end
[/rgss]
lines 86-92 are causing the window to fade out and disappear. calling @message_window.dont_fade_out will stop it from doing that.
Note how @dont_fade evaluates to false by default, as it doesn't exist until you call the dont_fade_out method. In other words, this will have no effect on in-game messages, as my if condition(line 80) will always be false for them.
 
Thanks silver wind! This is great! Now it works exactly like I've been wanting. If we only knew how the "Show Text" Event Command does it, then we wouldn't have to edit Window_Message!

XeroVolume (Yes I'm quoting myself!)":2vcm1t7f said:
When you "Show Text" from an Event Command, the message window does not disappear between each message.
silver wind":2vcm1t7f said:
Hmm. I don't know how it's done automatically.
I am very interested in finding out how this is done without having to edit Window_Message! Does anybody have any idea?

Either way, thank you so much silver wind! You've been a great help with not only my script, but also my understanding of RGSS!
 
Glad I could help :)
I'm also curious how it's done normally. I guess it's inside Interpreter's command 101 (show text), as this is the class handling event commands and it can check if the next command is another show-text.
 
You're exactly right silver wind. The "secret" is in the following lines inside Interpreter's command_101 method:

# Set message end waiting flag and callback
@message_waiting = true
$game_temp.message_proc = Proc.new { @message_waiting = false }

The help file doesn't do much to explain the Proc function, and all I know is that the "Show Text" Event Command uses it so if I want to mimic that command, I need to use it as well. It took a lot of copying and pasting of random blocks of suspicious code to figure this out, not to mention all the help from my fellow scripters! (Thank you bluescope, silver wind, and Night_Rider for all your help!)

And here is the functional core of my Intro Script:

Code:
#==============================================================================

# ** Scene_Intro

#------------------------------------------------------------------------------

#  This class performs intro screen processing.

#==============================================================================

 

class Scene_Intro

  #--------------------------------------------------------------------------

  # * Main Processing

  #--------------------------------------------------------------------------

  def main

     # Create message window

     @message_window = Window_Message.new

     # Create background image

     @sprite = Sprite.new

     @sprite.bitmap = RPG::Cache.title($data_system.title_name)

     # Array for storing intro messages

     @array = [ "first message", "second message", "third message" ]

     # The index of the message being displayed

     @i = -1

     # Transition run

     Graphics.transition

     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

    # Frreeze the Graphics

    Graphics.freeze

    # Dispose of message window

    @message_window.dispose

    # Dispose of title image

    @sprite.bitmap.dispose

    @sprite.dispose

    # If switching to map screen

    if $scene.is_a?(Scene_Map)

      # Fade out screen

      Graphics.transition

      Graphics.freeze

    end

  end

  #--------------------------------------------------------------------------

  # * Frame Update

  #--------------------------------------------------------------------------

  def update

    # If the message_text is empty

    if $game_temp.message_text == nil

      @i += 1

      # If finished showing all messages in array

      if (@i == @array.size)  

        # Switch to map screen

        return $scene = Scene_Map.new

      end

      # Set message end waiting flag and callback

      @message_waiting = true

      $game_temp.message_proc = Proc.new { @message_waiting = false }

      # Set the message text to the next item in the array

      $game_temp.message_text = @array[@i]

    end

    # Update the message_window

    @message_window.update

  end

end

This way, no editing of class Window_Message is needed!

Whew, now I can finally get back to work on the rest of the Intro Scene! :thumb:
 

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