ページ 11

RPGツクール風のマップ描画

Posted: 2012年1月15日(日) 12:03
by gran
課題が出ました。

マップチップ配置データを基にマップを描画するコードを下記の条件および手順にしたがって説明をしてください。

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;
				}

			}
		}
~プログラム2~

コード:


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();
	};
}
うまく僕に説明する感じで答えていただけるとありがたいです。

Re: RPGツクール風のマップ描画

Posted: 2012年1月16日(月) 10:57
by softya(ソフト屋)
開発環境やライブラリが不明な上に部分コードなのでコンパイルして見ることも出来ません。これで回答ができないんだと思いますが、出来るだけ詳しい説明をお願いします。
あとできるだけ自分でコメントを書いてみてください。分からない所は?で良いです。
問題の所と思われる箇所はマーキングもお願いします。