3. týždeň

Powering Devices

jeden reaktor dokáže napájať jedno svetlo... zatiaľ...

Motivácia

Vitaj pri brífingu ďalšej misie, kadet! Úvodné zahrievacie kolo máš úspešne za sebou a spolu s našim taktickým a strategickým tímom predpokladáme, že si sa určite dostatočne zahrial pri ovládaní reaktora.

Pri plnení rôznych misií v teréne sa ti však určite hodí niekoľko zručností, ktoré získaš počas dnešného tréningu. Jedná sa hlavne o zručnosť používania referenčných typov ako parametrov metód. Táto nenápadná zručnosť už zachránila život nejednému objektovému programátorovi, preto ju nepodceňuj!

Veľa šťastia pri dosahovaní cieľov dnešnej misie! Z veliteľského mostíka zdraví Manager.

Ciele

  1. Osvojiť si použitie kľúčového slova this vo vlastnom kóde.
  2. Osvojiť si tvorbu parametrických konštruktorov.
  3. Porozumieť využitiu referencie na objekt ako parametra metódy.

Postup

Krok 1: First tools

Ako ste si všimli, pracovať s atómovým reaktorom nie je žiadna sranda. Hlavne keď sa začne prehrievať a neexistuje spôsob, ako ho opraviť... Hádam sa nájdu nejaké užitočné nástroje.

Diagram tried, ktorý vyjadruje vzťah tried Hammer a AbstractActor.
Obr. 1: Diagram tried, ktorý vyjadruje vzťah tried Hammer a AbstractActor.

Úloha 1.1

V balíku sk.tuke.kpi.oop.game vytvorte triedu Hammer, ktorá bude reprezentovať kladivo.

Animácia reprezentujúca kladivo na mape je uložená v súbore hammer. Obdobne, ako obrázok s animáciou reaktora, je aj obrázok kladiva dostupný vo vašom projekte. Kladivo bude mať členskú premennú pre počet zostávajúcich použití, ktorú inicializujte prostredníctvom konštruktora na hodnotu 1. Premennej nastavte vhodnú viditeľnosť a prístup k nej zabezpečte patričnou get metódou.

Animácia hammer.png (rozmery sprite-u: 16x16)
Obr. 2: Animácia hammer.png (rozmery sprite-u: 16x16)

Poznámka

V prípade, že pri vytváraní animácie používate obrázok sprite-u, ktorý pozostáva len z jedného snímku animácie (tak, ako vyššie zobrazený sprite pre kladivo), môžete použiť konštruktor triedy Animation len s jedným parametrom - názvom obrázka:

new Animation("sprites/hammer.png");

Rozmery animácie budú v takom prípade automaticky nastavené podľa rozmerov použitého obrázka.

Úloha 1.2

Pridajte do triedy Hammer metódu use(), ktorá bude reprezentovať použitie kladiva.

Pri každom použití je potrebné aktualizovať počet zostávajúcich použití kladiva. Keď tento počet dosiahne 0, kladivo odstráňte z hernej scény (kladivo sa zlomilo).

Poznámka

Každý aktér zobrazený v hre sa nachádza v aktívnej hernej scéne, na ktorú má aj dostupnú referenciu. Scéna zas má možnosť aktérov pridávať aj odoberať. Využite možnosti vývojového prostredia alebo si prezrite dokumentáciu rozhrania Actor a nájdite spôsob, ako získať referenciu na hernú scénu a ako pomocou nej odstrániť použité kladivo z hry.

Krok 2: If all you have is a hammer, everything looks like a nail

V tomto kroku sa pokúsime poškodený reaktor včas opraviť vhodným nástrojom: kladivom.

Diagram tried, ktorý vyjadruje vzťah tried Reactor a Hammer.
Obr. 3: Diagram tried, ktorý vyjadruje vzťah tried Reactor a Hammer.

Úloha 2.1

Vytvorte v triede Reactor metódu repairWith(), pomocou ktorej bude možné reaktor opraviť.

Metóda nebude vracať žiadnu hodnotu, ale bude mať jeden parameter typu Hammer. Jej správanie bude nasledovné:

  • Metóda bude pracovať iba vtedy, ak hodnota parametra metódy obsahuje platnú referenciu na inštanciu triedy Hammer (a teda nie je null) a reaktor má hodnotu poškodenia vyššiu ako 0% ale ešte nie je úplne zničený.
  • Použitie kladiva zníži poškodenie reaktora o 50 percentuálnych bodov. Pozor ale na to, aby výsledná hodnota poškodenia neklesla pod 0. Teda, ak bude reaktor poškodený, povedzme, na 92%, po použití kladiva jeho poškodenie klesne na 42%. A ak bude poškodený na 35%, použitím kladiva sa úplne opraví (poškodenie 0%).

Poznámka

Keďže zvyšovaním teploty rastie poškodenie lineárne, po znížení poškodenia je potrebné odpovedajúcim spôsobom znížiť aj teplotu. K tejto časti úlohy sa vrátite neskôr v rámci doplňujúcich úloh.

Poznámka

