Rmakeで自由なゲームをつくろう / 第03回キャラクターをキー入力で操作する

投稿者:Cdv30200 aoi icon mini aoihikawa 投稿日:2011/08/05 22:09

Rmakeで自由なゲームをつくろう

 第03回 キャラクターをキー入力で操作する


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


 第02回 ではキャラクターの表示までのお話でした。
 第03回はそれを踏まえて、画面に表示したキャラクターを
 キー入力で操作するところまで、やっていきますね。



03-01 前回までのおさらいと、スクリプトの整理



  さて、前回の最後に完成したスクリプトですが、
#メニュー項目等の表示OFF
setMenuItemVisible(getMenuBackLog(), false)
setMenuItemVisible(getMenuSave(), false)
setMenuItemVisible(getMenuLoad(), false)
setHelpVisible(false)

#キャンバスの初期化
setCanvasVisible(false)
deleteAllSprite()
drawCanvas()


#キャラクター画像の設定
img_char_no = 76793
img_char = createSprite(img_char_no)

get_x = 0
get_y = 0
get_w = 64
get_h = 64

set_x = 0
set_y = 0
set_w = 64
set_h = 64

set_z = 7

pos_x = 368
pos_y = 500

setSpriteRect(img_char, get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
setSpriteZOrder(img_char, set_z)
setSpritePosition(img_char, pos_x, pos_y)

#背景画像の設定
img_bg_no = 76800
img_bg = createSprite(img_bg_no)

get_x = 0
get_y = 0
get_w = 800
get_h = 600

set_x = 0
set_y = 0
set_w = 800
set_h = 600

set_z = 1

pos_x = 0
pos_y = 0

setSpriteRect(img_bg, get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
setSpriteZOrder(img_bg, set_z)
setSpritePosition(img_bg, pos_x, pos_y)


#画面の更新
drawCanvas()
setCanvasVisible(true)

 と、とても縦に長いですね。
  キャラクターと背景の設定も似たようなところが多くありますし、
 今後、敵キャラクターなどの追加でさらに長くなると
 つくりかけの場所を探すのも大変です。


  そこで、まずはこのスクリプトをすっきりと整理しましょう。
#メニュー項目等の表示OFF
setMenuItemVisible(getMenuBackLog(), false)
setMenuItemVisible(getMenuSave(), false)
setMenuItemVisible(getMenuLoad(), false)
setHelpVisible(false)

#キャンバスの初期化
setCanvasVisible(false)
deleteAllSprite()
drawCanvas()

#_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
#画像を設定する関数
def setCreateSprite(img_name, img_no, get_x, get_y, get_w, get_h,
                    set_x, set_y, set_w, set_h, set_z, pos_x, pos_y)
    
    setVariable(img_name, createSprite(img_no))
    setSpriteRect(getVariable(img_name),
                  get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
    setSpriteZOrder(getVariable(img_name), set_z)
    setSpritePosition(getVariable(img_name), pos_x, pos_y)
end


#キャラクター画像の設定
img_no = 76793
img_char_name = "img_char"

get_x = 0;    get_y = 0;    get_w = 64;   get_h = 64
set_x = 0;    set_y = 0;    set_w = 64;   set_h = 64
set_z = 7
pos_char_x = 368;           pos_char_y = 500

setCreateSprite(img_char_name, img_no, get_x, get_y, get_w, get_h,
                set_x, set_y, set_w, set_h, set_z, pos_char_x, pos_char_y)


#背景画像の設定
img_no = 76800
img_bg_name = "img_bg"

get_x = 0;    get_y = 0;    get_w = 800;  get_h = 600
set_x = 0;    set_y = 0;    set_w = 800;  set_h = 600
set_z = 1
pos_bg_x = 0;               pos_bg_y = 0

setCreateSprite(img_bg_name, img_no, get_x, get_y, get_w, get_h,
                set_x, set_y, set_w, set_h, set_z, pos_bg_x, pos_bg_y)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#画面の更新
drawCanvas()
setCanvasVisible(true)

  いかがでしょうか。
 かなりすっきりとしましたが、動作する内容は前回と全く同じです。
 それでは、どのように変更したのか、1つずつ説明していきます。



  1つめテクニックは「,」と「;」です。

  文の最後が関数の途中の「,」だったとき、
 スクリプトでは改行された次の行も同じ行として判断されます。
#次の2つは同一
setCreateSprite(img_name, img_no, get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h, set_z, pos_char_x, pos_char_y)
#--------------------------------------------------
setCreateSprite(img_name, img_no, get_x, get_y, get_w, get_h,
                set_x, set_y, set_w, set_h, set_z, pos_char_x, pos_char_y)

 また、文の途中に「;」があったとき、
 スクリプトではそこで次の行として判断されます。
#次の2つは同一
get_x = 0
get_y = 0
get_w = 800
get_h = 600
set_x = 0
set_y = 0
set_w = 800
set_h = 600
#--------------------------------------------------
get_x = 0;    get_y = 0;    get_w = 800;  get_h = 600
set_x = 0;    set_y = 0;    set_w = 800;  set_h = 600


  引数が多くて長すぎる関数は、見た目を短く、
 似たような値の代入だけという短い変数は、見た目を纏めてセットに
 することができるのです。



  さて、2つめのテクニックは「自作の関数」をつくることです。
 似ているところを1つの関数として纏めてしまうわけです。


  def文で、setCreateSpriteという名前の関数を作っています。
#画像を設定する関数
def setCreateSprite(img_name, img_no, get_x, get_y, get_w, get_h,
                    set_x, set_y, set_w, set_h, set_z, pos_x, pos_y)
    
    setVariable(img_name, createSprite(img_no))
    setSpriteRect(getVariable(img_name),
                  get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
    setSpriteZOrder(getVariable(img_name), set_z)
    setSpritePosition(getVariable(img_name), pos_x, pos_y)
end

  この関数の中で、前回のものとは異なっているところとして、
 setVariablegetVariableという関数が追加されています。

  実は、変数は通常の「x = 1」と書かれているだけの場合
 その変数がつくられた関数や、チャプターの中だけでしか使うことが出来ません。
 関数や、チャプターの終了時に消えてしまうのです。
 これを「ローカル変数」と呼びます。
  これでは、折角関数でスクリプトデータを作っても、関数の外では利用できないのです。


  そこで、先ほどの2つの関数の登場です。
 「setVariable("suuji", 1)」は変数への値の代入である「suuji = 1」、
 「getVariable("suuji")」は変数からの値の取得である「suuji」と同じ意味で
 「通常変数」を生成してくれます。
  この「通常変数」は「ローカル変数」と異なり、同じゲーム内であれば
 関数や、チャプターの外でも消えずに残ります。
 ただし、通常変数とローカル変数で同じ名前を設定していても
 別の変数として扱われることに注意してください。


  つまり、この関数の中身は、というと、
 「setVariable(img_name, createSprite(img_no))」は「img_name = createSprite(img_no)」
 と、変数の形が異なるだけの同じ意味なので、
 createSprite、setSpriteRect、setSpriteZOrder、setSpritePositionという
 スプライトの設定に必要な関数をセットで実行してくれます。
  設定をするときに必要となる値を、関数の引数として受け取ることによって、
 異なる画像のや値の場合でも、この関数で実行できるようになっています。



03-02 ゲームのメインループをつくろう


  第01回で少しお話に出てきましたが、
 ゲームとは、「キーの入力→さまざまな判定→描画→はじめに戻る」、
 の繰り返しので出来ています。
  この固定された大きな循環を「メインループ」と呼びます。



  先ほどの途中からスクリプトの続きを描きますね。
#ここから↑は省略
#画面の更新
drawCanvas()
setCanvasVisible(true)

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
startInput()     #入力受付の開始

#メインループの開始
mainloop = true
while mainloop
    
    #キー入力の判定
    while hasInput()
        takeInput()
        #----- キー入力の判定処理を入れる場所 -----
        
        
        
    end
    
    #----- ゲームのメイン処理を入れる場所 -----
    #(ゲームの終了時はmainloopをfalseに)
    
    
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

  これがメインループの枠組みです。
 それでは、新しく登場した関数と命令文を上から順に見ていきましょう。


  startInputキーやマウスの入力の取得を開始させる関数です。
 最後の辺りにあるendInputとセットになっており、
 こちらはキーやマウスの入力の取得を終了する関数です。
  この2つの関数で囲まれている間、スクリプトが押されたキーを覚えてくれます。


  命令文のwhile文が登場しました。
 よく見ると、条件文のところが変数だけになっています。
 これは、この変数「mainloop」自体が、
 スイッチと同様な true か false になっているためです。
  つまり、変数がtrueになっている間、ずっとこの中を繰り返します。


  再びwhile文です。
 今度は条件式に関数が入っています。
 これはこの関数が、 true か false を返す関数のため、使用できる省略方法です。
#次の2つは同一
InputFlg = hasInput()
while InputFlg
    takeInput()
    
    
end
#--------------------------------------------------
while hasInput()
    takeInput()
    
    
end


  hasInput覚えているキーやマウスの入力があったかどうか調べる関数です。
 そして、takeInput覚えているキーやマウスの入力を取り出す関数です。
 つまり、この2つの関数のセットとwhile文で、
 覚えているキーやマウスの入力を、覚えている分だけ取り出すという動作になります。


  waitTime引数のミリ秒(1/1000秒)だけ、何もせずに待つ関数です。
 今回は「30」が設定されているため、1回あたりのループを、
 約0.03秒毎に実行してください。という意味になります。
  「約」とつけたのは、この待っている関数以外のところで、
 他の関数などを実行している時間があるためです。


  最後に、goEnding。これは、エンディング画面に移動する関数です。
 現在のところ、メインループから抜けることがないため、
 エンディング画面に移動することはないのですが、形式的なもので先に書いておきました。



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


  先ほどのメインループに、キーが押され時にON、離された時にOFFとなる
 仕組みを入れていきます。

  ONとOFFをスクリプトで扱うときは、trueとfalseでしたね。


  まずは、使用するスイッチの変数を準備します。
#ここから↑は省略
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#キー入力フラグの設定
key_flg_left  = false
key_flg_right = false
key_flg_up    = false
key_flg_down  = false
key_flg_z     = false
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#画面の更新
drawCanvas()
setCanvasVisible(true)


startInput()     #入力受付の開始

#メインループの開始
mainloop = true
while mainloop
    
    #キー入力の判定
    while hasInput()
        takeInput()
        #----- キー入力の判定処理を入れる場所 -----
        
        
        
    end
    
    #----- ゲームのメイン処理を入れる場所 -----
    #(ゲームの終了時はmainloopをfalseに)
    
    
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア

  カーソルの4つのキーと、Zキーの全部で5つの変数を準備しました。



  次は、実際にこの変数のスイッチを、
 キー入力によって入れ替えるスクリプトを書きます。
#ここから↑は省略

#キー入力フラグの設定
key_flg_left  = false
key_flg_right = false
key_flg_up    = false
key_flg_down  = false
key_flg_z     = false


#画面の更新
drawCanvas()
setCanvasVisible(true)


startInput()     #入力受付の開始

#メインループの開始
mainloop = true
while mainloop
    
    #キー入力の判定
    while hasInput()
        takeInput()
        #----- キー入力の判定処理を入れる場所 -----
        #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
        if isKeyDown("LEFT")
            key_flg_left = true
        elsif isKeyUp("LEFT")
            key_flg_left = false
        elsif isKeyDown("RIGHT")
            key_flg_right = true
        elsif isKeyUp("RIGHT")
            key_flg_right = false
        elsif isKeyDown("UP")
            key_flg_up = true
        elsif isKeyUp("UP")
            key_flg_up = false
        elsif isKeyDown("DOWN")
            key_flg_down = true
        elsif isKeyUp("DOWN")
            key_flg_down = false
        elsif isKeyDown("Z")
            key_flg_z = true
        elsif isKeyUp("Z")
            key_flg_z = false
        end
        #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    end
    
    #----- ゲームのメイン処理を入れる場所 -----
    #(ゲームの終了時はmainloopをfalseに)
    
    
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア

  isKeyDownキーが押されたときかどうかを判断する関数、
 isKeyUpキーが離されたときかどうかを判断する関数です。
  これを命令文のif文で分岐することによって、
 どの変数をどう変更するか動作を分岐させています。



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


  いよいよキャラクターを動かします。
 キャラクターが動く、というのはスプライトの表示座標が動くことです。

 横方向はx座標、縦方向はy座標となっており、
 x座標は右に行くほど数値が大きくなり、y座標は下に行くほど数値が大きくなります。

  それでは、これをスクリプトで書いてみましょう。
 まずは定数の準備から。
#ここから↑は省略

#キー入力フラグの設定
key_flg_left  = false
key_flg_right = false
key_flg_up    = false
key_flg_down  = false
key_flg_z     = false

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#定数の設定
char_speed = 10
char_w_max = 800 - 64
char_h_max = 600 - 64
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#画面の更新
drawCanvas()
setCanvasVisible(true)


startInput()     #入力受付の開始

#メインループの開始
mainloop = true
while mainloop
    
    #キー入力の判定
    while hasInput()
        takeInput()
        #----- キー入力の判定処理を入れる場所 -----
        if isKeyDown("LEFT")
            key_flg_left = true
        elsif isKeyUp("LEFT")
            key_flg_left = false
        elsif isKeyDown("RIGHT")
            key_flg_right = true
        elsif isKeyUp("RIGHT")
            key_flg_right = false
        elsif isKeyDown("UP")
            key_flg_up = true
        elsif isKeyUp("UP")
            key_flg_up = false
        elsif isKeyDown("DOWN")
            key_flg_down = true
        elsif isKeyUp("DOWN")
            key_flg_down = false
        elsif isKeyDown("Z")
            key_flg_z = true
        elsif isKeyUp("Z")
            key_flg_z = false
        end
    end
    
    #----- ゲームのメイン処理を入れる場所 -----
    #(ゲームの終了時はmainloopをfalseに)
    
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア

  定数という言葉が出てきましたが、定数とは、
 ゲームが終了するまで、最初に入れた値が変化することがない変数のことです。
  使い方は変数と変わりません。
 char_speedは1回辺りの移動量、char_w_maxは横方向の最大値、char_h_maxは縦方向の最大値が
 入れてあります。
  各最大値については、キャラクターの座標の基準点が左上なので、
 キャラクターの高さと横幅である「64」という数値を、全体のサイズから引いています。



  次に、キャラクターを移動させるスクリプトを書きます。
#ここから↑は省略

#キー入力フラグの設定
key_flg_left  = false
key_flg_right = false
key_flg_up    = false
key_flg_down  = false
key_flg_z     = false

#定数の設定
char_speed = 10
char_w_max = 800 - 64
char_h_max = 600 - 64


#画面の更新
drawCanvas()
setCanvasVisible(true)


startInput()     #入力受付の開始

#メインループの開始
mainloop = true
while mainloop
    
    #キー入力の判定
    while hasInput()
        takeInput()
        #----- キー入力の判定処理を入れる場所 -----
        if isKeyDown("LEFT")
            key_flg_left = true
        elsif isKeyUp("LEFT")
            key_flg_left = false
        elsif isKeyDown("RIGHT")
            key_flg_right = true
        elsif isKeyUp("RIGHT")
            key_flg_right = false
        elsif isKeyDown("UP")
            key_flg_up = true
        elsif isKeyUp("UP")
            key_flg_up = false
        elsif isKeyDown("DOWN")
            key_flg_down = true
        elsif isKeyUp("DOWN")
            key_flg_down = false
        elsif isKeyDown("Z")
            key_flg_z = true
        elsif isKeyUp("Z")
            key_flg_z = false
        end
    end
    
    #----- ゲームのメイン処理を入れる場所 -----
    #(ゲームの終了時はmainloopをfalseに)
    
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    #----- キャラクターの移動 -----
    if key_flg_left
        #左
        pos_char_x = pos_char_x - char_speed
        if pos_char_x < 0
            pos_char_x = 0
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y) 
    elsif key_flg_right
        #右
        pos_char_x = pos_char_x + char_speed
        if pos_char_x > char_w_max
            pos_char_x = char_w_max
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y) 
    end
    
    if key_flg_up
        #上
        pos_char_y = pos_char_y - char_speed
        if pos_char_y < 0
            pos_char_y = 0
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y) 
    elsif key_flg_down
        #下
        pos_char_y = pos_char_y + char_speed
        if pos_char_y > char_h_max
            pos_char_y = char_h_max
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    end
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア

  pos_char_x、pos_char_yはキャラクターの画像を設定したときに、
 表示する位置の値を入れていた変数ですね。
  この変数の値を、char_speedの値だけ加算、減算したあと
 再度pos_char_x、pos_char_yに戻しています。
 つまり、1回の入力の判定ごとにpos_char_x、pos_char_yがchar_speed分
 移動していくようになります。

  if文の中にある、もうひとつのif文は、
 座標の最小値である「0」、先ほど定数として準備しておいた最大値の座標を
 キャラクターが超えてしまったとき、最小値または最大値に戻すための分岐です。
 こうすることで、画面外までキャラクターが飛び出してしまうのを防いでいます。

  setSpritePositionは第02回に登場した、
 キャンバスに表示するときの位置を設定する関数でしたね。
  スプライトデータは今回一番最初に作成した関数の中ですが、
 ローカル変数から通常変数に変更したため、このようにメインループからでも
 getVariable(img_char_name)で利用することが出来るようになっています。



  これで、一通り完成です。
 保存、終了をして、テストプレーを行い、
 キー入力によってキャラクターが動くようになったかどうか、確認してみましょう。



03-05 キャラクターにアニメーションをつけよう




  これまでの「まとめ」と「復習」も兼ねて、
 キャラクターの動きに合わせて、アニメーションをつけてみましょう。


  まずは、キャラクターの表示を切り替える関数の準備から。
 スクリプトの一番上に戻ります。
#メニュー項目等の表示OFF
setMenuItemVisible(getMenuBackLog(), false)
setMenuItemVisible(getMenuSave(), false)
setMenuItemVisible(getMenuLoad(), false)
setHelpVisible(false)

#キャンバスの初期化
setCanvasVisible(false)
deleteAllSprite()
drawCanvas()


#画像を設定する関数
def setCreateSprite(img_name, img_no, get_x, get_y, get_w, get_h,
                    set_x, set_y, set_w, set_h, set_z, pos_x, pos_y)
    
    setVariable(img_name, createSprite(img_no))
    setSpriteRect(getVariable(img_name),
                  get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
    setSpriteZOrder(getVariable(img_name), set_z)
    setSpritePosition(getVariable(img_name), pos_x, pos_y)
end

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#キャラクターの表示内容を変更する関数
def setCharSpritePattern(no)
    img_char_name = "img_char"
    get_x = 0;    get_y = 0;    get_w = 64;   get_h = 64
    set_x = 0;    set_y = 0;    set_w = 64;   set_h = 64
    
    if no == 1
        get_x = 0;    get_y = 0
    elsif no == 2
        get_x = 64;   get_y = 0
    elsif no == 3
        get_x = 128;  get_y = 0
    elsif no == 4
        get_x = 0;    get_y = 64
    elsif no == 5
        get_x = 64;   get_y = 64
    elsif no == 6
        get_x = 128;  get_y = 64
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_char_name),
                  get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  引数の値によって、setSpriteRectの切り出し場所を変更する関数です。
 1~6の番号は、次の場所を切り出すように設定されています。

 1~6以外の番号を引数として渡された場合、横幅と高さが「0」、
 つまり何も表示しない、という実行内容になっています。




  次に使用する定数と変数を準備します。
 スクリプトの中央辺りです。
#ここから↑は省略

#定数の設定
char_speed = 10
char_w_max = 800 - 64
char_h_max = 600 - 64
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
char_anime_change = 3

#変数の設定
char_anime_count = 0
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#画面の更新
drawCanvas()
setCanvasVisible(true)

#ここから↓は省略

  アニメーションをするためのカウンターとなる変数と、
 アニメーションを切り替えるポイントとなる値の定数を
 設定しています。




  最後に、アニメーションカウンターの使用と、
 キー入力とアニメーションカウンターの状態から
 先ほどの関数を使用して、表示を切り替えます。
 スクリプトの一番下へ。
#ここから↑は省略

    if key_flg_up
        #上
        pos_char_y = pos_char_y - char_speed
        if pos_char_y < 0
            pos_char_y = 0
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    elsif key_flg_down
        #下
        pos_char_y = pos_char_y + char_speed
        if pos_char_y > char_h_max
            pos_char_y = char_h_max
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    end
    
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    
    #----- キャラクターのアニメーション -----
    
    #アニメーション用カウンター
    char_anime_count = char_anime_count + 1
    if char_anime_count == (char_anime_change * 2)
        char_anime_count = 0
    end
    
    #キャラクターの表示を切替
    if key_flg_left
        if char_anime_count < char_anime_change
            setCharSpritePattern(2)
        else
            setCharSpritePattern(5)
        end
    elsif key_flg_right
        if char_anime_count < char_anime_change
            setCharSpritePattern(3)
        else
            setCharSpritePattern(6)
        end
    else
        if char_anime_count < char_anime_change
            setCharSpritePattern(1)
        else
            setCharSpritePattern(4)
        end
    end
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア

  アニメーションカウンターのカウント実行と、
 切り替えポイントの2倍の値に達したとき、
 アニメーションカウンターをリセットする処理が前半部分。

  後半部分では、キー入力状態の変数とアニメーションカウンターを
 if文で分岐させることで、表示したい画像の番号を
 キャラクターの表示内容を変更する関数にセットしています。




  スクリプト全体(再び、少し整理しています)
#メニュー項目等の表示OFF
setMenuItemVisible(getMenuBackLog(), false)
setMenuItemVisible(getMenuSave(), false)
setMenuItemVisible(getMenuLoad(), false)
setHelpVisible(false)

#キャンバスの初期化
setCanvasVisible(false)
deleteAllSprite()
drawCanvas()


#画像を設定する関数
def setCreateSprite(img_name, img_no, get_x, get_y, get_w, get_h,
                    set_x, set_y, set_w, set_h, set_z, pos_x, pos_y)
    
    setVariable(img_name, createSprite(img_no))
    setSpriteRect(getVariable(img_name),
                  get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
    setSpriteZOrder(getVariable(img_name), set_z)
    setSpritePosition(getVariable(img_name), pos_x, pos_y)
end

#キャラクターの表示内容を変更する関数
def setCharSpritePattern(no)
    img_char_name = "img_char"
    get_x = 0;    get_y = 0;    get_w = 64;   get_h = 64
    set_x = 0;    set_y = 0;    set_w = 64;   set_h = 64
    
    if no == 1
        get_x = 0;    get_y = 0
    elsif no == 2
        get_x = 64;   get_y = 0
    elsif no == 3
        get_x = 128;  get_y = 0
    elsif no == 4
        get_x = 0;    get_y = 64
    elsif no == 5
        get_x = 64;   get_y = 64
    elsif no == 6
        get_x = 128;  get_y = 64
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_char_name),
                  get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h)
