Öffentliches RPG Projekt
-
Hallo Zusammen,
Ich bin ein Anfänger im C++ und möchte mich daher weiterentwickeln.
Hierfür möchte ich mich auf ein neues Gebiet wagen.
Für einige mag meine Idee vielleicht unsinnig sein, jedoch finde ich es ist ein Versuch wert.Ich möchte hier ein öffentliches RPG Projekt starten. Mit Hilfe meiner 2 C++ Bücher werde ich diese Woche (evtl. bereits heute Abend), damit beginnen, dass ich ein Textbasiertes RPG erstelle, welches über Klassen und Objekte verfügt.
Das RPG wird eine Konsolenanwendung sein.
Definition des Auftrages
Monster
Charakter
Bei Beginn des Spieles, wird der Benutzer gebeten einen Charakter zu erstellen, welcher über folgende Attribute verfügt:
- Name (durch User eingegeben)
- Leben
- Mana (sofern Magisch veranlagt)
- Klasse (wird ausgesucht)
- Waffe (Abhängig durch Klassenwahl)
- Rüstungsteile
- Inventar
- EXP
- Level
- GeldGegner
Im Verlaufe des Spieles, werden verschiedene Gegner auftauchen mit welchen interagiert werden kann (kämpfen, evtl. ausrauben usw…).
Die Gegner sind dem Charakter sehr ähnlich wie der Charakter:
- Name (durch User eingegeben)
- Leben
- Mana (sofern Magisch veranlagt)
- Waffe
- Rüstung
- Inventar
- EXP
- Level
- Beute
- GeldNPC
Natürlich wird es noch NPC’s geben mit welchen man sprechen kann, diese verfügen überfolgendes:
- Name
- Leben
- Mana (sofern Magisch veranlagt)
- Level
- Geld
- QuestsVerkäufer/Käufer
Die Shop Inhaber gibt es natürlich auch:
- Name
- Leben
- Mana (sofern Magisch veranlagt)
- Level
- Geld
- EXP
- InventarDie Gegenstände
Waffen
Die Waffen haben folgendes Schema:
- WaffeName
- WaffenAngriff
- WaffenVerteidigung
- WaffenSchaden
- PreisRüstungsteile
- RüstungName
- RüstungsWert
- PreisTränke
- TrankName
- Typ (HP, Mana)
- TrankWertDas Regelsystem
Das Projekt verfügt über ein klar definiertes System, welches dem Prinzip von DAS (Das schwarze Auge) sehr nahe kommt.
Das Kampfsystem
Der Kampf findet in 4 Phasen statt.Der Angriff durch den Charakter, wenn dieser trifft folgt die Verteidigung durch den Gegner, ist dieser erfolgreich wird der Schlag abgewehrt.
Danach Greift der Gegner an und der Charakter darf verteidigen.
Ob ein Monster/Charakter/NPC… zuschlägt oder abwehren kann, wird durch einen W20 (Würfel 20) entschieden.
Ist der Wert des Wurfes kleiner, gleich des Angriffes oder der Verteidigung, dann ist der Angriff/die Parade erfolgreich.Zum Schluss wird das Monster beraubt und gibt EXP (Charakter evtl. Stufen anstieg)
Schaden wird durch die Waffe bestimmt, welche über einen fest Schaden und einen optionalen W6 (Würfel 6) Schaden verfügt.
Die Welt
Bewegung
Man bewegt sich nicht selbst sondern wird durch den Text geleitet. Man kann verschiedene Entscheidungen treffen und somit die Story (ein wenig) selbst gestalten.Quests
Die Quest können jeweils bei einem Questgeber, welcher sich in Städten, auf dem Weg und anderen Plätzen, aufhält, angenommen werden.Wird der Quest erfolgreich abgeschlossen, erhält der Spieler bei Abgabe eine Belohnung.
Die Qusts sollen jederzeit einsehbar sein und verfügen überfolgende Attribute:- Name
- Beschreibung
- Ziel
- Status
- Questgeber
- QuestabgeberDas wär soweit mal alles, sollte ich etwas vergessen habe, bitte ich euch das mir mitzuteilen und mir weiter zu helfen.
Als nächstes werde ich dann mal ein paar der Klassen auflisten und meine Entscheidungen erklären, natürlich ist das ganze kommentiert, damit andere Anfänger die Zusammenhänge und das Konzept verstehen können.
Ich hoffe niemand ist erbost über meine Idee oder hat etwas dagegen.
Ich bitte um konstruktive Kritik sowie auch wenn möglich Feedback

