Ich brauche Hilfe um ein Skillsystem in ein Text-RPG zu implementieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Barrylim
User
Beiträge: 5
Registriert: Freitag 26. Februar 2021, 19:40

Ich bastle gerade an einem Text-RPG und möchte gerne ein Skillsystem einbauen. Mein Ansatz wäre dieses in eine Funktion zu schreiben und dem Benutzer per User-Input die Wahl zu ermöglichen, eine ausgewählte Fähigkeit zu verbessern. Nun weiß ich aber nicht wie ich dieses mit meinen Charakteren verknüpfen soll. Ich habe einen Charakter in einer Klasse angelegt und möchte, dass durch das Skillsystem seine Werte nachhaltig verbessert werden können. Ich wäre um eine Hilfestellung dankbar.

LG Barrylim







Code: Alles auswählen

#Anlegen einer Klasse für Charaktere:

class character:
    def __init__(self, name, hp, mana, att, shield):
        self.name = name
        self.hp = hp
        self.mana = mana
        self.att = att
        self.shield = shield

    def die(self):
        if self.hp > 1:
            print(self.name + "ist gestorben")

    def drink_potion_mana(self):
        self.hp = self.hp + hp_potion
        inventory.hp_potion = inventory.hp_potion -1

    def character_stats(self):
        print("hp =" + str(self.hp) + "\nmana =" + str(self.mana) + "\nattack =" + str(self.att) + "\nshield =" + str(self.shield))

wuddwick = character("Wuddwick", 100, 40, 10, 8)




#Anlegen einer Klasse für einen Charakter mit dem Namen "Wuddwick"



class character_wuddwick(character):
    def __init__(self):
        character.__init__("wuddwick", 100, 40, 10, 8)



#Anlegen einer Funktion für das Skillsystem

def skillsystem():
   print("mana    [1 eingeben]")
   print("attack  [2 eingeben]")
   print("hp      [3 eingeben]")
   print("shield  [4 eingeben]")

   improvement = input("Welche Fähigkeit möchtest du verbessern? ")

   if improvement == "1":

   

   elif improvement == "2":
    
    
   elif improvement == "3":
       
    
    
   elif improvement == "4":
       
       
   else:
       print ("wrong command")





#Anlegen des Spiel-Menüs mit einem Eintrag "Skillsystem", wodurch auf das Skillsystem zugegriffen können werden soll.


  Menu = input("\nopen inventory /I/\n"
             "open character_stats /C/"
             "\nopen quest_menu /Q/ \n"
             "open skill_window /S/")


if Menu == "I":
        inventory1.open_inventory()

elif Menu == "C":
            wuddwick.character_stats()

elif Menu == "Q":
            quests.quest_list()

elif Menu == "S":
            skillsystem()

else:
    print ("wrong command")
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird immer mit 4 Leerteichen pro Ebene, nicht mal 3, 7 oder 11.
Klassen schreibt man per Konvention mit großem Anfangsbuchstaben.
Die Klasse character_wuddwick ist überflüssig. Das wäre besser nur einer Instanz der Klasse character mit entsprechenden Parametern.
Benutze keine Abkürzungen. Wenn du healthpoints meinst, schreib das auch.
skillsystem braucht doch nur als Argument eine Karaktere mehr ist da nicht.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Wie man so etwas genau aufbaut, hängt aus meiner Sicht stark von den Funktionen, die du haben möchtest, ab. Überleg dir zunächst, was du eigentlich brauchst. Daraus ergibt sich dann, welche Methoden du für deine Charakterklasse implementieren musst und was du sonst noch so brauchst.

Nachfolgend mal ein einfaches Beispiel, wie man deinen Codeschnipisel umbauen könnte (das ist natürlich nur eine von vielen Varianten und sicher nicht die "Beste"; aber vielleicht gibt es dir ein paar Ideen/Ansätze zur modellierung):

Code: Alles auswählen

#!/usr/bin/env python3

from collections import namedtuple

Skill = namedtuple('Skill', ('name', 'cost', 'modifiers'))


class Character:
    def __init__(self, name, hitpoints, mana, attack, shield, modifiers=None):
        self.name = name
        self.base_hitpoints = hitpoints
        self.base_mana = mana
        self.base_attack = attack
        self.base_shield = shield
        self.reset()
        if modifiers is not None:
            self.modifiers = modifiers

    @property
    def hitpoints(self):
        return self.base_hitpoints \
               + self.modifiers.get('hitpoints', 0) \
               - self.damage

    @property
    def mana(self):
        return self.base_mana \
               + self.modifiers.get('mana', 0) \
               - self.mana_used

    @property
    def attack(self):
        return self.base_attack \
               + self.modifiers.get('attack', 0)

    @property
    def shield(self):
        return self.base_shield \
               + self.modifiers.get('shield', 0)

    def is_alive(self):
        return self.hitpoints > 0

    def reset(self):
        self.modifiers = dict()
        self.damage = 0
        self.mana_used = 0

    def apply_skill(self, skill):
        for attribute, value in skill.modifiers.items():
            self.modifiers.setdefault(attribute, 0)
            self.modifiers[attribute] += value

    def dump_stats(self):
        print(f'Name: {self.name}')
        print(f'Hitpoints: {self.hitpoints}')
        print(f'Mana: {self.mana}')
        print(f'Attack: {self.attack}')
        print(f'Shield: {self.shield}')
        print()

    def __str__(self):
        return self.name


