Bridge builder clone
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
BridgeBuilder
screenshots
.gitattributes
.gitignore
BridgeBuilder.sln
README.md

README.md

BridgeBuilder

Bridge builder je hra/hříčka inspirovaná Bridge Building Game. Program simuluje fyziku mostů ve 2D prostředí, umožňuje mosty stavět a testovat s neomezenými konstrukčními možnostmi. Na rozdíl od své předlohy umožňuje stavbu bez zachycování do mřížky s cílem dovolit vytvářet organičtější a zajímavější návrhy.

animace mostu

Spuštění

Program je vyvíjen v jazyce C# v Visual Studiu 2015 pro prostředí .NET Framework 4.5.2. Nevyžaduje žádné závislosti a funguje i v prostředí Mono.

Zkompilovaný program lze stáhnout v Releases.

Specifikace

Bridge builder je simulátor stavby mostů, program se skládá ze dvou hlavních částí - stavby a simulace.

Ve stavební části hráč může pomocí jednoduchého rozhraní umisťovat do prostoru pevné body (zastupující zemi), trámy (tedy dva propojené body) a vozovku (trám, na který lze ale aplikovat testovací zátěž). Jednotlivé body se zachycují do mřížky, pro jednodušší ovládání, nicméně tato funkce lze vypnout.

Po návrhu ve stavební části lze přepnout do simulační části, ve které lze myší interagovat s body mostu (aplikovat na ně zátěž), případně most "otestovat", čímž se rozumí nechat po mostu přejet zátěž, která se přesouvá zleva doprava po trámech typu vozovka.

Fyzikální simulace probíhá diskrétně, po časových úsecích, trámy jsou modelovány jako pružiny s vysokou tuhostí.

Při zvoleném pohledu "show stress" lze pozorovat intenzitu zátěže na jednotlivé trámy.

Ovládání

screenshot aplikace

V horní části okna se nachází simulace, v dolní pak nastavení rozdělená do kategorií, která ovlivňují chod programu.

Popis nastavení

Simulation

  • show stress: Zapne vizualizaci napětí v trámech pomocí barev. (konkrétně zobrazuje, jak moc je daný trám natažený oproti své klidové délky).
  • pause simulation: Zastaví simulaci, při spuštění programu je simulace zastavena.
  • gravitation: Zapne působení gravitační síly v simulaci.
  • align to grid: Zapne přichytávání do mřížky

Testing

  • speed: Rychlost pohyblivého závaží.
  • weight: Hmotnost pohyblivého závaží.
  • Run test: Spustí pohyb závaží po vozovce mostu.

Scene

  • Load: Načte uložený stav simulace.
  • Save: Uloží aktuální stav simulace.
  • Clear: Smaže vše z plochy simulace.

Interaction

  • place road: Při zaškrtnutí lze místo umisťování trámů umisťovat vozovku. (také lze držet Shift při umisťování trámů)
  • fix vertex: Při zaškrtnutí a kliknutí na bod v simulaci tento bod zafixuje.
  • add vertex: Při zaškrtnutí a kliknutí kamkoli v simulaci umístí nový bod.

Ovládání myší

Myší lze:

  • Rozšiřovat most o další trámy vybráním bodu (kliknutím levého tlačítka) a kliknutím na druhý bod v dosahu (přidá trám mezi těmito body) případně kliknutím do prostoru (přidá nový bod a trám).
  • Výběr bodu lze zrušit kliknutím pravého tlačítka myši.
  • Pohybovat body kliknutím a tažením (pokud není vybraný žádný bod).
  • Mazat body a trámy najetím a kliknutím pravého tlačítka myši.
  • Pokud je zaškrtnutý checkbox place road, místo trámů se přidávají vozovky.
  • Pokud je zaškrtnutý checkbox fix vertex, akce levého tlačítka myši je fixování existujících bodů (najetím nad bod a kliknutím)
  • Pokud je zaškrtnutý checkbox add vertex, akce levého tlačítka myši je přidávání nových bodů.

První most

Po prvním spuštění bude plocha simulace prázdná. Pro umístění prvního bodu zaškrtněte checkbox add vertex a klikněte kamkoli do černé plochy. Umístí se zde bod, ze kterého lze při stavbě vycházet. Odškrtněte add vertex, klikněte na přidaný bod a dalším klikáním mimo rozšiřujte vznikající most. Pro účely návodu vytvořte trojúhelník (levým tlačítkem lze vybrat existující body, a také nové přidávat, pravým tlačítkem zrušíte výběr). Nyní odškrtněte pause simulation pro spuštění simulace, trojúhelník by měl spadnout k zemi. Při spuštěné simulaci nelze přidávat body/trámy, nicméně lze se simulací interagovat. Pomocí myši vezměte trojúhelník a pohybujte s ním po ploše.

trojúhelník

Pro stavbu mostů je potřeba umístit do prostoru pevné body, které most bude spojovat. Zastavte tedy simulaci (zaškrtněte pause simulation), umístěte nový bod (zaškrtněte add vertex, umístěte bod, odškrtněte add vertex), umístěte 3 trámy vedle sebe (tak, aby ležely v přímce) a nyní zaškrtněte fix vertex, klikněte na oba krajní body této lávky (měl by se kolem nich objevit čtverec), odškrtněte fix vertex. Spusťte simulaci, lávka by měla držet mezi zafixovanými krajními body. Váš první most je hotový.

lávka