Danke schön für eure Wertvolle Zeit.
Gruss,
Dragon4411
-
Verwendest du dafür eine UI?
Oder machst du das auf der Konsole?
-
phlox81 schrieb:
Verwendest du dafür eine UI?
Oder machst du das auf der Konsole?Das ganze ist an Anfänger gerichtet und findet daher in der Konsole statt.
Sollte es irgendwann dann mal fertig sein, kann es immer noch umkonzipiert werden.Gruss,
Dragon4411
-
Wurde das Thema abischtlich hier hin verschoben?
Was haltet ihr von dieser Idee?
-
Dragon4411 schrieb:
Wurde das Thema abischtlich hier hin verschoben?
Was haltet ihr von dieser Idee?
Nein, du hast das Thema hier gepostet...
Verschieb dich mal nach C++...
-
Dieser Thread wurde von Moderator/in phlox81 aus dem Forum Andere GUIs - Qt, GTK+, wxWidgets in das Forum C++ (auch C++0x und C++11) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
phlox81 schrieb:
Dragon4411 schrieb:
Wurde das Thema abischtlich hier hin verschoben?
Was haltet ihr von dieser Idee?
Nein, du hast das Thema hier gepostet...
Verschieb dich mal nach C++...Tschuldigung :S
Danke dir

-
Nettes Projekt, aber vielleicht nicht doch ein bisschen zu hoch gegriffen? Schonmal Pong, Space Invaders oder Snake programmiert?
gruß
syntax
-
Quatsch, warum zu hoch gegriffen? Offen gesagt finde ich es zum lernen wesentlich besser als Pong, weil man viel mehr Datenstrukturen etc. kennen lernt, die man auch später noch verwenden kann. Ich kann das als Lernprojekt also nur unterstützen. Allerdings vermute ich mal, du wirst so schnell keine "Mitprogrammierer" finden, jedenfalls keine die C++ schon können.

Solange du allerdings sauber programmierst, kannst du den Code immer hier posten und es finden sich sicher ein paar Leute, die den dann ein bisschen kommentieren.
-
Bist du (Objektorientierter-)Programmieranfänger oder nur C++-Anfänger? Falls ersteres erachte ich das nicht so wirklich als sinnvoll, da wäre es eher von nützen wenn es jemand machte, der schon recht versiert im Programmieren ist.
-
Hiho,
Schöne Idee, ich hab doch glatt mal angefangen was zu schreiben

Ich bin auch noch Anfänger, hab +- vor zwei Monaten angefangen mit C++ zu schreiben also verzeiht meine Fehler

Hast du eigentlich noch ein anderes Kommunikationmittel als das Forum? vieleicht IRC? oder TS? oder was auch immer
so ne schnellere kommunikation wäre doch auch sehr schön 
Was ich mir jetzt überlegt habe is, das du sicherlich mal ne Klasse für das eigentliche Spiel brauchst, und einen für den Spieler. Hab ich mir das mal so erstellt:
Player.hpp
#include <string> #include <iostream> using namespace std; class CPlayer { public: CPlayer(); void Init(); string InputName(); private: struct SPlayer { string Name; int Live; int Mana; int Exp; int Level; int Money; } player; };Game.hpp
#include <fstream> #include <string> #include <iostream> #include "Player.hpp" using namespace std; class CGame { public: void Init(); private: void Run(); CPlayer player; };und dann hab ich mir noch ein kleinen Code geschrieben der schonmal überprüft ob man schon einen Spieler erstellt hat (Also er schaut ganz einfach ob das "Player.txt" File schon besteht oder nicht), und wenn nicht fragt er mal nach dem Namen.
Game.cpp
#include "Game.hpp" void CGame::Init() { string line; ifstream playerfile("Player.txt"); if (playerfile) { } else { string name; name = player.InputName(); ofstream playerfile("Player.txt"); playerfile << "Name: " << name; } Run(); } void CGame::Run() { }Player.cpp
#include "Player.hpp" string CPlayer::InputName() { cout << "Name: "; cin >> player.Name; return player.Name; } void CPlayer::Init() { } CPlayer::CPlayer() { }Jo, wer weis was man hier alles so lernt zusammen, aber ein versuch isses sicherlich Wert!
-
Würde auch wohl mitmachen, da ich noch nie etwas größeres gemacht hab.

