Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
P PVJCs2021
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Container Registry
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Ing. Lukáš Hruška
  • PVJCs2021
  • Wiki
  • cv4

cv4 · Changes

Page history
Create cv4 authored Oct 10, 2021 by Ing. Lukáš Hruška's avatar Ing. Lukáš Hruška
Show whitespace changes
Inline Side-by-side
Showing with 128 additions and 0 deletions
+128 -0
  • cv4.md cv4.md +128 -0
  • No files found.
cv4.md 0 → 100644
View page @ 39d355af
# Cvičenie 4
Cieľom dnešného cvičenia bude precvičiť si dedenie, abstraktné triedy a ukážeme si ďalší návrhový vzor - `Command` a tiež sa pohráme s užívateľským vstupom.
## 4.1 Observer - part 2
Na minulom cvičení sme si ukázali jednoduchú implementáciu observera. Malo to však zásadnú chybu - nedokázal zistiť, v akom stave aktuálne IObservable je.
Toto vieme vyriešiť niekoľkými spôsobmi. Jedno riešenie (bez použitia typových parametrov) si uvedieme:
Pridajte do konštruktora pre `Crystal` referenciu na `PowerSource` ku ktorému bude pripojený. Následne z tohoto konštruktora viete priamo dať subscribe a keďže máte referenciu, viete sa aj spýtať na stav.
Ďalší krok (aj keď teraz nie úplne nutný, keďže `PowerSource` nadobúda iba 2 stavy) je získať aktuálny stav - upravte teda `IObserver`:
```csharp
void Notify(IObservable)
```
V `Crystal` upravte zodpovedajúcu metódu aby ste získali
## 4.2 Abstract thinking
Naposledy sme si vytvorili 2 triedy, ktoré mali časť funkcionality rovnakú, dnes sa pozrieme ako by sme mohli túto časť dať dokopy.
Vytvorte si triedu `AbstractSwitchable` nech táto rozširuje `AbstractActor` a implementuje `ISwitchable`.
Metódy `Toggle(), IsOn(), TurnOn(), TurnOff()` v `Crystal` majú na prvý pohľad veľmi podobnú implementáciu ako aj v `PowerSource`. Rozdiel je len v `UpdateAnimation()` na ktorý sa odkazujú.
Z `Crystal` presuňte `Toggle, IsOn, TurnOn, TurnOff` do `AbstractSwitchable` (samozrejme to vymažte z `PowerSource`). Chýbajúcu `UpdateAnimation()` iba deklarujte ako `abstract` a ponechajte implementácie, ktoré už máte v `Crystal` a `PowerSource` - toto zabezpečí, že budú použité zodpovedajúce implementácie, ale nemusíte zbytočne opakovať kód, ktorý je spoločný. __Nastala chyba...__ C# neumožňuje prekrývať ľubovoľné metódy, iba tie, ktoré sú na to označené - keyword `virtual`. Doplňte ho tam.
```csharp
private virtual void UpdateAnimation()
```
_`UpdateAnimation()` nepotrebujete volať z iných tried, teda by mala byť `private` - keďže ale ju chceme prekrývať, tak musí byť minimálne dostupná v triedach potomkov, ale nechceme aby bola verejná. Tu sa nám hodí použiť tretí modifikátor prístupu - `protected` (dostupné iba vrámci triedy a jej potomkov).
## 4.3 base class
Vytvorte si triedu `CrackedCrystal` - bude sa jednať o kryštál, ktorý je poškodený a dá sa rozsvietiť len x-krát. Ako predka(rodiča) zoberte `Crystal`.
Prekryte `TurnOn()` (nezabudnite v `AbstractSwitchable` upraviť deklaráciu aby obsahovala `virtual`)
Teraz už je možné túto metódu prekryť, tak v `CrackedCrystal` upravte implementáciu tak, aby sa len x-krát zapol, potom sa už nič nestane.
Prekrytím metódy je schovaný pôvodný kód, ale nie je úplne stratený - pomocou `base` sa k nemu vieme dostať:
```csharp
base.TurnOn();
```
Pridajte aj nový konštruktor s ďalším parametrom - počtom zapnutí (`int`). Využite kód, ktorý ste už implementovali v `Crystal`. Konštruktory je možné vzájomne volať pomocou `this` (vrámci jednej triedy) a `base` pre konštruktor rodičovskej triedy:
```csharp
public class DerivedClass : BaseClass
{
public DerivedClass() : base()
{
//magic happens here
}
public DerivedClass(string s) : base()
{
//some more magic happens here
}
public DerivedClass(int x) : this()
{
//and magic again
}
}
```
## 4.4 Cometh forth mine own apprentice
Nadišiel čas, vševediaci Merlin volá svojho učňa. Predstúp!
Vytvorte si triedu `Player` (rozširuje `AbstractActor`), ako animáciu použite `player.png` - v prípade, že sa hráč otočí, použite `Animation.FlipAnimation()` a keď sa nehýbe `Animation.Stop()`
## 4.5 Didst thee forget how to moveth?
Ale, ako sa hýbať?
Asi najjednoduchšie by bolo priamo do update implementovať čítanie klávesnice a upravovať takto pozíciu. Ale prečo si to trošku neskomplikovať?
Vytvorte si interface `IMovable` (nech sa nachádza v namespace `Merlin.Actors`) - tento interface v sebe nebude mať žiadnu funkcionalitu, jedná sa o tzv. marker interface - slúži len na odlíšenie tried.
Nech `Player` implementuje `IMovable`
V engine máte definovaný ďalší interface:
```csharp
public interface Command
{
void Execute();
}
```
Jedná sa o základ rovnomenného návrhového vzoru. Teraz si ho implementujeme.
Vytvorte si priečinok `Commands` a pridajte si do neho triedu `Move` (implementuje `Command`).
Nech je konštruktor deklarovaný nasledovne: `public Move(IMovable movable, int step, int dx, int dy)` kde step udáva rýchlosť a dx a dy udávajú smer pohybu.
_Svet používa klasické indexovanie súradníc ako v poli, kde ľavý horný roh má [0,0], X-ová súradnica je vodorovná a rastie doprava, Y-ová je zvislá a rastie smerom dole._
Nezabudnite vykonať typovú kontrolu, či ste dostali objekt, ktorý je aj `Actor`. Ak by to neplatilo, program nesmie pokračovať - vyvolajte chybu (s vhodnou chybovou hláškou):
```csharp
throw new ArgumentException("error message goes here");
```
Ak chybu nikde v kóde neošetríme, toto spôsobí, že program spadne - čo je dnes náš cieľ.
V `Execute()` zabezpečte zmenu pozície `IMovable` actora - využite metódy `GetX, GetY` a `SetPosition`
V triede `Player` si na vhodnom mieste (asi konštruktor) inicializujte veci potrebné pre pohyb zabezpečte, aby sa v metóde `Update` vykonalo čítanie z klávesnice a zodpovedajúci pohyb vykonajte pomocou návrhového vzoru command.
_Čítanie z klávesnice je dostupné pomocou triedy `Input`. Táto implementuje vzor Singleton, ktorý umožňuje mať vždy len jednu dostupnú inštanciu - dostanete sa ku nej pomocou `GetInstance()`_
Príklad použitia ste mali na minulom cvičení. Okrem `IsKeyPressed` je dostupná aj metóda `IsKeyDown`, vyskúšajte si ich, aký je v nich rozdiel?
_Klávesy sú vymenované v `Input.Key`, zatiaľ sú pre nás zaujímavé `Input.Key.UP / DOWN /LEFT / RIGHT` - tieto mapujú šípky._
Nezabudnite si hráča pridať do sveta a svoju implementáciu vyskúšať.
S využitím command dokážeme zabezpečiť aj viaceré nezávislé pohyby - napríklad vstup od užívateľa a gravitáciu, prípadne odkopnutie atď.
\ No newline at end of file
Clone repository
  • assignment 1
  • assignment 2
  • cv10
  • cv2
  • cv3
  • cv4
  • cv5
  • cv7
  • cv8
  • cv9
  • exam 0
  • exam 1
  • exam 2
  • exam 3
  • exam 4
View All Pages