Pri implementácii nezabudnite na to, že okrem úrovne poškodenia a teploty je potrebné zmeniť aj obrázok, ktorý vizualizuje teplotu reaktora. Predíďte však duplikovaniu kódu!

Úloha 2.2

Overte správnosť svojej implementácie.

Vytvorte na mape inštanciu reaktora a niekoľkých kladív. Následne reaktor prehrejte a pokúste sa ho opraviť použitím kladiva.

Krok 3: Shutting Down Reactor

Výborne! Reaktor už zvládame opraviť, aj keď sa nadmieru prehreje (škoda, že v skutočnosti nestačí len to kladivo). Teraz by sa zišlo nájsť spôsob, ako reaktor v prípade potreby zastaviť alebo ho naopak naštartovať.

Úloha 3.1

V triede reaktora vytvorte metódy turnOn() a turnOff(), pomocou ktorých bude možné reaktor zapnúť a vypnúť.

To, či je reaktor zapnutý alebo vypnutý, reprezentuje jeho stav. Z minulého cvičenia už viete, ako sa reprezentuje stav objektov.

Samozrejme, reaktor môže pracovať len vtedy, keď je zapnutý. Ak nebude zapnutý, nebude možné mu zvyšovať ani znižovať teplotu pomocou jeho metód (nemali by mať efekt). Rovnako zabezpečte, aby reaktor nebol zapnutý automaticky po vytvorení jeho inštancie. Pri pokazení reaktora zabezpečte, aby bol vo vypnutom stave. Urobte potrebné úpravy, aby ste tieto skutočnosti zohľadnili.

Úloha 3.2

Pre reprezentáciu reaktora vo vypnutom stave použite obrázok animácie reactor. V prípade, že sa reaktor vypne dôsledkom zničenia, zabezpečte, aby ako jeho animácia ostal nastavený obrázok reactor_broken.

Potrebný objekt animácie si pripravte v konštruktore reaktora, patrične upravte metódu nastavujúcu aktuálnu animáciu a práve vytvorené metódy turnOn() a turnOff().

Úloha 3.3

V triede Reactor vytvorte metódu isRunning(), ktorá zistí, či je reaktor zapnutý (vráti hodnotu true) alebo vypnutý (vráti hodnotu false).

Krok 4: Gaining Control

Ovládanie rozhorúčeného reaktora môže byť poriadne nebezpečná záležitosť. Preto sa teraz pokúsime vytvoriť diaľkový ovládač, ktorý nám umožní reaktor zapnúť alebo vypnúť bez priameho fyzického kontaktu s ním.

Diagram tried, ktorý vyjadruje vzťah tried Reactor a Controller.
Obr. 4: Diagram tried, ktorý vyjadruje vzťah tried Reactor a Controller.

Úloha 4.1

Vytvorte triedu Controller, ktorá bude reprezentovať ovládač pre príslušný reaktor.

Obrázok ovládača sa nachádza v súbore switch. Trieda bude mať len jednu členskú premennú nazvanú reactor, ktorá bude predstavovať referenciu na ovládaný reaktor. Jej hodnotu nastavte pri volaní konštruktora, ktorému bude referencia na príslušný reaktor odovzdaná v parametri.

Animácia switch.png (rozmery sprite-u: 16x16)
Obr. 5: Animácia switch.png (rozmery sprite-u: 16x16)

Úloha 4.2

Vytvorte v triede ovládača metódu toggle(), ktorá zapne alebo vypne ovládaný reaktor vzhľadom na jeho aktuálny stav.

Zapnutý reaktor bude volaním metódy vypnutý, a naopak.

Úloha 4.3

Overte správnosť svojej implementácie.

Pomocou nástroja Inšpektor vytvorte niekoľko inštancií reaktorov a ku každému potrebný ovládač. Overte funkčnosť ovládačov.

Štyri bloky reaktorov ovládané štyrmi diaľkovými ovládačmi. Ktorý však ovláda ktorý?
Obr. 6: Štyri bloky reaktorov ovládané štyrmi diaľkovými ovládačmi. Ktorý však ovláda ktorý?

Krok 5: Powering Light

Reaktor, ktorý ste implementovali minulý týždeň a vylepšili dnes, vyrába elektrinu. V tomto kroku vytvoríme spotrebič, ktorý ku reaktoru pripojíme. Samozrejme - bude fungovať len vtedy, ak bude reaktor vyrábať elektrinu.

Diagram tried, ktorý vyjadruje vzťah tried Light, Reactor a AbstractActor.
Obr. 7: Diagram tried, ktorý vyjadruje vzťah tried Light, Reactor a AbstractActor.

Úloha 5.1

Podľa diagramu tried vyššie vytvorte v balíku sk.tuke.kpi.oop.game triedu Light, ktorá bude reprezentovať svetlo, a otestujte svoju implementáciu.

Trieda bude mať dve metódy:

  • toggle() - Metóda bude vedieť zmeniť stav svetla zo zapnutého na vypnuté a naopak, ako vypínač. Svetlo však bude reálne svietiť (jeho animácia bude light_on) len v tom prípade, ak bude aj napájané elektrinou.
  • setElectricityFlow() - Metóda bude mať jeden parameter typu boolean, ktorý bude udávať, či je svetlu elektrina poskytovaná alebo nie.