-
Flutscherino:
Bitte schreib kein C vor Klassennamen, das ist total 90er. Eine Methode Init()? Was soll das? Dafür hast du einen Konstruktor. Globales using namespace std; ist schon kontrovers, aber in einer Header Datei? Autsch.
InputName als Methode von Play macht gar keinen Sinn, die Klasse sollte im Konstruktor einen Namen erwarten, wo der her kommt, geht die Klasse nichts an. Wozu Membervariablen in einem struct verpacken? Macht so auch wenig Sinn. Zudem sind live und mana eher float/double, da sie durch verschiedene buffs etc. verändert werden können. exp, level und money könnten vielleicht eher unsigned sein, zumindest ein negatives Level macht irgendwie keinen Sinn. Zudem würde ich hier einen der Typen aus <cstdint> nutzen, sodass die immer eine Feste größe haben. exp > 2^16-1 kann durchaus vorkommen denke ich, und da will man ja nun keine Probleme bekommen. Macht das Serialisieren auch gleich einfacher. Für die Init() Methode der Game Klasse gilt das gleiche wie oben. Konstruktor lautet das Stichwort.Hui, so viele Fehler in so wenig Code, das schafft man nur mit C++.

-
Hmm danke schonmal für die Aussagen, aber macht eine Init nicht vielmehr sinn da ich steuern kann wann die aufgerufen wird? ich will ja vieleicht nicht immer, wenn ich das Objekt erstelle, das es das macht was in der Init steht...
z.b. eben genau überprüfen ob ich das Spiel schonmal gestartet hab vorher, das brauch ich ja wirklich nur 1mal.
oder seh ich was falsch?
jojo, ich muss ncoh soviel lernen... CClassName ist einfach irgendwie soviel einfacher? vorallem am anfang muss ich da nich immer überlegen was jetzt das is, hab schon sonst zuviel zum überlegen

Membervariablen in ner Struct halt deswegen damit ich weis wozu die gehören, wer weis was später noch in die Spieler Klasse kommt das vieleicht nicht explizip zum Spieler gehört...
das mit den Typen stimmt, hab ich mir noch gar nich überlegt, hab einfach standart int genommen weil ich es mir gewöhnt bin ^^
-
Flutscherino schrieb:
z.b. eben genau überprüfen ob ich das Spiel schonmal gestartet hab vorher, das brauch ich ja wirklich nur 1mal.
Na für alles, was du am Anfang nur genau ein mal brauchst, ist der Konstruktor doch prädestiniert.
Flutscherino schrieb:
Membervariablen in ner Struct halt deswegen damit ich weis wozu die gehören, wer weis was später noch in die Spieler Klasse kommt das vieleicht nicht explizip zum Spieler gehört...
Logisch wäre es andersherum. Was direkt zum Spieler gehört, ist einfach ein normales Member. "Anhängsel", wie z.B. ein Inventar oder was weiß ich, kannst du dann mit einer neuen Klasse verwirklichen (die wiederum Member vom Spieler sein kann).
Wenn dein Spieler irgendwann aber sehr, sehr viele Attribute mit sich schleppt, finde ich es durchaus in Ordnung, die noch mal in structs zu gruppieren (sofern die wirklich alle in der Spieler-Klasse am rechten Platz sind).
-
Flutscherino schrieb:
jojo, ich muss ncoh soviel lernen... CClassName ist einfach irgendwie soviel einfacher? vorallem am anfang muss ich da nich immer überlegen was jetzt das is, hab schon sonst zuviel zum überlegen

