CoRでゲームをつくってみよう / 第03回 背景やキャラクターを動かす

投稿者:Cdv30200 aoi icon mini aoihikawa 投稿日:2022/08/11 01:45

CoRでゲームをつくってみよう

 第03回 背景やキャラクターを動かす


  こんにちは。
 フリーデザイナープログラマー(自称)の
 簸川 葵(ひかわ あおい)と申します。


 第02回 では、画面に背景やキャラクターを
 描画するところまでスクリプトを実装しました。
 第03回は画面に描画した背景やキャラクターを動かすところまで
 やっていきますね。



03-01 キー入力を受けとろう


  新CoRでは、ゲームを動かすためのメインループを自作しなくても
 メインループの役割を持つ機能が最初から実装されています。

  キャラクターを動かすには、まずこのメインループに
 キーが押された時、押され続けているとき、離された時といった状態を
 判定する仕組みをスクリプトで実装していきます。



  キーの3種類の状態を管理するために
 1つのキー毎に3種類のフラグローカル変数を準備します。

scene 'start' do
  #_/_/_/ ローカル変数の定義 _/_/_/
  #---------- ここから ----------
  #キー入力用のフラグ
  key_flg_up_st    = nil
  key_flg_up_do    = nil
  key_flg_up_en    = nil
  
  key_flg_down_st  = nil
  key_flg_down_do  = nil
  key_flg_down_en  = nil
  
  key_flg_left_st  = nil
  key_flg_left_do  = nil
  key_flg_left_en  = nil
  
  key_flg_right_st = nil
  key_flg_right_do = nil
  key_flg_right_en = nil
  #---------- ここまで ----------

  stがキー入力の開始、
 doがキー入力の継続中、
 enがキー入力の終了を判定するために利用します。



  定義したローカル変数を
 シーンの実行時に初期化します。

  create do
    #----- シーンロード時に実行される処理 -----
    #_/_/_/ 変数の初期化 _/_/_/
    #---------- ここから ----------
    #キー入力用のフラグ
    key_flg_up_st    = false
    key_flg_up_do    = false
    key_flg_up_en    = false
    
    key_flg_down_st  = false
    key_flg_down_do  = false
    key_flg_down_en  = false
    
    key_flg_left_st  = false
    key_flg_left_do  = false
    key_flg_left_en  = false
    
    key_flg_right_st = false
    key_flg_right_do = false
    key_flg_right_en = false
    #---------- ここまで ----------



  キー入力を受け取ったとき、
 フラグ変数を変更する処理を実装します。

  キー入力の受け取りは、シーン毎のメインループとなる
 update内に、書いていく形になります。

  update do
    #----- シーンのメインループ処理 -----
    #_/_/_/ 入力の判定 _/_/_/
    #---------- ここから ----------
    #キー入力判定
    if keyboard.down?('UP')
      key_flg_up_st = true
    else
      key_flg_up_st = false
      key_flg_up_do = false
    end
    
    if keyboard.down?('DOWN')
      key_flg_down_st = true
    else
      key_flg_down_st = false
      key_flg_down_do = false
    end
    
    if keyboard.down?('LEFT')
      key_flg_left_st = true
    else
      key_flg_left_st = false
      key_flg_left_do = false
    end
    
    if keyboard.down?('RIGHT')
      key_flg_right_st = true
    else
      key_flg_right_st = false
      key_flg_right_do = false
    end
    #---------- ここまで ----------

  keyboard.down?はキー入力を受け取る関数です
 引数にUP、DOWN、LEFT、RIGHTを指定すると方向キーの入力、
 Z、X、Cなどを指定すると英字キーの入力を受け取れます

  関数から受け取った戻り値を直接、if文で分岐させて
 それぞれのフラグ変数の値を変更しています。



  キーの3種類の状態を区別するために
 スクリプトをもうひと工夫します。

    #_/_/_/ メイン処理 _/_/_/
    #---------- ここから ----------
    #キー入力処理
    if (key_flg_up_st && !key_flg_up_do)
      key_flg_up_do = true
      #--- 押された時に実行する処理 ---
      
      debug_log '上キーが押された'
    elsif key_flg_up_do
      key_flg_up_en = true
      #--- 押されつづけている時に実行する処理 ---
      
      debug_log '上キーが押されています'
    elsif key_flg_up_en
      key_flg_up_en = false
      #--- 離された時に実行する処理 ---
      
      debug_log '上キーが離された'
    end
    
    if (key_flg_down_st && !key_flg_down_do)
      key_flg_down_do = true
      #--- 押された時に実行する処理 ---
      
      debug_log '下キーが押された'
    elsif key_flg_down_do
      key_flg_down_en = true
      #--- 押されつづけている時に実行する処理 ---
      
      debug_log '下キーが押されています'
    elsif key_flg_down_en
      key_flg_down_en = false
      #--- 離された時に実行する処理 ---
      
      debug_log '下キーが離された'
    end
    
    if (key_flg_left_st && !key_flg_left_do)
      key_flg_left_do = true
      #--- 押された時に実行する処理 ---
      
      debug_log '左キーが押された'
    elsif key_flg_left_do
      key_flg_left_en = true
      #--- 押されつづけている時に実行する処理 ---
      
      debug_log '左キーが押されています'
    elsif key_flg_left_en
      key_flg_left_en = false
      #--- 離された時に実行する処理 ---
      
      debug_log '左キーが離された'
    end
    
    if (key_flg_right_st && !key_flg_right_do)
      key_flg_right_do = true
      #--- 押された時に実行する処理 ---
      
      debug_log '右キーが押された'
    elsif key_flg_right_do
      key_flg_right_en = true
      #--- 押されつづけている時に実行する処理 ---
      
      debug_log '右キーが押されています'
    elsif key_flg_right_en
      key_flg_right_en = false
      #--- 離された時に実行する処理 ---
      
      debug_log '右キーが離された'
    end
    #---------- ここまで ----------

  debug_logは、デバッグウインドウ内に文字を表示する関数です。

  画面には表示されない情報を表示するなど、
 スクリプトのテストを行うときに重要な役割を持つ関数なので
 覚えておくと便利です。



  ここまでで、キー入力を受け取り、
 デバッグウインドウにその状態を表示するスクリプトが出来ました。

  画面上部メニューにある、「保存をして実行」を押して
 実際のゲーム画面を確認してみましょう。





