Grundsatzfragen für ein RPG in Python

Code-Stücke können hier veröffentlicht werden.
Antworten
Graf Wasserrutsche
User
Beiträge: 37
Registriert: Donnerstag 17. Juli 2008, 06:59
Wohnort: Köln
Kontaktdaten:

Mittwoch 3. September 2008, 09:26

Hallo zusammen!

Ich habe vor mich an einem kleinen (wirklich sehr kleinem :)) Test RPG zu versuchen, um einige grundlegende Programmiertechniken besser zu lernen oder zu verstehen.

Hierzu verwende ich das erste mal Klassen und würde gerne wissen, ob der Grundgedanke den ich vollziehe korrekt ist.

Für den Anfang hatte ich vor die Daten eines Charakters mit pickle zu speichern und bei einem späteren Level-Up auszulesen, zu verändern und wieder zu speichern. Bei einer evtl. Erweiterung würde ich dann auf SQLite zurückgreifen.

Alle Charakterinformationen, das Erstellen eines Charakters, den Level-Up, den evtl. Tod etc. werde ich in der Klasse Charakter definieren, der Übersichtlichkeit und Funktion halber. Dies auch für alle anderen Klassen wie die Gegner und die Waffen Klasse. Ist dieser Denkansatz richtig, oder könnte/müsste das auf eine andere Art und Weise umgesetzt werden?

Wie könnte ein mehr oder minder zufälliges Treffen auf einen Gegner umgesetzt werden? Eine Schleifenfunktion, welche durch ein zufälliges Ergebnis reagiert?
Wie kann auf Eingaben des Benutzers reagiert werden? Sollte irgendwann eine Art Karte bestehen auf der man sich bewegen kann soll man sich dann durch Verwendung der Pfeiltasten bewegen können.

Kennt ihr weitere Literatur, die nicht allzu kompliziert ist die ich mir dazu zu Gemüte führen können? Auf eine GUI würde ich gerne erstmal verzichten, da ich mir für den Anfang nicht zu viel zumuten möchte.

Code: Alles auswählen

import pickle

class charakter:
    def char_create(self):
        maximale_skillpunkte = 20
        dict = {}
        dict['name'] = raw_input('Welchen Namen soll der Charakter tragen? ')
        dict['staerke'] = raw_input('Wieviele Punkte in Staerke investieren? ')
        dict['beweglichkeit'] = raw_input('Wieviele Punkte in Beweglichkeit investieren? ')
        dict['charisma'] = raw_input('Wieviele Punkte in Charisma investieren? ')
        dict['erfahrung'] = raw_input('Wieviele Punkte in Erfahrung investieren? ')
        
        filename = str(dict['name']).lower()
        datei = open(filename, 'w')
        pickle.dump(dict, datei)
        datei.close()

class weapons:
    pass

class enemies:
    pass
        
char = charakter()
char.char_create()

weapon = weapons()