end


#キャラクター画像の設定
img_no = 76793
img_char_name = "img_char"

get_x = 0;    get_y = 0;    get_w = 64;   get_h = 64
set_x = 0;    set_y = 0;    set_w = 64;   set_h = 64
set_z = 7
pos_char_x = 368;           pos_char_y = 500

setCreateSprite(img_char_name, img_no, get_x, get_y, get_w, get_h,
                set_x, set_y, set_w, set_h, set_z, pos_char_x, pos_char_y)


#背景画像の設定
img_no = 76800
img_bg_name = "img_bg"

get_x = 0;    get_y = 0;    get_w = 800;  get_h = 600
set_x = 0;    set_y = 0;    set_w = 800;  set_h = 600
set_z = 1
pos_bg_x = 0;               pos_bg_y = 0

setCreateSprite(img_bg_name, img_no, get_x, get_y, get_w, get_h,
                set_x, set_y, set_w, set_h, set_z, pos_bg_x, pos_bg_y)


#キー入力フラグの設定
key_flg_left  = false;      key_flg_right = false
key_flg_up    = false;      key_flg_down  = false
key_flg_z     = false


#定数の設定
char_speed = 10
char_w_max = 800 - 64;      char_h_max = 600 - 64
char_anime_change = 3


#変数の設定
char_anime_count = 0


