ページ 11

クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月19日(月) 14:51
by KEYONN_
こんにちは、TKOZです。
また、クォータービューで分からない所が出てきました。
それは、移動範囲を求め、表示し、クリックした座標へ移動する処理の事です。
VBのサンプルでKone's D Stationというサイトのサンプルを参考にやっているのですが、
うまくいきません。

とりあえず、プログラム本体とは切り離して、サンプルをとりあえず、クォータービューではなく、
矩形(くけい)のマスで計算し、移植しているのですが、上手くいきません。

具体的には、Timer1_Timer()の処理や、Command1.enableの値をどうするのか分かりません。

Cに移植したソースを載せます。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<time.h>
#include"DxLib.h"
#include<windows.h>

int MX,MY;//キャラ座標
int FPX[7];int FPY[7];int Way;//移動経路座標と移動するマス数
int ImageBG,ImageChara;
Part Parts[9][9];//各地形

void Command1_Click();
void MoveAreaPaint();
class T{
public:
bool Enabled;//フラグ
int Interval;
int NowTime;
T()
{
Enabled=false;
Interval=0;
NowTime=0;
}
void SetTimer1_Timer()
{
NowTime=GetTickCount();
}
int GetTimer1_Timer()
{
if(Enabled==true && Interval>0)
{
if(GetTickCount()-NowTime>Interval)
{
NowTime=GetTickCount();
Timer1_Timer();
}
}
}
void Timer1_Timer()
{
DrawBox(FPX[Way]*32,FPY[Way]*32,
FPX[Way]*32+32,FPY[Way]*32+32,GetColor(255,255,0),TRUE);
Way--;
if(Way==-1)
{
MX=FPX[0];
MY=FPY[0];
Way=0;
Enabled =false;
MoveAreaPaint();
Command1_Click();
}
}

};

void MoveAreaPaint()
{
int a,b,c,d;

for(a=0;a<9;a++)
{
for(b=0;b<9;b++)
{
DrawRectGraph(a*32,b*32,
(Parts[a].PType/2)*32,(Parts[a].PType%2)*32,
32,32,ImageBG,FALSE,FALSE);
Parts[a].FPointX =0;
Parts[a].FPointY = 0;
Parts[a].LMPoint = 0;
}
}

//メイン判定ルーチン
Parts[MX][MY].LMPoint = 7;
for(c=1;c<=7;c++)
{
for(a=MX-c;a<=MX+c;a++)
{
for(b=(7-abs(MX-a));b<=abs(7-abs(MX-a));b++)
{
if( a>=0 && a<10 && b>=0 && b<10)
{
//左側判定
if(a>=0)
{
if(Parts[a].MPoint <= Parts[a - 1].LMPoint && Parts[a].LMPoint <= Parts[a - 1].LMPoint - Parts[a].MPoint)
{
Parts[a][b].LMPoint = Parts[a - 1][b].LMPoint - Parts[a][b].MPoint;
Parts[a][b].FPointX = -1;
Parts[a][b].FPointY = 0;
}
}
//右がわ判定
if (a < 9)
{
if (Parts[a][b].MPoint <= Parts[a + 1][b].LMPoint && Parts[a][b].LMPoint <= Parts[a + 1][b].LMPoint - Parts[a][b].MPoint)
{
Parts[a][b].LMPoint = Parts[a + 1][b].LMPoint - Parts[a][b].MPoint;
Parts[a][b].FPointX = 1;
Parts[a][b].FPointY = 0;
}
}

//上がわ判定
if( b >= 0)
{
if (Parts[a][b].MPoint <= Parts[a][b - 1].LMPoint && Parts[a][b].LMPoint <= Parts[a][b - 1].LMPoint - Parts[a][b].MPoint)
{
Parts[a][b].LMPoint = Parts[a][b - 1].LMPoint - Parts[a][b].MPoint;
Parts[a][b].FPointX = 0;
Parts[a][b].FPointY = -1;
}
}
//下がわ判定
if (b < 9)
{
if (Parts[a][b].MPoint <= Parts[a][b + 1].LMPoint && Parts[a][b].LMPoint <= Parts[a][b + 1].LMPoint - Parts[a][b].MPoint)
{
Parts[a][b].LMPoint = Parts[a][b + 1].LMPoint - Parts[a][b].MPoint;
Parts[a][b].FPointX = 0;
Parts[a][b].FPointY = 1;
}
}
}
}
}
}

for(a=0;a<9;a++)
{
for(b=0;b<9;b++)
{
if(Parts[a][b].FPointX!=0 || Parts[a][b].FPointY!=0)
{
DrawBox(a*32,b*32,a*32+32,b*32+32,GetColor(255,0,0),FALSE);
}
}
}
DrawBox(MX*32,MY*32,MX*32+32,MY*32+32,GetColor(255,255,255),TRUE);
}



画像

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月19日(月) 14:51
by KEYONN_
void Command1_Click()
{
int a,b,temp;

for(a=0;a<9;a++)
{
for(b=0;b<9;b++)
{
temp=rand()%10;
if(temp<=5)
{
Parts[a].PType=0;//平地
Parts[a].MPoint =1;
}
else if(temp>5 && temp<=7)
{
Parts[a].PType=1;//森
Parts[a].MPoint =2;
}
else if(temp>7 && temp<8)
{
Parts[a].PType =2;//砂漠
Parts[a].MPoint =4;
}
else{
Parts[a].PType =3;
Parts[a].MPoint =8;//必要移動力を大きな数にすれば移動不能点になる
}

}
}

MX=rand()%10;
MY=rand()%10;
MoveAreaPaint();
}
T Timer1;
void Init()
{
srand(time(NULL));
Command1_Click();
Timer1.Interval=200;
ImageBG=LoadGraph("./BG.png");
if(ImageBG!=-1)
MessageBox(NULL,"OK!","OK",MB_OK);
ImageChara=LoadGraph("./Chara.png");
}

