Input Text Event Command

15 de março de 2013

Este é um minigame/tutorial do Input Text Event Command, um script desenvolvido por Wachunga que lida com o input de mensagens de texto num jogo de RPG Maker XP.

Ele permite o jogador a digitar textos com o teclado de forma semelhante ao comando “Input Number”.

Para instalar o script, basta adicionar acima do Main, no seu projeto. Ele precisa do RMXP Standard Development Kit (SDK) e do Keyboard Input Module que já estão incluidos na demo. Analise esta para entender melhor o funcionamento do script!

#==============================================================================
# ** Input Text Event Command
#------------------------------------------------------------------------------
# Wachunga
# Version 2.0
# 2006-05-20
#==============================================================================
=begin

  Version history:

  0.99 - original release
  1.0 - switched over to using regular variables
  2.0
   - vastly improved quality of keyboard input
     - variable-width letters
     - all characters on standard US keyboard supported (punctuation etc.)
     - added support for Delete (not just backspace), Home and End keys
     - added Capslock support
     - added cursor and Ctrl-cursor support
     - added numpad support
     - max number of displayable characters dynamically found and enforced
       (user can set lower maximum if desired)
   - added configurable sound
   - fixed bug with long input strings
   - SDK compatible

  Allows the player to input text with the keyboard in much the
  same way as the "Input Number" command. Simply enter the
  following into a call script event command:

  input_text(id, chars_max, 'default')

  where...
  id        : ID of the variable in which to store the input text, e.g. 1
                Note: leading 0's will cause problems, e.g. 008
  chars_max : (optional) max number of characters to be allowed, e.g. 10
                Note: leave blank or set as 0 for no limit
  'default' : (optional) default text to appear, e.g. 'Bob'

  As with the "Input Number" command, if it is directly preceded
  by a "Show Text" command and there is available space
  in the message window, the "Text Input" prompt will appear in
  the same window as the message text. Otherwise, it will appear
  in its own window.

  The input text can then be used as any variable,
  e.g. in messages (\V[x]), conditional branches, call scripts, etc.

  A sample use is for passwords, riddles, and names.

  Note: This script requires Near Fantastica's Keyboard Input Module version 5
  (http://www.rmxp.org/forums/local_links.php?catid=31&linkid=493) and
  the SDK (http://www.rmxp.org/forums/showthread.php?t=1802).

  Some keycodes assume the US standard keyboard. See the MSDN library's
  virtual keycodes reference for complete details:
  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/
  WindowsUserInterface/UserInput/VirtualKeyCodes.asp

=end

#------------------------------------------------------------------------------
# * SDK Log Script
#------------------------------------------------------------------------------
SDK.log('Input Text Event Command', 'Wachunga', 2.0, '2006-05-20')

if not SDK.state('Keyboard Input')
  p 'Keyboard Input script not found'
  SDK.disable("Input Text Event Command")
  p 'Input Text Event Command script disabled'
end

#------------------------------------------------------------------------------
# * Begin SDK Enable Test
#------------------------------------------------------------------------------
if SDK.state('Input Text Event Command') == true

#------------------------------------------------------------------------------
# configurable sound mode
# 0 - no extra sounds
# 1 - typing and deleting sounds
$input_text_sound_mode = 1
#------------------------------------------------------------------------------

module Keyboard
  @lock = []
  Del = 46
  Tilde = 192
  Forwardslash = 220
  Ctrl = 17
  Capslock = 20
  End = 35
  Home = 36
  Left = 37
  Right = 39

  # Note: original Numberpad constants in Keyboard Input Module are off
  Numpad = {}
  Numpad[0] = 96
  Numpad[1] = 97
  Numpad[2] = 98
  Numpad[3] = 99
  Numpad[4] = 100
  Numpad[5] = 101
  Numpad[6] = 102
  Numpad[7] = 103
  Numpad[8] = 104
  Numpad[9] = 105

  # trick to alias module method
  class << self
    alias wachunga_itec_Keyboard_update update
  end

  def Keyboard.testlock(key)
    State.call(key) & 0x01 == 1
  end

  def Keyboard.update
    wachunga_itec_Keyboard_update
    @lock.push(Keyboard::Capslock) if Keyboard.testlock(Keyboard::Capslock)
    @keys.push(Keyboard::Del) if Keyboard.testkey(Keyboard::Del)
    @keys.push(Keyboard::Tilde) if Keyboard.testkey(Keyboard::Tilde)
    if Keyboard.testkey(Keyboard::Forwardslash)
      @keys.push(Keyboard::Forwardslash)
    end
    @keys.push(Keyboard::Ctrl) if Keyboard.testkey(Keyboard::Ctrl)
    @keys.push(Keyboard::Capslock) if Keyboard.testkey(Keyboard::Capslock)
    @keys.push(Keyboard::End) if Keyboard.testkey(Keyboard::End)
    @keys.push(Keyboard::Home) if Keyboard.testkey(Keyboard::Home)
    @keys.push(Keyboard::Left) if Keyboard.testkey(Keyboard::Left)
    @keys.push(Keyboard::Right) if Keyboard.testkey(Keyboard::Right)
    for key in Keyboard::Numpad.values
      @keys.push(key) if Keyboard.testkey(key)
    end
    @pressed.push(Keyboard::Del) if Keyboard.getstate(Keyboard::Del)
    @pressed.push(Keyboard::Tilde) if Keyboard.getstate(Keyboard::Tilde)
    if Keyboard.getstate(Keyboard::Forwardslash)
      @pressed.push(Keyboard::Forwardslash) 
    end
    @pressed.push(Keyboard::Ctrl) if Keyboard.getstate(Keyboard::Ctrl)
    @pressed.push(Keyboard::Capslock) if Keyboard.getstate(Keyboard::Capslock)
    @pressed.push(Keyboard::End) if Keyboard.getstate(Keyboard::End)
    @pressed.push(Keyboard::Home) if Keyboard.getstate(Keyboard::Home)
    @pressed.push(Keyboard::Left) if Keyboard.getstate(Keyboard::Left)
    @pressed.push(Keyboard::Right) if Keyboard.getstate(Keyboard::Right)
    for key in Keyboard::Numpad.values
      @pressed.push(key) if Keyboard.getstate(key)
    end
  end

  def Keyboard.lock?(key)
    return true if @lock.include?(key)
    return false
  end
end

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

class Game_Temp

  attr_accessor :text_input_start       # opening line
  attr_accessor :text_input_variable_id # variable ID
  attr_accessor :text_input_chars_max   # max chars

  alias input_text_init initialize
  def initialize
    input_text_init
    @text_input_start = 99
    @text_input_variable_id = 0
    @text_input_chars_max = 0
  end
end

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

class Window_Message < Window_Selectable

 alias input_text_dispose dispose
 def dispose
   if @input_text_window != nil
     @input_text_window.dispose
   end
   input_text_dispose
 end

 alias input_text_tm terminate_message
 def terminate_message
   input_text_tm
   $game_temp.text_input_start = 99
   $game_temp.text_input_variable_id = 0
   $game_temp.text_input_chars_max = 0
 end

 alias input_text_refresh refresh
 def refresh
   input_text_refresh
   if $game_temp.text_input_variable_id > 0
     chars_max = $game_temp.text_input_chars_max
     text = $game_variables[$game_temp.text_input_variable_id]
     if text == 0 then text = nil end
     # create the window
     @input_text_window = Window_InputText.new(chars_max, text)
     @input_text_window.x = self.x + 4
     @input_text_window.y = self.y + $game_temp.text_input_start * 32
   end
 end

 def update
   super
   if @fade_in
     self.contents_opacity += 24
     if @input_number_window != nil
       @input_number_window.contents_opacity += 24
     end
#------------------------------------------------------------------------------
# Begin Input Text Event Command Edit
#------------------------------------------------------------------------------
     if @input_text_window != nil
       @input_text_window.contents_opacity += 24
     end
#------------------------------------------------------------------------------
# End Input Text Event Command Edit
#------------------------------------------------------------------------------
     if self.contents_opacity == 255
       @fade_in = false
     end
     return
   end
   if @input_number_window != nil
     @input_number_window.update
     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
       @input_number_window.dispose
       @input_number_window = nil
       terminate_message
     end
     return
   end
#------------------------------------------------------------------------------
# Begin Input Text Event Command Edit
#------------------------------------------------------------------------------
   if @input_text_window != nil
     @input_text_window.update
     if Keyboard.trigger?(Keyboard::Enter)
       $game_system.se_play($data_system.decision_se)
       # save the input text in the hash
       $game_variables[$game_temp.text_input_variable_id] =
         @input_text_window.text.to_s.strip
       $game_map.need_refresh = true
       @input_text_window.dispose
       @input_text_window = nil
       terminate_message
     end
     return
   end
#------------------------------------------------------------------------------
# End Input Text Event Command Edit
#------------------------------------------------------------------------------
   if @contents_showing
     if $game_temp.choice_max == 0
       self.pause = true
     end
     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
     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 @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
#------------------------------------------------------------------------------
# Begin Input Text Event Command Edit
#------------------------------------------------------------------------------
     if @input_text_window != nil
       @input_text_window.contents_opacity = 0
     end
#------------------------------------------------------------------------------
# End Input Text Event Command Edit
#------------------------------------------------------------------------------
     @fade_in = true
     return
   end
   if self.visible
     @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

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

class Interpreter

  # Show message
  def command_101
   if $game_temp.message_text != nil
     return false
   end
   @message_waiting = true
   $game_temp.message_proc = Proc.new { @message_waiting = false }
   $game_temp.message_text = @list[@index].parameters[0] + "\n"
   line_count = 1
   loop do
     if @list[@index+1].code == 401
       $game_temp.message_text += @list[@index+1].parameters[0] + "\n"
       line_count += 1
     else
       if @list[@index+1].code == 102
         if @list[@index+1].parameters[0].size <= 4 - line_count
           @index += 1
           $game_temp.choice_start = line_count
           setup_choices(@list[@index].parameters)
         end
       elsif @list[@index+1].code == 103
         if line_count < 4
           @index += 1
           $game_temp.num_input_start = line_count
           $game_temp.num_input_variable_id = @list[@index].parameters[0]
           $game_temp.num_input_digits_max = @list[@index].parameters[1]
         end
#------------------------------------------------------------------------------
# Begin Input Text Event Command Edit
#------------------------------------------------------------------------------
       elsif @list[@index+1].code == 355 # call script
         if line_count < 4 and
             @list[@index+1].parameters[0].include?('input_text')
           @index += 1
           $game_temp.text_input_start = line_count
           command_355
         end
#------------------------------------------------------------------------------
# End Input Text Event Command Edit
#------------------------------------------------------------------------------
       end
       return true
     end
     @index += 1
   end
  end

  #----------------------------------------------------------------------------
  # * Input Text (to be called by Script... event command)
  #     id        : ID of the variable in which to store the input text, e.g. 1
  #                   Note: leading 0's will cause problems, e.g. 008
  #     chars_max : (optional) max number of characters to be allowed, e.g. 10
  #                   Note: leave blank or set as 0 for no limit
  #     default   : (optional) default text to appear, e.g. 'Bob'
  #----------------------------------------------------------------------------
  def input_text(id, chars_max=0, default=nil)
   # check to see if in own window
   if $game_temp.text_input_start == 99
     # only do below if in its own window
     if $game_temp.message_text != nil
       return false
     end
     @message_waiting = true
     $game_temp.message_proc = Proc.new { @message_waiting = false }
     $game_temp.message_text = ''
     $game_temp.text_input_start = 0
   end
   $game_temp.text_input_variable_id = id
   $game_temp.text_input_chars_max = chars_max
   $game_variables[$game_temp.text_input_variable_id] = default
   return true     
  end

end

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

class Scene_Map

  def main_loop
    # Update game screen
    Graphics.update
    # Update input information
#------------------------------------------------------------------------------
# Start Input Text Event Command Edit
#------------------------------------------------------------------------------
    Keyboard.update # can't alias here: Input.update ruins GetAsyncKeyState
#------------------------------------------------------------------------------
# End Input Text Event Command Edit
#------------------------------------------------------------------------------
    Input.update
    # Frame update
    update
  end
end

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

#==============================================================================
# ** Window_InputText
#------------------------------------------------------------------------------
#  This window is for inputting text and is used within the
#  message window.
#==============================================================================
class Window_InputText < Window_Base

  attr_reader :text

  # maximum length of input text (in pixels)
  MAX_WIDTH = 448
  CURSOR_WIDTH = 2

  #----------------------------------------------------------------------------
  # * Object Initialization
  #     chars_max : max number of characters (0 is infinite)
  #     default   : (optional) default text to appear, e.g. 'Bob'
  #----------------------------------------------------------------------------
  def initialize(chars_max=0, default=nil)
   @chars_max = (chars_max == 0 ? 1000 : chars_max)
   @char_widths = calculate_char_widths
   @cursor_width = CURSOR_WIDTH
   super(0, 0, 480, 64)
   self.contents = Bitmap.new(width - 32, height - 32)
   self.z += 9999
   self.opacity = 0
   @cursor_x = 0
   @text = Array.new
   if default != nil
     for i in 0...default.size
       @text[i] = default[i].chr
       @cursor_x += @char_widths[@text[i]]
     end
     @index = @text.size
   else
     @index = 0
   end
   @last_text = @text.clone
   refresh
   update_cursor_rect
  end

  #----------------------------------------------------------------------------
  # * Character Width Calculation
  #----------------------------------------------------------------------------
  def calculate_char_widths
    widths = {}
    dummy_bitmap = Bitmap.new(32, 32)
    for i in 32..126 # ASCII values
      widths[i.chr] = dummy_bitmap.text_size(i.chr).width
    end
    dummy_bitmap.dispose
    # text_size() is inaccurate in some cases, so manually adjust
    widths['f'] += 2
    widths['A'] += 1
    widths['a'] += 1
    widths['V'] += 1
    widths['v'] += 1
    widths['M'] += 1
    widths['W'] += 1
    widths['w'] += 1
    widths['y'] += 1
    widths['/'] += 1
    widths['\\'] += 1
    return widths
  end

  #----------------------------------------------------------------------------
  # * Cursor Rectangle Update
  #----------------------------------------------------------------------------
  def update_cursor_rect
   self.cursor_rect.set(@cursor_x, 0, @cursor_width, 32)
  end

  #----------------------------------------------------------------------------
  # * Character Addition
  #     character - character to be displayed
  #----------------------------------------------------------------------------
  def add(character)
    if @total_width + @char_widths[character] <= MAX_WIDTH and
        @text.size < @chars_max
      if $input_text_sound_mode == 1
        $game_system.se_play($data_system.cursor_se)
      end
      @text.size.downto(@index+1) do |i|
        @text[i] = @text[i-1]
      end
      @text[@index] = character
      @index += 1
      @cursor_x += @char_widths[character]
    else
      $game_system.se_play($data_system.cancel_se)
    end
  end

  #----------------------------------------------------------------------------
  # * Frame Update
  #----------------------------------------------------------------------------
  def update
    super
    if Keyboard.trigger?(Keyboard::Back) # backspace key
      if @index == 0
        $game_system.se_play($data_system.cancel_se)
      else
        if $input_text_sound_mode == 1
          $game_system.se_play($data_system.cursor_se)
        end
        @index -= 1
        @cursor_x -= @char_widths[@text[@index]]
        @text[@index] = nil
        @text.compact!
      end
    end
    if Keyboard.trigger?(Keyboard::Del) # delete key
      if @index == @text.size
        $game_system.se_play($data_system.cancel_se)
      else
        if $input_text_sound_mode == 1
          $game_system.se_play($data_system.cursor_se)
        end
        @text[@index] = nil
        @text.compact!
      end
    end
    if Keyboard.trigger?(Keyboard::End)
      @index = @text.size
      @cursor_x = @total_width
      update_cursor_rect
    end
    if Keyboard.trigger?(Keyboard::Home)
      @index = @cursor_x = 0
      update_cursor_rect
    end
    if Keyboard.trigger?(Keyboard::Right)
      if @index < @text.size
        if not Keyboard.pressed?(Keyboard::Ctrl)
          # regular cursor movement (one letter)
          @index += 1
          @cursor_x += @char_widths[@text[@index-1]]
        else
          # Ctrl-cursor movement (next word)
          # scan right until beginning of new word found
          space_found = false
          target = -1
          x = 0
          for i in @index...@text.size
            x += @char_widths[@text[i]]
            if space_found == false
              if @text[i] == ' '
                space_found = true
              end
            else
              if @text[i] != ' '
                target = i
                x -= @char_widths[@text[i]]
                break
              end
            end
          end
          if target != -1
            # a new word was found
            @index = target
            @cursor_x += x
          else
            # jump to end of input
            @index = @text.size
            @cursor_x = @total_width
          end
        end
        update_cursor_rect
      end
    end
    if Keyboard.trigger?(Keyboard::Left)
      if @index != 0
        if not Keyboard.pressed?(Keyboard::Ctrl)
          # regular cursor movement (one letter)
          @index -= 1
          if @index == 0 then @cursor_x = 0
          else
            @cursor_x -= @char_widths[@text[@index]]
          end
        else
          # Ctrl-cursor movement (next word)
          # scan left until beginning of new word found
          non_space_found = false
          target = -1
          x = 0
          (@index-1).downto(0) do |i|
            x += @char_widths[@text[i]]
            if non_space_found == false
              if @text[i] != ' '
                non_space_found = true
              end
            else
              if @text[i] == ' '
                target = i+1
                x -= @char_widths[@text[i]]
                break
              end
            end
          end
          if target != -1
            # a new word was found
            @index = target
            @cursor_x -= x
          else
            # jump to start of input
            @index = 0
            @cursor_x = 0
          end
        end
        update_cursor_rect
      end
    end
    # Letters...
    for key in Keyboard::Letters.values
      if Keyboard.trigger?(key)
        if ( Keyboard.lock?(Keyboard::Capslock) and
             !Keyboard.pressed?(Keyboard::Shift) ) or
           ( !Keyboard.lock?(Keyboard::Capslock) and
             Keyboard.pressed?(Keyboard::Shift) )
          add(key.chr.upcase)
        else add(key.chr.downcase)
        end
      end
    end
    # Numbers...
    for key in Keyboard::Numberkeys.values
      if Keyboard.trigger?(key)
        if Keyboard.pressed?(Keyboard::Shift)
          case key
            when Keyboard::Numberkeys[0] then add(')')
            when Keyboard::Numberkeys[1] then add('!')
            when Keyboard::Numberkeys[2] then add('@')
            when Keyboard::Numberkeys[3] then add('#')
            when Keyboard::Numberkeys[4] then add('$')
            when Keyboard::Numberkeys[5] then add('%')
            when Keyboard::Numberkeys[6] then add('^')
            when Keyboard::Numberkeys[7] then add('&')
            when Keyboard::Numberkeys[8] then add('*')
            when Keyboard::Numberkeys[9] then add('(')
          end
        else
          add(key.chr)
        end
      end
    end
    # Numpad...
    for key in Keyboard::Numpad.values
      if Keyboard.trigger?(key)
        case key
          when Keyboard::Numpad[0] then add('0')
          when Keyboard::Numpad[1] then add('1')
          when Keyboard::Numpad[2] then add('2')
          when Keyboard::Numpad[3] then add('3')
          when Keyboard::Numpad[4] then add('4')
          when Keyboard::Numpad[5] then add('5')
          when Keyboard::Numpad[6] then add('6')
          when Keyboard::Numpad[7] then add('7')
          when Keyboard::Numpad[8] then add('8')
          when Keyboard::Numpad[9] then add('9')
        end
      end
    end
    if Keyboard.trigger?(Keyboard::Space)
      add(' ')
    end
    if Keyboard.trigger?(Keyboard::Tilde)
      if Keyboard.pressed?(Keyboard::Shift) then add('~')
      else add('`') end
    end
    if Keyboard.trigger?(Keyboard::Lb)
      if Keyboard.pressed?(Keyboard::Shift) then add('{')
      else add('[') end
    end
    if Keyboard.trigger?(Keyboard::Rb)
      if Keyboard.pressed?(Keyboard::Shift) then add('}')
      else add(']') end
    end
    if Keyboard.trigger?(Keyboard::Comma)
      if Keyboard.pressed?(Keyboard::Shift) then add('<')
      else add(',') end
    end
    if Keyboard.trigger?(Keyboard::Dot)
      if Keyboard.pressed?(Keyboard::Shift) then add('>')
      else add('.') end
    end
    if Keyboard.trigger?(Keyboard::Backslash)
      if Keyboard.pressed?(Keyboard::Shift) then add('?')
      else add('/') end
    end
    if Keyboard.trigger?(Keyboard::Forwardslash)
      if Keyboard.pressed?(Keyboard::Shift) then add('|')
      else add("\\") end
    end
    if Keyboard.trigger?(Keyboard::Collon)
      if Keyboard.pressed?(Keyboard::Shift) then add(':')
      else add(';') end
    end
    if Keyboard.trigger?(Keyboard::Quote)
      if Keyboard.pressed?(Keyboard::Shift) then add('"')
      else add("'") end
    end
    if Keyboard.trigger?(Keyboard::Equal)
      if Keyboard.pressed?(Keyboard::Shift) then add('+')
      else add("=") end
    end
    if Keyboard.trigger?(Keyboard::Underscore)
      if Keyboard.pressed?(Keyboard::Shift) then add('_')
      else add("-") end
    end
    if (@text <=> @last_text) != 0
      @last_text = @text.clone
      refresh
    end
  end

  #----------------------------------------------------------------------------
  # * Refresh
  #----------------------------------------------------------------------------
  def refresh
   self.contents.clear
   x = 0
   for i in 0...@text.size
     width = @char_widths[@text[i]]
     self.contents.draw_text(x, 0, width, 32, @text[i], 1)
     x += width
   end
   @total_width = x
   update_cursor_rect
  end

end

#------------------------------------------------------------------------------
# * End SDK Enable Test
#------------------------------------------------------------------------------
end

Download e ficha técnica

  • Download (clique com o botão esquerdo do mouse ou toque no link).
  • Desenvolvedor, publisher e/ou distribuidor: Wachunga
  • SO: Windows 98/98SE/Me/2000/XP/Vista/7
  • Tamanho: 281KB
  • Licença: Grátis
  • Categoria: Programação XP
  • Tag: RPG Maker XP
  • Adicionado por: LichKing
  • Acessos: 38

Observação: se você gostou deste post ou ele lhe foi útil de alguma forma, por favor considere apoiar financeiramente a Gaming Room. Fico feliz só de ajudar, mas a contribuição do visitante é muito importante para que este site continua existindo e para que eu possa continuar provendo este tipo de conteúdo e melhorar cada vez mais. Acesse aqui e saiba como. Obrigado!

Deixe um comentário

Inscreva-se na nossa newsletter!