enemy = enemies()
[url=http://myspace.com/deathmetalvictory][myspace][/url][url=http://grunzgewitter.blogspot.com][blog][/url][url=http://twitter.com/AgatheBauer][twitter][/url]
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mittwoch 3. September 2008, 09:43

Was hat "char_create" in "charakter" zu suchen?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 3. September 2008, 09:43

Graf Wasserrutsche hat geschrieben:Alle Charakterinformationen, das Erstellen eines Charakters, den Level-Up, den evtl. Tod etc. werde ich in der Klasse Charakter definieren, der Übersichtlichkeit und Funktion halber. Dies auch für alle anderen Klassen wie die Gegner und die Waffen Klasse. Ist dieser Denkansatz richtig, oder könnte/müsste das auf eine andere Art und Weise umgesetzt werden?
Eigentlich nicht falsch, aber so wie du es machst würde man es nicht machen. Denn: Klassen würde man groß schreiben und ``char_create`` würde eigentlich ``__init__()`` heißen. Noch dazu würde man das ``raw_input`` nicht in der Klasse machen, sondern in einer externen Funktion, welche Name, Stärke als Funktionsparameter an ``Charakter`` weitergibt (Vermischung von UI und Eigenschaften). Zum Speichern könnte man ``Charakter.dump`` aufrufen, welche sich darum kümmern würde das Objekt zu speichern, egal ob nun via pickle oder etwas anderes.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Graf Wasserrutsche
User
Beiträge: 37
Registriert: Donnerstag 17. Juli 2008, 06:59
Wohnort: Köln
Kontaktdaten:

Mittwoch 3. September 2008, 10:15

So, habe mal einiges umgewurstet nur verstehe ich einige Sachen nicht so ganz. Die Funktion ist auch noch fehlerhaft.

Habe jetzt aus char_create() die __init__() Funktion gemacht, soweit so gut. Ursprünglich hatte ich ja vor diese Funktion dazu benutzen einen Charakter zu erschaffen, aber nur wenn ich das denn auch möchte bzw. brauche.
Wozu würde die Funktion denn jetzt genutzt werden? Würde da eine Abfrage hineinkommen, welche abfragt, ob schon ein Charakter vorhanden ist? Den bisherigen Charakter auslesen, oder etwas komplett anderes?
Und wo bzw. wie müsste die dump() Funktion aufgerufen werden? Wenn ich es zum jetzigen Zeitpunkt mache erscheint eine Fehlermeldung.

Ich stehe total aufm Schlauch, hoffe mal das es sich mit der Zeit und dem Lernen gibt. Sorry schonmal für die ganzen Fragen und vielen Dank für die Antworten.

Code: Alles auswählen

import pickle

def char_info():
    dict = {}
    dict['name'] = raw_input('Welchen Namen soll der Charakter tragen? ')
    dict['staerke'] = raw_input('Wieviele Punkte in Staerke investieren? ')
    dict['beweglichkeit'] = raw_input('Wieviele Punkte in Beweglichkeit investieren? ')
    dict['charisma'] = raw_input('Wieviele Punkte in Charisma investieren? ')
    dict['erfahrung'] = raw_input('Wieviele Punkte in Erfahrung investieren? ')
    return dict   

class Character:
    def __init__(self, dict):
        maximale_skillpunkte = 20     
        
    def dump(self, dict):
        filename = str(dict['name']).lower()
        datei = open(filename, 'w')
        pickle.dump(dict, datei)
        datei.close()
    
char = Character(char_info())
[url=http://myspace.com/deathmetalvictory][myspace][/url][url=http://grunzgewitter.blogspot.com][blog][/url][url=http://twitter.com/AgatheBauer][twitter][/url]
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 3. September 2008, 10:37

Code: Alles auswählen

import pickle

def create_char():
    char = Character()
    char.name = raw_input('Welchen Namen soll der Charakter tragen? ')
    char.staerke = int(raw_input('Wieviele Punkte in Staerke investieren? '))
    char.beweglichkeit = int(raw_input('Wieviele Punkte in Beweglichkeit investieren? '))
    char.charisma = int(raw_input('Wieviele Punkte in Charisma investieren? '))
    char.erfahrung = int(raw_input('Wieviele Punkte in Erfahrung investieren? '))
    return char

class Character:
    def __init__(self):
        maximale_skillpunkte = 20     
       
    def dump(self):
        filename = self.name.lower()
        datei = open(filename, 'wb')
        pickle.dump(self, datei)
        datei.close()
   
my_char = create_char()
Edit: Stimmt BlackJack, angepasst.
Zuletzt geändert von Leonidas am Mittwoch 3. September 2008, 11:21, insgesamt 1-mal geändert.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Mittwoch 3. September 2008, 11:10

Ich nehme mal an die Punkte sollten eigentlich Zahlen sein und "pickle"-Dateien bitte immer im Binärmodus öffnen!
Graf Wasserrutsche
User
Beiträge: 37
Registriert: Donnerstag 17. Juli 2008, 06:59
Wohnort: Köln
Kontaktdaten:

Mittwoch 3. September 2008, 11:59

So, um den Charakter mit dem weitergespielt werden soll zu laden habe ich jetzt die Funktion ``load_char()`` geschrieben, welche aus der "pickle-Datei" die jeweiligen Daten ausliest und in die neue Variable my_char schreibt.

Hierbei ist es mir auch möglich auf die in der Klasse ``Character`` definierten Funktionen zuzugreifen. Wird durch "pickle" auch die übergebene Klasse bzw. die Klassenzugehörigkeit gespeichert?

Um dem Charakter jetzt z.b. eine Waffe zu geben, könnte ich eine Klasse ``Weapons`` schreiben in der verschiedene Waffen definiert sind, welche ich dann einfach per my_char.waffe = Beispielklasse.Waffe1() zuweisen könnte, oder?

edit:

Habe weiter probiert und stehe sofort wieder vor dem nächsten Problem.

Ich möchte dem erstellten Charakter gerne eine Waffe zuweisen. Hierfür habe ich in der Klasse ``Weapons`` die Instanz ``kurzschwert`` erstellt in welcher erst einmal nur Informationen der Waffe selbst vorhanden
sind.

Wenn ich dem Charakter per my_char.waffe = my_weapon.kurzschwert() die Instanz zuweise erhält dieser ja nur den Wert den die Funktion zurückgibt und nicht den Namen dieser. Wie ist es möglich dem Charakter eine Waffe zuzuordnen, welche mit pickle gespeichert wird und welche, wie auch immer, auf die entsprechende Funktion innerhalb der Klasse ``Weapon`` zugreift? Oder müsste das Objekt anders gespeichert werden? Die Variablen aus der Instanz ``kurzschwert()`` hatte ich dann auch vor später in der Instanz ``attack`` zu verwenden, um den entstanden Schaden zu berechnen.

Ich hoffe ich habe mein Problem verständlich vorgetragen :)

Code: Alles auswählen

import pickle

from sys import exit
from os import listdir

def create_char():  
    skillpunkte = 20
    char = Character()
    char.name = raw_input('Welchen Namen soll der Charakter tragen? ')
    char.staerke = int(raw_input('Wieviele Punkte in Staerke investieren? (noch ' + str(skillpunkte) + ')'))   
    char.beweglichkeit = int(raw_input('Wieviele Punkte in Beweglichkeit investieren? (noch ' + str(skillpunkte) + ')'))
    char.charisma = int(raw_input('Wieviele Punkte in Charisma investieren? (noch ' + str(skillpunkte) + ')'))
    char.moral = int(raw_input('Wieviele Punkte in Moral investieren? (noch ' + str(skillpunkte) + ')'))
    char.erfahrung = int(raw_input('Wieviele Punkte in Erfahrung investieren? (noch ' + str(skillpunkte) + ')'))
    char.waffe = ''
    char.leben = 100
    return char  

def load_char():
    dir = listdir('characters/')
    print 'Mit welchem Charakter moechten Sie weiterspielen?'
    x = 0
    for i in dir:
        x += 1
        print str(x) + ') ' + i
    i = int(raw_input())
    datei = open('characters/' + dir[i-1], 'rb')
    char = pickle.load(datei)
    datei.close()
    return char
        
class Character:
    def __init__(self):
        pass
       
    def dump(self):
        filename = self.name.lower()
        datei = open('characters/' + filename, 'wb')
        pickle.dump(self, datei)
        datei.close()
        
    def attack(self):
        print waffe
    
    def defend(self):
        pass
    
    def move(self):
        pass
    
class Weapons:
    def __init__(self):
        pass
    
    def kurzschwert(self):
        schaden = 5
        gewicht = 2

print '|------------TestRPG-------------|'        
print '| 1) Neuen Charakter erstellen   |'
print '| 2) Mit Charakter weiterspielen |'
print '| 3) Programm beenden            |'
print '|--------------------------------|'

i = int(raw_input())

if i == 1:
    my_char = create_char()
    my_char.dump()
elif i == 2:
    my_char = load_char()
    my_weapon = Weapons()
elif i == 3:
    exit()
[url=http://myspace.com/deathmetalvictory][myspace][/url][url=http://grunzgewitter.blogspot.com][blog][/url][url=http://twitter.com/AgatheBauer][twitter][/url]
BlackJack

Mittwoch 3. September 2008, 14:56

Stop, Du bringst da Einiges durcheinander! `kurzschwert` ist kein Exemplar (Instanz) einer Waffe, sondern eine Funktion in der Klasse `Weapon`. Und die enthält auch nicht wirklich Informationen, sondern nur zwei lokale Namen, die sofort nach dem Ausführen wieder verschwinden, wie das bei Funktionen halt so üblich ist.

Wenn Du Waffenobjekte haben möchtest, dann sähe das eher so aus:

Code: Alles auswählen

class Weapon(object):
    def __init__(self, name, damage, weight):
        self.name = name
        self.damage = damage
        self.weight = weight


def main():
    weapon = Weapon('Kurzschwert', 5, 2)
Ausserdem ist IMHO eine leere `__init__()` beim `Character` keine gute Idee. Nach dem initialisieren eines Objekts sollte das möglichst voll funktionstüchtig sein, also sollte man die ganzen Attribute dort mindestens mit sinnvollen Startwerten belegen.
Graf Wasserrutsche
User
Beiträge: 37
Registriert: Donnerstag 17. Juli 2008, 06:59
Wohnort: Köln
Kontaktdaten:

Mittwoch 3. September 2008, 15:12

Ah, klasse! Jetzt versteh ichs! Vielen Dank :)

Ich werde mal die Tage ein wenig weiter probieren und den gesamten Code erweitern und dann das nächste Ergebnis, ob mit oder ohne Fehler posten. Vielleicht interessiert den Werdegang ja noch jemand, der die gleiche Problematik wie ich hat/hatte.

Möchte noch ein großes Lob aussprechen wie kompetent und schnell hier geholfen wird! Erste Sahne.

edit:

Naja, einige Tage waren es jetzt nicht, aber ich poste trotzdem mal :)

