にしのクエスト2

情報処理技術者試験と資格学校講師の日常

20221224103753

Unityで学ぶプログラミング  テトリス的を作る(7)前半のプログラムリスト

こんにちは!

今回からテトリス的なものを作っていきます。長い連載にな
りますので、気長にお付き合いください。

なお、プログラムの内容は難しいので、初心者には向きませ
ん。いきなり作るのは厳しいのでよろしくお願いします。
また、説明も大幅に省いていきます。

最後に注意事項
ご紹介するのはあくまで「テトリス的」です。そのものでは
ありませんし、非常にシンプルに遊べるだけのものです。

連載終了後に、より詳しい技術的な解説&追加機能を加えた
電子書籍を発行する予定ですので、よろしくお願いします。


今回はまとめ。ここまでのプログラムの全貌

解説はこれまでの記事を参考にしてください。載せてるだけです。
GameC.cs

public class GameC : MonoBehaviour
{
//フィールドの状態
public int[,] field = new int[16,23];

//フィールドの状態を保存する場所
public int[,] stage = new int[16,23];

//ブロックを格納
int[,] blk =new int[4,4];

//ブロックを一時保存
int[,] blktmp =new int[4,4];
 
 
//ブロックを格納
public GameObject BlkObj;
 
//ブロックの位置(初期値)
public int x=5;
public int y=0;

//時間
public float delta;
 
//間隔
float span=0.8f;

//ブロック番号
public int blkno;

//gameOverの判定
int gameOverFlag=0;
 
//そろっているか判定
int comp;

void Start()
{
 
//コントロール変数
int i,j;
//ブロックを並べる(物理的に)
//タテ21並べた後それを横12
for(i=2;i<14;i++){
for(j=0;j<21;j++){
Instantiate(BlkObj,new Vector3(i*1.0f,j*-1.0f,0),Quaternion.identity);
}
}
 
//壁の設定
for(i=0;i<16;i++){
for(j=0;j<23;j++){
//壁に該当する部分は9
if(i==2||i==13||j==20){
stage[i,j]=9;
}else{
//それ以外は0を入れる
stage[i,j]=0;
}
}
}

//ステージのデータを描く
for(i=2;i<14;i++){
for(j=0;j<21;j++){
field[i,j]=stage[i,j];
}
}
 
//ブロック作成
makeBlk();
//フィールドを描画
Render();
}

void makeBlk(){
int i,j;
blkno=Random.Range(0,7);
switch(blkno){
case 0:
blk =new int[4,4]{
{0,0,0,0},
{0,1,1,0},
{0,1,0,0},
{0,1,0,0}};
break;
case 1:
blk =new int[4,4]{
{0,0,0,0},
{0,1,1,0},
{0,0,1,0},
{0,0,1,0}};
break;
case 2:
blk =new int[4,4]{
{0,0,0,0},
{0,1,1,0},
{0,1,1,0},
{0,0,0,0}};
break;
case 3:
blk =new int[4,4]{
{0,0,0,0},
{0,1,0,0},
{1,1,1,0},
{0,0,0,0}};
break;
case 4:
blk =new int[4,4]{
{0,0,0,0},
{0,1,0,0},
{0,1,1,0},
{0,0,1,0}};
break;
case 5:
blk =new int[4,4]{
{0,0,0,0},
{0,0,1,0},
{0,1,1,0},
{0,1,0,0}};
break;
case 7:
blk =new int[4,4]{
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{0,0,0,0}};
break;
case 6:
blk =new int[4,4]{
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0}};
break;
default:
break;
}


//フィールドにブロックを加える
for(i=0;i<4;i++){
for(j=0;j<4;j++){
field[i+5,j]=stage[i+5,j]+blk[i,j];

// //ゲームオーバーかどうかチェックする
// if(field[i+x,j+y+4]>=1){
// gameOverFlag=1;
// }
}
}
}

void Render(){
int i,j;
//ステージのデータを描く
for(i=0;i<12;i++){
for(j=0;j<21;j++){
field[i,j]=stage[i,j];
}
}
//ブロックを追加する
for(i=0;i<4;i++){
for(j=0;j<4;j++){
field[i+x,j+y]=stage[i+x,j+y]+blk[i,j];
}
}
}

void MoveBlk(int x2,int y2){
int i,j;

//ブロックをいったん消して
for(i=0;i<4;i++){
for(j=0;j<4;j++){
field[x+i,y+j]-=blk[i,j];
}
}

//座標を更新
x=x2;
y=y2;

//ブロック入れ替え
for(i=0;i<4;i++){
for(j=0;j<4;j++){
field[x+i,y+j]+=blk[i,j];
}
}
}

//移動チェック

int ChkBlk(int x2,int y2){
int i,j;

for(i=0;i<4;i++){
for(j=0;j<4;j++){
//ブロックがあって
if(blk[i,j]!=0){
//移動予定地もブロックなら
if(stage[x2+i,y2+j]!=0){
//1を返しなさい
return 1;
}
}
}
}
//どちらも該当しないなら0を返す
return 0;
}

void Update()
{
//時間の加算
delta += Time.deltaTime;
 
//時間経過後
if(delta>=span){
//自然移動下に行けるかチェックして
if(ChkBlk(x,y+1)==0){
//重なってないなら移動
MoveBlk(x,y+1);
delta=0;
}
//右を押した場合
if(Input.GetKey(KeyCode.RightArrow)&&ChkBlk(x-1,y)!=1){
//重なってないなら移動
MoveBlk(x-1,y);
}
//左を押した場合
if(Input.GetKey(KeyCode.LeftArrow)&&ChkBlk(x+1,y)!=1){
//重なってないなら移動
MoveBlk(x+1,y);
}
}
}
}


BlockC

public class BlockC : MonoBehaviour
{
//座標を格納
int posx;
int posy;

//GameDirectorの格納
GameObject GD;
GameC GDP;

//色を格納
public Material[] MT;
 
//Blockの色
int BlkCol;

//時間
float delta;

void Start()
{
//座標の取得
posx=(int)this.transform.position.x;
posy=(int)this.transform.position.y*-1;
 
//GameDirectorの発見
GD = GameObject.Find("GameDirector");
//スクリプトを取得する
GDP = GD.GetComponent<GameC>();
}

void Update()
{

//時間の加算
delta += Time.deltaTime;
 
//時間経過後
if(delta>=0.1f){
//座標に該当する番地の値を読み込む
BlkCol=GDP.field[posx,posy];

//その値によって色を変化させる
this.GetComponent<Renderer>().material=MT[BlkCol];

//時間をリセット
delta=0;
}
}
}


Block(prefab)の設定

f:id:koharuwest:20210123113856p:plain

 

f:id:koharuwest:20210123113948p:plain


Main Camera

f:id:koharuwest:20210123114037p:plain


GameDirector

f:id:koharuwest:20210123114112p:plain


次回は、ブロックを次々と降らせる!

 

f:id:koharuwest:20210117110657p:plain


それではよきプログラミングライフを!
またね。