void MouseDown(int X,int Y)
{
if(Timer1.Enabled ==true) return;

if(Parts[X/32][Y/32].FPointX==0 && Parts[X/32][Y/32].FPointY==0)
return;

int a,b,c;

a=X/32;
b=Y/32;
FPX[0]=a;
FPY[0]=b;
c=0;

//逆向きで経路を探す
do{
c++;
a+=Parts[a].FPointX;
b+=Parts[a].FPointY;
FPX[c]=a;
FPY[c]=b;
}while(a!=MX && b!=MY);

Way=c;
Timer1.Enabled =true;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode( TRUE );
SetGraphMode(32*10 ,32*10 ,32 ) ;
ChangeWindowMode(TRUE) ;
SetMainWindowText("SLG 移動処理win32") ;
if(DxLib_Init() == -1 ) return -1;
SetDrawScreen( DX_SCREEN_BACK );

Init();

while(ProcessMessage()==0 && !CheckHitKey(KEY_INPUT_ESCAPE)){
static int X,Y;
GetMousePoint(&X,&Y);
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 )
{
//ClearDrawScreen();
MouseDown(X,Y);
// 押されている
}
else if(( GetMouseInput() & MOUSE_INPUT_RIGHT)!=0)
{
// 押されていない
ClearDrawScreen();
Command1_Click();
}
//Timer1.Timer1_Timer();


ScreenFlip();
}
DxLib_End();
return 0;

}

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月21日(水) 09:43
by ookami
誰もレスしてないようなので...

もうちょっと補足しないと回答が集まらないと思います。
例えば...
 ・どこが判定部分かよく分かりません。
   「//メイン判定ルーチン」のような気もしますが
   「MoveAreaPaint()」の中だし、ホントにここかなぁ...とか。
   3重forループだけどカウンタ a,b,c の意味が分からない、とか。
 ・各変数の意味がよく分かりません。
   Partの中身とか、
   int FPX[7];int FPY[7];int Way;//移動経路座標と移動するマス数
   の「移動経路座標」というのもよく分かりません。
   「Command1.enableの値をどうするのか分かりません」と言われても、
   その変数をどういうつもりで使うのかが分からなければ、何とも言えません。
   (enableそのものは、VBなら ボタンの有効/無効(灰色表示でクリックできなくする)のフラグです。)
 ・テスト用のコード?
   MX=rand()%10;
   MY=rand()%10;
   では、「自分の座標をランダムに移動する」と言うことだと思いますが、
   たぶんテスト用のコードなんですよね。

など、まぁ全体的に分かりにくくてレスが無いんだろうなと。
がんばってくださいw

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月21日(水) 23:03
by Poco
元のソースは何処にあります?

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月22日(木) 16:42
by KEYONN_
ここです。
ttp://kone.vis.ne.jp/program/#sample10
(先頭のhを抜いてあります)

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月22日(木) 19:45
by softya
参考になりそうなサイトを紹介しておきます。
「シミュレーションゲーム作成工房」
http://www.jyouhoukaiseki.com/
こちらもVB,VBAのサイトです。説明が丁寧なので分かりやすいと思います。

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月23日(金) 01:05
by Poco
> ここです。
> ttp://kone.vis.ne.jp/program/#sample10
> (先頭のhを抜いてあります)

提示ありがとうございます。
今日の夜に見てみます。

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月23日(金) 23:03
by Poco
とりあえず、自分なりに直してみました。
元プログラムを動かせなかったので、多分こうだろうなぁと、
想像していますんで、期待と違っていたらすみません。

あと、かなりバギーな作りになっております。

#というのも、TKOZさんの移植プログラムをとVBの元ソース見ながら、
#私が想像で書き直したので、現状、何処に原因があるか絞り込みづらい状況です^^;

まあ、それでも雰囲気はつかめると思います。。

取り敢えず、中間報告ってことで。
#最終報告は期待しないでください。諦めるかもしれないんで。

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月24日(土) 00:45
by Poco
多分、完成です。

----追記

私が1箇所(2箇所だったかな?)、配列の範囲ミスをしてました。
TKOZさんは1箇所、移動経路検索処理でのdo-while文の継続条件が間違ってました。

----追記2
#質問に答えてなかった。。

Command1_Click()は単純にマップの初期化と一番最初の表示を行っているだけだったので、
初期化ルーチンInit()に組むこみました。

Timer1_Timer()は、200ミリごとにVBのランタイムから呼ばれ、キャラ移動時に経路を順に表示する処理を行っています。

Timer1_Timer()はVBのランタイムが呼び出すタイミングを図ってくれるのですが、
DXライブラリには(私が知る限り)そういうことができるフレームワークが無いので、
自分でタイミングを図ってTimer1_Timer()が行っている処理を実行する必要があります。

なので、私が提示したソースコードでTimer1_Timer()に該当する関数、GetNextPart()の内部に
カウンタを用意し、一定カウントを超えた場合に実際の処理を行っています。
画像

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月24日(土) 01:22
by Poco
う~ん、まだちょっとバギーな感じです。
#いろんな配列の境界を間違っているのがアリアリなんですが。。
大体の方向性は示せていると思うので、申し訳ありませんが、これ以上は修正しません。

Re:クォータービューの移動範囲を求め、移動するアルゴリズムについて

Posted: 2010年7月24日(土) 21:51
by KEYONN_
ぽこさんへ

サンプルの動作確認しました。ありがとうございます。
これを基にして、クォータービューに実装していきたいと思います。