トップページ > 電子工作インデックス > テトリス > 8. 落下関数

8. ブロック落下処理関数

main()関数のループの中で主に呼び出される関数です。 操作中のブロックを地面(フィールドの底or他の積み上がったブロック) に当たるまで落下させます。 落下完了した後は、操作していたブロックをstage配列(背景)の一部として、 次に上から降ってくる新しいブロックを生成して終わります。

処理を分かりやすくするために、処理をいくつかの関数にわけてあります。 ブロックを移動させるmove_block()関数や、 ブロックが一列すべてそろっているかを判断するcheck_lines()関数 は前述の通りです。 それに加えて、操作中のブロックが背景(フィールド&落下済みブロック)に干渉して いないかをチェックする関数と、落下完了した後に操作していたブロックを背景の 一部として組み込んで操作対象外にする関数もつくっておきます。

準備(1)〜ブロックが背景と干渉するか調べる関数〜

操作中のブロックが壁にめり込んだり、積み上がったブロックをすり抜ける ことを防ぐために、背景に対して重なっている場合に"1"を返す関数をつくります。 操作中のブロックの座標は、左上の頂点の座標を使っていますが、 そのブロックの座標を引数として、ブロックが存在する点 (block配列の要素が"1"である点)においてback配列(背景を管理する配列) の要素が"1"であれば、ステージと干渉しているということなので、見つかり次第"1"を返します。 最後までひっかからなければ"0"を返します。

//********************************************************************
//ブロックがbackと重なっているか判断
//2つの引数new_xとnew_yは、ブロックが干渉するかどうかを調べる座標。

int check_back_block(int new_x,int new_y)
{
 int i,j; //for文用の変数


 //ブロックのデータを扱うblock配列は8×8ですので、そのすべてのマスを調べます。
 for(i=0;i<8;i++)
 {
  for(j=0;j<8;j++)
  {

   //各ブロックの形は違うので、blockの要素が"1"のところを狙ってチェックします。
   if(block[i][j] ==1)
   {
   
    //stageは背景を扱う配列です。背景にすでにブロックがある場所には
    //ブロックを移動させることはできません…
    if(back[new_y+i][new_x+j] ==1)
    {

     //干渉する場合は"1"を返します。
     return 1;
    }
   }
  }
 }

  //最後までif文の条件にひっかからなかった場合は、干渉なしと判断します。
  return 0;
}


//********************************************************************


準備(2)〜落下完了したブロックを背景に組み込む関数〜

操作中のブロック以外は、別の背景用配列(back)にデータを入れて管理します。 処理内容は単純で、backの指定座標にblockを加算するだけです。


//********************************************************************
//ブロック固定関数

void lock_block(void) //ブロックの固定と消し判定 
{

 int i,j;

 //backは「固定済みのブロック+壁」を記憶する背景用配列です。 
 //check_lines()関数はbackを処理対象とするので、一度画面のデータを移します。  
 
 for(i=1;i<36;i++)
 {
  for(j=0;j<24;j++)
  {
   back[i][j]=field[i][j];
  }
 }


 //1列そろっているかどうかの判定、得点の管理、1列分の消去など、
 //すべてここで処理します。

 check_lines();


 //1列消されている場合も、そうでない場合も、とりあえず画面を更新。  
 for(i=1;i<36;i++)
 {
  for(j=0;j<24;j++)
  {
   display[i][j] = back[i][j];
  }
 }
  
 //ブロックが着地した時の音。
 voice1();

} 

//********************************************************************


ブロック落下処理関数



//********************************************************************
//ブロックを落とす…


void drop_block(void)
{

 //スコア管理用変数。
 unsigned long temp;
 

 //下に1マスずらした場合の干渉がなければ、check_stage_block関数が"0"を返します。
 //x,yはブロックの現在座標を扱うグローバル変数です。
 
 if(check_stage_block(x,y+1) == 0)
 {
  //下に1マスずらす。
  moveblock(x,y+1);
 }

 //ブロックが下まで落ちきった場合
 else
 {
 
  //まず操作していたブロックを背景扱いにする。
  //lock_block()関数内で、1列そろった場合の処理も実行します。

  lockblock();

  //新しい操作ブロックを呼び出します。
  createblock();

  //一通りの処理結果を画面に表示します。
  putout();

 }


 temp=score;
 
 //ゲームスピードを決める変数eは、2000点ごとに小さくなっていきます。
 e = 8-temp/2000;  
  
 //eが3より小さくなる場合は3で止めておきます。(速すぎるので…)
 if(e<3) e=3;
}

//********************************************************************

前へ   次へ