Last active
March 1, 2020 14:08
-
-
Save G4rryS1ngh/71191279fd7859073828699bd0dd59ac to your computer and use it in GitHub Desktop.
街づくりシミュレーションっぽいデモ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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