移動範囲について

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

移動範囲について

#1

投稿記事 by ZP » 7年前

こんにちは。この度C++の勉強も兼ねて、シンプルなシミュレーションゲームを作成しようと考えているのですが、移動範囲の捜索が思ったような動作をしません。
ユニットのクリックをすると、選択状態になり、移動範囲が表示される仕組みにしましたが、移動後同じユニットを選択すると、選択範囲がズレて表示される現象が起きています。

コード:

//main.cpp
#include "DxLib.h"
#include "Unit.h"

#define WIDTH 640
#define HEIGHT 480
#define CHIPSIZE 32
#define GRIDW WIDTH / CHIPSIZE	//20
#define GRIDH HEIGHT / CHIPSIZE       //15

#define WHITE GetColor(255, 255, 255)
#define RED GetColor(255, 0, 0)
#define GREEN GetColor(0, 255, 0)
#define BLUE GetColor(0, 0, 255)
#define MBOX(text) MessageBox(NULL, text, "ERROR", MB_OK)

int Key[256];
int mouseX, mouseY;
int gridX, gridY;
int keepX, keepY;

int map[GRIDH][GRIDW];
int map_move[GRIDH][GRIDW] = {{-1, -1, -1....}};

int state_unit;
int sel;
int mouse_left_before = 0;
int mouse_left_after;
int mouse_right_before = 0;
int mouse_right_after;

enum{
	STATE_UNIT_NORMAL,
	STATE_UNIT_SELECT,
	STATE_UNIT_MOVED
};

enum{
	OPERATE_NULL,
	OPERATE_LEFT,
	OPERATE_RIGHT,
	OPERATE_LEFT_RIGHT,
	OPERATE_MIDDLE,
	OPERATE_LEFT_MIDDLE,
	OPERATE_MIDDLE_RIGHT,
	OPERATE_LEFT_RIGHT_MIDDLE
};

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

int Draw(){
	for(int i=0; i<GRIDH*CHIPSIZE; i+=CHIPSIZE){
		for(int j=0; j<GRIDW*CHIPSIZE; j+=CHIPSIZE){
			switch(map[i/CHIPSIZE][j/CHIPSIZE]){
			case 0:
				DrawBox(j, i, j+CHIPSIZE, i+CHIPSIZE, WHITE, 1);
				break;
			case 1:
				DrawBox(j, i, j+CHIPSIZE, i+CHIPSIZE, GREEN, 1);
				break;
			}
		}
	}
	return 0;
}

void Inisialize_Map_Move(){
	for(int i=0; i<GRIDH; i++){
		for(int j=0; j<GRIDW; j++){
			map_move[i][j] = -1;
		}
	}
}
以下がメイン関数です。

コード:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
	/* --------------------------------------------------------------------------------------------- */
	/* 初期化--------------------------------------------------------------------------------------- */
	/* --------------------------------------------------------------------------------------------- */
	ChangeWindowMode(true), SetGraphMode(WIDTH, HEIGHT, 32);

    if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){
		MBOX("初期化に失敗しました。");
		return -1;
	}
	Unit *unit;
	unit = new Unit[3];
	unit[0].Input("プレイヤー1", 2, 1, 1);
	unit[1].Input("プレイヤー2", 2, 2, 2);
	unit[2].Input("プレイヤー3", 2, 10, 10);

	state_unit = STATE_UNIT_NORMAL;
	/* --------------------------------------------------------------------------------------------- */
	/* メインループ--------------------------------------------------------------------------------- */
	/* --------------------------------------------------------------------------------------------- */
    while(ProcessMessage() == 0 && ClearDrawScreen() == 0 && GetHitKeyStateAll_2(Key) == 0 && Key[KEY_INPUT_ESCAPE] == 0){
		/* 各値の更新----------------------------------------------------------------------------------- */
		GetMousePoint(&mouseX, &mouseY);
		gridX = mouseX / CHIPSIZE;
		gridY = mouseY / CHIPSIZE;
		mouse_left_after = GetMouseInput() & MOUSE_INPUT_LEFT;
		mouse_right_after = GetMouseInput() & MOUSE_INPUT_RIGHT;

		Draw();
		for(int i=0; i<3; i++)
			unit[i].Draw();
		/* --------------------------------------------------------------------------------------------- */
		/* ユニットステップ----------------------------------------------------------------------------- */
		/* --------------------------------------------------------------------------------------------- */
		switch(state_unit){
		/* 非選択状態----------------------------------------------------------------------------------- */
		case STATE_UNIT_NORMAL:
			DrawString(0, 0, "ユニット未選択状態です。", RED);
			if(mouse_left_before == 0 && mouse_left_after == OPERATE_LEFT){
				for(int i=0; i<3; i++){
					if(unit[i].unitX == gridX && unit[i].unitY == gridY && unit[i].move == false){
						sel = i;
						unit[sel].SearchCourse(unit[sel].unitX, unit[sel].unitY, unit[sel].movement);
						keepX = unit[sel].unitX;
						keepY = unit[sel].unitY;
						state_unit = STATE_UNIT_SELECT;
						break;
					}
				}
			}
			break;

		/* 選択状態------------------------------------------------------------------------------------- */
		case STATE_UNIT_SELECT:
			DrawString(0, 0, "ユニット選択状態です。", RED);
			unit[sel].DrawRoot();
			if(mouse_left_before == 0 && mouse_left_after == OPERATE_LEFT){
				if(map_move[gridX][gridY] > -1){
					unit[sel].unitX = gridX;
					unit[sel].unitY = gridY;
					state_unit = STATE_UNIT_MOVED;
				}
			}
			if(mouse_right_before == 0 && mouse_right_after == OPERATE_RIGHT){
				Inisialize_Map_Move();
				state_unit = STATE_UNIT_NORMAL;
			}
			break;

		/* 移動後の状態--------------------------------------------------------------------------------- */
		case STATE_UNIT_MOVED:
			DrawString(0, 0, "移動しました。", RED);
			DrawString(0, 16, "左クリック=>この場に留まる", RED);
			DrawString(0, 32, "右クリック=>キャンセル", RED);
			if(mouse_left_before == 0 && mouse_left_after == OPERATE_LEFT){
				//unit[sel].move = true;
				Inisialize_Map_Move();
				state_unit = STATE_UNIT_NORMAL;
			}
			if(mouse_right_before == 0 && mouse_right_after == OPERATE_RIGHT){
				unit[sel].unitX = keepX;
				unit[sel].unitY = keepY;
				state_unit = STATE_UNIT_SELECT;
			}
			break;
		}
		
		mouse_left_before = mouse_left_after;
		mouse_right_before = mouse_right_after;

		ScreenFlip();
	}
    DxLib_End();

    return 0;
}
ヘッダファイルです。まだ全然勉強足らずなので、クラスの書き方や、defineの書く場所が合っているのか非常に不安です・・・ミスがあったら指摘してくださると嬉しいです。