#画面の更新
drawCanvas()
setCanvasVisible(true)


startInput()     #入力受付の開始

#メインループの開始
mainloop = true
while mainloop
    
    #キー入力の判定
    while hasInput()
        takeInput()
        #----- キー入力の判定処理を入れる場所 -----
        if isKeyDown("LEFT")
            key_flg_left = true
        elsif isKeyUp("LEFT")
            key_flg_left = false
        elsif isKeyDown("RIGHT")
            key_flg_right = true
        elsif isKeyUp("RIGHT")
            key_flg_right = false
        elsif isKeyDown("UP")
            key_flg_up = true
        elsif isKeyUp("UP")
            key_flg_up = false
        elsif isKeyDown("DOWN")
            key_flg_down = true
        elsif isKeyUp("DOWN")
            key_flg_down = false
        elsif isKeyDown("Z")
            key_flg_z = true
        elsif isKeyUp("Z")
            key_flg_z = false
        end
    end
    
    #----- ゲームのメイン処理を入れる場所 -----
    #(ゲームの終了時はmainloopをfalseに)
    
    #----- キャラクターの移動 -----
    if key_flg_left
        #左
        pos_char_x = pos_char_x - char_speed
        if pos_char_x < 0
            pos_char_x = 0
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    elsif key_flg_right
        #右
        pos_char_x = pos_char_x + char_speed
        if pos_char_x > char_w_max
            pos_char_x = char_w_max
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    end
    
    if key_flg_up
        #上
        pos_char_y = pos_char_y - char_speed
        if pos_char_y < 0
            pos_char_y = 0
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    elsif key_flg_down
        #下
        pos_char_y = pos_char_y + char_speed
        if pos_char_y > char_h_max
            pos_char_y = char_h_max
        end
        setSpritePosition(getVariable(img_char_name),
                           pos_char_x, pos_char_y)
    end
    
    
    #----- キャラクターのアニメーション -----
    
    #アニメーション用カウンター
    char_anime_count = char_anime_count + 1
    if char_anime_count == (char_anime_change * 2)
        char_anime_count = 0
    end
    
    #キャラクターの表示を切替
    if key_flg_left
        if char_anime_count < char_anime_change
            setCharSpritePattern(2)
        else
            setCharSpritePattern(5)
        end
    elsif key_flg_right
        if char_anime_count < char_anime_change
            setCharSpritePattern(3)
        else
            setCharSpritePattern(6)
        end
    else
        if char_anime_count < char_anime_change
            setCharSpritePattern(1)
        else
            setCharSpritePattern(4)
        end
    end
    
    
    #----- 画面の更新 -----
    drawCanvas()
    
    waitTime(30)