CPlayer und SPlayer unterscheiden sich in einem Buchstaben. Ist das schonmal nicht optimal.
Aber:
Warum interessiert dich, ob Player eine struct ist oder eine class? Du weißst schon, dass eine struct genau wie eine class verwendet werden kann?gruß
syntax
-
Flutscherino schrieb:
Hmm danke schonmal für die Aussagen, aber macht eine Init nicht vielmehr sinn da ich steuern kann wann die aufgerufen wird? ich will ja vieleicht nicht immer, wenn ich das Objekt erstelle, das es das macht was in der Init steht...
Der Konstruktor dient zur Initialisierung und danach sollte das Objekt idealerweise in einem gültigen Zustand sein. Wenn du mehr Steuermöglichkeiten haben willst, wird dies eher durch eine statische Fabrikmethode etc. gemacht.
Flutscherino schrieb:
CClassName ist einfach irgendwie soviel einfacher?
Warum einfacher?
1. Der Klassenname wird dadurch länger
2. Bei einigen (u.a. bei mir) nimmt die Lesegeschwindigkeit ab, da ich beim Lesen Worte erwarte, und nicht noch irgendwelche Präfixe.Flutscherino schrieb:
...vorallem am anfang muss ich da nich immer überlegen was jetzt das is,...
Dann hast du schlechte Klassennamen gewählt und ggf. auch eine schlechte IDE. Was sollte "Spiel" (um in der deutschen Nomenklatur des Threadersteller) den deiner Meinung nach sein?
Bei einer Funktion erwarte ich eher ein Verb, bei einer Variable verwende ich grundsätzlich einen Kleinbuchstaben und ansonsten bleibt eigentlich nur die Klasse. Wenn ich wirklich einen Typ wissen muss, sollte die Entwicklungsumgebung etwas anbieten (wie z.B. Intellisense bei MSVC).
Flutscherino schrieb:
Membervariablen in ner Struct halt deswegen damit ich weis wozu die gehören, wer weis was später noch in die Spieler Klasse kommt das vieleicht nicht explizip zum Spieler gehört...
Dann verschiebt man sie, wenn man es feststellt das sie da unsinnig sind. Warum eine unnötige struct, wo sie nach deiner Argumentation ggf. auch nicht richtig angeordnet sein können.
Und eine Regel an die sich alle halten sollten, die an einem gemeinsamen Projekt arbeiten: Einigt euch zumindest grundsätzlich auf die Formatierung und Sprache.
-
Ich hatte mir das etwas abstrakter eher so vorgestellt:
enum class Ruestungsart{Helm,Brustpanzer,Beinpanzer,Armband,Ring,Halskette,Schuh,Schild}; struct Basis_gegenstand { Basis_gegenstand(const std::string& n,int w):name(n),wert(w){} Basis_gegenstand():Basis_gegenstand("",0){} std::string name; int wert; virtual ~Basis_gegenstand(){} }; class Ruestungsteil:public Basis_gegenstand { int verteidigung; Ruestungsart art; public: Ruestungsteil(int v,Ruestungsart a,const std::string& name,int wert):Basis_gegenstand(name,wert),verteidigung(v),art(a){} ~Ruestungsteil(){} };Die anderen Gegenstände kann man ebenfalls davon erben lassen. Dann ist es z.B. viel einfacher das Inventar zu gestalten (Polymorphie).
Die Konstruktoren habe ich nur so hingeschrieben um das kurz zu testen. Das müsste man sich genauer überleben, jenachdem wie man die überhaupt verwenden will.
-
Nymer schrieb:
Basis_gegenstand(const std::string& n,int w):name(n),wert(w){}1. Die Unterstriche würde ich im Namen vermeiden, und wenn sollte Gegenstand wohl Groß geschrieben werden. Ich würde hier entweder "BasisGegenstand" oder wenn schon mit Unterstrich "Basis_Gegenstand" oder warum nicht einfach "Gegenstand" verwenden. Eine Rüstung ist ein Gegenstand, das Basis dient da aller höchstens als Markierung das es sich um eine Basisklasse handelt.
2. Bitte alleine schon für andere Leser: Kürze niemals, auch nicht Parameter, kryptisch ab.
Gegenstand(const std::string& name, int wert) : name(name), wert(wert) {}Ist sicherlich lesbarer, da man bereits an der Deklaration alles ablesen kann, ohne die Initialisierung zu bemühen (die ja in der Regel in der Sourcedatei steht und nicht im Header).
zu guter Letzt: Leerzeichen können die Lesbarkeit erhöhen

(Ich würde z.B. class Ruestungsteil:public Basis_gegenstand nicht so quetschen, in einem Satz würde man ja auch Leerzeichen erwarten).
-
enum classBasisgegenstand() : Basisgegenstand("",0)Warum nicht den Konstruktor gleich so schreiben:
Basisgegenstand(std::string n = "", int w = 0);Warum einmal struct und dann class?
was ist wert? Rüstungswert? oder doch wie viel wert die Rüstung ist?gruß
syntax