「さめがめ」とはご存知の方が多いかと思いますが、
選択したパネルの周囲に同じ色があった場合のみ消せるパズルゲームです。
1つずつでは消せません。
消した際に自分の下にパネルがなければ落下し、左の列が空いていたら詰めます。
参考サイトを元にコーディングをしてみたのですが、アニメーションの部分で詰まってしまいました。
(現在、参考サイトを見ながら落下アニメーション以外の実装は出来ました。)
アニメーションは落下しているのを表現したく、縦が優先、縦で落ちれなくなったら横をつめるみたいな感じで実装したいです。
現在の物だと直接配列の値を変えてしまっているので、もしかすると大々的な改修が必要かもしれません。
開発環境はMac、Xcodeです。
少し変わっておりましてWindowsの環境が御座いません。
その為、OpenGLを使って実装しております。
参考サイト http://www40.atwiki.jp/spellbound/pages/1066.html
ソースが見づらくて恐縮なのですが、添付させて頂きます。
修正のアドバイスを頂けないでしょうか。
----------------------------------------------------------------------
// パネルタッチ用
class MENU{
public:
int Px, Py;
int Width, Height;
float SizeX, SizeY;
bool TouchCheck( void );
void Init( int Px, int Py, int width, int height, float Sx, float Sy );
};
bool MENU::TouchCheck( void ){
int x = System.touchPos.x;
int y = System.touchPos.y;
int sx = ( this->Width * this->SizeX) / 2;
int sy = ( this->Height * this->SizeY) / 2;
if(x < this->Px+sx && x > this->Px-sx &&
y < this->Py+sy && y > this->Py-sy ){
return true;
}else{
return false;
}
}
void MENU::Init( int Px, int Py, int width, int height, float Sx, float Sy ){
this->Px = Px;
this->Py = Py;
this->Width = width;
this->Height = height;
this->SizeX = Sx;
this->SizeY = Sy;
}
----------------------------------------------------------------------
#define PANEL_SIZE 64
#define PANEL_WIDTH_MAX 10
#define PANEL_HEIGHT_MAX 10
#define PANEL_TYPE 3
#define DROP_SPEED 0
typedef struct{
int TouchX;
int TouchY;
}OBJECT_GAME;
// パネルクラス
class PANEL : public MENU{
public:
int Type;
int TargetX, TargetY;
void Delete( void );
};
void PANEL::Delete( void ){
this->Type = 0;
}
static PANEL Panel[PANEL_HEIGHT_MAX][PANEL_WIDTH_MAX];
static OBJECT_GAME Obj;
/******************** ********************/
// 削除
void DeletePanel( int x, int y, int color ){
// 配列外ならリターン
if (x < 0 || PANEL_WIDTH_MAX <= x ||
y < 0 || PANEL_HEIGHT_MAX <= y) return;
// 消えていたら
if( Panel[y][x].Type == 0 ) return;
if( Panel[y][x].Type != color ) return;
// 消す
Panel[y][x].Delete();
// 再帰
DeletePanel( x-1, y, color );
DeletePanel( x+1, y, color );
DeletePanel( x, y-1, color );
DeletePanel( x, y+1, color );
}
// 詰める処理
void DropPanel( void ){
// 縦の判定
for(int j=0; j<PANEL_WIDTH_MAX; j++){
for(int i=PANEL_HEIGHT_MAX-1; i>=0; i--){
// 隙間があった
if( Panel[i][j].Type == 0 ){
for(int yy=i-1; yy>=0; yy--){
if( yy >= 0 ){
if( Panel[yy][j].Type != 0 ){
Panel[i][j].Type = Panel[yy][j].Type;
Panel[yy][j].Type = 0;
Panel[i][j].Py = i*PANEL_SIZE;
//Panel[i][j].TargetY = i*PANEL_SIZE;
//Panel[yy][j].TargetY = i*PANEL_SIZE;;
break;
}
}
}
}
}
}
// 横方向
int underY = PANEL_HEIGHT_MAX-1;
for (int x=0; x<PANEL_WIDTH_MAX; x++){
if( Panel[underY][x].Type == 0 ){
for (int xx=x+1; xx<PANEL_WIDTH_MAX; xx++){
if( Panel[underY][xx].Type != 0 ){
for(int yy=PANEL_HEIGHT_MAX-1; yy>=0; yy--){
if( Panel[yy][xx].Type == 0 ) break;
Panel[yy][x].Type = Panel[yy][xx].Type;
Panel[yy][xx].Type = 0;
Panel[yy][x].Px = x*PANEL_SIZE;
//Panel[yy][x].TargetX = x * PANEL_SIZE;
}
break;
}
}
}
}
}
// カラーチェック
bool CheckType( int x, int y, int color ){
bool check = false;
if (0 <= x - 1 && Panel[y][x-1].Type != 0 && Panel[y][x-1].Type == color) check = true;
else if (x + 1 < PANEL_WIDTH_MAX && Panel[y][x + 1].Type != 0 && Panel[y][x + 1].Type == color) check = true;
else if (0 <= y - 1 && Panel[y-1][x].Type != 0 && Panel[y-1][x].Type == color) check = true;
else if (y + 1 < PANEL_HEIGHT_MAX && Panel[y+1][x].Type != 0 && Panel[y+1][x].Type == color) check = true;
return check;
}
// クリア判定
bool CheckEnd( void ){
for(int i=0; i<PANEL_HEIGHT_MAX; i++){
for(int j=0; j<PANEL_WIDTH_MAX; j++){
if (Panel[i][j].Type == 0) continue;
if (CheckType( j, i, Panel[i][j].Type )) return false; // 周りに同じ色が一つでもあったら
}
}
return true;
}
static void Init(){
// パネルの初期化
for(int i=0; i<PANEL_HEIGHT_MAX; i++){
for(int j=0; j<PANEL_WIDTH_MAX; j++){
Panel[i][j].Init( j*PANEL_SIZE, i*PANEL_SIZE, PANEL_SIZE, PANEL_SIZE, 1.0f, 1.0f );
//Panel[i][j].Init( j*PANEL_SIZE-PANEL_SIZE/2, i*PANEL_SIZE-PANEL_SIZE/2, PANEL_SIZE, PANEL_SIZE, 1.0f, 1.0f );
Panel[i][j].Type = rand()%PANEL_TYPE+1;
Panel[i][j].TargetX = Panel[i][j].Px;
Panel[i][j].TargetY = Panel[i][j].Py;
}
}
Obj.TouchX = -1;
Obj.TouchY = -1;
}
static void Loop(){
Obj.TouchX = -1;
Obj.TouchY = -1;
if( System.touch.trgFlag ){
for(int i=0; i<PANEL_HEIGHT_MAX; i++){
for(int j=0; j<PANEL_WIDTH_MAX; j++){
if( Panel[i][j].TouchCheck() ){
Obj.TouchX = j;
Obj.TouchY = i;
break;
}
}
}
NSLog( @"%d%d", Obj.TouchX, Obj.TouchY );
//タッチされたら
if( Obj.TouchX != -1 && Obj.TouchY != -1 ){
// 隣同士で同じ色があったら消す
if( CheckType( Obj.TouchX , Obj.TouchY, Panel[Obj.TouchY][Obj.TouchX].Type ) )
DeletePanel( Obj.TouchX , Obj.TouchY, Panel[Obj.TouchY][Obj.TouchX].Type );
}
}
// 詰める
DropPanel();
// 目標値へ移動
for(int i=0; i<PANEL_HEIGHT_MAX; i++){
for(int j=0; j<PANEL_WIDTH_MAX; j++){
//Panel[i][j].Px -= DROP_SPEED;
//Panel[i][j].Py += DROP_SPEED;
//if( Panel[i][j].Px <= Panel[i][j].TargetX ) Panel[i][j].Px = Panel[i][j].TargetX;
//if( Panel[i][j].Py >= Panel[i][j].TargetY ) Panel[i][j].Py = Panel[i][j].TargetY;
}
}
NSLog( @"%d", CheckEnd() );
}
static void Draw(){
// パネルの描画
for(int i=0; i<PANEL_HEIGHT_MAX; i++){
for(int j=0; j<PANEL_WIDTH_MAX; j++){
if( Panel[i][j].Type == 1 ) DrawBox( Panel[i][j].Px, Panel[i][j].Py, Panel[i][j].Px+PANEL_SIZE, Panel[i][j].Py+PANEL_SIZE, 0xff0000, 255 );
else if( Panel[i][j].Type == 2 ) DrawBox( Panel[i][j].Px, Panel[i][j].Py, Panel[i][j].Px+PANEL_SIZE, Panel[i][j].Py+PANEL_SIZE, 0x00ff00, 255 );
else if( Panel[i][j].Type == 3 ) DrawBox( Panel[i][j].Px, Panel[i][j].Py, Panel[i][j].Px+PANEL_SIZE, Panel[i][j].Py+PANEL_SIZE, 0x0000ff, 255 );
}
}
}