RPGツクール風のマップ描画
Posted: 2012年1月15日(日) 12:03
課題が出ました。
マップチップ配置データを基にマップを描画するコードを下記の条件および手順にしたがって説明をしてください。
1.プログラム1のマップ描画コードはまだ部分描画を行うためのコードが実装されていません。そこでまず下記の プログラム1のマップ描画コード を使って、マップ全体をマップ表示領域に描画するコードの説明をしてください。
2.プログラム2のマップ描画コードには部分描画を行うためのコードが実装されています。そこで次は下記の プログラム2のマップ描画コード を使って、新たに追加されたコードに着目してマップの一部分をマップ表示領域に描画するコードの説明をしてください。
とのことです。
やっていることは分かるのですが、うまく説明できず、採点もからめです。
~プログラム1~
~プログラム2~
~これらのヘッダー~
うまく僕に説明する感じで答えていただけるとありがたいです。
マップチップ配置データを基にマップを描画するコードを下記の条件および手順にしたがって説明をしてください。
1.プログラム1のマップ描画コードはまだ部分描画を行うためのコードが実装されていません。そこでまず下記の プログラム1のマップ描画コード を使って、マップ全体をマップ表示領域に描画するコードの説明をしてください。
2.プログラム2のマップ描画コードには部分描画を行うためのコードが実装されています。そこで次は下記の プログラム2のマップ描画コード を使って、新たに追加されたコードに着目してマップの一部分をマップ表示領域に描画するコードの説明をしてください。
とのことです。
やっていることは分かるのですが、うまく説明できず、採点もからめです。
~プログラム1~
bool Map::draw(const Scene * const scene, const LPD3DXSPRITE & lpSprite) const
{
const GameScene * const gameScene = dynamic_cast<const GameScene *> (scene);
const Virgo16::Rectangle<int> mapArea(gameScene->frame->getMapArea());
const Virgo16::Rectangle<int> src(mapArea.getSize());
const Virgo16::Rectangle<int> dst(mapArea);
if (!drawPartially(lpSprite, src, dst)) {
WriteErrorLog(__FUNCTION__, "drawPartially()");
return false;
}
return true;
}
bool Map::drawPartially(const LPD3DXSPRITE lpSprite, const Virgo16::Rectangle<int> & src, const Virgo16::Rectangle<int> & dst) const
{
const int left = src.left / info.chipSize.width;
const int top = src.top / info.chipSize.height;
const int right = src.right / info.chipSize.width; //マップの大きさ(チップの枚数)
const int bottom = src.bottom / info.chipSize.height; //マップの大きさ(チップの枚数)
//マップ描画
for (int r = top; r < bottom; r++) {
for (int c = left; c < right; c++) {
const int k = r * info.col + c; //vectorの番号
const int chip = info.data[k]; //vectorに入ってるマップの番号(0~b)
if (chip < 0) {
continue;
}
int y = chip / info.chipCol; //チップの番号
int x = chip - y * info.chipCol; //チップの番号
y *= info.chipSize.height; //チップの位置
x *= info.chipSize.width; //チップの位置
Virgo16::Rectangle<int> rectangle(Virgo16::Point<int>(x, y), info.chipSize); //x,y~32切り取り
Virgo16::Point<int> point(c * info.chipSize.width, r * info.chipSize.height); //描画位置
point.translate(dst.left, dst.top); //描画位置を真ん中に
if (!(*texture)->draw(lpSprite, rectangle, point)) {
WriteErrorLog(__FUNCTION__, "(*texture)->draw()");
return false;
}
}
}
bool Map::draw(const Scene * const scene, const LPD3DXSPRITE & lpSprite) const
{
const GameScene * const gameScene = dynamic_cast<const GameScene *> (scene);
const Virgo16::Rectangle<int> mapArea(gameScene->frame->getMapArea());
const Virgo16::Rectangle<int> dst(mapArea);
Virgo16::Rectangle<int> src(mapArea.getSize());
src.translate(point.x, point.y);
if (!drawPartially(lpSprite, src, dst)) {
WriteErrorLog(__FUNCTION__, "drawPartially()");
return false;
}
return true;
}
bool Map::drawPartially(const LPD3DXSPRITE lpSprite, const Virgo16::Rectangle<int> & src, const Virgo16::Rectangle<int> & dst) const
{
const int left = src.left / info.chipSize.width;
const int top = src.top / info.chipSize.height;
const int right = (src.right + info.chipSize.width - 1) / info.chipSize.width; // src.right / info.chipSize.width (切り上げ)
const int bottom = (src.bottom + info.chipSize.height -1) / info.chipSize.height; // src.bottom / info.chipSize.height (切り上げ)
const int lmargin = src.left - left * info.chipSize.width; // src.left % info.chipSize.width
const int tmargin = src.top - top * info.chipSize.height; // src.top % info.chipSize.height
for (int r = top; r < bottom; r++) {
for (int c = left; c < right; c++) {
const int k = r * info.col + c;
const int chip = info.data[k];
if (chip < 0) {
continue;
}
int y = chip / info.chipCol;
int x = chip - y * info.chipCol;
y *= info.chipSize.height;
x *= info.chipSize.width;
Virgo16::Rectangle<int> rectangle(Virgo16::Point<int>(x, y), info.chipSize);
Virgo16::Point<int> point((c - left) * info.chipSize.width, (r - top) * info.chipSize.height);
point.translate(dst.left - lmargin, dst.top - tmargin);
if (point.x < dst.left) {
rectangle.left += dst.left - point.x;
point.x = dst.left;
}
else if (point.x + info.chipSize.width > dst.right) {
rectangle.right -= point.x + info.chipSize.width - dst.right;
}
if (point.y < dst.top) {
rectangle.top += dst.top - point.y;
point.y = dst.top;
}
else if (point.y + info.chipSize.height > dst.bottom) {
rectangle.bottom -= point.y + info.chipSize.height - dst.bottom;
}
if (!(*texture)->draw(lpSprite, rectangle, point)) {
WriteErrorLog(__FUNCTION__, "(*texture)->draw()");
return false;
}
}
}
return true;
}
#pragma once
namespace Game16
{
class Map : public Sprite
{
public:
struct Info {
int chipCol; // マップチップテクスチャの列数
Virgo16::Dimension<int> chipSize; // マップチップのサイズ(ピクセル)
int col; // マップの列数
int row; // マップの行数
Virgo16::Dimension<int> mapSize; // マップのサイズ(ピクセル)
std::vector<int> data; // マップチップ配置データ
};
// コピー・コンストラクタ
inline Map(const Map & right) throw()
: Sprite(right)
, texture(right.texture)
, info(right.info)
{
copyFieldsForConstructor(right);
}
// デストラクタ
virtual inline ~Map() throw()
{
}
// コンストラクタ
explicit inline Map(const Virgo16::Texture * const * const texture, const Info & info) throw()
: texture(texture)
, info(info)
{
initializeFieldsForConstructor();
}
// データ初期化メソッド
bool initialize(Scene * const scene) throw();
// データ変更メソッド
bool move(Scene * const scene) throw();
// 描画メソッド
bool draw(const Scene * const scene, const LPD3DXSPRITE & lpSprite) const throw();
// 代入演算子
inline Map & operator=(const Map & right) throw()
{
if (this != &right) {
Sprite::operator=(right);
copyFieldsForConstructor(right);
}
return *this;
}
protected:
const Virgo16::Texture * const * const texture;
const Info info;
private:
// フィールド・クリア・メソッド(主にデフォルト・コンストラクタが使用)
void initializeFieldsForConstructor() throw();
// フィールド複写メソッド(主にコピー・コンストラクタと代入演算子が使用)
void copyFieldsForConstructor(const Map & right) throw();
bool drawPartially(const LPD3DXSPRITE lpSprite, const Virgo16::Rectangle<int> & src, const Virgo16::Rectangle<int> & dst) const throw();
};
}