マップチップを配置するタイプのマップ、タイルマップを表示できるようにしました。
そのクラス設計? を見ていただきたいです。このような質問の仕方をしてもいいでしょうか。
シングルトンを使うメリットが分からなかったため、呼び出しやすい名前空間を使ってみました。
今のところ問題は出ていませんが、このような書き方をした例を見たことがないので、不安になっています。
ソースについて、自分で気付いたこととしては、
//とりあえず読み飛ばして大丈夫
・名前空間のMapDataという名前がややこしい。(データだけではなくて、機能も入っている)
・MapData::MapLayer この名前が不適切。(layerという名前のレイヤ構造体と、関数を持つ)
・MapData::MapLayer::layer[0] と書くのが面倒くさい
・MapData::EventDataに、キャラ画像の描画用の補正座標が入っているのは不適切?
他に質問させていただきたいこととしては、
・namespaceとsingletonはどちらを使うべきだと考えられるでしょうか
・このような設計? について学べる本で、お勧めはありますか
以下ソースです。よかったら「こう組んだ方が良い」などの指摘などをお願いしたいです。
//map.h
► スポイラーを表示
class MapBase
{
//レイヤとして機能するクラスの基底クラス
//表示方法を変えるために、多態性を使う可能性有り
public:
//setter
virtual void Initialize(int width,int height,int thisLayerNum) = 0;
virtual void FreeThisLayer() = 0;
//from control
virtual void DrawMap() = 0;
virtual void ScrollUpdate() = 0;
//from actor, dungeon generation
virtual bool IsPassable(int,int) = 0;
virtual void SetCell_chipID(int,int,int) = 0;
virtual ~MapBase() = 0 {}//純粋仮想デストラクタ:定義が必要 (= 0 では仮想関数であることを示すだけ)
};
namespace MapTree
{
void LoadMapTree();//全マップファイルのパス等を構造体に得る ゲーム開始時に実行
}
namespace MapData
{
//loader
void LoadMap(int mapID);
void DeleteMap();
//マップ情報を受けて
int GetCellID(int x,int y);
bool IsInsideMap(int x, int y);
//この2つは、多態性の代わりに分岐を使う。(多態性を使いたかった)。
//MapBaseから派生するクラスはレイヤとして機能するが、
//これら2つの関数はレイヤの機能ではないと考えたたため、ここに置いた。
void ToScreen(int,int,int*,int*,int changePoint = 1,int onMap = 0);//デフォルト引数はオウヴァロード前の値になる、注意
void ToCell(int,int,int*,int*);//【警告】絶対位置を引数に取る
//メンバ変数のカプセル化
bool IsQMap();
void GetMapSize(int *width, int *height);
int GetAllLayerNum();
void GetScroll(int *x,int *y);
void SetScroll(int x, int y);
//layer
namespace MapLayer
{
extern MapBase *layer[3];
//3レイヤを見る関数
bool IsPassable(int x,int y);
//fovLayer
void ResetVisible();
void SetVisible(int x,int y,bool visible);
bool IsVisible(int x,int y);
}
//マップ上への描画位置の補正用 from actor
//ここに置くべきか?
namespace EventData
{
int GetEventsNum();
void GetCharaShift(int *x,int *y);
}
}
► スポイラーを表示
struct MapDataStruct//MapTree用
{
char mapName[30];
char mapFile[30];
int tileID; int BGM; int BGS;
};
struct TileSetsStruct//MapTree用
{
char tileFile[30];
char tileGraph[30];
};
namespace MapTree
{
MapDataStruct mapDatas[10];
TileSetsStruct tileSets[10];
void LoadMapTree();
}
namespace MapData
{
//Map情報(マップ毎の定数)
int mapWidth,mapHeight; void GetMapSize(int *width, int *height){*width = mapWidth; *height = mapHeight;}
int allLayerNum = 3; int GetAllLayerNum(){return(allLayerNum);}
//MapLoader
void LoadMap(int mapID);
void DeleteMap()
{
for(int i = 0; i < allLayerNum; i++)
{
delete MapLayer::layer[i];//下の名前空間の中身にアクセスしてしまっている
}
}
//定数を受けて
bool IsInsideMap(int x, int y)
{
if(x >= 0 && x < mapWidth &&
y >= 0 && y < mapHeight )
{
return(TRUE);
}else
{
return(FALSE);
}
}
int GetCellID(int x,int y){return(y*mapWidth + x);}
void ToScreen(int,int,int*,int*,int changePoint,int onMap);//デフォルト引数はオウヴァロード前の値になる、注意
void ToCell(int,int,int*,int*);//【警告】絶対位置を引数に取る
//描画用定数
bool isQMap; bool IsQMap(){return(isQMap);}
int mapShiftX,mapShiftY;
int minScrollX,minScrollY;
int maxScrollX,maxScrollY;
//QMap用
int leftSpace,rightSpace,upSpace,downSpace;
//一時情報
int scrollX,scrollY;
void GetScroll(int *x,int *y){*x = scrollX; *y = scrollY;}
void SetScroll(int x, int y)
{
if(maxScrollX < x) x = maxScrollX;
if(minScrollX > x) x = minScrollX;
if(maxScrollY < y) y = maxScrollY;
if(minScrollY > y) y = minScrollY;
scrollX = x; scrollY = y;
}
namespace TileData
{
int tileID;
int *traffic;
char *tileGraph;
int cellWidth,cellHeight;
int tileWidth,tileHeight;//ピクセル
int *tileDiv;
//QMap用
int qCellWidth,qCellHeight;
}
namespace MapLayer
{
//layers
MapBase *layer[3];
bool IsPassable(int x,int y)//全レイヤを見て返す
{
if( IsInsideMap(x,y) == FALSE ) return(0);
int result = 0;
for(int i = 0; i < allLayerNum; i++)
{
result += layer[i]->IsPassable(x,y);
}
if( result == allLayerNum) return(TRUE);//全て通行可能タイル
else return(FALSE);//少なくとも1つが通行不能タイル
}
bool *isVisible;
void ResetVisible()//使わない?
{
int num = mapWidth * mapHeight;
for(int i = 0; i < num; i++)
{
isVisible[i] = 0;
}
}
void SetVisible(int x,int y,bool visible)
{
isVisible[ GetCellID(x,y) ] = visible;
}
bool IsVisible(int x,int y)
{
return( isVisible[ GetCellID(x,y) ] );
}
}
//Event 描画座標の補正用変数はここにおくべきではない?
namespace EventData
{
int charaShiftX,charaShiftY;
int eventsNum;
void GetCharaShift(int *x,int *y){*x = charaShiftX; *y = charaShiftY;}
}
}