スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ゲーム制作状況 - 2013/11/24版 -

今日の報告!

とりあえず、前回

衝突判定⇒当たらなければ移動⇒衝突判定⇒当たらなければ移動 を
とりあえず移動⇒とりあえず移動⇒全部の衝突判定実施に変えたのですが、

その方法が纏まってきたので、その詳細を書いてみたいと思います。


まず、「移動」についてですが、
座標の変数の値を変えた際に、"差分"も任意の変数に保存します。

例えば下記の衝突判定用矩形の構造体があり、
座標が x = 50, y = 100だとします。

struct CollisionInfo {
int m_PosX, m_PosY;
int m_MoveX, m_MoveY;
};


SetPosX( m_CollisionHandle, 20 );
SetPosY( m_CollisionHandle, 120 );


で、上記の様に座標をセットした場合、
値はそれぞれ下記の様になっています。
m_PosX = 20
m_PosY = 120
m_MoveX = -30
m_MoveY = 20


何で差分も保存するのかというと、最後に衝突判定をまとめて行う以上、
「衝突している」という事だけを判定しても、
どの方向へ押し出して
めり込みを解消すれば良いのか分からない
からです。

例:
矩形Aと矩形Bが衝突しているとしています。

しかし、どう移動してきたかが分からないと、
矩形Aを上方向に押し出せば良いのか、下方向に押し出せば良いのか、
それとも右、または左方向に押し出せば良いのか全くわかりません。



また、最後に纏めて衝突判定を行うので、
全通りの組み合わせで衝突判定を行う必要があります。

全通りのオブジェクトの衝突を判定する方法についてですが、
これは簡単です。

A、B,C,Dの矩形が登録されている場合、

AB
AC
AD
BC
BD
CD

という風に先頭から順に、末尾までの矩形と順に判定を行っていきます。
これで全通りになります。

そして、Y軸方向の移動と、X軸方向の移動に分解して判別するようにしたので、
合計2回の全通り判定が行われます。

プログラムだと、大まかに下記の通り。
Listなので、イテレータを使用します。

//Y座標の衝突判定
for( it = t_CollisionManager.m_CollisionList.begin(); it != t_CollisionManager.m_CollisionList.end(); it++ )
{
std::list< std::tr1::shared_ptr< CollisionInfo > >::iterator it2;
it2 = it;
++it2;
//一番最後の要素の場合、イテレータを増やすとListの範囲外となる。
//よって、その際はループを抜ける

if( it2 == t_CollisionManager.m_CollisionList.end() ){
break;
}

if( ( *it )->m_MoveY == 0 && ( *it2 )->m_MoveY == 0 ){
//衝突判定を行う2つの矩形が、両方とも全く移動してなければ衝突はしない。
//なので、何もしない。

}else{
for( ; it2 != t_CollisionManager.m_CollisionList.end(); it2++ )
{
int t_RightA = ( *it )->m_PosX + ( *it )->m_Width - 1 - ( *it )->m_MoveX;
int t_LeftA = ( *it )->m_PosX - ( *it )->m_MoveX;
int t_TopA = ( *it )->m_PosY;
int t_BottomA = ( *it )->m_PosY + ( *it )->m_Height - 1;

int t_RightB = ( *it2 )->m_PosX + ( *it2 )->m_Width - 1 - ( *it2 )->m_MoveX;
int t_LeftB = ( *it2 )->m_PosX - ( *it2 )->m_MoveX;
int t_TopB = ( *it2 )->m_PosY;
int t_BottomB = ( *it2 )->m_PosY + ( *it2 )->m_Height - 1;

//2つの矩形が衝突していれば
if( ( t_RightA >= t_LeftB && t_LeftA <= t_RightB ) &&
( t_TopA <= t_BottomB && t_BottomA >= t_TopB ) ){
//省略
}
}
}
}


//X座標の衝突判定
for( it = t_CollisionManager.m_CollisionList.begin(); it != t_CollisionManager.m_CollisionList.end(); it++ )
{
std::list< std::tr1::shared_ptr< CollisionInfo > >::iterator it2;
it2 = it;
++it2;
//一番最後の要素の場合、イテレータを増やすとListの範囲外となる。
//よって、その際はループを抜ける

if( it2 == t_CollisionManager.m_CollisionList.end() ){
break;
}
if( ( *it )->m_MoveX == 0 && ( *it2 )->m_MoveX == 0 ){
//衝突判定を行う2つの矩形が、両方とも全く移動してなければ衝突はしない。
//なので、何もしない。

}else{
for( ; it2 != t_CollisionManager.m_CollisionList.end(); it2++ )
{
int t_RightA = ( *it )->m_PosX + ( *it )->m_Width - 1;
int t_LeftA = ( *it )->m_PosX;
int t_TopA = ( *it )->m_PosY;
int t_BottomA = ( *it )->m_PosY + ( *it )->m_Height - 1;

int t_RightB = ( *it2 )->m_PosX + ( *it2 )->m_Width - 1;
int t_LeftB = ( *it2 )->m_PosX;
int t_TopB = ( *it2 )->m_PosY;
int t_BottomB = ( *it2 )->m_PosY + ( *it2 )->m_Height - 1;

//2つの矩形が衝突していれば
if( ( t_RightA >= t_LeftB && t_LeftA <= t_RightB ) &&
( t_TopA <= t_BottomB && t_BottomA >= t_TopB ) ){
//省略
}
}
}
}



重要なのが、赤字の部分ですね。
"Y軸のみの移動"にする為に、X軸方向の座標は、
差分を引いて
います。

※X軸方向に30動いて、X座標が130、
 Y軸方向に10動いて、Y座標が110になった場合、下記の様になる。
 Y座標 … 110
 X座標 … 130 - 30  ( =100)



そして、現状の実行画面が下記の通り。
まだまだ質素な状態です。

【参考画像】
Sample_20131124_1.jpg
オレンジ … 主人公
茶色 … 床、およびブロック
水色 … 摩擦0の床 (滑ります)


次回は、下記の2点を実装予定です…!
・カメラワーク
・押すと動かせる物体





~今日のひとこと~
スーパーマリオという、
ほとんどの人が知っているアクションゲームがあると思います。

そのマリオなんですが、映画化された事があるらしいですね。
全然知らなかった…!

【参考画像】
Sample_20131124_2.jpg

アメリカで50億円の費用をかけて制作
日本とアメリカで公開されたそうです。

で、どちらの国でもヒットしなかった模様。
うーん面白いのかなぁ…?
スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント
コメントの投稿
管理者にだけ表示を許可する



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。