end

endInput()     #入力受付の終了
goEnding()     #ゲームのクリア

  これで、一通り完成です。
 保存、終了をして、テストプレーを行い、
 キャラクターの動きに合わせて、アニメーションされるように
 なったかどうか、確認してみましょう。




03-06 おわりに


  いかがでしたでしょうか。
 動きとアニメーションがついて、
 より、ゲーム画面らしくなってきました。

  さて、次回は
 「敵キャラクターを登場させる」を実践してみましょう。


  第01回 スクリプトって何?
  第02回 画面にキャラクターを描画する
  第03回 キャラクターをキー入力で操作する
  第04回 敵キャラクターを登場させる
  第05回 弾を発射させる
  第06回 より面白くするために

コメントする

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

コメント一覧

User icon mini akito0705(投稿日:2012/12/15 20:45, 履歴)
はじめまして、質問失礼します。

テストプレイをするときに

etSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 46

という警告が出てきてしまいます。
どうやればいいのか全然わかりません、教えていただけたら嬉しいです。
User icon mini akito0705(投稿日:2012/12/15 20:50, 履歴)
すみません

setSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 46

でした
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/12/15 22:12, 履歴)
エラーが発生した場合、まずは
Error一覧で原因を特定します

今回の場合、「ハンドルnullは無効です」ですので
この一覧から
「戻り値(=ハンドル)を指定しなければいけないところに、
 別のものを指定している」
