Architettura per l'aggiunta di proiettili a un gioco di Tower Defense che utilizza il modello Flyweight per le torri?

3

Ho chiesto a domanda sulla strutturazione di un gioco di Tower Defense qualche tempo fa, e alla fine ho utilizzato il modello di peso vivo per le mie torri. Ecco cosa guarda ora il mio TowerType (sto usando Python ma sto cercando risposte generiche per l'architettura):

class TowerType:

    def __init__(self, name, image, attack_speed, damage,
                 splash_radius, range, cost, upgrade, purchasable):
        self.name = name
        self.image = image
        ... # etc

E in realtà carico questi tipi dinamicamente da un file JSON:

[
    {
        "name": "Arrow Tower 1",
        "image": "images/arrow.png",
        "attack_speed": 1.5,
        "damage": 10,
        "splash_radius": 0,
        "range": 80,
        "cost": 80,
        "upgrade": "Arrow Tower 2",
        "purchasable": true
    },
    {
        "name": "Arrow Tower 2",
         ...
    },
    ...
]

Ora la mia classe Tower non fa molto altro che cercare obiettivi e attaccarli:

class Tower(Entity):

    def __init__(self, type_, x=0, y=0):
        self.type = type_
        self.x = x
        self.y = y
        self._attack_timer = self.type.attack_speed

    def update(self, dt, game):  # This is called from the main/game loop
        self._attack_timer += dt
        time_between_attacks = 1 / self.type.attack_speed * 1000
        if self._attack_timer >= time_between_attacks:
            self._attack_timer -= time_between_attacks
            self.attack(game.monsters)

    def find_target(self, monsters):
        for monster in monsters:
            if distance(self.position, monster.position) <= self.type.range:
                return monster
        return None

    def attack(self, monsters):
        target = self.find_target(monsters)
        if target is None:
            return
        if self.type.splash_radius == 0:
            target.health -= self.type.damage
            return
        # Splash damage!
        for monster in monsters:
            dist = distance(monster.position, target.position)
            if dist > self.type.splash_radius:
                continue
            monster.health -= self.type.damage * (1 - dist / self.type.splash_radius)

Il problema è che le mie torri danneggiano immediatamente i servitori nemici. Quello che voglio è una specie di proiettili che volano dalla mia torre al mostro nemico. Sto cercando aiuto su come strutturare questi proiettili nel mio sistema:

  1. Devo spostare damage e splash_radius da TowerType a ProjectileType , o dovrei semplicemente copiarlo da Tower a Projectile ?
  2. Desidero quindi anche una classe ProjectileType , o dovrei semplicemente creare% randomProjectile s al volo?
  3. Dovrei provare a mettere i proiettili anche nel JSON? Dovrebbero essere in un file JSON separato o dovrei metterli all'interno delle torri corrispondenti?
  4. Qualcosa che mi è sfuggito?
posta Markus Meskanen 09.12.2017 - 15:00
fonte

1 risposta

3

Should I move the damage and splash_radius from TowerType to ProjectileType, or should I just copy it from a Tower to a Projectile?

Eviterei i pesi volanti per proiettili a meno che non si possa anticipare che i proiettili non hanno bisogno della flessibilità di avere più dati che diventano unici e condivideranno un carico di dati immutabili. Tuttavia, anche in questo caso potresti evitare i pesi massimi perché a meno che i tuoi proiettili non siano davvero fantasiosi, generalmente non è necessario archiviare così tanti dati condivisi in uno solo per giustificare l'indirezione a meno che il tuo TD non sia molto diverso dalla maggior parte che ho incontrato.

Sono un po 'diversi dalle torri in un gioco TD, dal momento che le torri potrebbero memorizzare un sacco di informazioni che vale la pena condividere da una torre all'altra, e rende anche più facile ragionare sulla logica del gioco quando si centralizza i metadati del tipo tower e non intercalano i dati condivisi con i dati univoci in una classe. Il tuo gioco ruota attorno a torri con proprietà interessanti, per così dire. I proiettili sono solo elementi di breve durata e qualcosa che puoi descrivere attraverso i metadati / metafunzionalità della torre stessa.

Do I therefore even want a ProjectileType class, or should I just create random Projectiles on the fly?

In questo caso mi piace ProjectileSystem . È una specie di design ingombrante ma può essere responsabile dell'animazione dei proiettili e della loro ricerca del nemico più vicino o di qualsiasi cosa tu voglia. Questo è il mio amore per ECS e non sto suggerendo un sistema di componenti di entità per un TD, ma trovo utile pensare ai "sistemi" di cui il mio gioco ha bisogno che tendono ad essere un'idea più ampia di "oggetti". Rende più facile ragionare su tutto ciò che sta succedendo e quando.

Quando le tue torri lanciano proiettili, puoi aggiungerli in un punto in cui il sistema proiettile può raggiungerli e può essere responsabile di fare il resto. E penso che sia giusto creare e descrivere le loro proprietà al volo. In questo modo ottieni una soluzione più flessibile, come se tu avessi una torre che spara proiettili con danni casuali o effetti di stato ogni volta che spara o qualcosa del genere. Ciò diventa imbarazzante se usi i pesi massimi per proiettili.

Inoltre alcune cose potrebbero essere più facili da descrivere con le funzioni polimorfiche piuttosto che i dati, come lo scenario precedente, in cui un proiettile potrebbe causare effetti di stato casuali quando si colpisce un nemico. Questo mi lega alla mia precedente risposta, dove ho suggerito di ereditare da MetaTower o TowerType per il polimorfismo con funzioni sovrascrivibili, poiché a volte è più facile descrivere cosa vuoi che siano le torri o i proiettili con le funzioni sovrascritte piuttosto che i campi dati.

Come altro esempio, potresti fare come una torre che spara da una mitragliatrice ai nemici vicini, ma un cecchino a fuoco lento in cima alla torre che spara lentamente ai nemici a distanza ... quindi è come, "pewpewpewpewpewpewpewpew ... bam! pewpewpewpewpewpewpewpew ..... bam! " ... con il proiettile da cecchino che ha fatto più danni ma la torre li ha sparati molto più lentamente. Ed è difficile ottenere una tale flessibilità di comportamento per uno specifico tipo di torre cercando di descrivere tutto con solo proprietà / dati anziché funzionalità / codice. Per questo potresti voler semplicemente sovrascrivere un metodo attack nelle tue torri rosse o qualcosa del genere.

Da un punto di vista del design del gioco penso che sia bello avere torri e / o proiettili che possono avere attacchi non uniformi come questo, dal momento che molto del divertimento e della sfida dei TD è capire le torri ottimali da usare e quando . Quando rendi le torri meno uniformi nei loro attacchi, rende più difficile capirlo.

Should I attempt to put the projectiles in the JSON too? Should they be in a separate JSON file or should I put them inside of the corresponding towers?

Domanda difficile in quanto dipende davvero da me su quanto sarà complesso il progetto che ruota intorno a proiettili / particelle. In caso di dubbio, preferirei iniziare a risolvere un problema piuttosto che a sovraccaricarlo. È più semplice trasformare una soluzione da semplice a più sofisticata, da una più sofisticata a una più semplice.

    
risposta data 09.12.2017 - 17:19
fonte

Leggi altre domande sui tag