Cvičenie 7
Changelog:
-
IMovable: double GetSpeed(double speed)
fixed definition to properly reflect strategy pattern (originallydouble GetSpeed()
)
7.1 Gimme a plan
Player a Enemy majú niečo spoločné vo svete - sú to postavičky. Zatiaľ sme ich považovali iba za actorov, ale narozdiel od predmetov (kotlík, pec) by mali mať ešte niečo navyše - život a pohyb.
Vytvorte si rozhranie ISpeedStrategy
ktoré bude mať jednu metódu: double GetSpeed(double speed)
. Vytvorte si triedy NormalSpeedStrategy
a ModifiedSpeedStrategy
.
Vytvorte si teda rozhranie ICharacter
nech rozširuje IMovable
. Vytvorte si abstraktnú triedu AbstractCharacter
, ktorá bude implementovať ICharacter, IMovable
a samozrejme rozširovať AbstractActor
nech ICharacter
definuje nasledujúce metódy:
void ChangeHealth(int delta);
int GetHealth();
void Die();
void AddEffect(ICommand effect);
void RemoveEffect(ICommand effect);
Do IMovable
pridajte nasledujúce metódy:
void SetSpeedStrategy(ISpeedStrategy);
double GetSpeed(double speed);
kde effect bude uložený do zoznamu a vykonaný počas update. Môžu tu byť veci, ako periodické dopĺňanie života / many, DoT efekty, spomalenie, zrýchlenie...
Triedu Move
upravte Move tak, aby pracovala s desatinnými číslami. Speed sa nebude udávať v konštruktore, ale bude pýtaný od IMovable
(keďže pozícia actora musí byť celé číslo, zabezpečte, aby sa rozdiel akumuloval a následne pripočítal keď dosiahne 1).
Obidve triedy SpeedStrategy implementujte tak, aby používali návrhový vzor strategy a tiež modifikujte AbstractCharacter tak, aby využíval spomínané triedy na nastavenie rýchlosti.
Upravte triedy Player
a Enemy
tak aby rozširovali AbstractCharacter
. Enemy
premenujte na Skeleton
.
Pridajte si enum ActorOrientation
ktorý bude obsahovať dve hodnoty: FacingLeft
a FacingRight
. Využite ho na určenie orientácie actora vo svete.
7.2 I smell magic in here
Vytvorte si:
- priečinok Spells
- rozhrania
IWizard
,ISpell
,ISpellBuilder
,ISpellDirector
- triedy
ProjectileSpell : AbstractActor, IMovable, ISpell
SelfCastSpell : ISpell
ProjectileSpellBuilder : ISpellBuilder
SelfCastSpellBuilder : ISpellBuilder
SpellEffectFactory : IFactory
SpellDirector : ISpellDirector
SpellInfo
- enum
SpellType
public Interface IWizard : IActor
{
void ChangeMana(int delta);
int GetMana();
void Cast(ISpell spell);
}
public class ISpell
{
ISpell AddEffect(ICommand effect);
void AddEffects(IEnumerable<ICommand> effects);
int GetCost();
void Cast();
}
public interface ISpellBuilder
{
ISpellBuilder AddEffect(string effectName);
ISpellBuilder SetAnimation(Animation animation); //unused for self-cast spells
ISpellBuilder SetSpellCost(int cost);
ISpell CreateSpell(IWizard caster);
}
public interface ISpellDirector
{
ISpell Build(string spellName);
}
public class SpellInfo
{
public string Name { get; set; }
public SpellType SpellType { get; set; }
public IEnumerable<string> EffectNames { get; set; }
public string AnimationPath { get; set; }
public int AnimationWidth { get; set; }
public int AnimationHeight { get; set; }
}
Nech ProjectileSpell
a SelfCastSpell
majú v sebe konštruktor v ktorom dostanú referenciu na toho, kto to vyčaroval a IEnumerable<ICommand>
zoznam efektov.
Nech SpellType
určuje, či sa jedná o self-cast alebo projektil.
Vytvorte si efekty (triedy, implementujúce ICommand): damage over time, speed change, heal, heal over time a samozrejme podľa chuti ďalšie.
Každý efekt má svoju cenu, výsledná cena kúzla bude súčet cien jednotlivých efektov (pre self-cast nech je táto cena upravená, napr. 70%).
Implementujte ProjectileSpellBuilder
, SelfCastSpellBuilder
a SpellDirector
ako návrhový vzor builder a nech SpellDirector
v sebe obsahuje dva slovníky: Dictionary<string, int>
kde bude cena jednotlivých efektov a Dictionary<string, SpellInfo>
kde budú uložené zoznamy efektov pre jednotlivké kúzla. Zatiaľ si tieto slovníky inicializujte ručne, nabudúce si ukážeme ako si ich načítať zo súboru.