ページ 11

パネルの反転について

Posted: 2010年4月16日(金) 05:46
by 猫旅
前回、質問させて頂いた時に構造体で行った方が良いという
助言をいただいたので使って製作する方向に切り替えました。

取りあえずは選択した場所にパネルがあったら1⇒2⇒3と変化するようにソースを書こうと思います。
構造体を使わないで行えば問題なく反転できるのですが
使ってしまうと変な場所が反転されてしまいます。

構造体のメンバにNumという変数があり1~OBJ_MAXまで被らないように値がふってあります。
毎フレームこのNumの値を二次元配列に格納しそこからデータを呼び出しに行っております。

但し、変な部分が反転されてしまい非常に困っております。
ここで何十時間もつまづき正直、モチベーションが下がりまくってきております・・・。
何とか解決したいのですがお力添え願えないでしょうか。

Re:パネルの反転について

Posted: 2010年4月16日(金) 07:20
by conio
もう一度確認しますが、

カーソルがMap_01[2][2]の場所にあった場合、
下記の様に変化(反転)させたい、と言う事で宜しいでしょうか?
--------------------------------------------
int Map_01[CEL_H][CEL_W] = {
{0, 0,0,0, 0,0,0, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 0,0,0, 0,0,0, 0}
};



int Map_01[CEL_H][CEL_W] = {
{0, 0,0,0, 0,0,0, 0},

{0, 2,3,1, 1,2,3, 0},
{0, 1,3,2, 2,3,2, 0},
{0, 2,2,1, 2,3,2, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 1,2,3, 1,2,3, 0},
{0, 3,2,1, 2,3,2, 0},
{0, 1,1,3, 2,3,2, 0},

{0, 0,0,0, 0,0,0, 0}
};

--------------------------------------------
違うのであれば指摘してください。


あと、PLAYERクラスが持つメンバPazzとは何を表しているのでしょうか?
128個用意しているみたいなのですが。
----------------------------------------------------
#define OBJ_MAX 128
typedef struct{
bool Flg;
float Px,Py; // 位置座標
float Mx,My; // 移動速度
int Cx,Cy; // セル
int Ptn; // パターン
int Num; // ナンバー
}OBJECT;
OBJECT Pazz[OBJ_MAX];
----------------------------------------------------


あと、「構造体で実装したい」との事でしたが、
具体的に何を構造体にしようとしているのでしょうか?

PANEL型の構造体の2次元配列を作成して、その値を1→2→3と言う風に変えるというのでは
駄目なのでしょうか?

Re:パネルの反転について

Posted: 2010年4月16日(金) 08:15
by 猫旅
>>conio様
何度も本当に回答ありがとうございます。

>>PANEL型の構造体の2次元配列を作成して、その値を1→2→3と言う風に変えるというのでは
>>駄目なのでしょうか?
最初はそのように実装しておりました・・・。

最初は構造体なしに実装しておりました。
それで問題なく反転処理は動いておりました。
問題があったのは起動時に必ず32ドット落下してしまうということです。

しかしこちらで質問させて頂いた所、構造体でパネルの座標などを
持った方が良いと指摘して頂いたのでそれで実装しようとしております。

int Map_01[CEL_H][CEL_W]は初期化用の配列です。
PLAYERクラスが持つメンバPazzはパネル一つ一つの座標等を格納している構造体です。
取りあえずはカーソルの位置だけの反転をしてみようと思っております。

毎フレームPLAYERクラスが持つメンバのMapにそこにあるパネルのナンバーを入れていきます。

{0, 0,0,0, 0,0,0, 0},

{0, 1,2,3, 4,5,6, 0},
{0, 7,8,9, 10,11,12, 0}, ...

この数字を使って○番のパネルの構造体にアクセスするといったような仕様にしようと考えております。
しかし現在、添付させて頂いたソースでは変な位置のパネルが反転してしまいます。

Re:パネルの反転について

Posted: 2010年4月16日(金) 08:31
by conio
>>問題があったのは起動時に必ず32ドット落下してしまうということです。
それは多分、別の部分がおかしかったんだと思います。

とりあえず、反転するプログラムを作ってみたので実行してみてください。
これで一応 意図通りの動作にはなってないですか?

なってなかったらまた返信をお願いします。
---------------------------------------------------------------------------------
#include "DxLib.h"

int Key[256];
int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
else KeyStateBuf=0;
}
return 0;
}

#define MAP_W 8
#define MAP_H 12

enum MY_COLOR{
COL_WHITE,
COL_RED,
COL_BLUE,
COL_YELLOW,
COL_BLACK,
COL_MAX
};

