Introduzione al mio problema
Sto provando a progettare un videogioco molto semplice in cui ci sono diversi% di% giocatori (tutti ereditano da Animals
):
-
Animal
-
Cat
-
Dog
Esistono anche alcune azioni eseguibili (solo una per Rabbit
) che possono eseguire come:
-
Animal
: fatto solo daBite
(se un animale viene morso, perderà una quantità di vita) -
Dogs
: fatto solo daKick
(se un animale viene calciato non sarà in grado di muoversi per X secondi) -
Rabbits
: fatto solo daScratch
(se un animale si graffia ridurrà il loro movimento di velocità di -50% per Y secondi)
Stavo pensando a un progetto che potrebbe essere estensibile in futuro: avere nuovi animali (o anche nuovi giocatori come alieni / piante / umani), azioni e persino essere in grado di assegnare casualmente un'azione a un giocatore.
La mia soluzione fino ad ora
Interfacce
Prima di tutto, ogni giocatore che vorrebbe giocare, deve implementare l'interfaccia Cats
(In questo caso, Playable
implementerebbe Animal
):
L'interfaccia riproducibile
interface Playable {
move(distance: number): void,
getPosition(): number,
attack(): void,
beingBitten(): void,
beingKicked(): void,
beingScratched(): void
}
Interfaccia esecutore
Inoltre, ho pensato di avere un'interfaccia chiamata Playable
per ogni azione che un giocatore può eseguire su un altro giocatore:
interface Performer {
perform(enemy: Playable): void
}
Implementazioni
In questo modo, l'implementazione Performer
di Rabbit
è simile alla seguente:
class Rabbit extends Animal {
private action: Performer;
// ... etc ...
public attack(enemy: Playable): void {
action.perform(enemy);
}
// ... etc ...
}
E l'azione performativa .attack()
sarebbe simile a questa:
class Kick implements Performer {
public perform(enemy: Playable): void {
enemy.beingKicked();
}
}
Le mie preoccupazioni
In termini di organizzazione ed essere più chiari, stavo pensando che avrei potuto rompere l'interfaccia Kick
in tre:
L'interfaccia dell'attacker
Le azioni relative all'attacco andrebbero qui.
interface attack { attacco (nemico: giocabile): vuoto }
L'interfaccia Attackable
Le azioni relative all'essere attaccabili andrebbero qui.
interface Attackable {
beingBitten(): void,
beingKicked(): void,
beingScratched(): void
}
L'interfaccia riproducibile
Le azioni relative alla possibilità di spostarsi andrebbero qui.
interface Playable extends Attacker, Attackable {
move(distance: number): void,
getPosition(): number
}
Non ho molta esperienza quando si tratta di OOP, quindi ogni volta che finisco per pensare troppo a qualcosa e progettare alternative diverse, ma faccio fatica a decidere quale dovrei scegliere.
Come vedi tutto questo? Ha senso scindere Playable
in tre per rendere le cose più chiare?