「テトリスもどき」ゲームのプログラムを紹介します。
case 2: piece[3][1] = bp; piece[3][2] = bp; break; case 3: piece[1][2] = bp; piece[1][3] = bp; break;
copy_piece[4-j][i] = piece[i][j];で右回転が表現できます。
(piece[i][j] >= 1 && area[bx + i - 2][by + j - 1] == 0)であれば、つまり、ピースのダイスがある位置のフィールドが空白であれば、その位置にピースを移動することができます。bx + i - 2 の -2 はピースの中心から左端までの距離です。by + j - 1 の -1 は、ピースを一つ下に落としたときの、中心から上端までの距離になります。このチェックを checkPiece(piece,x,y) で行います。
ld=1; for(j=2; j<12; j++) ld = ld * area[j][i];で、ld が 0 でなければ、横方向にすべてダイスがありますから、削除可能です。行を削除するには、上の行を1行下げれば良いので、
for(k=i-1;k>0;k--) for(s=2;s<12;s++) area[s][k+1]=area[s][k];となります。
//テトリスもどき //フォントが必要 MS-Gothic-48.vlw //音用ライブラリ //import ddf.minim.*; //Minim minim;//音のクラス //AudioSample sound_roll, sound_clear; PImage backImage; PFont font; int area[][] = new int[14][24];//ピース記憶領域 int piece[][] = new int[5][5];//ブロック生成領域 int piece_next[][] = new int[5][5];//次のピース int copy_piece[][] = new int[5][5]; int preFrame;//前の時刻 int startTime = 0;//時間 int playTime;//利用時間 int nline = 0;//消したラインの総数 int nlevel = 1;//現在のレベル int nfast = 800;//落下時間間隔 int bx, by;//落下中のピースの座標 int x = 2, y = 0; int z = 0; boolean rs; void setup() { size(320, 440); frameRate(45); //minim = new Minim(this); //sound_roll = minim.loadSample("meka_ta_sui01.mp3"); //sound_clear = minim.loadSample("magic23.mp3"); backImage = createBackgroundImage(); font = loadFont("MS-Gothic-48.vlw"); bx = 7; by = 2; getNewPiece(piece_next); updatePiece(); for (int i = 2;i < 12;i++) for (int j = 0;j < 22;j++) area[i][j] = 0; startTime = millis(); preFrame = startTime; //0 : ピースが存在しない、-1 :壁 //左右の壁 for (int i = 0;i < 22;i++) { area[1][i] = -1; area[12][i] = -1; }//for i //下の壁 for (int i = 2;i < 12;i++) { area[i][22] = -1; area[i][23] = -1; }//for i }//setup void draw() { int i, j, count; //背景フィールド再描画 image(backImage, 0, 0); //落とす時間がチェック int nowFrame = millis(); int frameSpan = nowFrame - preFrame; if (frameSpan >= nfast) { if (by <= 22) by++;//ピースを落とす preFrame = nowFrame; }//if frame //利用時間 playTime = (int)((nowFrame - startTime) / 1000); //ピースをひとつ下に落下が可能かどうか? if (!checkPiece(piece, bx, by+1)) { //落下は不可:ピースをフィールドにおく for (i = 0;i < 5;i++) for (j = 0;j < 5;j++) if (piece[i][j] >= 1) area[bx + i - 2][by + j - 2] = piece[i][j]; Check_Clear();//行クリアできたか updatePiece();//次のピース作成 bx = 7; by = 2;//最初の位置 }//if count //落下中のピースを描く for (i = 0;i < 5;i++) for (j = 0;j < 5;j++) Draw_Block(piece[i][j], i + bx - 3, j + by - 3); //エリアのピースを描く for (i = 0;i < 12;i++) for (j = 2;j < 22;j++) Draw_Block(area[i][j], i - 1, j - 2); //次のピースを描画 for (i = 1;i < 5;i++) for (j = 1;j < 5;j++) Draw_Block(piece_next[i][j], i + 11, j + 3); if (area[7][2] >= 1) { //ゲームオーバー noLoop();//停止 fill(255, 0, 0); textFont(font, 32); textAlign(CENTER, CENTER); text("GameOver", 120, height / 2 - 10); }//if gameover //数字の描画 textFont(font, 18); fill(0); textAlign(RIGHT); text(int(playTime), 294, 48);//時間 text(int( nlevel), 294, height - 80);//現在のレベル text(int( nline), 294, height - 26);//消したラインの数 }//draw void stop() { super.stop(); //sound_roll.close(); //sound_clear.close(); //minim.stop(); }//stop void keyPressed() { if (keyCode==LEFT) { Move_Left(); }//if left else if (keyCode == RIGHT) { Move_Right();//右移動 }//if right else if (keyCode == DOWN) { Move_Down();//下移動 }//if down else if (keyCode == UP) { Roll_piece(); }//if up // repaint(); }//keypress //次ぎに落とすピースを作成 void updatePiece() { for (int i = 0;i < 5;i++) for (int j = 0;j < 5;j++) piece[i][j] = piece_next[i][j]; getNewPiece(piece_next); }//createBlock //ピースの要素を描画 void Draw_Block(int blockID, int addressX, int addressY) { if (blockID >= 1) { stroke(64); //番号から色を決定 fill(0 + blockID * 22, 150 + blockID % 2 * 70, 100 + blockID * 25); rect(addressX * 20, 20 + addressY * 20, 20, 20); }//if blockID }//draw_block public int[][] getNewPiece(int[][] newPiece) { //int[][] newPiece = new int[5][5]; int pieceID = (int)(Math.random() * 140000) % 7 + 1; for (int i = 0;i < 5;i++) for (int j = 0;j < 5;j++) newPiece[i][j] = 0; newPiece[2][2] = pieceID; newPiece[2][3] = pieceID; switch(pieceID) { case 1: newPiece[1][1] = pieceID; newPiece[1][2] = pieceID; break; case 2: newPiece[3][1] = pieceID; newPiece[3][2] = pieceID; break; case 3: newPiece[1][2] = pieceID; newPiece[1][3] = pieceID; break; case 4: newPiece[2][1] = pieceID; newPiece[3][3] = pieceID; break; case 5: newPiece[2][1] = pieceID; newPiece[1][3] = pieceID; break; case 6: newPiece[1][3] = pieceID; newPiece[3][3] = pieceID; break; case 7://I 型ピース newPiece[2][1] = pieceID; newPiece[2][4] = pieceID; break; }//switch return newPiece; }//getnewpiece public void Check_Clear() { //ピースが消えるかどうかを判定・ピースの消去 int i, j, s, k; int ld; boolean cleared = false; //ラインが消せるかどうか判定 for (i = 21;i > 0;i--) { ld = 1; for (j = 2;j < 12;j++)ld = ld * area[j][i]; if (ld != 0) { //一行が揃った cleared = true; //上からプレスする for (k = i - 1;k > 0;k--) for (s = 2;s < 12;s++) area[s][k + 1] = area[s][k]; i++; nline++; }//if ld }//for i if (cleared) { //レベル上げの処理 delay(100); //level up nlevel=(int)sqrt(nline+10); nfast = 850 - (50 * nlevel); //最低でも0.1秒 if (nfast <= 100) nfast = 100; }//if cleared }//check_clear public void Move_Down() { if (checkPiece(piece, bx, by+1)) by++; }//down void Move_Right() { if (checkPiece(piece, bx+1, by)) bx++; }//right void Move_Left() { if (checkPiece(piece, bx-1, by)) bx--; }//left public void Roll_piece() { int i, j, count; count = 0; //仮回転体生成 for (i=0;i<5;i++) for (j=0;j<5;j++) copy_piece[4 - j][i] = piece[i][j]; //回転可能なら回転する if (checkPiece(copy_piece, bx, by)) { //生成したピースを回転後の形に更新 for (i = 0;i < 5;i++) for (j = 0;j < 5;j++) piece[i][j] = copy_piece[i][j]; //sound_roll.trigger(); }//if }//roll boolean checkPiece(int[][] piece, int bx, int by) { int count=0; for (int i = 0;i < 5;i++) { for (int j = 0;j < 5;j++) if (piece[i][j] >= 1 && area[bx + i - 2][by + j - 2] == 0) count++; } if (count==4) return true; else return false; } PImage createBackgroundImage() { PFont ft = createFont("MS Gothic", 14); fill(232, 240, 255);//background noStroke(); rect(0, 0, width, height); //white background fill(255); stroke(208); rect( 20, 20, 200, height - 40);//game field rect(240, 10, 60, 46);//time back rect(240, 70, 60, 114);//next back rect(240, height - 123, 60, 46);//level back rect(240, height - 67, 60, 46);//line back //label background fill(32, 80, 128); noStroke(); rect(241, 11, 59, 15);//time rect(241, 71, 59, 15);//next rect(241, height - 123, 59, 16);//level rect(241, height - 67, 59, 16);//line //text textFont(ft); fill(0, 6, 16); textAlign(RIGHT, BASELINE); text("←→:move ↑:roll ↓:fall", width, height - 2);//guide fill(250); textAlign(LEFT, BASELINE); text( "TIME", 246, 24); text( "NEXT", 246, 84); text("LEVEL", 246, height - 109); text( "LINE", 246, height - 53); return get(); }