[アクション]敵を出現させよう(つづき)


えーと,『今日は体育の日だったが,特に運動はしなかった…まる』っというわけで,とりあえず日記らしいことを書いておきましょう.


前回の続きということで,今日は実際にプログラミングしてみた.

前回は,敵の出現データはX方向に昇順に並んでいれば,次の検索は頭から全てを行う必要がないんじゃないかなーと考えた.
データ構造として,下のようになっていると思う.
X       Y      TYPE
-------------------
1       1       0
1       8       0
1       16      0
1       24      0    
8       1       0
8       8       0
8       16      0   
8       24      0
16      1       0   ←前回の検索開始位置
16      8       0
16      16      0
16      24      0
24      1       0
24      8       0
「前回の検索開始位置」と,現在のウインドウ(表示されている領域)の位置とを比較し,検索開始位置を求めます.

/*----------------------------------------------------------------------------------*/
/*  テーブルに対しての検索開始位置を探す                                            */
/*      in_Map1 : 検索対象位置の始点                                                */
/*      m_HeadX : ファイル読み込み時に初期化しておくこと.                           */
/*      次回の検索もこの m_HeadX を基準にちょっと前を見たり                         */
/*      後ろを見たりして決定する.                                                  */
/*----------------------------------------------------------------------------------*/
void    EnemyTable ::FindHeadX ( const int in_MapX1 )
{
    //---- 安全策
    if ( m_HeadX < 0 )              m_HeadX = 0 ;
    if ( m_HeadX >= m_EnemyNum )    m_HeadX = m_EnemyNum ;

    //---- ヘッドが検索対象枠より左にあったとき
    if ( m_pTable[m_HeadX].x < in_MapX1 )
    {
        do {
            //-- m_HeadX が配列より大きくならない為の安全策
            if ( ++m_HeadX >= m_EnemyNum ) {
                m_HeadX = m_EnemyNum - 1 ;
                break ;
            }
        } while ( m_pTable[m_HeadX].x < in_MapX1 ) ;
    }
    //---- 逆に検索対象枠より 右にあったとき
    else if ( m_pTable[m_HeadX].x > in_MapX1 )
    {
        do { 
            //-- 配列をゼロより下を指さない安全策
            if ( --m_HeadX < 0 ) {
                m_HeadX = -1;   // 4行下でインクリメントするから結局0になる
                break ;
            }
        } while ( m_pTable[m_HeadX].x >= in_MapX1 ) ;
        m_HeadX ++ ;    // ちょい戻す
    }
}


in_MapX1はウインドウの左座標と同じで,m_HeadX が 例の「前回の検索開始位置」になります.

んで,これは次の関数から呼びます.

/*==================================================================================*/
/*  敵を作成する                                                                    */
/*      引数 : 敵配列の先頭アドレス                                                 */
/*                                                                                  */
/*      手順1.なるべく無駄な検索を避ける為,検索開始位置を定める                  */
/*      手順2.その検索位置からウィンドウ枠よりちょっと外側に                      */
/*              出現するであろう敵を見つける                                        */
/*      手順3.その敵の状況(既に出現しているとか)を調べ実際に発生させる          */
/*                                                                                  */
/*==================================================================================*/
void    EnemyTable ::CreateEnemy ( Enemy in_pEnemy[] )
{
    //---- 検索対象枠→マス座標に変換
    int MapX1   = ウインドウの左端 -1 ;
    int MapX2   = ウインドウの右端 +1 ;
    int MapY1   = ウインドウの上端 -1 ;
    int MapY2   = ウインドウの下端 +1 ;

    //---- 検索開始位置を見つける (m_HeadX のセット)
    FindHeadX ( MapX1 );    // ■ここで呼んでいる

    //---- 検索開始
    int e=0 ;   // 無駄な検索させないためにここで初期化

    for ( int id = m_HeadX ; id < m_EnemyNum ; id++ ) {
        //-- 右端まで検索したら終了
        if ( m_pTable[id].x > MapX2 ) break ;

        //-- 画面左端と右端の敵発生の検索
        if ( m_pTable[id].x == MapX1  ||  m_pTable[id].x == MapX2 )
        {
            if ( m_pTable[id].y >= MapY1  &&  m_pTable[id].y <= MapY2  &&
                 m_pTable[id].status == ETABLE_OK )
            {
                //-- ここで敵を発生させる
            }
        }

        //-- 画面上端と下端の敵発生の検索
        else 
        {
            if ( ( m_pTable[id].y == MapY1  ||  m_pTable[id].y == MapY2 ) &&
                 m_pTable[id].status == ETABLE_OK )
            {
                //-- ここで敵を発生させる
            }
        }
    }
}

こんな感じです.
変数に日本語とかあるけど,気にしないでぇ!
今回はウインドウの外側から発生することしか考えてないので,ウインドウ内部では敵発生のことは考えてません.
あー忘れてた.
敵のデータを管理するテーブル(m_pTable)はこんな感じで定義してます.

/*==================================================================================*/
/*      ■ 実際のデータを格納する構造体 ■                                          */
/*==================================================================================*/
struct EnemyTableData
{
    int     x ;         // 敵の出現位置
    int     y ;
    byte    type ;      // そこに出現する敵のタイプ
    byte    status ;    // 「出現中」とかの情報を保持する
};

ありゃ,前回のとほとんど同じね.


というわけで(?),サンプルのソース.
余計な部分が多すぎたので Zip(106K) にしました.
というより,これ当たり判定のサンプルですねぇ.



< Back to Diary.