DWORD c[COL_MAX];

struct PANEL{
int cNum;
int DifY;
int DifX;
PANEL(){
cNum = COL_BLUE;
}
};

PANEL panel[MAP_H][MAP_W];

struct Cursor{
int cNum;
int pX;
int pY;
Cursor(){
cNum = COL_WHITE;
pX = 1;
pY = 1;
}
};

Cursor cursor;

void SetColor(void)
{
c[COL_WHITE] = GetColor(255,255,255);
c[COL_RED] = GetColor(255,0,0);
c[COL_BLUE] = GetColor(0,0,255);
c[COL_YELLOW] = GetColor(255,255,0);
c[COL_BLACK] = GetColor(0,0,0);
}

void MoveCursor(void)
{
if(Key[KEY_INPUT_RIGHT] == 1)
{
if(cursor.pX + 1 < MAP_W - 1){
++cursor.pX;
}
}else if(Key[KEY_INPUT_LEFT] == 1)
{
if(cursor.pX - 1 > 0){
--cursor.pX;
}
}

if(Key[KEY_INPUT_UP] == 1)
{
if(cursor.pY - 1 > 0){
--cursor.pY;
}
}else if(Key[KEY_INPUT_DOWN] == 1)
{
if(cursor.pY + 1 < MAP_H - 1){
++cursor.pY;
}
}
}

void CheckReverse(void)
{
if(Key[KEY_INPUT_Z] == 1){
for(int i = cursor.pY - 1; i < cursor.pY + 2; i++){
for(int j = cursor.pX - 1; j < cursor.pX + 2; j++){
if(panel[j].cNum == COL_BLUE){
panel[j].cNum = COL_YELLOW;
}else if(panel[j].cNum == COL_YELLOW){
panel[j].cNum = COL_RED;
}else if(panel[j].cNum == COL_RED){
panel[j].cNum = COL_BLUE;
}
}
}
}
}

void DrawPanel(void)
{
for(int i = 0; i < MAP_H; i++){
for(int j = 0; j < MAP_W; j++){
DrawString(j*20, i*20, "●", c[panel[j].cNum]);
}
}
}

void DrawCursor(void)
{
DrawString(cursor.pX*20, cursor.pY*20, "□", c[cursor.cNum]);
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode( TRUE );

if(DxLib_Init() == -1 ) return -1;
SetDrawScreen( DX_SCREEN_BACK );

SetColor();

while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0 ){

MoveCursor();
CheckReverse();
DrawPanel();
DrawCursor();
ScreenFlip();
}
DxLib_End();
return 0;
}
---------------------------------------------------------------------------------
画像

Re:パネルの反転について

Posted: 2010年4月17日(土) 09:15
by 猫旅
サンプルソースまでありがとうございます。
そうです!!こんな感じに反転を行いたかったんです。

やはり構造体を使うやり方では理解できそうにないので
当初出来てた様に二次元配列を直接いじる組みなおしております。

3×3マスの反転ではなく取りあえずは選択したますのみ色が1⇒2⇒3の様に変化し
縦か横3マスが同じだったら消えて落下すると言った簡単なものにしようとしております。

落下はDropDown関数で行っているのですが
一度でも消える判定が入ってしまうと消えたパネルの
上にあるものが全て消えてしまうというバグが出てしまいました。

色々な部分を弄っては見たのですが直りません・・・。
お手数おかけして申し訳ないのですが今一度ご教授願えないでしょうか?

Re:パネルの反転について

Posted: 2010年4月17日(土) 18:14
by conio
まず、この消去する関数ですが、最初はi = 0, j = 0と代入されてますよね。
---------------------------------------------------------------------------------------------
void PLAYER::PazzleDisappear(){

int Check = 0;

for(int i=0; i<CEL_H; i++){
for(int j=0; j<CEL_W; j++){
for(int num=1; num<4; num++){

// 縦
if(Map[i-1][j].Flg && Map[j].Flg && Map[i+1][j].Flg){
if(Map[j].Ptn == num){
if(Map[i-1][j].Ptn == num) Check++;
if(Map[j].Ptn == num) Check++;
if(Map[i+1][j].Ptn == num) Check++;
}
}

// チェック
if(Check == 3){
if(Map[i-1][j].Ptn == num) Map[i-1][j].Flg = false;
if(Map[j].Ptn == num) Map[j].Flg = false;
if(Map[i+1][j].Ptn == num) Map[i+1][j].Flg = false;
Check = 0;
}else{
Check = 0;
}

/************** 中略 **************/
}
// 初期化
if(Map[j].Flg == false){
Map[j].Flg = false;
Map[j].Ptn = 0;
Map[j].Px = (float)j*32+48;
Map[j].Py = (float)i*32+16;
Map[i][j].Cx = int(Map[i][j].Px-48)/32;
Map[i][j].Cy = int(Map[i][j].Py-16)/32;
Map[i][j].ScaleX = 1.0f;
Map[i][j].ScaleY = 1.0f;
Map[i][j].Status = STATUS_NORMAL;
}
}
}
}
---------------------------------------------------------------------------------------------


