アクションつくってみる3
投稿者: rurun9 投稿日:2012/04/17 00:10
≪みゃー。
|
アクションつくってみる2≫
ハイ、こんにちわー。
結局、ブロックとの当たり判定は一画面毎に細かく指定していく、最も面倒だけど確実な方法を採用してみますた…
例によって直前回とは根本的な設計を変えているので再び激変しております
今回は作り方の枠組みが決まったので、俺ルールをできるだけ解説してみるけど、たぶん自分で後から見直す用にしかならない気ガス
使う変数が減ってスッキリ
固定1画面を順にクリアしていくスクロール無しの単純なゲームに落ち着く
画面毎のステージを『ゾーン』と呼ぶ事にした
壁や床のスプライトを作成するdefを置き、各ゾーン毎にパーツ1個ずつ位置や大きさを指定してゆく
・宇宙人:スプライト番号0
・弾:1~4
・壁、床、敵、敵弾など:5~19までの最大15個
全てのスプライトについて、
・位置(x,y)
・幅w、高さh
・移動量(dx,dy)
・状態番号j
のデータで管理する
jに入る数値は種類によって全く意味が異なる俺ルールなので注意
ゾーン毎に地形が異なるのを、宇宙人がめり込まないように細かく座標を管理&制御してゆく
setzoneにて配置した位置&大きさに沿って、移動可能範囲を座標で計算(ゾーン毎に疲れる作業量…)
移動する床もwallcheck内で位置を変更してる
尚、上下移動する土色の浮き床の移動量dyは自由落下速度の初速と全く同じにしてあるので、下に動いている場合でも常に「乗っている」=ジャンプ可能となる
宇宙人が上に動いてるかdy[0]<=0、下に動いてるか0<dy[0]で、浮き床にめり込んだ際に上下どちらに押し出すかを決めている
ナナメの坂は、登っている場合は常に接地しているのでジャンプが可能なのに対して
坂を下っている場合にx方向のみ前に移動させると一瞬空中にいる状態になってしまい、空中ではジャンプができない。そこで「直前まで歩いていたなら」坂に沿って高さも同時にズラさないといけない
また「敵を倒すと地形が変化する」ギミックを入れたので、地形変化後の判定もココに書いてある
ゾーンが増えるほど、when i が増えてどんどん長くなっていく形
地形が変化する処理と、弾が敵に当たってたら耐久値を減らす処理
まだ敵は弾を出してないので、敵弾の当たり判定も追加予定
このメイン部分からは、ほぼ変更してないカモ
臨時のテキスト表示は完成したら消す
ゾーンクリア時の演出、そして次へ
◆【こんな感じになった】
よし、後はどんだけ根気良くゾーンを配置していくか、だけだわぁ~
つくってみるブログはとりあえず、終了カモ?仕組みは全部書いちゃったので、とりあえずゾーン20くらいを目標に作業を進めましょーか
ここまで読んでるくらいの暇な人はコレをベースにオリジナルな続きを作って勝手に公開しちゃってくだちぃ
お疲れしたー
ツイート
結局、ブロックとの当たり判定は一画面毎に細かく指定していく、最も面倒だけど確実な方法を採用してみますた…
例によって直前回とは根本的な設計を変えているので再び激変しております
今回は作り方の枠組みが決まったので、俺ルールをできるだけ解説してみるけど、たぶん自分で後から見直す用にしかならない気ガス
#chapter0 setVariable("e",118038) #スプライト用の素画像番号 def sv(a,b) setVariable(a,b) end def gv(a) return getVariable(a) end sv("x",createArray()); sv("y",createArray()) #スプライトの位置(x,y) sv("j",createArray()) #スプライトの状態、向きや種類の番号、敵なら耐久力を入れる sv("dx",createArray()); sv("dy",createArray()) #スプライトの移動量(dx,dy) sv("zone",0) #何画面目か #◆スプライトの作成 deleteAllSprite(); drawCanvas() #最初に使う前にキャンバスをキレイにしておく sv("h",createArray()) #スプライト表示番号 0=宇宙人, 1~4=弾, 5~19=敵や床など n=0 while n<20 gv("h")[n]=createSprite(gv("e")) n=n+1 end setSpriteRect(gv("h")[0], 0,0,32,32, -32,-32,64,64) #宇宙人 setSpriteZOrder(gv("h")[0], 2) n=1 while n<=4 setSpriteRect(gv("h")[n], 0,96,32,32, -16,-16,32,32) #弾 setSpriteZOrder(gv("h")[n], 1) n=n+1 end
固定1画面を順にクリアしていくスクロール無しの単純なゲームに落ち着く
#chapter_setzone def sp(i, x,y, w,h, dx, dy, what) #◆◆◆スプライトを作成する処理 case what when 0 #固定の緑色 setSpriteRect(gv("h")[i], 96,96,1,1, 0,0,w,h) when 1 #移動の土色 setSpriteRect(gv("h")[i], 70,20,1,1, 0,0,w,h) when 2 #左側の坂 setSpriteRect(gv("h")[i], 64,96,32,32, 0,0,w,h) when 3 #右側の坂 setSpriteRect(gv("h")[i], 96,96,32,32, 0,0,w,h) when 4 #敵 setSpriteRect(gv("h")[i], 64,0,32,32, -32,-32,64,64) when 5 #敵の弾 setSpriteRect(gv("h")[i], 32,96,32,32, -16,-16,32,32) end gv("x")[i]=x; gv("y")[i]=y; gv("dx")[i]=dx; gv("dy")[i]=dy if what!=4 gv("j")[i]=0 #敵なら耐久力になる end end #sp()終 def setzone() #◆◆◆画面切り替え時にステージ床&壁&敵を配置する処理 setCanvasVisible(false) #一度、全スプライトを見えなくする n=0 while n<=4 gv("x")[n]=0; gv("y")[n]=640 #弾は最初、見えない位置に置く gv("j")[n]=0 #弾は出てない状態にする gv("dx")[n]=0; gv("dy")[n]=0 #宇宙人と弾の初期移動量は(0,0) n=n+1 end gv("j")[0]=2 #宇宙人は右向きでスタート case gv("zone") when 0 showImage(2495) sv("max",12); gv("x")[0]=100; gv("y")[0]=100 sp(5, 240,300, 160,40, 0,-4, 1) #浮床 sp(6, 0,0, 100,500, 0,0, 0) #左の壁 sp(7, 700,164, 100,336, 0,0, 0) #右の壁 sp(8, 0,500, 800,100, 0,0, 0) #床 sp(9, 500,400, 200,100, 0,0, 2) #左坂 sp(10, 636,164, 64,40, 0,0, 0) #敵の足場 sp(11, 636+32,100+32, 64,64, 0,0, 4); gv("j")[11]=5 #敵 sp(12, 0,600, 100,40, 0,0, 0) #ゴールへ行ける足場 when 1 sv("max",7); gv("x")[0]=100; gv("y")[0]=500-32 sp(5, 0,0, 100,500, 0,0, 0) #左壁 sp(6, 700,0, 100,500, 0,0, 0) #右壁 sp(7, 0,500, 800,100, 0,0, 0) #床 end #case zone終 n=gv("max")+1 #使わないスプライトをとりあえず無効化 while n<20 gv("x")[n]=0; gv("y")[n]=640; gv("dx")[n]=0; gv("dy")[n]=0; gv("j")[n]=0 n=n+1 end n=0 while n<20 setSpritePosition(gv("h")[n], gv("x")[n],gv("y")[n] ) #スプライト全てを位置(x,y)に配置 n=n+1 end drawCanvas() #スプライトを載せたキャンバスを更新 setCanvasVisible(true) #【重要】キャンバスを見えるようにしている sv("goal",false) #このステージのゴールが開いてるかどうか end #setzone()終
壁や床のスプライトを作成するdefを置き、各ゾーン毎にパーツ1個ずつ位置や大きさを指定してゆく
・宇宙人:スプライト番号0
・弾:1~4
・壁、床、敵、敵弾など:5~19までの最大15個
全てのスプライトについて、
・位置(x,y)
・幅w、高さh
・移動量(dx,dy)
・状態番号j
のデータで管理する
jに入る数値は種類によって全く意味が異なる俺ルールなので注意
#chapter_wallcheck def wallcheck() #◆◆◆宇宙人と床や壁との衝突判定 x=gv("x")[0]+gv("dx")[0]; y=gv("y")[0]+gv("dy")[0] walk=false case gv("zone") when 0 #◆◆ gv("y")[5]=gv("y")[5]+gv("dy")[5] #上下移動床を動かして再表示 if gv("y")[5]<200 gv("dy")[5]=4 elsif 420<gv("y")[5] gv("dy")[5]=-4 end setSpritePosition(gv("h")[5], gv("x")[5],gv("y")[5]) if 500-32<y #全体の床 y=500-32; gv("dy")[0]=0; walk=true end if x<100 #左壁 x=100; gv("dx")[0]=0 elsif 240<=x && x<400 #上下移動床 if gv("y")[5]-32<=y && y<gv("y")[5]+40 if gv("dy")[0]<0 y=gv("y")[5]+40; gv("dy")[0]=0 else y=gv("y")[5]-32; gv("dy")[0]=0; walk=true end end elsif 500<=x && x<700 #坂 if 750-32-(x/2)<y y=750-32-floor(x/2); gv("dy")[0]=0; walk=true elsif gv("dx")[0]<0 && gv("walk") y=750-32-floor(x/2); gv("dy")[0]=0; walk=true end elsif 700<=x #右壁 if y<=164-16 changeChapter("chapter2") end x=700; gv("dx")[0]=0 if 400-32<y y=400-32; gv("dy")[0]=0; walk=true end end if gv("goal") #敵を倒したら右上の足場に行ける if 0<=gv("dy")[0] if 468<=x && x<568 && 164-32<=y && y<204 y=164-32; gv("dy")[0]=0; walk=true elsif 636<=x && 164-32<=y && y<204 y=164-32; gv("dy")[0]=0; walk=true end end end when 1 #◆◆ if 500-32<y #全体の床 y=500-32; gv("dy")[0]=0; walk=true end if x<100 x=100; gv("dx")[0]=0 elsif 700<=x x=700; gv("dx")[0]=0 end end #case zone終 gv("x")[0]=x; gv("y")[0]=y #座標の更新 if walk sv("walk",true) else sv("walk",false) end end #wallcheck()終
setzoneにて配置した位置&大きさに沿って、移動可能範囲を座標で計算(ゾーン毎に疲れる作業量…)
移動する床もwallcheck内で位置を変更してる
尚、上下移動する土色の浮き床の移動量dyは自由落下速度の初速と全く同じにしてあるので、下に動いている場合でも常に「乗っている」=ジャンプ可能となる
宇宙人が上に動いてるかdy[0]<=0、下に動いてるか0<dy[0]で、浮き床にめり込んだ際に上下どちらに押し出すかを決めている
ナナメの坂は、登っている場合は常に接地しているのでジャンプが可能なのに対して
坂を下っている場合にx方向のみ前に移動させると一瞬空中にいる状態になってしまい、空中ではジャンプができない。そこで「直前まで歩いていたなら」坂に沿って高さも同時にズラさないといけない
また「敵を倒すと地形が変化する」ギミックを入れたので、地形変化後の判定もココに書いてある
ゾーンが増えるほど、when i が増えてどんどん長くなっていく形
#chapter_hitcheck def setgoal() #◆◆◆敵を倒したらゴールを出す処理 case gv("zone") when 0 setSpritePosition(gv("h")[12], 468,164) #when 1 end #case zone終 sv("goal",true) end #setgoal()終 def hitcheck(i) #◆◆◆弾の当たり判定処理 m=5 while m<=gv("max") if 0<gv("j")[m] #残り耐久値があるヤツだけ判定する if gv("x")[m]-32<gv("x")[i] && gv("x")[i]<gv("x")[m]+32 && gv("y")[m]-32<gv("y")[i] && gv("y")[i]<gv("y")[m]+32 gv("j")[m]=gv("j")[m]-1 #敵の耐久値を1減らす gv("x")[i]=0; gv("y")[i]=640; gv("j")[i]=0 #当たった弾も出てない状態にする if gv("j")[m]<1 #敵の耐久値が0になったら画面外へ gv("j")[m]=0; gv("x")[m]=0; gv("y")[m]=800; gv("dx")[m]=0; gv("dy")[m]=0 setSpritePosition(gv("h")[m], gv("x")[m],gv("y")[m]) setgoal(); playSound(63622) else playSound(44339) end end end m=m+1 end end #hitcheck()終
まだ敵は弾を出してないので、敵弾の当たり判定も追加予定
#chapter1 z=createText(0,0,800,600) #臨時テキスト setzone() #ステージを作成&設置 speak("ZONE ",gv("zone")) p=createArray(); p[0]=400; p[1]=300 #マウス位置用、最初は画面ド真ん中という事にしておく anime=0 #アニメ用カウント tama=0 #何番の弾を出すか sv("walk",false) #歩いているかどうか、つまりジャンプ可能かどうか startInput() #入力受付 key=true while key while hasInput() takeInput() if isMouseMove() p=getMousePosition() elsif isMouseDown() && gv("walk") #歩いてるときにクリックしたら、ジャンプ gv("dy")[0]=-36; sv("walk",false); playSound(66602) elsif isKeyUp("ESC") key=false end end #hasInput終 gv("dy")[0]=gv("dy")[0]+4 #重力による自由落下 if p[0]<gv("x")[0]-32 #プレイヤーキャラ宇宙人の横移動 gv("dx")[0]=-8; gv("j")[0]=1 #左向き elsif gv("x")[0]+32<p[0] gv("dx")[0]=8; gv("j")[0]=2 #右向き else gv("dx")[0]=0 end wallcheck() #宇宙人と、床壁との衝突判定 if 800<gv("y")[0] #もしもの壁抜けに対応 speak("画面外に落ちた"); gv("x")[0]=100; gv("y")[0]=-100 end anime=anime+1 #◆アニメカウントが一定になったら絵を切り替える if anime==6 if gv("dx")[0]==0 #横移動してたらそっちを向く m=0 elsif gv("dx")[0]<0 m=32 else #0<gv("dx")[0] m=64 end setSpriteRect(gv("h")[0], 32,m,32,32, -32,-32,64,64) elsif anime==12 if gv("dx")[0]==0 #横移動してないときは正面向き m=0 elsif gv("dx")[0]<0 #横移動してたらそっちを向く m=32 else #0<gv("dx")[0] m=64 end setSpriteRect(gv("h")[0], 0,m,32,32, -32,-32,64,64) anime=0; tama=tama+1 #一定の間隔で、自動で弾がひとつ出る if tama==5 tama=1 end if gv("j")[tama]==0 #今回の弾番号が出てない状態なら、位置と飛ぶ方向を決める gv("x")[tama]=gv("x")[0]; gv("y")[tama]=gv("y")[0] case gv("j")[0] when 1 gv("j")[tama]=1 when 2 gv("j")[tama]=2 end #case終 end end setSpritePosition(gv("h")[0], gv("x")[0], gv("y")[0]) #宇宙人位置更新 n=1 while n<=4 #◆弾位置更新 case gv("j")[n] when 1 #左向き移動中 gv("x")[n]=gv("x")[n]-12 if gv("x")[n]<-40 gv("j")[n]=0 #画面外に来たら出てない状態にする end when 2 #右向き移動中 gv("x")[n]=gv("x")[n]+12 if 840<gv("x")[n] gv("j")[n]=0 #画面外に来たら出てない状態にする end end #case終 hitcheck(n) setSpritePosition(gv("h")[n], gv("x")[n],gv("y")[n]) n=n+1 end setText(z, "walk=",gv("walk"),"\nx0=",gv("x")[0],"\ny0=",gv("y")[0],"\nlife=",gv("j")[11] ) drawCanvas(); waitTime(20) #忘れずに入れる end #keyループ終 endInput() #入力終 goBadEnding()
臨時のテキスト表示は完成したら消す
#chapter2 speak("ZONE ",gv("zone")," Clear") sv("zone",gv("zone")+1) deleteTextAll() changeChapter("chapter1")
◆【こんな感じになった】
よし、後はどんだけ根気良くゾーンを配置していくか、だけだわぁ~
つくってみるブログはとりあえず、終了カモ?仕組みは全部書いちゃったので、とりあえずゾーン20くらいを目標に作業を進めましょーか
ここまで読んでるくらいの暇な人はコレをベースにオリジナルな続きを作って勝手に公開しちゃってくだちぃ
お疲れしたー
コメントする
コメントするには、ログインする必要があります。
コメント一覧
コメントはありません。