Ako animáciu zasvieteného svetla použite súbor light_on a pre animáciu zhasnutého svetla použite súbor light_off.

Animácia light_on.png (rozmery obrázka: 16x16).
Obr. 8: Animácia light_on.png (rozmery obrázka: 16x16).

Animácia light_off.png (rozmery obrázka: 16x16).
Obr. 9: Animácia light_off.png (rozmery obrázka: 16x16).

Poznámka

Nezabudnite, že svetlo sa má zasvietiť aj vtedy, ak je jeho vypínač prepnutý do polohy zapnutý a práve ho pripojíme k dodávke elektriny!

Úloha 5.2

V triede reaktora vytvorte metódy addLight() a removeLight(), pomocou ktorých budete vedieť k reaktoru pripojiť a odpojiť svetlo.

Aktuálny model reaktora bude vedieť súčasne napájať práve jeden spotrebič - v našom prípade to bude práve jedno svetlo. Referenciu naň dostanete prostredníctvom parametra metódy addLight().

Pri volaní metód nezabudnite aktualizovať aj stav napájania spotrebiča vzhľadom na stav reaktora - ak je reaktor zapnutý a nie je pokazený, tak elektrinu vyrába. Nezabudnite rovnako aktualizovať aj všetky ostatné potrebné metódy, ktoré sa podieľajú na uvedenej zmene stavu.

Úloha 5.3

Overte správnosť svojej implementácie vytvorením dvoch inštancií reaktorov a k nim pripojte dve inštancie svetiel.

Pri overovaní činnosti sa môžete riadiť nasledovnou pravdivostnou tabuľkou, ktorá ilustruje správanie svetla:

isOn isPowered stav svetla
true true svieti
true false nesvieti
false true nesvieti
false false nesvieti

Každý reaktor napája jedno svetlo (jeden už zrejme donapájal).
Obr. 10: Každý reaktor napája jedno svetlo (jeden už zrejme donapájal).

Krok 6: Repository

Úloha 6.1

Nahrajte (cez commit a push) váš zdrojový kód do repozitára na GitLab-e. Spravte tak do nasledujúceho cvičenia. Zároveň si pripravte otázky, ktoré by ste na cvičení chceli vyriešiť.

Zdrojový kód nahrajte aj v prípade, ak ste nestihli dokončiť všetky úlohy. Rozpracované časti, ktoré by mohli spôsobiť kompilačné chyby, odporúčame zakomentovať.

Doplňujúce úlohy

Úloha A.1

V rámci opravy reaktora kladivom v metóde repairWith() patrične upravte aj teplotu reaktora.

Vráťte sa k úlohe 4.1 minulého cvičenia a všimnite si uvedený graf závislosti poškodenia od teploty. Ak ho invertujeme pre získanie závislosti teploty od poškodenia, tak jeho správanie v oblasti 0% poškodenia nie je pre výpočet teploty jednoznačné (nie je to funkcia). Preto výpočet teploty pri oprave reaktora upravte nasledovne:

  • Najskôr určte vzťah teploty od poškodenia na základe časti grafu, kde je ich závislosť lineárna.
  • Určte pomocnú hodnotu poškodenia (zníženú o 50 oproti hodnote pred opravou) bez ohľadu na to, či výsledok bude kladné alebo záporné číslo.
  • Získanú hodnotu dosaďte do pripraveného vzťahu a výsledok nastavte ako teplotu reaktora po oprave, avšak len ak by nová teplota reaktora bola nižšia ako tá pred opravou.

Úloha A.2

Vytvorte triedu pre Thorovo kladivo s názvom Mjolnir, odvodenú od triedy Hammer.

Mjolnir vydrží 4 použitia (úplná oprava dvoch reaktorov), po ktorých sa, tak ako pôvodné kladivo, tiež zlomí.

Úloha A.3

Vytvorte triedu FireExtinguisher pre hasiaci prístroj, ktorým bude možné uhasiť horiaci zničený reaktor.

Trieda bude potomkom triedy AbstractActor a bude mať členskú premennú pre počet použití, ktorej nastavte vhodnú viditeľnosť, a implementujte aj patričnú get metódu. Trieda nech má aj metódu use() na odrátavanie zostávajúceho počtu použití. Keď sa hasiaci prístroj spotrebuje, zmizne z hernej mapy. Animácia reprezentujúca hasiaci prístroj na mape je uložená v súbore extinguisher.

Na uhasenie implementujte v triede Reactor metódu extinguishWith(), ktorá bude ako parameter vyžadovať objekt typu FireExtinguisher, ktorý sa na hasenie použije. Hasiaci prístroj vydrží jedno použitie, pri ktorom sa teplota reaktora zníži na 4000 stupňov a animácia reaktora sa zmení na obrázok reactor_extinguished. Poškodenie reaktora sa uhasením nezmení.

Doplňujúce zdroje