で、次の条件文のところですが、
---------------------------------------------------------
// 縦
if(Map[i-1][j].Flg && Map[i][j].Flg && Map[i+1][j].Flg){
---------------------------------------------------------
iが0の時どうなるでしょう?


それと、CEL_H = 5と仮定します。
for文でiを増やすとなると範囲は 0~4となりますね。
では、i == 4の時、3番目の条件はどうなるでしょうか?
---------------------------------------------------------
// 縦
if(Map[i-1][j].Flg && Map[i][j].Flg && Map[i+1][j].Flg){
---------------------------------------------------------

いずれも範囲外アクセスとなります。

2次元配列の場合、添え字が範囲外アクセスすると、
2次元配列内の予想外の場所が書き換わる可能性があります。

例えば、int map[3][3]; という2次元配列があるとすると、 map[0][3] = 10;と指定した場合、
map[1][0]の値が10になります。

なんでこうなるか、というと
メモリ上は 2次元配列の次の要素が連続して並んでいるからです。
-------------------------------------------
//メモリ上の配列の並び
┃map[0][0]
┃map[0][1]
┃map[0][2]
┃map[1][0] == map[0][3]
┃map[1][1] == map[0][4]
┃map[1][2] == map[0][5]
┃map[2][0] == map[0][6] == map[1][3]
┃map[2][1] == map[0][7] == map[1][4]
▼map[2][2] == map[0][8] == map[1][5]
-------------------------------------------

なので、範囲外アクセスして内部の値が無茶苦茶になっている可能性があります。 画像"編集済み]

Re:パネルの反転について

Posted: 2010年4月17日(土) 22:06
by 猫旅
何度も回答ありがとうございます。
ご指摘ありがとうございます。
間違えておりました><助かりました。

全ては消えなくなったのですがやはりパネルが落ちてきてくれません・・・。
Drop関数が行けないのでしょうか・・・。

Re:パネルの反転について

Posted: 2010年4月17日(土) 23:22
by conio
んー。 main関数の部分が無いのでなんとも。
とりあえず、初期化する関数を毎回呼び出してたりしないか確認してみてください。

それと描画するこの部分ですが、やり方がマズいです。
---------------------------------------------------------------------------------------
if(Play01.Map[j].Ptn == 1) DrawAlphaScale( Px, Py, Handle.Paz01, 0xff, Sx, Sy );
if(Play01.Map[j].Ptn == 2) DrawAlphaScale( Px, Py, Handle.Paz02, 0xff, Sx, Sy );
if(Play01.Map[j].Ptn == 3) DrawAlphaScale( Px, Py, Handle.Paz03, 0xff, Sx, Sy );
if(Play01.Map[j].Ptn == 4) DrawAlphaScale( Px, Py, Handle.Paz04, 0xff, Sx, Sy );
---------------------------------------------------------------------------------------
パネルの種類が増えるたびにif文が増えていきます。

【解決策】
Play01.Map[j].Ptnをハンドルの配列の添え字として使ってください。

【やり方】
・ハンドルを配列にして、それぞれの画像のハンドルを得ます。
---------------------------
Handle[0] = 青パネルの画像
Handle[1] = 黄パネルの画像
Handle[2] = 赤パネルの画像
Handle[3] = 緑パネルの画像
---------------------------

・Play01.Map[j].Ptnを添え字として使います。
-------------------------------------------------------------------------
DrawAlphaScale( Px, Py, Handle[Play01.Map[j].Ptn], 0xff, Sx, Sy );
-------------------------------------------------------------------------
この一行で全てのptnに対応できます。




あと、この部分はTrueにしてないような・・・?
-----------------------------------------------------
// 動いた箇所があったので、検査結果フラグをtrueにする
Map[j].Py += 32;
-----------------------------------------------------

最後に、落下&消去するプログラムを書いてみました。
参考にしてみて下さい。

あと意味が分からない所があれば言ってください。

【追記】
一部ソースコードを修正しました。(CheckVanish関数の部分) 画像