Rmakeで自由なゲームをつくろう / 第03回キャラクターをキー入力で操作する
投稿者: 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
この関数の中で、前回のものとは異なっているところとして、
setVariableとgetVariableという関数が追加されています。
実は、変数は通常の「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回 より面白くするために
コメントする
コメントするには、ログインする必要があります。
コメント一覧
いちから勉強させて頂いています。
記事の上の方なんですが、
「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
ではないでしょうか。
勘違いでしたらすみません。
記事の上の方なんですが、
「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
ではないでしょうか。
勘違いでしたらすみません。
ご先祖様が教えてくれた気がしたので補足ー。
妄想含んでる話なので的外れな可能性もあり。話半分にお願いー。
キー入力の話なのでこの回でいいのかな?
キー入力のデータを保持しているらしき関数hasInputや関数takeInputの中身?では
「押された」「離された」の記録を残しているだけのようで、
関数getMousePositionみたいに常に現在の情報を取れるわけではないみたい。
だから何なのよっていうと例えば
「左押しっぱ→メニュー開く→左離す→メニュー閉じる」という手順を行うと
メニュー表示中は当然ながら、メニュー閉じても左に進み続けてしまう動作になります。
「離された」瞬間はメニュー表示中だと記録されないので
実際押されてなくても「押された」状態が維持される状況が作れるんちゃう?
というお話です。
STGサンプルや他のゲームを遊ばせて頂いた限りじゃ
もっかい該当のキーやマウスを押せば直るので
「気をつければいい」レベルでそんなにゲームバランスに直結してない模様です。
自分のゲームもまだ影響しそうにないのでそんなに必死になる必要無かったりするんですけど。
ただ、これをどうしてやろうかと考えた時に、自分はうまい手が思いつかなくて
簸川さん&皆さんの知恵を貸して頂けたらなーと思いまして書かせて頂きました。
# 自コード側でゲーム止めるとかにしてもー
# 現状はキー「X」「C」の入力は取れないしー今メニュー開いてる?的な関数も特にないぽいしー。
# 処理の上流で離された判定が来てないとなると
# 自コードで1フレ前(メニュー開く前)のキー記録してもたぶん同じ結果だしー。
そうそう、お前何言ってるかワカンネーんだよって人も
を似たような処理の所に追加するのをおすすめしておきますねー。
「ウィンドウを隠す」の状態もメニュー表示中と同じようなもんらしいので
間違ってメニュー開いてもほんの少しだけマシになりますー。
妄想含んでる話なので的外れな可能性もあり。話半分にお願いー。
キー入力の話なのでこの回でいいのかな?
キー入力のデータを保持しているらしき関数hasInputや関数takeInputの中身?では
「押された」「離された」の記録を残しているだけのようで、
関数getMousePositionみたいに常に現在の情報を取れるわけではないみたい。
だから何なのよっていうと例えば
「左押しっぱ→メニュー開く→左離す→メニュー閉じる」という手順を行うと
メニュー表示中は当然ながら、メニュー閉じても左に進み続けてしまう動作になります。
「離された」瞬間はメニュー表示中だと記録されないので
実際押されてなくても「押された」状態が維持される状況が作れるんちゃう?
というお話です。
STGサンプルや他のゲームを遊ばせて頂いた限りじゃ
もっかい該当のキーやマウスを押せば直るので
「気をつければいい」レベルでそんなにゲームバランスに直結してない模様です。
自分のゲームもまだ影響しそうにないのでそんなに必死になる必要無かったりするんですけど。
ただ、これをどうしてやろうかと考えた時に、自分はうまい手が思いつかなくて
簸川さん&皆さんの知恵を貸して頂けたらなーと思いまして書かせて頂きました。
# 自コード側でゲーム止めるとかにしてもー
# 現状はキー「X」「C」の入力は取れないしー今メニュー開いてる?的な関数も特にないぽいしー。
# 処理の上流で離された判定が来てないとなると
# 自コードで1フレ前(メニュー開く前)のキー記録してもたぶん同じ結果だしー。
そうそう、お前何言ってるかワカンネーんだよって人も
setMenuItemVisible( getMenuHideWindow(), false )
を似たような処理の所に追加するのをおすすめしておきますねー。
「ウィンドウを隠す」の状態もメニュー表示中と同じようなもんらしいので
間違ってメニュー開いてもほんの少しだけマシになりますー。
退会したユーザー(投稿日:2011/08/07 13:04,
履歴)
ありがとうございます^^
でわ早速逝かせてもらいます(逝くなあああああああ)
でわ早速逝かせてもらいます(逝くなあああああああ)
退会したユーザー(投稿日:2011/08/06 22:36,
履歴)
そういや最近他の人の素材勝手にいじって
すくりぷととかほぼまるまるコピってゲームツクってルナ・・・。
あ、これもそうさせて(殴
すくりぷととかほぼまるまるコピってゲームツクってルナ・・・。
あ、これもそうさせて(殴
退会したユーザー(投稿日:2011/08/06 01:52,
履歴)
第01回から、とても興味深く読ませて頂きました!
凄く分かり易く丁寧に書かれていて、感心してしまいます。
漠然とした説明ではなく、具体的なシューティングゲームを
作る過程が説明されていることが、分かり易い要因なのでしょうね。
シューティングゲーム自体は、作る気が無かったけど、
学ぶ所が大きく、次回も楽しみにしてしまいます。
凄く分かり易く丁寧に書かれていて、感心してしまいます。
漠然とした説明ではなく、具体的なシューティングゲームを
作る過程が説明されていることが、分かり易い要因なのでしょうね。
シューティングゲーム自体は、作る気が無かったけど、
学ぶ所が大きく、次回も楽しみにしてしまいます。
テストプレイをするときに
etSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 46
という警告が出てきてしまいます。
どうやればいいのか全然わかりません、教えていただけたら嬉しいです。
setSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 46
でした
Error一覧で原因を特定します
今回の場合、「ハンドルnullは無効です」ですので
この一覧から
「戻り値(=ハンドル)を指定しなければいけないところに、
別のものを指定している」
ということが原因であるとわかります。
さらに原因となっている箇所で
使用している関数は「setSpritePosition」
エラーの発生場所は「46行目」ということを示しています。
なお、エラーが発生した場合は
こちらの記事もご一読ください
この通りにやってもできないのですか?
line: 60 not defined variable : img_no
line: 72 not defined variable : pos_bg_x
line: 72 not defined variable : pos_bg_y
これもエラーですか?
行番号、エラーの内容、エラーの原因の順で書かれています
途中の解説用スクリプトは
一部を抜粋しているため
単体では動作しませんが、
最後に掲載しております
全体スクリプトは
正常に動作する形となっております。
別途掲載しております
もし、スクリプトを扱うのがはじめての場合、
こちらもご一読いただけましたら幸いです。
はじめてのRmakeスクリプト / 第01回 変数と数値をマスターしよう
最後の全体スクリプトはコピペすればおkなんですか?
上手く動きましたら
どの箇所でどういった内容が実行されているのか
上の解説用スクリプトで
復習してみるのも良いかと思います。
setSpritePosition(getVariable(img_char_name),がエラー発生源だと思うんですが・・つまり、()の中に戻り値が入っていなきゃダメなのに、img_char_nameに、戻り値が入っていないから無効ですってことですか?もしそうだったら、何をいれればいいですか?教えてください><
行番号の情報やエラーの詳細内容が異なる場合もあります
また、『思う』と言われても
実際は違う可能性もあります
現在の投稿内容では
何が原因なのか分かりかねます
申し訳ありませんが、
こちらの記事を参考に、
いま一度、情報を整理してから
ご連絡いただけましたら幸いです
スクリプトに関する質問を、投稿する場合のテンプレート
setSpritePositionに不正なハンドルが指定されました。ハンドルnullは無効です。 line : 133
というエラーでした。情報が曖昧ですみません。あと、not definedのエラーも出てましたが、
pos_bg_x =1-1を入れてみたら治りましたが、これを入れても大丈夫なんですか?これでも情報が足りなかったらすいません・・・;
有志の方が収集したError一覧より
該当のエラー内容を調べることが
第一の手順となります
「ハンドルnullは無効です」ということから
Sprite…すなわち拡張画像表示系の関数でのエラー
createSprite()の戻り値(=ハンドル)を
指定しなければいけないところに、別のものを指定している
という原因が分かります
また、エラーの発生している場所は「line : 133」
つまり133行目です
この記事の全体スクリプトでは
133行目にsetSpritePositionはありませんので
恐らく、何か変更を加えている箇所か
コピーした内容に誤りがあるものと思われます
なお、pos_bg_xに関しては
上記と同じ理由で現在の状況が
全体スクリプトと異なっておりますので
スクリプトの提示がない以上
分かりかねます