Folgende Aufgaben habe ich mir noch vorgenommen:

1. Beim erstellen eines Charakters sollen die Skillpunkte nicht wahlweise vergeben werden sondern definitiv an die maximal verfügbare Skillpunktgrenze gebunden sein. Ich bin mir nur noch nicht sicher, wie ich das realisieren kann und soll. Wären hier einfache If-Abfragen geeignet, oder wäre das bei mehreren Attributen zu kompliziert?

2. Ich möchte einen Dungeon / eine Spielwelt erstellen. Hier weiß ich nicht ob ich es in Form einer Textausgabe mache ("Sie stehen vor einer Gabelung, wollen Sie rechts oder links gehen"), oder in Form einer Karte. Hierbei weiß ich leider auch nicht wie man das realisieren kann.

Version Textausgabe: Vielleicht verschiedene Klassen erstellen, welche zufällig ausgewählt werden, damit eine Spielwelt aufgebaut wird? Oder doch If-Abfragen? Nur wie könnte ich dann Items und Gegner integrieren?

Version Karte: Z.B. ein Feld von 15x15 Positionen erstellen, welche vielleicht zufällig erzeugt werden. Hier auch wieder die Frage wie Items und Gegner integriert werden können.

3. Die Spielfigur soll sich natürlich bewegen können. Gibt es eine Möglichkeit z.B. eine Pfeiltaste zu drücken und dann ohne die zwingende Eingabe der Enter-Taste etwas auszulösen?