ということが原因であるとわかります。

さらに原因となっている箇所で
使用している関数は「setSpritePosition」
エラーの発生場所は「46行目」ということを示しています。


なお、エラーが発生した場合は
こちらの記事もご一読ください
User icon mini akito0705(投稿日:2012/12/15 23:33, 履歴)
このブログの通りにやらせてもらってるのですが、提示していただいた記事を読んでもいまいちわかりません・・・
この通りにやってもできないのですか?
User icon mini akito0705(投稿日:2012/12/15 23:35, 履歴)
連続ですみません、今気が付いたのですが

line: 60 not defined variable : img_no
line: 72 not defined variable : pos_bg_x
line: 72 not defined variable : pos_bg_y

これもエラーですか?
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/12/16 01:22, 履歴)
エラーメッセージです

行番号、エラーの内容、エラーの原因の順で書かれています


途中の解説用スクリプトは
一部を抜粋しているため
単体では動作しませんが、

最後に掲載しております
全体スクリプトは
正常に動作する形となっております。
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/12/16 01:27, 履歴)
なお、スクリプトの初級者向けの記事も
別途掲載しております

もし、スクリプトを扱うのがはじめての場合、
こちらもご一読いただけましたら幸いです。

はじめてのRmakeスクリプト / 第01回 変数と数値をマスターしよう
User icon mini akito0705(投稿日:2012/12/16 01:58, 履歴)
一応第1回から読ませていただいてるのですが・・・

