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

投稿者:Material 185033 3 mini 光楼(114) 投稿日:2020/09/26 16:05

さて前回の続き……?
メッセージのアニメーション表示が出来ました!!!

aoihikawaさんの「半角英数以外を全て3バイトとして判定する」案によって解決いたしました!有難うございます!

空白と改行の判定を書き加えて完成したコードがこちら↓
def StrSplit(t)
  #debug_log t
  t = t.split('')
  #debug_log t
  #set_t = ""
  new_t = []
  counter = 0
  
  t.each_with_index do |item, i|
    if counter > 0
      counter = counter - 1
    else
      #set_t << item
      if !(('a'..'z') === item || ('A'..'Z') === item || ('0'..'9') === item || ('!'..'~') === item || ' ' == item || "\n" == item)
        #debug_log set_t
        new_t << t[i] + t[(i + 1)] + t[(i + 2)]
        counter = 2
      else
        new_t << item
      end
    end
  end
  return new_t
end



うん、ちゃんと表示されてます。良かった!!!





だがしかし!!!



改行した文字列を表示させるとこんなことに……






なんということでしょう!!!
1行目が勝手に右へ右へと移動し始めたではありませんか!

これは完全に想定外orz
まさか中央揃えになっているとは!

だが心配ご無用!
Rubyには文字の配置を指定するメソッドが存在するのだ!!!

な、なんだってー!?





では左詰めを行うljustを使ってみようではないか。フハハハハ!





ダメだった!!!!!

ljustとかrjustとかはちゃんと機能するんですが、全体的に移動するだけで各行は中央揃えのままでした!くせう!

仕方がないので、改行の所で新たにテキストスプライトを増やすことにしました。
ということで早速メッセージウィンドウの関数を書き換えます。

完成したのがこちら↓
#========== メッセージウィンドウ ==========#
#===== 素材定義 =====#
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, :h_interval => 5}
  # 引数書換え
  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_sprites = []
  text_y = arguments[:y] + ofst #各行のY位置
  while text_y+arguments[:size] < arguments[:y]+arguments[:h]
    message_sprite = put_text 'message-text' do
      position arguments[:x] + ofst, text_y
      font_size arguments[:size]
      color arguments[:c]
      bold arguments[:b]
      italic arguments[:it]
      wordwrap true
      wordwrap_width arguments[:w] - ofst*2
      camera_fixed!
    end
    message_sprites << message_sprite
    text_y += arguments[:size] + arguments[:h_interval] #次の行の位置を設定
  end
  
  
  #レイヤー設定
  $system_layer.add msbg_sprite #背景
  msbg_sprite.layer_index 0
  msfr.each do |item| #枠
    $system_layer.add item
    item.layer_index 1
  end
  message_sprites.each do |item| #テキスト
    $system_layer.add item
    item.layer_index 2
  end

  #テキストのアニメーション表示
  text_over = false
  str_arr = StrSplit(m)
  print_text = ''
  line = 0
  str_arr.each_with_index do |item, i|
    if item === "\n"
      line += 1
      print_text = ''
      if line >= message_sprites.size
        m = str_arr[i+1..-1].join
        text_over = true
        break
      end
    else
      print_text += item
      message_sprites[line].text print_text
      wait_time(10)
    end
  end
  

  #離すのを待つ
  while waitloop
    if !keyboard.down?('Z')
      break
    end
    wait_time(10)
  end
  #Zキー押したら終了
  while !keyboard.down?('Z')
    wait_time(10)
  end

  #スプライトの削除
  msbg_sprite.destroy
  msfr.each do |item|
    item.destroy
  end
  message_sprites.each do |item|
    item.destroy
  end
  
  if text_over
    message(m, arguments)
  end
end

背景表示とテキスト表示を別の関数に分けておくべきだったと後悔中。メンドクサイので必要があればやります。

さて大まかに説明すると、メッセージウィンドウに入る行数分テキストスプライトを最初に設定しておき、アニメーション表示させるときに改行を判定して、テキスト表示する箇所を変えています。

ついでに入りきらなかった行は次のウィンドウ?ページ?に表示させるようにする機能も付けました。

実行結果がこれ↓


ちゃんと左に揃えられました!やったね!


プレーヤーの向き

CoRのサンプルをやってみた方いらっしゃいます?

サンプルのキャラクターの制御は
    # キャラクターがカーソルキーの方向に向いて、向いた方向に移動する
    if keyboard.down?('LEFT')
      pos = player_sprite.position
      player_sprite.position pos[0] - 1, pos[1]
      player_sprite.start_animation('left')
    end
    
    if keyboard.down?('DOWN')
      pos = player_sprite.position
      player_sprite.position pos[0], pos[1] + 1
      player_sprite.start_animation('down')
    end
    
    if keyboard.down?('RIGHT')
      pos = player_sprite.position
      player_sprite.position pos[0] + 1, pos[1]
      player_sprite.start_animation('right')
    end
    
    if keyboard.down?('UP')
      pos = player_sprite.position
      player_sprite.position pos[0], pos[1] -1
      player_sprite.start_animation('up')
    end

こんな風に単純なものになっています。

しかしこれだと、斜め移動時に操作キャラのアニメーションが止まってしまうんですよね。
というか方向キー2個押ししたら止まります。
なので対処せねばなりません。

どうするかというと、「操作キャラが向いている方向を取得して実行するアニメーションを指定する」です。
先ほどのプログラムでは、押したキーによって指定しています。
なので2個キーを押すと、2つのアニメーションが連続で交互に何度も切り替えられ、アニメーションが止まっているように見えるわけです。

因みにこのstart_animationってメソッド、現在実行中のアニメを指定しても最初からやり直すわけではなく、そのまま継続してくれるようですね。

さっそく操作キャラの向きを取得しようとしたのですが、実行しているアニメーションが何かを得る方法は無さそうでした。
なのでクラスで管理することにしたぞ!

変数じゃないの?

なんか変数どんどん増えて管理が大変なことになりそうなので、プレーヤーの情報を1つのクラスで管理しようと思ったんです。
class Player_ctrl
  @@d = 'down'

  def self.direction(d = nil)
    if d != nil
      @@d = d
    end
    return @@d
  end
end

いまは向きしか管理できないけど、HPとかそういうのも管理できるようにするつもり。

向きをセットする処理はこんな感じ。
      if keyboard.down?('LEFT')
        player_sprite.velocity -speed, nil
        Player_ctrl.direction('left') #これ
      end


アニメーションの実行処理はrenderに書いた。
player_sprite.start_animation(Player_ctrl.direction())


これで斜め移動時もアニメーションが止まらなくなりました!

今回はここまで。
有難うございました!

コメントする

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

コメント一覧

Cdv30200 aoi icon mini aoihikawa(投稿日:2020/09/29 21:23, 履歴)
テキスト表示関連は
その後も難航があったようですが

順調に機能追加が
進行していますね


クラスは様々な要素が増えてきたときも
まとめて管理できるようになるので
良い案ですね
Material 185033 3 mini 光楼(114)(投稿日:2020/09/29 23:50, 履歴)
まだまだ作らなければならない機能が盛りだくさんで先が思いやられます。


ありがとうございます!
なるべくスッキリとしたプログラムを書くのが目標です。