Es wäre auch cool, wenn ihr mir einfach Stichworte, oder Seiten nennt mit denen ich dann vielleicht auch selber auf eine Lösung kommen kann.

Code: Alles auswählen

import pickle
import random

from sys import exit
from os import listdir

def create_char():  
    skillpunkte = 20
    char = Character()
    char.name = raw_input('Welchen Namen soll der Charakter tragen? ')
    char.staerke = int(raw_input('Wieviele Punkte in Staerke investieren? (noch ' + str(skillpunkte) + ')'))   
    char.beweglichkeit = int(raw_input('Wieviele Punkte in Beweglichkeit investieren? (noch ' + str(skillpunkte) + ')'))
    char.charisma = int(raw_input('Wieviele Punkte in Charisma investieren? (noch ' + str(skillpunkte) + ')'))
    char.moral = int(raw_input('Wieviele Punkte in Moral investieren? (noch ' + str(skillpunkte) + ')'))
    char.erfahrung = int(raw_input('Wieviele Punkte in Erfahrung investieren? (noch ' + str(skillpunkte) + ')'))
    char.waffe = ['nichts','1','1']
    char.leben = 100
    return char

def load_char():
    dir = listdir('characters/')
    print 'Mit welchem Charakter moechten Sie weiterspielen?'
    x = 0
    for i in dir:
        x += 1
        print str(x) + ') ' + i
    i = int(raw_input())
    datei = open('characters/' + dir[i-1], 'rb')
    char = pickle.load(datei)
    datei.close()
    return char

