StarRubyでFC風文字表示(とキーボードからの文字入力)を試すでござるの巻
簡単な作業ツールをRfmで作り始めたが、カッとなってUIをFC風にすることにした。
DXRubyでやろうと思いましたが、Rfmと一緒に使うとnet/protocolあたりでtimeoutのエラーが出てしまう*1のでStar Rubyに変更。
表示はともかく、キーボードからの文字入力は大変。ゲーム用ライブラリだからしょうがないけど。
require 'starruby' include StarRuby #画面表示系のサポート処理 module StarRuby::Texture::Support FCWIN_FONT = Font.new("MS Gothic", 12) FCWIN_FORECOLOR = Color.new(255, 255, 255, 255) FCWIN_BACKCOLOR = Color.new(0, 0, 0, 255) #---------------------------------------------------------------------- #FC風枠の描画 def self.draw_fc_frame(aScreen, aLeft, aTop, aWidth, aHeight) aScreen.fill_rect(aLeft, aTop, aWidth, aHeight, FCWIN_BACKCOLOR) aScreen.fill_rect(aLeft + 1, aTop + 1, aWidth - 2, aHeight - 2, FCWIN_FORECOLOR) aScreen.fill_rect(aLeft + 3, aTop + 3, aWidth - 6, aHeight - 6, FCWIN_BACKCOLOR) aScreen[aLeft + 1, aTop + 1] = FCWIN_BACKCOLOR aScreen[aLeft + aWidth - 2, aTop + 1] = FCWIN_BACKCOLOR aScreen[aLeft + 1, aTop + aHeight - 2] = FCWIN_BACKCOLOR aScreen[aLeft + aWidth - 2, aTop + aHeight - 2] = FCWIN_BACKCOLOR end #---------------------------------------------------------------------- #FC風ウィンドウの描画 def self.draw_fc_window(aScreen, aLeft, aTop, aTexts) win_width = 0 win_height = 0 aTexts.each do |line| ts = FCWIN_FONT.get_size(line) win_width = ( win_width < ts[0] ) ? ts[0] : win_width win_height += ts[1] end win_width += 16 win_height += 12 draw_fc_frame(aScreen, aLeft, aTop, win_width, win_height) text_x = aLeft + 8 text_y = aTop + 6 aTexts.each do |line| aScreen.render_text(line, text_x, text_y, FCWIN_FONT, FCWIN_FORECOLOR) ts = FCWIN_FONT.get_size(line) text_y += ts[1] end end end #入力系のサポート処理 module StarRuby::Input::Support SHIFT_CHAR_MAP = { :a => ['a', 'A'], :b => ['b', 'B'], :c => ['c', 'C'], :d => ['d', 'D'], :e => ['e', 'E'], :f => ['f', 'F'], :g => ['g', 'G'], :h => ['h', 'H'], :i => ['i', 'I'], :j => ['j', 'J'], :k => ['k', 'K'], :l => ['l', 'L'], :m => ['m', 'M'], :n => ['n', 'N'], :o => ['o', 'O'], :p => ['p', 'P'], :q => ['q', 'Q'], :r => ['r', 'R'], :s => ['s', 'S'], :t => ['t', 'T'], :u => ['u', 'U'], :v => ['v', 'V'], :w => ['w', 'W'], :x => ['x', 'X'], :y => ['y', 'Y'], :z => ['z', 'Z'], :d0 => ['0', ''], :d1 => ['1', '!'], :d2 => ['2', '"'], :d3 => ['3', '#'], :d4 => ['4', '$'], :d5 => ['5', '%'], :d6 => ['6', '&'], :d7 => ['7', '\''], :d8 => ['8', '('], :d9 => ['9', ')'], :numpad0 => ['0', ''], :numpad1 => ['1', ''], :numpad2 => ['2', ''], :numpad3 => ['3', ''], :numpad4 => ['4', ''], :numpad5 => ['5', ''], :numpad6 => ['6', ''], :numpad7 => ['7', ''], :numpad8 => ['8', ''], :numpad9 => ['9', ''], :space => [' ', ' '], :add => ['+', ''], :backslash => ['\\', '|'], :backquotes => ['@', '`'], :closebrackets => ['[', '{'], :comma => [',', '<'], :decimal => ['.', ''], :divide => ['/', ''], :equals => ['^', '~'], :minus => ['-', '='], :multiply => ['*', ''], :openbrackets => ['@', '`'], :period => ['.', '>'], :quotes => [':', '*'], :slash => ['/', '?'], :semicolon => [';', '+'], :subtract => ['-', ''] } @@last_keys = [] #---------------------------------------------------------------------- #文字列編集メソッド(引数は編集する文字列、戻り値は [編集結果文字列, [残りのキーコード]]) def self.edit_text(text) #キーを取得 keys = Input.keys(:keyboard).dup #SHIFT状態を作成 shift_on = false if keys.include?(:capslock) shift_on = ! shift_on keys.delete(:capslock) end if keys.include?(:lshiftkey) || keys.include?(:rshiftkey) shift_on = ! shift_on keys.delete(:lshiftkey) if keys.include?(:lshiftkey) keys.delete(:rshiftkey) if keys.include?(:rshiftkey) end #前回と同じ状態ならなにもせず終了 return text, keys if @@last_keys == keys #キー状態を保存 last_keys = @@last_keys @@last_keys = keys.dup #前回と重複する文字を削除 keys.delete_if {|x| last_keys.include?(x)} #バックスペース処理 if keys.include?(:back) keys.delete(:back) text = text.slice(0, text.length - 1) if text.length > 0 #文字入力処理 else shift_idx = shift_on ? 1 : 0 keys.each do |key| key_info = SHIFT_CHAR_MAP[key] text += key_info[shift_idx] if key_info end end #文字列全体を返す return text, keys end end
英語キーボードには対応してませんのであしからず。
で、使ってみる。
$KCODE="u" require 'starruby' require 'support/starruby_support' include StarRuby account = "" password = "" dummy = "" last_keys = nil progress = :input_account Game.run(320, 120, :title => "Login Prompt", :cursor => true, :window_scale => 2) do |game| game.screen.clear #キー入力 keys = [] case progress when :input_account account, keys = Input::Support.edit_text(account) progress = :input_password if keys.include?(:enter) and last_keys != keys when :input_password password, keys = Input::Support.edit_text(password) progress = :complete if keys.include?(:enter) and last_keys != keys else dummy, keys = Input::Support.edit_text(dummy) end break if keys.include?(:escape) last_keys = keys.dup #表示 Texture::Support.draw_fc_window(game.screen, 20, 20, ["'あかうんと'をにゅうりょくせよ!:#{account}#{'_' if progress == :input_account }", "'ぱすわーど'をにゅうりょくせよ!:#{'*' * password.length}#{'_' if progress == :input_password }"]) if progress == :complete Texture::Support.draw_fc_window(game.screen, 100, 45, ["しょりはかんりょうした!"]) end end
もうこれでUI作ってリリースする!
...MacでやってみたらColor.new(0, 0, 0, 255)がブルーになりました。・・・これは見なかったことに。
*1:DXRubyが標準のtimeoutメソッドを書き換えてるのかしら?