最後の全体スクリプトはコピペすればおkなんですか?
User icon mini akito0705(投稿日:2012/12/16 02:47, 履歴)
できました!ありがとうございました!
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/12/16 10:05, 履歴)
おめでとうございます


上手く動きましたら
どの箇所でどういった内容が実行されているのか
上の解説用スクリプトで
復習してみるのも良いかと思います。
Edamame icon mini 茹で小豆(投稿日:2013/08/01 15:17, 履歴)
すみません、最後の全体スプリクトをコピペしても、できませんでした・・・↑と同じエラーが出ました。
setSpritePosition(getVariable(img_char_name),がエラー発生源だと思うんですが・・つまり、()の中に戻り値が入っていなきゃダメなのに、img_char_nameに、戻り値が入っていないから無効ですってことですか?もしそうだったら、何をいれればいいですか?教えてください><
Cdv30200 aoi icon mini aoihikawa(投稿日:2013/08/01 17:57, 履歴)
同じエラーのように見えても
行番号の情報やエラーの詳細内容が異なる場合もあります

また、『思う』と言われても
実際は違う可能性もあります


現在の投稿内容では
何が原因なのか分かりかねます

申し訳ありませんが、
こちらの記事を参考に、
いま一度、情報を整理してから
ご連絡いただけましたら幸いです

スクリプトに関する質問を、投稿する場合のテンプレート
Edamame icon mini 茹で小豆(投稿日:2013/08/02 11:10, 履歴)
setSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 133
setSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 133
というエラーでした。情報が曖昧ですみません。あと、not definedのエラーも出てましたが、
pos_bg_x =1-1を入れてみたら治りましたが、これを入れても大丈夫なんですか?これでも情報が足りなかったらすいません・・・;
Cdv30200 aoi icon mini aoihikawa(投稿日:2013/08/02 18:29, 履歴)
エラー情報を纏めたら
有志の方が収集したError一覧より
該当のエラー内容を調べることが
第一の手順となります

「ハンドルnullは無効です」ということから
Sprite…すなわち拡張画像表示系の関数でのエラー
createSprite()の戻り値(=ハンドル)を
指定しなければいけないところに、別のものを指定している
という原因が分かります

また、エラーの発生している場所は「line : 133」
つまり133行目です

この記事の全体スクリプトでは
133行目にsetSpritePositionはありませんので
恐らく、何か変更を加えている箇所か
コピーした内容に誤りがあるものと思われます

なお、pos_bg_xに関しては
上記と同じ理由で現在の状況が
全体スクリプトと異なっておりますので

スクリプトの提示がない以上
分かりかねます
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/09/07 17:44, 履歴)
>miyakin2さま

