パズルゲームに自然なアニメーションを付けたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
marn

パズルゲームに自然なアニメーションを付けたい

#1

投稿記事 by marn » 7年前

現在、パズドラのようなゲームをDXライブラリを使って作っています
コンボの計算とかは順調に実装できている中、1つだけどうしても自分では作れないものが出て来ました、それがドロップが落ちてくるアニメーションです

[nico]http://www.nicovideo.jp/watch/sm18787729[/nico]

本家パズドラでは、ドロップ(動画の画面で操作している丸い玉のこと)を3つ以上揃えると、それらのドロップを消します
ドロップが消えた場所には、上のドロップを下に落とさせるようにしていて、そのアニメーションはとてもなめらかです


そして、これが私が書いてみたドロップが下に落ちてくるアニメーションの部分のコードです

コード:

#include<DxLib.h>

typedef struct{
	//int color;
	int flag;
}drop_t;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
	ChangeWindowMode(TRUE);
	if(DxLib_Init()==-1) return -1;
	SetDrawScreen(DX_SCREEN_BACK);

	drop_t drop[10];

	//flag=0の場所が、ドロップが消えてなくなっている場所
	drop[0].flag = 1;
	drop[1].flag = 1;
	drop[2].flag = 0;
	drop[3].flag = 0;
	drop[4].flag = 0;
	drop[5].flag = 1;
	drop[6].flag = 1;
	drop[7].flag = 0;
	drop[8].flag = 0;
	drop[9].flag = 0;

	int count = 1;
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
		//ここと下の部分のコメントを外すと、マウスが押されている時だけ動かせます
		//if(GetMouseInput() & MOUSE_INPUT_LEFT){
			if(count % 10 == 0){
				for(int i=0;i<10;i++){
					if(drop[i].flag == 0){
						if(i==0){
							drop[0].flag = 1;
							i=10;
						}
						else {
							int tmp = drop[i].flag;
							drop[i].flag = drop[i-1].flag;
							drop[i-1].flag = tmp;
						}
					}
				}
			}
			count++;
		//}
		for(int i=0;i<10;i++){
			DrawCircle(100,30*i+15,15,(drop[i].flag == 1) ? GetColor(255,0,0) : GetColor(0,0,0),TRUE);
		}
	}
	DxLib_End();
	return 0;
}
自分なりに頑張ったのですが、本家とはかけ離れたものになりました
ボトッ、ボトッ、っとドロップが落ちてきて、全然なめらかではありません

本当は、drop_tのメンバにx,yなど直接座標を指すものを作って、それで管理したいのですが、そうするとドロップが3つ以上つながっているかの判定ができなくなってしまいます


ここしばらくずっとこれで悩んでいるのですが、まったく解決策が浮かびません
なにかいい方法はないでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: パズルゲームに自然なアニメーションを付けたい

#2

投稿記事 by softya(ソフト屋) » 7年前

落ちてくるエフェクトは今のブロック単位の管理では思うようには出来ないと思います。
パズドラ未経験ですが、落ちるエフェクト中は操作不能でしょうから状態遷移で落ちているエフェクト専用処理を設ければ良いと思います。
落ちているエフェクト専用処理では、数ドット単位で玉を動かします。これは構造体で管理すると良いでしょう。

【追記】
・パズル解き中はブロック単位の配列管理。
・エフェクト中は構造体管理です。
・相互に変換して処理します。 ブロック単位の配列管理 ⇔ 構造体管理
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: パズルゲームに自然なアニメーションを付けたい

#3

投稿記事 by ISLe » 7年前

ひとつずつ説明すると長くなるので改造したコードを投稿します。
分からないところがあったら聞いてください。

カウンタをアニメーションテーブルを参照するカウンタとして使えば、自由落下っぽくしたり凝ったアニメーションにできます。

コード:

#include<DxLib.h>
 
typedef struct{
    //int color;
    int flag;

    // 落下アニメのカウント。フラグも兼ねてる
    // とりあえず座標のオフセットとしている
    int drop_count;
}drop_t;

enum {
	PHASE_DROPPING, // 落下中
	PHASE_FIXED,    // 固定
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
    ChangeWindowMode(TRUE);
    if(DxLib_Init()==-1) return -1;
    SetDrawScreen(DX_SCREEN_BACK);
 
    drop_t drop[10];
 
    //flag=0の場所が、ドロップが消えてなくなっている場所
    drop[0].flag = 1;
    drop[1].flag = 1;
    drop[2].flag = 0;
    drop[3].flag = 0;
    drop[4].flag = 0;
    drop[5].flag = 1;
    drop[6].flag = 1;
    drop[7].flag = 0;
    drop[8].flag = 0;
    drop[9].flag = 0;

	int phase = PHASE_FIXED;

    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
        //ここと下の部分のコメントを外すと、マウスが押されている時だけ動かせます
        //if(GetMouseInput() & MOUSE_INPUT_LEFT){
			switch (phase) {
			case PHASE_FIXED:
				{
					/*
					 * 固定時の処理
					 */
					for (int i=10-1; i>0; i--) {
						if (drop[i].flag == 0 && drop[i-1].flag == 1) {
							// 落下する玉を見付けて落下先に移動
							// アニメーション開始を設定
							drop[i].flag = 1;
							drop[i].drop_count = 30-3;
							drop[i-1].flag = 0;
							// 落下する玉が一個でも見付かったら遷移
							phase = PHASE_DROPPING;
						}
					}
				}
				break;
			case PHASE_DROPPING:
				{
					/*
					 * 落下中の処理
					 */
					phase = PHASE_FIXED; // 落下する玉がなくなったときの遷移先
					for (int i=0; i<10; i++) {
						if (drop[i].flag == 1) {
							// 落下中の玉のアニメーションを進行
							if (drop[i].drop_count > 0) {
								drop[i].drop_count -= 3;
								// 落下中の玉が一個でもあったら遷移しない
								phase = PHASE_DROPPING;
							}
						}
					}
				}
				break;
			}
        //}
        for(int i=0;i<10;i++){
			if (drop[i].flag == 1) {
				DrawCircle(100,30*i+15-drop[i].drop_count,15,GetColor(255,0,0),TRUE);
			}
        }
    }
    DxLib_End();
    return 0;
}

marn

Re: パズルゲームに自然なアニメーションを付けたい

#4

投稿記事 by marn » 7年前

1日放置してしまい、すみません

ISLe様に書いていただいたコードをほとんどそのまま流用して、なめらかに動くアニメーションを無事実装することができました
softya様に教えていただいた方法でも考えてみたのですが、なかなか難しくてこまっていたところでした


お二方とも素早く的確な回答をありがとうございました

また何かありましたらよろしくおねがいします

閉鎖

“C言語何でも質問掲示板” へ戻る