def main():
    skills = [
            Skill(
                name='Health +1',
                cost=100,
                modifiers={'hitpoints': 1}
                ),
            Skill(
                name='Fight boost +3',
                cost=700,
                modifiers={'shield': 3, 'attack': 3}
                )
            ]
    player = Character(
            name='Sir Foo of Bar',
            hitpoints=30,
            mana=25,
            attack=10,
            shield=12
            )
    player.dump_stats()
    player.apply_skill(skills[1])
    player.dump_stats()
    player.reset()
    player.dump_stats()
    while player.is_alive():
        print('The newt bites!')
        player.damage += 8
    print('You die...')


if __name__ == '__main__':
    main()
Barrylim
User
Beiträge: 5
Registriert: Freitag 26. Februar 2021, 19:40

@sirius 3, Danke für die Anregungen. Was meinst du genau mit "immer" 4 Einrückungen je nachdem, muss ich doch beispielsweise nach einer if-Abfrage oder wenn eine Klasse eingeleitet wird darunter mehr einrücken und nicht alles auf einer Ebene haben?

Gibt es einen Grund keine aussagekräftigen Abkürzungen zu nutzen? Das "hp" für healthpoints steht, sollte im Spiele-Kontext ja ziemlich klar sein.
Barrylim
User
Beiträge: 5
Registriert: Freitag 26. Februar 2021, 19:40

@nezzcarth, danke für die ausführliche Antwort, was genau macht denn das "@property", was vor die Methoden geschrieben wird?
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Im konkreten Beispiel wird der Dekorator @property für berechnete Attribute verwendet (insgesamt kann er noch etwas mehr, was hier aber nicht zum Einsatz kommt). Die Idee ist, dass man die Startwerte und später erworbene Modifikationen sowie verbrauchtes Mana und erlittenen Schaden jeweils getrennt vorhält und den effektiven Wert dann berechnet, wenn er abgerufen wird. So lassen sich leicht Funktionen wie Heilen, Zurücksetzen oder Verlernen von Skills umsetzen. Muss man natürlich nicht so machen, finde ich aber praktisch.
Barrylim
User
Beiträge: 5
Registriert: Freitag 26. Februar 2021, 19:40

@sirius:
Die Klasse(Character_wuddwick) brauche ich, weil ich diesem später noch einzigartige Methoden zuordnen will, die die anderen Charaktere nicht aufweisen.

Meine Idee wäre jetzt folgendes:
Bin ich da auf dem richtigen Weg?

Code: Alles auswählen

class Character_wuddwick(character):
    def __init__(self):
        character.__init__("wuddwick", 100, 40, 10, 8)

    def change_hp(self):
        self.hp = self.hp +1





def skillsystem():
   print("mana    [1 eingeben]")
   print("attack  [2 eingeben]")
   print("hp      [3 eingeben]")
   print("shield  [4 eingeben]")

   improvement = input("Welche Fähigkeit möchtest du verbessern? ")

   if improvement == "1":
       pass




   elif improvement == "2":
       pass

   elif improvement == "3":
        Character_wuddwick.change_hp()

   elif improvement == "4":
        pass


   else:
       print ("wrong command")
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Barrylim: ``Character_wuddwick.change_hp()`` ist falsch weil das auf einem Exemplar von diesem Character aufgerufen werden muss, nicht auf der Klasse. Die Klasse macht auch wirklich keinen Sinn, wie schon gesagt wurde. Die `change_hp()`-Methode ist nicht wirklich speziell genug als das man sie nicht auch einfach auf der Basisklasse `Character` definieren könnte.

`skillsystem()` müsste ein `Character`-Objekt als Argument übergeben bekommen. Und der Name ist schlecht für eine Funktion. Funktionen (und Methoden) werden üblicherweise nach der Tätigkeit benannt die sie ausführen. `skillsystem` ist keine Tätigkeit, daran kann man nicht wirlklich ablesen was diese Funktion tut. Das ist ein eher passiver Name der für ein Objekt geeignet wäre das ein Skill-System repräsentiert.

Und auch ich würde Abkürzungen vermeiden. Es hat keinen Nachteil `hitpoints` oder `attention_span` auch wirklich so zu nennen, statt `hp` und `att` zu schreiben. Wobei ich übrigends erfrischend finde das Charactere in Deinem Spiel eine Aufmerksamkeitsspanne als Eigenschaft haben. 😉
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich dachte das war Attraktivität. Ich möchte bitte einen wirklich heissen Dunkelelf spielen, der seine Gegner einfach qua physischer Präsenz überwältigt.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@__deets__: Das kann nach hinten losgehen. Ich sehe da schon das Du stark in Deiner Bewegungsfreiheit eingeschränkt bist durch den Tross an NPC-Groupies die Dir ständig folgen und dauernd im Weg herum stehen. 🙂
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

"You swap places with your kitten." – klappt sicher auch mit Fan-Trauben. :)
Barrylim
User
Beiträge: 5
Registriert: Freitag 26. Februar 2021, 19:40

Danke für die Hilfe :)

ihr Scherzkekse ;)
Antworten