上手く動いて良かったです。
お気になさらず。

また何かありましたら
お気軽にコメントなど頂けましたら
幸いです。
Icon2 icon mini miyakin2(投稿日:2011/09/07 17:02, 履歴)
いま動きました。こちらのミスでした。
ご迷惑をお掛けしましてすみませんでした。
Icon2 icon mini miyakin2(投稿日:2011/09/07 16:42, 履歴)
テストプレーをしたらエラー文が出て、
_char と、 _bg を消したら動いたものですから。
余計なコメントを書いてしまってすみませんでした。
(無意味なコメントでしたのでこのコメントも併せて削除して頂いてけっこうです。)
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/09/07 15:24, 履歴)
>miyakin2さま

ご指摘いただきました変数について、
整理を行う前は
統一して pos_x、pos_y が
座標の管理に使用されていますが、

整理後、
pos_char_x、pos_char_y に、キャラクター画像の座標
pos_bg_x、pos_bg_y に、背景画像の座標
をそれぞれ格納するように変更しています。

これに合わせて、関数に渡す変数名も
変更されています。
Icon2 icon mini miyakin2(投稿日:2011/09/07 15:10, 履歴)
いちから勉強させて頂いています。

記事の上の方なんですが、
「03-01 前回までのおさらいと、スクリプトの整理」
「そこで、まずはこのスクリプトをすっきりと整理しましょう。」
の中の、

setCreateSprite(img_char_name, img_no, get_x, get_y, get_w, get_h,
set_x, set_y, set_w, set_h, set_z, pos_char_x, pos_char_y)

setCreateSprite(img_bg_name, img_no, get_x, get_y, get_w, get_h,
set_x, set_y, set_w, set_h, set_z, pos_bg_x, pos_bg_y)

の各行の末尾にある、

pos_char_x, pos_char_y
pos_bg_x, pos_bg_y

は、

pos_x, pos_y
pos_x, pos_y

ではないでしょうか。
勘違いでしたらすみません。
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/15 13:50, 履歴)
>fmyさま

Xキーの入力に判定ついては
一応、メニューを開いた後に流れてきている様子。
恐らく上流にメニュー表示があり、
先に実行されているのでしょうね。

ご紹介頂きましたコードも良い案ですね。
ただ、「メニューを閉じる」の項目が残るので
完全解決、とまで行かないのが難点でしょうか。

