Skip to content

Instantly share code, notes, and snippets.

@G4rryS1ngh
Last active March 1, 2020 14:08
Show Gist options
  • Select an option

  • Save G4rryS1ngh/71191279fd7859073828699bd0dd59ac to your computer and use it in GitHub Desktop.

Select an option

Save G4rryS1ngh/71191279fd7859073828699bd0dd59ac to your computer and use it in GitHub Desktop.
街づくりシミュレーションっぽいデモ
# include <Siv3D.hpp> // OpenSiv3D v0.4.2
RectF GetRectFrom2Pts(Vec2 _p1, Vec2 _p2)
{
Vec2 size(Abs(_p1.x - _p2.x), Abs(_p1.y - _p2.y));
if (_p1.x < _p2.x)
{
if (_p1.y < _p2.y)
return RectF(Arg::topLeft = _p1, size);
else
return RectF(Arg::bottomLeft = _p1, size);
}
else
{
if (_p1.y < _p2.y)
return RectF(Arg::topRight = _p1, size);
else
return RectF(Arg::bottomRight = _p1, size);
}
}
struct Lot
{
RectF rect;
ColorF color = RandomHSV();
Stopwatch duration = Stopwatch(true);
void draw() const
{
double e = EaseOutElastic(duration.sF());
rect.scaled(e).draw(color).drawFrame();
}
};
struct Road
{
Line line;
double size;
double ratio = Random();
double speed = Random(0.5, 1.0);
bool isHorizontal() const { return line.begin.y == line.end.y; }
RectF getHitbox() const
{
Vec2 offset = Vec2::All(size / 2 + 2);
return GetRectFrom2Pts(line.begin - offset, line.end + offset);
}
void update(const Array<Lot>& _lots)
{
// サイズのx倍の長さまで伸ばす
if (line.length() < size * 50 &&
_lots.none([&](const Lot& lot) { return lot.rect.intersects(this->getHitbox()); }))
{
if (isHorizontal())
{
line.begin.x -= size * speed * (1 - ratio);
line.end.x += size * speed * ratio;
}
else
{
line.begin.y -= size * speed * (1 - ratio);
line.end.y += size * speed * ratio;
}
}
}
void draw() const
{
line.draw(LineStyle::RoundCap, size, Palette::Brown);
}
};
void AddNewRoad(Array<Road>& _roads, const Array<Lot>& _lots)
{
if (_roads.isEmpty()) return;
Road base = _roads.choice();
Vec2 begin = base.line.begin.lerp(base.line.end, Clamp(Random(-0.5, 1.5), 0.0, 1.0));
Vec2 end = base.isHorizontal() ? begin.movedBy(0, 0.01) : begin.movedBy(0.01, 0);
double size = Max(3.0, Random(base.size - 3, base.size - 1));
_roads << Road{ Line(begin, end), size };
}
bool AddNewLot(const Array<Road>& _roads, Array<Lot>& _lots)
{
if (_roads.isEmpty()) return false;
Road road = _roads.choice();
int side = Sample({ 1, -1 });
Vec2 offset = (road.isHorizontal()) ? Vec2(0, road.size + 2) : Vec2(road.size + 2, 0);
Vec2 begin = road.line.begin.lerp(road.line.end, Random()).movedBy(offset * side);
Vec2 size(Random(10, 50) * (road.isHorizontal() ? Sample({ 1, -1 }) : side), Random(10, 50) * (road.isHorizontal() ? side : Sample({ 1, -1 })));
Vec2 end = begin.movedBy(size);
Lot new_lot{ GetRectFrom2Pts(begin, end) };
if (_lots.none([&](const Lot& lot) { return lot.rect.intersects(new_lot.rect); })
&& _roads.none([&](const Road& road) { return road.getHitbox().intersects(new_lot.rect); }))
{
_lots << new_lot;
return true;
}
else
return false;
}
void Main()
{
Array<Road> roads;
Array<Lot> lots;
Timer road_spawn_timer(Random(1.0s, 2.0s), true);
Timer lot_spawn_timer(Random(0.5s, 1.0s), true);
Camera2D camera(Vec2(0, 0));
while (System::Update())
{
camera.update();
auto t = camera.createTransformer();
if (MouseL.down())
{
roads << Road{ Line(Vec2(0, 0), Sample({ Vec2(1, 0), Vec2(0, 1) })).movedBy(Cursor::PosF()), 10.0 };
}
if (road_spawn_timer.reachedZero())
{
AddNewRoad(roads, lots);
road_spawn_timer.restart(Random(0.3s, 0.5s));
}
if (lot_spawn_timer.reachedZero())
{
AddNewLot(roads, lots);
lot_spawn_timer.restart(Random(0.1s, 0.2s));
}
roads.each([&](Road& r) { r.update(lots); });
roads.each([](const Road& r) { r.draw(); });
lots.each([](const Lot& l) { l.draw(); });
camera.draw();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment