Creazione di istanze di un'abilità quando ci sono più tipi diversi di abilità

-1

Sto creando un gioco RPG in cui un giocatore ha una serie di abilità, ognuna delle quali può salire di livello per migliorare il suo effetto. Ecco due abilità di esempio:

  • health : aumenta la salute massima del giocatore
  • regeneration : lentamente rigenera la salute perduta del giocatore

Le abilità hanno molti attributi simili, come name , description , maximum_level , e alcuni callback di eventi che indicano cosa dovrebbe fare l'abilità, quindi ho pensato che dovrei forse creare una classe e queste sarebbero istanze di essa :

class Skill:
    def __init__(self, name, description, max_level, level=0):
        self.name = name
        self.description = description
        self.max_level = max_level
        self.level = level
        self.event_callbacks = {}

    def register_callback(self, event_name):
        def decorator(f):
             self.event_callbacks[event_name] = f
             return f
        return decorator

health_skill = Skill('health', 'increase player\'s maximum health', 8)

@health_skill.register_callback('player_spawn')
def on_player_spawn(skill, player):
    player.maximum_health += skill.level * 5

regeneration_skill = Skill('regeneration', 'regenerate player\'s lost health back', 8)

@regeneration_skill.register_callback('time_tick_second')
def on_second_tick(skill, player):
    if player.health < player.maximum_health:
        player.health = max(player.health + skill.level, player.maximum_health)

player.skills.extend([health_skill, regeneration_skill])

E questo sistema funziona bene, ma ecco il problema: il mio gioco può avere più giocatori e ognuno di essi ha bisogno della propria istanza di ogni abilità. Ora ho bisogno di capire in qualche modo una buona struttura dove posso

  1. crea facilmente competenze
  2. crea facilmente più istanze di ogni abilità

Qualche idea di una buona struttura? Metaclassi? Subclassing? Di solito, come fanno i giochi?

Modifica: questa struttura simile è usata in molti giochi popolari come League of Legends, Dota 2, Hearthstone, ecc ... Un altro buon esempio di questo problema è eroi / campioni in questi giochi: ciascuno l'eroe è simile e ovviamente hanno una base comune, ma ogni eroe ha bisogno di molti attributi di istanza personalizzati come salute, mana, livello, ecc.

    
posta Markus Meskanen 22.09.2016 - 14:45
fonte

2 risposte

0

Purtroppo, non conosco la lingua che stai usando, ma proverò ad usare Java:

Creerei un'interfaccia Skill che usi al di fuori del codice interno delle abilità. Quindi puoi avere una classe astratta DefaultSkill che definisce le tue proprietà comuni. Puoi quindi creare una nuova sottoclasse di classi di abilità con Skill o DefaultSkill per implementare un comportamento speciale:

interface Skill {
    public String getName();
    public int getCurrentLevel();
    public int getMaximumLevel();

    public void onPlayerSpawn();
    public void onTick();
}

abstract class DefaultSkill implements Skill {
    private int currentLevel;
    private Player owningPlayer;

    public DefaultSkill(int startLevel, Player owningPlayer) {
        // .. assign to instance variables
    }
}

class HealthSkill extends DefaultSkill {

    public HealthSkill(Player player) {
        super(100, player);
    }

    public String getName() {
        return "Health";
    }

    public int getCurrentLevel() {
        return this.currentLevel;
    }

    public int getMaximumLevel() {
        return 100;
    }

    // implement onPlayerSpawn()
    // implement onTick()
}

Skill health = new HealthSkill(player);

Puoi fare un ulteriore passo avanti e separare le abilità e il loro sviluppo per ogni giocatore:

interface Skill {
    public String getName();
    public int getMinimumLevel();
    public int getMaximumLevel();

    public void onPlayerSpawn(SkillDevelopment development, Player player);
    public void onTick(SkillDevelopment development, Player player);
}

interface SkillDevelopment {
    public Skill getSkill();
    public Player getPlayer();
    public int getCurrentLevel();
    public void setCurrentLevel(int level);

    public void onPlayerSpawn();
    public void onTick();
}

class DefaultSkillDevelopment implements SkillDevelopment {
    private int level;
    private Skill skill;
    private Player player;

    public DefaultSkillDevelopment(Skill skill, Player player, int startLevel) {
        // ...
    }

    public int getCurrentLevel() {
        return level;
    }

    public void setCurrentLevel(int level) {
        if (level < skill.getMinimumLevel() || level > skill.getMaximumLevel())
            throw new IllegalArgumentException();

        this.level = level;
    }

    public void onPlayerSpawn() {
        skill.onPlayerSpawn(this, player);
    }

    public void onTick() {
        skill.onTick(this, player);
    }
}

class HealthSkill implements Skill {

    private static final HealthSkill INSTANCE = new HealthSkill();

    public static HealthSkill getInstance() {
        return INSTANCE;
    }

    public String getName() {
        return "Health";
    }

    public int getMinimumLevel() {
        return 0;
    }

    public int getMaximumLevel() {
        return 100;
    }

    // implement onPlayerSpawn()
    // implement onTick()
}

SkillDevelopment health = new DefaultSkillDevelopment(HealthSkill.getInstance(), player);
    
risposta data 22.09.2016 - 15:55
fonte
0

Creare solo una classe di abilità è, e quindi registrare i callback con una decorazione è un IMO scomodo. Crea una classe per ogni abilità. Ogni classe di abilità aggiunge direttamente i callback di cui ha bisogno. Puoi quindi dare a ciascun giocatore una serie di oggetti di abilità istanziati da queste classi.

    
risposta data 23.09.2016 - 05:43
fonte