03-02 キャラクターを動かそう


  いよいよキャラクターを動かします。
 キャラクターが動く、というのは画像オブジェクトの表示座標が動くことです。



  キャラクターを動かすときに使用する
 ローカル変数を定義します。

  #プレイヤーキャラクターオブジェクト
  obj_char_spr = nil
  
  obj_char_pos_x = nil
  obj_char_pos_y = nil
  obj_char_size_w = nil
  obj_char_size_h = nil
  #---------- ここから ----------
  obj_char_pos_x_old = nil
  obj_char_pos_y_old = nil
  
  obj_char_speed = nil
  obj_char_speed_r_x = nil
  obj_char_speed_r_y = nil
  
  obj_char_w_max = nil
  obj_char_h_max = nil
  
  obj_char_anime = nil
  
  obj_char_flg_up    = nil
  obj_char_flg_down  = nil
  obj_char_flg_left  = nil
  obj_char_flg_right = nil
  #---------- ここまで ----------

  obj_char_pos_x_old、obj_char_pos_y_oldは
 過去のキャラクターの座標を保管しておき
 位置が変更されたときのみ
 画像オブジェクトを移動する判定として使用します。

  obj_char_speed、obj_char_speed_r_x、obj_char_speed_r_yは
 プレイヤーキャラクターの移動速度を保管しておく定数です。
  obj_char_speedは前後左右の移動時に、
 obj_char_speed_r_x、obj_char_speed_r_yは斜めの移動時に使用します。

  obj_char_w_max、obj_char_h_maxは
 プレイヤーキャラクターの移動限界を保管しておく定数です。

  obj_char_animeは
 過去のアニメーションの種類を保管しておき
 アニメーションが変更されたときのみ
 表示を変更する判定として使用します。

  obj_char_flg_up、obj_char_flg_down、
 obj_char_flg_left、obj_char_flg_rightは
 プレイヤーキャラクター移動方向を示す、フラグ変数です。



  定義したローカル変数を
 シーンの実行時に初期化します。

    #プレイヤーキャラクターオブジェクト
    obj_char_size_w = 64
    obj_char_size_h = 64
    
    obj_char_pos_x = (800 - obj_char_size_w) / 2
    obj_char_pos_y = 500
    #---------- ここから ----------
    obj_char_pos_x_old = obj_char_pos_x
    obj_char_pos_y_old = obj_char_pos_y
    
    obj_char_speed = 5
    
    wrk_r = 45 * Math::PI / 180
    obj_char_speed_r_x = Math.cos(wrk_r) * obj_char_speed
    obj_char_speed_r_y = Math.sin(wrk_r) * obj_char_speed
    
    obj_char_w_max = (800 - obj_char_size_w)
    obj_char_h_max = (600 - obj_char_size_h)
    
    obj_char_anime = 'neutral'
    
    obj_char_flg_up    = false
    obj_char_flg_down  = false
    obj_char_flg_left  = false
    obj_char_flg_right = false
    #---------- ここまで ----------

  obj_char_speed_r_x、obj_char_speed_r_yの
 値を決めるときに使用している
 Math::PI、Math.cos、Math.sinは
 三角関数関連の関数を呼び出す命令です。

  wrk_rに45度の時のラジアンを求め
 三角関数とwrk_rを使用して
 斜め移動時のX座標とY座標の移動距離を求めています。



  キー入力処理に移動方向のフラグを変更する処理を追加します。
 なお、テスト用に使用したdebug_logは削除しています。