Pokud bychom chtěli most otestovat (tlačítko Run test), narazíme na problém, jelikož lávka se skládá pouze z trámů. Stiskněte tedy tlačítko Clear, opakujte předchozí postup vytváření lávky, nicméně při umisťování trámů zaškrtněte place road (případně držte Shift). Nyní by se lávka měla skládat z dvojitých čar, které značí vozovku.

první most

Před testováním je dobré si most uložit, klikněte na tlačítko Save, pro zajímavější pohled na simulaci zaškrtněte show stress, pak spusťte simulaci (testování je možné jen při spuštěné simulaci) a klikněte na Run test. Testování probíhá přejezdem závaží (vizualizovaném kruhem, valícím se po vozovce). Zjistíme, že naše lávka se pod zátěží přetrhla.

Naštěstí jsme si most uložili, takže zastavíme aplikaci (pause simulation) a klikneme na Load. Pomocí trámů se pokuste zpevnit kontrukci mostu tak, aby vydržel zátěž 30000. Pro inspiraci přikládám obrázek svého řešení.

druhý most

Nyní můžete zkusit spojit vzdálenější pevné body (možná s pomocí nosných pilířů?), případně se pokusit most vyztužit a připravit na ještě větší zátaž.

třetí most

Popis chodu programu

Technologie

Pro zobrazovaní realtime grafiky jsem použil WinForms a komponentu pictureBox. I když je tento způsob pomalejší a renderování probíhá na CPU, pro potřeby velmi jednoduché vizualizace naprosto stačí a má tu výhodu, že lze spustit i na platformě Mono.

Rendering

Program v rendering threadu (funkce RenderLoop) v pravidelných intervalech překresluje Bitmap, který zobrazuje pictureBox v okně aplikace. Pro samotné renderování jsem musel zajistit vlastní double buffering (třída DoubleBuffer) pro eliminaci blikání při překreslování snímků a také vlastní časovač, který stabilizuje počet snímků za sekundu na nastavenou hodnotu (třída FpsMeter).

Vykreslování zajišťují třídy *Renderer, které pro jednotlivé části programu (simulace, interakce, testování) vykreslují danou vrstvu zobrazení. Implementace vykreslování je již přímočará, za použití třídy Graphics, která poskytuje metody pro kreslení primitivních tvarů.

Simulace

Jelikož simulace pro vyšší stabilitu a přesnost musí probíhat v jemnějších časových intervalech než vykreslování, probíhá v jiném threadu (UpdateLoop), který si časování zajišťuje nezávisle na rendering threadu. Toto je také z mé zkušenosti běžná praxe. Jelikož jsou některé konstanty simulace částečně závislé na délce simulovaného časového úseku, je nutné simulovat vždy pevně daný čas, v případě mého simulátoru 4ms. Pokud thread čekal déle, simulace se spustí několikrát, aby dohnala reálný čas.

Simulace využívá Verletovy metody integrace bez rychlostí, která má tu výhodu, že jsou v ní stabilní nekonečně tuhé pružiny, které dobře modelují trámy mostů. Pro reálnou aplikaci by bylo nutné implementovat některou metodu konečných prvků, pro mé účely ale jednoduchá simulace stačí. Původně jsem experimentoval s Eulerovou (naivní) metodou a s RK4 metodou (pro implementaci viz starší commit), obě ale při nastavení vyšší tuhosti vedly k velmi nestabilním simulacím. Implementace simulace je ve třídách Edge, Vertex a Simulation, konkrétně Simulation udržuje celý stav simulace (který lze i ukládat a načítat ze souboru), stará se o přidávání a odebírání bodů, Vertex udržuje stav jednotlivých bodů a zajišťuje jejich pohyb a aplikaci sil, Edge vynucuje stálé vzdálenosti mezi propojenými body.

Seznam bodů a trámů v simulaci je nutné udržovat v ConcurrentBag, kvůli interakci tří různých threadů (SimulationRenderer z tohoto seznamu čte a Interaction naopak volá metody, které do seznamu přidávají nové prvky, Simulation čte i zapisuje)

Interakce

Logiku interakce uživatele se stavem simulace jsem měl původně implementovanou přímo ve třídě Simulation, jak jsem ale přidával další možnosti interakce, simulace začala zastávat příliš mnoho funkcí programu. Po vzoru MVC architektur jsem tedy interakci odčlenil do zvláštní třídy Interaction. Na rozdíl od renderování a simulace tato třída nemá svůj vlastní thread, jelikož její metody volají event handlery myši a klávesnice - jednoduše řečeno se tedy tato třída stará o všechna klikání na plochu simulace. Obsahuje svou podtřídu VertexConnector, která zajišťuje dvoufázové spojování bodů - jedním kliknutím bod vybere, druhým spojí s dalším.

Krom interakce simulace s myší jsou v aplikaci i tlačítka, checkboxy a číselné vstupy, nicméně na obsluhu všech stačilo buď registrovat vhodné data bindingy, případně šlo o několikařádkové funkce, které se vešly do třídy BridgeBuilderForm

Testování mostu zajišťuje třída TestingStress. Ta funguje velmi jednoduše - při zahájení testování nalezne v simulaci hranu, která je vozovka a zároveň má nejlevější bod na scéně. Na tomto bodu se závaží začne valit po hraně. Jakmile narazí na konec hrany, hledá další hranu, která navazuje na předchozí. Jakmile takovou nenalezne, závaží dojelo na konec vozovky.