def move():
    pass
        
class Character:
    def __init__(self):
        name = 'unknown'
        staerke = 1
        beweglichkeit = 1
        charisma = 1
        moral = 1
        erfahrung = 1
       
    def dump(self):
        filename = self.name.lower()
        datei = open('characters/' + filename, 'wb')
        pickle.dump(self, datei)
        datei.close()
        
    def get_weapon(self, weapon):
        my_char.waffe = weapon
        
    def attack(self):
        schaden = (self.staerke + self.beweglichkeit) * (self.waffe.damage + self.waffe.weight) + (self.moral + self.erfahrung) - random.randint(1,30)
        print 'Sie haben ' + str(schaden) + ' Punkte Schaden mit einem ' + str(self.waffe.name) + ' verursacht'
    
    def defend(self, gegner):
        erlittener_schaden = (self.staerke + self.erfahrung) - gegner.damage
        print 'Sie werden von einem ' + gegner.name + ' angegriffen!'
        print 'Sie haben ' + str(erlittener_schaden) + ' Punkte Schaden erlitten.'
 
class Weapons(object):
    def __init__(self, name, damage, weight, distance):
        self.name = name
        self.damage = damage
        self.weight = weight
        self.distance = distance
        
class Enemies(object):
    def __init__(self, name, damage, skillpoints):
        self.name = name
        self.damage = damage
        self.skillpoints = skillpoints

print '|------------TestRPG-------------|'        
print '| 1) Neuen Charakter erstellen   |'
print '| 2) Mit Charakter weiterspielen |'
print '| 3) Programm beenden            |'
print '|--------------------------------|'

i = int(raw_input())

if i == 1:
    my_char = create_char()
    my_char.dump()
elif i == 2:
    my_char = load_char()
elif i == 3:
    exit()    
 
# Definition aller verfuegbaren Waffen mit ihrer Angriffskraft,
# ihrem Gewicht und der moeglichen Distanz
kurzschwert = Weapons('Kurzschwert', 5, 2, 1)
langschwert = Weapons('Langschwert', 8, 4, 1)
bogen = Weapons('Bogen', 6, 1, 10)

# Definition aller moeglichen Gegner mit ihrer Angriffskraft
# und den zu erhaltenden Erfahrungspunkten
gnom = Enemies('Gnom', 5, 15)
troll = Enemies('Troll', 8, 20)

# Beispielaktionen

my_char.get_weapon(langschwert)
my_char.attack()
my_char.defend(gnom)

my_char.dump()
[url=http://myspace.com/deathmetalvictory][myspace][/url][url=http://grunzgewitter.blogspot.com][blog][/url][url=http://twitter.com/AgatheBauer][twitter][/url]
Antworten