#include "Stage.h"

#include "DxLib.h"

namespace
{
    // 0: 空白、1: 床、2: ゴール位置の目印
    const int tiles[Stage::mapHeight][Stage::mapWidth] =
    {
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1},
        {0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0},
        {0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    };

    // ピクセル座標をタイル座標に変換する
    int PixelToTile(int pixel)
    {
        // C++の整数除算は負の値を0方向へ丸めるため、自前で下方向へ丸めます。
        if (pixel >= 0)
            return pixel / Stage::tileSize;

        return (pixel - Stage::tileSize + 1) / Stage::tileSize;
    }
}

// ステージの初期化
void Stage::Initialize()
{
    // マップ上のゴールタイルと同じ位置に、当たり判定用の矩形を置く
    for (int y = 0; y < mapHeight; y++)
    {
        for (int x = 0; x < mapWidth; x++)
        {
            if (tiles[y][x] == TileGoal)
            {
                goal = { x * tileSize, y * tileSize, tileSize, tileSize };
                return;
            }
        }
    }
}

// 指定したタイル座標が床タイルかどうかを返す
bool Stage::IsSolidTile(int tileX, int tileY) const
{
    // マップの左右と上は壁扱いにして、画面外へ進めないようにする
    if (tileX < 0 || tileX >= mapWidth)
        return true;

    if (tileY < 0)
        return true;

    // 下方向は落下できるように、マップ外でも床ではない扱いにする
    if (tileY >= mapHeight)
        return false;

    return tiles[tileY][tileX] == TileSolid;
}

// 指定した矩形が床タイルと重なっているかどうかを返す
bool Stage::IsSolidAtRect(const Rect& rect) const
{
    // 矩形が少しでも重なっているタイル範囲を調べる
    int leftTile = PixelToTile(rect.x);
    int rightTile = PixelToTile(rect.x + rect.width - 1);
    int topTile = PixelToTile(rect.y);
    int bottomTile = PixelToTile(rect.y + rect.height - 1);

    for (int y = topTile; y <= bottomTile; y++)
    {
        for (int x = leftTile; x <= rightTile; x++)
        {
            if (IsSolidTile(x, y))
                return true;
        }
    }

    return false;
}

// ステージの描画
void Stage::Draw() const
{
    // マップ全体を走査し、床タイルだけを描画する
    for (int y = 0; y < mapHeight; y++)
    {
        for (int x = 0; x < mapWidth; x++)
        {
            if (tiles[y][x] != TileSolid)
                continue;

            DrawTile(x, y);
        }
    }

    DrawGoal();
}

// ゴールの矩形を取得する
Rect Stage::GetGoal() const
{
    return goal;
}

// 指定したタイル座標のタイルを描画する
void Stage::DrawTile(int tileX, int tileY) const
{
    // タイル座標を画面上のピクセル座標へ変換して描画します。
    DrawBox(tileX * tileSize, tileY * tileSize,
        tileX * tileSize + tileSize, tileY * tileSize + tileSize,
        GetColor(80, 80, 110), TRUE);
}

// ゴールの矩形を描画する
void Stage::DrawGoal() const
{
    DrawBox(goal.x, goal.y, goal.x + goal.width, goal.y + goal.height,
        GetColor(90, 220, 120), TRUE);
}