scene 'start' do
    #_/_/_/ メイン処理 _/_/_/
    
    #キー入力処理
    if (key_flg_up_st && !key_flg_up_do)
      key_flg_up_do = true
      #--- 押された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_up = true
      #---------- ここまで ----------
    elsif key_flg_up_do
      key_flg_up_en = true
      #--- 押されつづけている時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_up = true
      #---------- ここまで ----------
    elsif key_flg_up_en
      key_flg_up_en = false
      #--- 離された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_up = false
      #---------- ここまで ----------
    end
    
    if (key_flg_down_st && !key_flg_down_do)
      key_flg_down_do = true
      #--- 押された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_down = true
      #---------- ここまで ----------
    elsif key_flg_down_do
      key_flg_down_en = true
      #--- 押されつづけている時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_down = true
      #---------- ここまで ----------
    elsif key_flg_down_en
      key_flg_down_en = false
      #--- 離された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_down = false
      #---------- ここまで ----------
    end
    
    if (key_flg_left_st && !key_flg_left_do)
      key_flg_left_do = true
      #--- 押された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_left = true
      #---------- ここまで ----------
    elsif key_flg_left_do
      key_flg_left_en = true
      #--- 押されつづけている時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_left = true
      #---------- ここまで ----------
    elsif key_flg_left_en
      key_flg_left_en = false
      #--- 離された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_left = false
      #---------- ここまで ----------
    end
    
    if (key_flg_right_st && !key_flg_right_do)
      key_flg_right_do = true
      #--- 押された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_right = true
      #---------- ここまで ----------
    elsif key_flg_right_do
      key_flg_right_en = true
      #--- 押されつづけている時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_right = true
      #---------- ここまで ----------
    elsif key_flg_right_en
      key_flg_right_en = false
      #--- 離された時に実行する処理 ---
      #---------- ここから ----------
      obj_char_flg_right = false
      #---------- ここまで ----------
    end



  キー入力処理のすぐ下に、
 プレイヤーキャラクター移動方向のフラグによって
 分岐される処理を追加します。

  ここで実際に、アニメーションの切り替えや
 プレイヤーキャラクター座標値の変更を行っています。

    if (key_flg_right_st && !key_flg_right_do)
      key_flg_right_do = true
      #--- 押された時に実行する処理 ---
      obj_char_flg_right = true
    elsif key_flg_right_do
      key_flg_right_en = true
      #--- 押されつづけている時に実行する処理 ---
      obj_char_flg_right = true
    elsif key_flg_right_en
      key_flg_right_en = false
      #--- 離された時に実行する処理 ---
      obj_char_flg_right = false
    end
    
    #---------- ここから ----------
    #プレイヤーキャラクター移動方向のフラグによって処理を分岐
    if (obj_char_flg_up && obj_char_flg_left)
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'left'
        obj_char_anime = 'left'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_x -= obj_char_speed_r_x
      obj_char_pos_y -= obj_char_speed_r_y
      
    elsif (obj_char_flg_down && obj_char_flg_left)
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'left'
        obj_char_anime = 'left'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_x -= obj_char_speed_r_x
      obj_char_pos_y += obj_char_speed_r_y
      
    elsif (obj_char_flg_up && obj_char_flg_right)
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'right'
        obj_char_anime = 'right'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_x += obj_char_speed_r_x
      obj_char_pos_y -= obj_char_speed_r_y
      
    elsif (obj_char_flg_down && obj_char_flg_right)
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'right'
        obj_char_anime = 'right'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_x += obj_char_speed_r_x
      obj_char_pos_y += obj_char_speed_r_y
      
    elsif obj_char_flg_up
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'neutral'
        obj_char_anime = 'neutral'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_y -= obj_char_speed
      
    elsif obj_char_flg_down
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'neutral'
        obj_char_anime = 'neutral'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_y += obj_char_speed
      
    elsif obj_char_flg_left
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'left'
        obj_char_anime = 'left'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_x -= obj_char_speed
      
    elsif obj_char_flg_right
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'right'
        obj_char_anime = 'right'
        obj_char_spr.start_animation(obj_char_anime)
      end
      
      #プレイヤーキャラクターの座標を変更
      obj_char_pos_x += obj_char_speed
      
    else
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'neutral'
        obj_char_anime = 'neutral'
        obj_char_spr.start_animation(obj_char_anime)
      end
    end
    #---------- ここまで ----------



  プレイヤーキャラクターが画面の端を越えて出て行かないように
 座標値が限界値を超えたら、引き戻す処理を追加します。

      
    else
      #プレイヤーキャラクターのアニメーションを変更
      if obj_char_anime != 'neutral'
        obj_char_anime = 'neutral'
        obj_char_spr.start_animation(obj_char_anime)
      end
    end
    
    #---------- ここから ----------
    #プレイヤーキャラクターの移動範囲制限
    if obj_char_pos_x < 0
      obj_char_pos_x = 0
    end
    if obj_char_pos_x > obj_char_w_max
      obj_char_pos_x = obj_char_w_max
    end
    if obj_char_pos_y < 0
      obj_char_pos_y = 0
    end
    if obj_char_pos_y > obj_char_h_max
      obj_char_pos_y = obj_char_h_max
    end
    #---------- ここまで ----------



  プレイヤーキャラクターの座標値が変更されていたら
 プレイヤーキャラクタのオブジェクトを
 画面上で移動する処理を追加します。

    #プレイヤーキャラクターの移動範囲制限
    if obj_char_pos_x < 0
      obj_char_pos_x = 0
    end
    if obj_char_pos_x > obj_char_w_max
      obj_char_pos_x = obj_char_w_max
    end
    if obj_char_pos_y < 0
      obj_char_pos_y = 0
    end
    if obj_char_pos_y > obj_char_h_max
      obj_char_pos_y = obj_char_h_max
    end
    #---------- ここから ----------
    #プレイヤーキャラクターのオブジェクトを移動する
    if (obj_char_pos_x_old != obj_char_pos_x) || (obj_char_pos_y_old != obj_char_pos_y)
      obj_char_pos_x_old = obj_char_pos_x
      obj_char_pos_y_old = obj_char_pos_y
      
      obj_char_spr.position obj_char_pos_x, obj_char_pos_y
    end
    #---------- ここまで ----------
  end

  ここで再び、
 オブジェクトに対して操作を指定する命令が登場しました。

  ここでは、obj_char_sprのオブジェクトに対して
 positionを呼び出し、表示座標を変更する命令を行っています。



  ここまでで、キャラクター画像を
 画面上で移動するスクリプトが出来ました。

  画面上部メニューにある、「保存をして実行」を押して
 実際のゲーム画面を確認してみましょう。





