ゲーム作りは楽しい

なんか書く

ブレゼンハムのアルゴリズムもgeneratorで実装すると楽だ

Bresenham's Line Algorithm

ペイントソフトの直線ツールみたいな、ドットの直線をかくようなアルゴリズムがある

ja.wikipedia.org

こういうのもgeneratorだと書きやすいな

実装例

#include <Siv3D.hpp>
#include <experimental/generator>

template<class T>
using generator = std::experimental::generator<T>;

// ブレゼンハムのアルゴリズム
generator<Point> BresenhamLine(Point start, Point end)
{
    int32 dx = Abs(end.x - start.x);
    int32 dy = Abs(end.y - start.y);
    int32 sx = (start.x < end.x) ? 1 : -1;
    int32 sy = (start.y < end.y) ? 1 : -1;
    int32 error = dx - dy;
    while (true)
    {
        co_yield start;
        if (start == end) {
            co_return;
        }
        int e2 = 2 * error;
        if (e2 > -dy) {
            error = error - dy;
            start.x += sx;
        }
        if (e2 < dx) {
            error = error + dx;
            start.y += sy;
        }
    }
}
void Main()
{
    Window::Resize(600, 600);
    Scene::SetBackground(Palette::White);
    Grid<bool> grid(60, 60);
    Optional<Point> start;
    Optional<Point> end;

    while (System::Update())
    {
        Point mousePos = Cursor::Pos() / 10;
        mousePos.x = Clamp(mousePos.x, 0, 59);
        mousePos.y = Clamp(mousePos.y, 0, 59);
        if (MouseL.down()) {
            if (!start) {
                start = mousePos;
            }
            else if (!end) {
                end = mousePos;
                for (auto [x, y] : BresenhamLine(*start, mousePos)) {
                    grid[y][x] = true;
                }
            }
            else {
                start = mousePos;
                end = s3d::none;
            }
        }
        else if (MouseR.down()) {
            grid.clear();
            grid.resize(60, 60);
        }
        for (size_t i = 1; i < 60; ++i) {
            Line({ i * 10, 0 }, { i * 10,600 }).draw(Palette::Gray);
            Line({ 0, i*10 }, { 600, i * 10 }).draw(Palette::Gray);
        }
        for (size_t y = 0; y < grid.height(); ++y) {
            for (size_t x = 0; x < grid.width(); ++x) {
                if (grid[y][x]) {
                    Rect(x * 10, y * 10, 10, 10).draw(Palette::Black);
                }
            }
        }
        if (!start) {
            Rect(mousePos * 10, 10, 10).draw(Palette::Red.withAlpha(128));
        }
        else if (!end) {
            for (auto [x, y] : BresenhamLine(*start, mousePos)) {
                Rect(x * 10, y * 10, 10, 10).draw(Palette::Red.withAlpha(128));
            }
        }
    }
}