CoRでRPG作ろうとしたら色々ぶつかった #2

投稿者:    mini 光楼(114) 投稿日:2020/09/16 23:40

テンション抑えて行きますわよ!

メッセージウィンドウ

Rmakeではspeekで済むのですが、CoRにはまだそんな便利なものはない。
だからこれも自作する。

まず何が必要か考える。
テキストと画像。
うん、簡単だね!

CoRならスプライトテキストってのがあるので、それを使いましょう。
スプライトをカメラから独立させるcamera_fixed!メソッドも忘れずに設定すること!

そして背景だけども、指定色で塗り潰してくれるような便利なメソッドは無いので、これも自作します。
こんなのを作ったよ!
1色あたり1px四方。
一番左が透明、一番右が不透明。
1pxごとに透明度が変わる。

良い感じの透明度の部分を切り取って、scaleメソッドで拡大して使おうという算段だったんですが……

なんか隣の白が見えてる!!!

仕方がないのでさっきの画像を10倍のサイズにして、1色あたり10pxにしたのだがこれも同じ症状が発生。
結局切り取るのを中央付近の5px*5pxにして解決した。

さて、背景とテキストだけではつまらないので枠を付けます。
枠は上下左右4本必要なのですが、1つ1つ書くのは面倒というかスタイリッシュじゃありません。
なので繰り返し文を使って、ポジションと拡大率の所だけ分岐させる事にしました。
もちろん返り値は配列に入れることになります。

さて、Rmakeでループと言えばwhile文なのですが、CoRにはもっと便利な何かがないかな~と探していたらありました。
(0..3).each do |item|
    debug_log item #0~3まで順番に出力される
end

ループ回数が決まっているならこれが扱いやすそうです。

そしてこれらの表示、キーボード入力、削除を一つの関数にまとめて……
先日作ったイベントに書き込むと……

出来た!

せっかくなので文字色やらサイズやら表示位置を設定で変えられるようにしたい。
設定を変更する関数を用意しようかと思ったけど、それだと設定変更→メッセージ表示→設定戻すって感じになって煩わしい。

なので関数実行時にオプションで指定出来るようにすることにした。
さて、大雑把に説明すると……
def message(m)
  ~略~
end
今関数はこんな感じになっている
message("おはよう!", color = "#00FF00", size = 20)
関数実行時にオプションで、こんな感じで設定できるようにしたい
さて、どう引数を設定しよう?
def message(m, color = "#FFFFFF", size = 18)
  ~略~
end
引数を設定するときに初期値も書くやり方。 他の言語ではよくある方法
message("おはよう!")
message("おはよう!", "#0000FF")
どうやら成功! 初期値が反映されているようだ!!!
message("おはよう!", size = 22)
だが残念! sizeだけ指定しようとしたらエラーが出た! これでは意味がない……
def message(m: "", color: "#FFFFFF", size: 18)
  ~略~
end
Rubyのキーワード引数を試してみた。
message(m: "おっはー!", size: 25)
これも失敗!
どうすりゃいいんだ!!!
message("Hello!", nil, 20)
こんなことも考えた。関数内でnilなら初期値を設定する方法。
煩わしい!引数の数だけ判定文書かなきゃならねぇ!可読性悪い!意地でも避けたい!
なんかないかな~ってCoRのリファレンス読んでたらありました。使えそうなのが。
hash_table = {:key => "値"}
speak(hash_table[:key]) # 「値」と表示される
Hashクラスってやつ
早速書いてみる。
def message(m="", {:color => "#FFFFFF", :size => 18})
  ~略~
end

message("Good morning!", {:size => 30})
ダメだった! sizeしか設定されなかったorz

もはやこれまで……

いや、まだ諦めるには早い!
初期値を中に書けば……!!!

カチカチカチ……ッターン!!!!!
def message(m='', args = {}) # 引数はハッシュテーブル
  # 引数初期値
  #座標, サイズ, テキストサイズ・色・太字・イタリック, 背景透明度、色, 枠色
  arguments = {:x => 100, :y => 300, :w => 600, :h => 125, :size => 18, :c => '#FFFFFF', :b => false, :it => false, :bg_opacity => 80, :bg_c => 0, :frame_c => 1}
  # 引数書換え
  args.each do |key, value|
    arguments[key] = value
  end
~略~

message("うおおお!", {:c => '#FF0000'})

出来た!動くか!?






動いたあああああああああああ!!!





message("あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ",
        {:bg_c => 1, :c => '#0000FF', :frame_c => 0, :size => 36})

こんなことも出来っ…………!






はみ出てるうううううううううう!!!