03-03 背景を動かそう


  キャラクターの動かし方を踏まえて、
 背景を動かしてみましょう。

  背景を動かすためには、縦に長ーい画像を準備する方法もありますが、
 今回は、1枚の絵を2枚使用して、これをループさせて表示します。



  スクロール中に表示される
 2枚目の背景画像を生成します。

  今回は1枚目の背景と同じものを使用するため
 素材の定義や素材のロードなどの処理をとばして
 2枚目の背景画像オブジェクトで使用する
 ローカル変数の定義から書き始めます。

  #メイン背景オブジェクト
  obj_bg_00_spr = nil
  #---------- ここから ----------
  obj_bg_01_spr = nil
  #---------- ここまで ----------
  obj_bg_pos_x = nil
  obj_bg_pos_y = nil
  #---------- ここから ----------
  obj_bg_speed = nil
  #---------- ここまで ----------

  obj_bg_01_sprは2枚目の画像オブジェクトを格納するための変数。

  obj_bg_speedはスクロール速度を保管しておく定数です。



  定義したローカル変数を
 シーンの実行時に初期化します。

    #_/_/_/ 変数の初期化 _/_/_/
    
    #キー入力用のフラグ
    key_flg_up_st    = false
    key_flg_up_do    = false
    key_flg_up_en    = false
    
    key_flg_down_st  = false
    key_flg_down_do  = false
    key_flg_down_en  = false
    
    key_flg_left_st  = false
    key_flg_left_do  = false
    key_flg_left_en  = false
    
    key_flg_right_st = false
    key_flg_right_do = false
    key_flg_right_en = false
    
    
    #メイン背景オブジェクト
    obj_bg_pos_x = 0
    obj_bg_pos_y = 0
    #---------- ここから ----------
    obj_bg_speed = 1.5
    #---------- ここまで ----------



  2枚目の背景画像のオブジェクトを生成します。

  sprite名は1枚目と同じものを使用することで
 1枚目と同じ画像オブジェクトを追加で生成することができます。

    #_/_/_/ 素材の初期化 _/_/_/
    
    #メイン背景
    obj_bg_00_spr = put_sprite 'spr_bg_00' do
      position obj_bg_pos_x, obj_bg_pos_y
      src_rect 0, 0, 800, 600
    end
    #---------- ここから ----------
    obj_bg_01_spr = put_sprite 'spr_bg_00' do
      position obj_bg_pos_x, (obj_bg_pos_y - 600)
      src_rect 0, 0, 800, 600
    end
    #---------- ここまで ----------

  positionのy座標を-600することで
 2枚目の表示位置を上にずらしています。



  背景画像をスクロールさせる処理を
 メインループに追加します。

    #プレイヤーキャラクターのオブジェクトを移動する
    if (obj_char_pos_x_old != obj_char_pos_x) || (obj_char_pos_y_old != obj_char_pos_y)
      obj_char_pos_x_old = obj_char_pos_x
      obj_char_pos_y_old = obj_char_pos_y
      
      obj_char_spr.position obj_char_pos_x, obj_char_pos_y
    end
    
    #---------- ここから ----------
    #背景のスクロール
    obj_bg_pos_y += obj_bg_speed
    
    #背景のスクロールをループさせる
    if obj_bg_pos_y > 600
      obj_bg_pos_y -= 600
    end
    
    #背景のオブジェクトを移動する
    obj_bg_00_spr.position obj_bg_pos_x, obj_bg_pos_y
    obj_bg_01_spr.position obj_bg_pos_x, (obj_bg_pos_y - 600)
    #---------- ここまで ----------

  スクロールした座標値が600を超えたとき
 座標値を-600することで、表示がループするようになっています。

  実際のオブジェクトの移動は
 プレイヤーキャラクターの場合と同様に
 obj_bg_00_sprオブジェクト、obj_bg_01_sprオブジェクトそれぞれに対して
 positionに座標値を指定することにより
 画面上の2枚の背景画像を移動しています。



  ここまでで、背景画像をスクロール表示させる
 スクリプトが出来ました。

  画面上部メニューにある、「保存をして実行」を押して
 実際のゲーム画面を確認してみましょう。





03-04 おわりに


  いかがでしたでしょうか。
 キャラクターが操作出来るようになり
 より、ゲーム画面らしくなってきました。

  さて、次回は敵キャラクターを登場させて
 配列や当たり判定について実践してみましょう。


  今回までのスクリプト全体
CoRでゲームをつくってみよう / 第03回



  第01回 CoRの開発準備をしよう
  第02回 画面に背景やキャラクターを描画する
  第03回 背景やキャラクターを動かす
  第04回 敵キャラクターを登場させる
  第05回 弾を発射する
  第06回 ゲームとして必要な機能を追加する
  第07回 より面白くするために

コメントする

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

コメント一覧

Material 71926 1 mini なとおとき(投稿日:2022/08/11 02:31, 履歴)
押し続けの処理の分け方はいつも若干困ってました!