ヘルプメニューと同様な感じで
「setMenuVisible」みたいな関数を用意してもらえれば
良いのでしょうけれど。。。
Logo1 mini fmy(投稿日:2011/08/14 12:05, 履歴)
ご先祖様が教えてくれた気がしたので補足ー。
妄想含んでる話なので的外れな可能性もあり。話半分にお願いー。
キー入力の話なのでこの回でいいのかな?

キー入力のデータを保持しているらしき関数hasInputや関数takeInputの中身?では
「押された」「離された」の記録を残しているだけのようで、
関数getMousePositionみたいに常に現在の情報を取れるわけではないみたい。

だから何なのよっていうと例えば
「左押しっぱ→メニュー開く→左離す→メニュー閉じる」という手順を行うと
メニュー表示中は当然ながら、メニュー閉じても左に進み続けてしまう動作になります。

「離された」瞬間はメニュー表示中だと記録されないので
実際押されてなくても「押された」状態が維持される状況が作れるんちゃう?
というお話です。


STGサンプルや他のゲームを遊ばせて頂いた限りじゃ
もっかい該当のキーやマウスを押せば直るので
「気をつければいい」レベルでそんなにゲームバランスに直結してない模様です。
自分のゲームもまだ影響しそうにないのでそんなに必死になる必要無かったりするんですけど。

ただ、これをどうしてやろうかと考えた時に、自分はうまい手が思いつかなくて
簸川さん&皆さんの知恵を貸して頂けたらなーと思いまして書かせて頂きました。

# 自コード側でゲーム止めるとかにしてもー
# 現状はキー「X」「C」の入力は取れないしー今メニュー開いてる?的な関数も特にないぽいしー。
# 処理の上流で離された判定が来てないとなると
# 自コードで1フレ前(メニュー開く前)のキー記録してもたぶん同じ結果だしー。


そうそう、お前何言ってるかワカンネーんだよって人も
setMenuItemVisible( getMenuHideWindow(), false )

を似たような処理の所に追加するのをおすすめしておきますねー。
「ウィンドウを隠す」の状態もメニュー表示中と同じようなもんらしいので
間違ってメニュー開いてもほんの少しだけマシになりますー。
Material 71926 1 mini なとおとき(投稿日:2011/08/07 21:54, 履歴)
「敵キャラクターを登場させる」
というタイトルだけで次回が楽しみになりますね。
User icon mini 退会したユーザー(投稿日:2011/08/07 13:04, 履歴)
ありがとうございます^^
でわ早速逝かせてもらいます(逝くなあああああああ)
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/06 23:14, 履歴)
>foodmakesさま

スクリプトのコピー、OKです。

自分なりのペースで、
ある程度、理解してきたところから
「こうしてみたら面白くなるかも。」というアレンジに
挑戦してみてはいかがでしょうか。
User icon mini 退会したユーザー(投稿日:2011/08/06 22:36, 履歴)
そういや最近他の人の素材勝手にいじって
すくりぷととかほぼまるまるコピってゲームツクってルナ・・・。
あ、これもそうさせて(殴
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/06 11:10, 履歴)
>usaさま

お褒めの言葉、ありがとうございます。

シューティングゲームというジャンルは、
ゲームの歴史において、初期の頃から存在しながら、
今でも基本となるルールは大きく変化していない、
シンプルな仕組みとなっています。

そのため、実践的につくったり、
より面白くなるよう、皆さんがそれぞれに
アレンジしてみることが簡単であるため、
シューティングゲームをテーマに選びました。
User icon mini 退会したユーザー(投稿日:2011/08/06 01:52, 履歴)
第01回から、とても興味深く読ませて頂きました!
凄く分かり易く丁寧に書かれていて、感心してしまいます。

漠然とした説明ではなく、具体的なシューティングゲームを
作る過程が説明されていることが、分かり易い要因なのでしょうね。

シューティングゲーム自体は、作る気が無かったけど、
学ぶ所が大きく、次回も楽しみにしてしまいます。
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/05 23:50, 履歴)
>fmyさま

「no」については、エディタ上では色が変更されていなかったので
こちらで色が変更されていたことに、気がつきませんでした。。。(w;

 欲求、という程のものはないですが、
「ここが分かりにくかった」などの意見やコメントがありましたら
参考にさせていただきたいと考えております。
Logo1 mini fmy(投稿日:2011/08/05 23:13, 履歴)
関数の実体の定義がコード中に置けるのが目からウロコ!
逆に思いつかなかった…。

変数noがコード表記で青文字になってたので
アレ?予約語だったかな?と思ったけど別に違うみたい。
文字色が文字列とコメントで入れ違ってるくらいならいいけど
紫って何なのよ?って感じですよねー。

記事の書き手さんとしてはそろそろどのくらいの方がついて来れてるか、
レスポンスが欲しい欲求に駆られてるところではないでしょうか。
Material 71926 1 mini なとおとき(投稿日:2011/08/05 22:32, 履歴)
ローカル変数の存在に始めれきずいたw
いままで、普通の使ってたw