コード:

//Unit.h
#include "DxLib.h"

#define WIDTH 640
#define HEIGHT 480
#define CHIPSIZE 32
#define GRIDW WIDTH / CHIPSIZE
#define GRIDH HEIGHT / CHIPSIZE
#define WHITE GetColor(255, 255, 255)
#define BLACK GetColor(0, 0, 0)
#define RED GetColor(255, 0, 0)
#define GREEN GetColor(0, 255, 0)
#define BLUE GetColor(0, 0, 255)
#define MBOX(text) MessageBox(NULL, text, "ERROR", MB_OK)

class Unit{
public:
	//メンバ変数
	char *name;
	int movement;
	int unitX;
	int unitY;
	bool move;
	//メンバ関数
	Unit(){};
	Unit(char *n, int x, int y);
	void Draw();
	void Input(char *n, int m, int x, int y);
	void SearchCourse(int x, int y, int m);
	void Search(int x, int y, int m);
	void DrawRoot();
};
unit.cppです。恐らくここのSearchCourseやSearchに問題があると思われます・・・。

コード:

//Unit.cpp
#include "Unit.h"


extern int map_move[GRIDH][GRIDW];

Unit::Unit(char *n, int x, int y) : name(n), unitX(x), unitY(y) {};


void Unit::Draw(){
	if(move == false)
		DrawBox(unitX*CHIPSIZE, unitY*CHIPSIZE, unitX*CHIPSIZE+CHIPSIZE, unitY*CHIPSIZE+CHIPSIZE, RED, 1);
	else
		DrawBox(unitX*CHIPSIZE, unitY*CHIPSIZE, unitX*CHIPSIZE+CHIPSIZE, unitY*CHIPSIZE+CHIPSIZE, BLUE, 1);
};

void Unit::Input(char *n, int m, int x, int y){
	name = n;
	movement = m;
	unitX = x;
	unitY = y;
	move = false;
};

void Unit::SearchCourse(int x, int y, int m){
	Search(x, y-1, m);
	Search(x+1, y, m);
	Search(x, y+1, m);
	Search(x-1, y, m);
}
void Unit::Search(int x, int y, int m){
	if(x >= 0 && x <= GRIDW && y >= 0 && y <= GRIDH){
		m--;
		if(m > map_move[x][y])
			map_move[x][y] = m;
		if(m > 0) SearchCourse(x, y, m);
	}
	else
		return;
};

void Unit::DrawRoot(){
	for(int i=0; i<GRIDH; i++){
		for(int j=0; j<GRIDW; j++){
			if(map_move[i][j] > -1){
				DrawBox(j*CHIPSIZE, i*CHIPSIZE, j*CHIPSIZE+CHIPSIZE, i*CHIPSIZE+CHIPSIZE, BLACK, 0);
			}
		}
	}
}

ZP

Re: 移動範囲について

#2

投稿記事 by ZP » 7年前

画像
右下の赤いユニットは本来2マス下にあったのですが、上に2マス移動した状態(画像の状態)でユニットを選択すると、
移動範囲の黒い四角が左に2マスずれてしまいます。初回時は上手くいくのですが・・・

ホヅミ
記事: 110
登録日時: 9年前

Re: 移動範囲について

#3

投稿記事 by ホヅミ » 7年前

ずれ方に規則性があるみたい。
1次と2次の配列の添え字が逆になってたり、表示する座標のX,Yが逆だったりと
そのへんを見てみてはいかがでしょうか?

ZP

Re: 移動範囲について

#4

投稿記事 by ZP » 7年前

コード:

void Unit::DrawRoot(){
	for(int i=0; i<GRIDH; i++){
		for(int j=0; j<GRIDW; j++){
			if(map_move[i][j] > -1){
				DrawBox(i*CHIPSIZE, j*CHIPSIZE, i*CHIPSIZE+CHIPSIZE, j*CHIPSIZE+CHIPSIZE, BLACK, 0);
			}
		}
	}
}
ここのDrawBoxのiとjが逆だったんですね・・・ものすごくつまらないミスでした。
ホヅミさんありがとうございました。

閉鎖

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