お、おかしいぞ!?文章を折り返すwordwrapメソッドwordwrap_widthメソッドを設定しているのに!

というか従来のcreateText等でも範囲外へはみ出す始末……CoRのバグかな?
仕方がないのではみ出さないように\nで改行させることにしましょうか。

では最後にメッセージウィンドウのコードを載せてお別れです。
次回あるか分からないけど乞うご期待!
#========== 塗り潰し ==========#
#===== 素材定義 =====#
sprite 'color_sprite' do
  image 'color_sp'
  origin :left_top
end

#===== 関数定義 =====#
#配置座標, サイズ, 色0~, 不透明度0~100, カメラ独立
def filling(x, y, w, h, c, opacity, camera = true)
  filsp = put_sprite 'color_sprite' do
    src_rect(opacity*$parts_size+2, c*$parts_size+2, $clip_size, $clip_size)
    position x, y
    scale w / $clip_size, h / $clip_size
    if camera
      camera_fixed!
    end
  end
  return filsp
end


#========== メッセージウィンドウ ==========#
#===== 素材定義 =====#
text 'message-text' do
  origin :left_top
end

#===== 関数定義 =====#
def message(m='', args = {}) # 引数はハッシュテーブル
  # 引数初期値
  #座標, サイズ, テキストサイズ・色・太字・イタリック, 背景不透明度、色, 枠色
  arguments = {:x => 100, :y => 300, :w => 600, :h => 125, :size => 18, :c => '#FFFFFF', :b => false, :it => false, :bg_opacity => 80, :bg_c => 0, :frame_c => 1}
  # 引数書換え
  args.each do |key, value|
    arguments[key] = value
  end

  #Zキーを離していなければtrue
  if keyboard.down?('Z')
    waitloop = true
  else
    waitloop = false
  end

  #画像用設定
  ofst = 10 #枠と文字位置決定用
  fr_w = 2 #フレーム幅 2pxに設定

  #背景の設定
  msbg_sprite = filling(arguments[:x], arguments[:y], arguments[:w], arguments[:h], arguments[:bg_c], arguments[:bg_opacity])

  #枠の設定
  msfr = []
  #上
  msfr << filling(arguments[:x], arguments[:y], arguments[:w], fr_w, arguments[:frame_c], 100)
  #左
  msfr << filling(arguments[:x], arguments[:y], fr_w, arguments[:h], arguments[:frame_c], 100)
  #右
  msfr << filling(arguments[:x] + arguments[:w], arguments[:y], -fr_w, arguments[:h], arguments[:frame_c], 100)
  #下
  msfr << filling(arguments[:x], arguments[:y] + arguments[:h], arguments[:w], -fr_w, arguments[:frame_c], 100)

  #テキストの設定
  message_sprite = put_text 'message-text' do
    position arguments[:x] + ofst, arguments[:y] + ofst
    font_size arguments[:size]
    color arguments[:c]
    bold arguments[:b]
    italic arguments[:it]
    wordwrap true
    wordwrap_width arguments[:w] - ofst*2
    camera_fixed!
    text m
  end
  
  #レイヤー設定
  $system_layer.add msbg_sprite #背景
  $system_layer.add message_sprite #テキスト
  msbg_sprite.layer_index 0
  message_sprite.layer_index 2
  msfr.each do |item| #枠
    $system_layer.add item
    item.layer_index 1
  end


  #離すのを待つ
  while waitloop
    if !keyboard.down?('Z')
      break
    end
    wait_time(10)
  end

  #Zキー押したら終了
  while !keyboard.down?('Z')
    wait_time(10)
  end
  #スプライトの削除
  message_sprite.destroy
  msbg_sprite.destroy
  msfr.each do |item|
    item.destroy
  end
end


上記で述べてた枠設定のループの件……
実はスプライトを配置する部分を関数化したのでループ不要になりました。(∀`*ゞ)テヘッ
  #枠の設定
  msfr = []
  #上
  msfr << filling(arguments[:x], arguments[:y], arguments[:w], fr_w, arguments[:frame_c], 100)
  #左
  msfr << filling(arguments[:x], arguments[:y], fr_w, arguments[:h], arguments[:frame_c], 100)
  #右
  msfr << filling(arguments[:x] + arguments[:w], arguments[:y], -fr_w, arguments[:h], arguments[:frame_c], 100)
  #下
  msfr << filling(arguments[:x], arguments[:y] + arguments[:h], arguments[:w], -fr_w, arguments[:frame_c], 100)

コメントする

コメントするには、ログインする必要があります。

コメント一覧

コメントはありません。