Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

11

27.07.2013, 13:45

Nicht nur sollten, natürlich sind die in VC 2010 verfügbar.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

12

27.07.2013, 14:09

Du musst, wenn du sie für irgendwas benutzen willst, memory.h inkludieren.

EDIT: Heut ist nicht mein Tag ;(

MfG
Check

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Checkmateing« (27.07.2013, 15:10)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

13

27.07.2013, 14:10

Um Gottes Willen!
Bitte
#include <memory>
UND NICHT
#include <memory.h>
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

14

27.07.2013, 18:07

Ah ok danke, gut zu wissen, dachte die sind von boost und deswegen erst bei C++ 11 dabei. Wieder was neues gelernt.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

15

27.07.2013, 22:00

Die sind erst bei C++11 dabei und deswegen braucht man dort boost nicht mehr. Ich glaub Du verdrehst da einiges. VC 2010 unterstützt einiges von C++11. Ersteres ist ein Produkt von Microsoft, letzteres ist ein Standard.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

16

28.07.2013, 12:38

Ich hab die Framework Referenz da jetzt einfach mal rausgeworfen und hab das Sprite ins Unit_Managment geschoben. Solange es bei einem einfachen Sprite bleibt, wird es dort jetzt auch drin bleiben, sollte ich aber Animationen noch vorsehen, werd ich wohl früher oder später vor dem gleichen Problem wieder stehen, nur mit einer anderen Klasse dann.


Nein nein... Sprite gehört schon nach c_unit. das war schon richtig. Denn bei Sfml stellt ein Sprite quasi eine Instanz eines "Bildes" auf dem Bildschirm dar! Und du willst für jede deiner Einheiten doch ein neues bild (also es soll ja nicht nur ein bild zu sehen sein ;) ).
Deshalb, hat auch die Draw funktion keine weiteren Parameter! die setzt du nämlich vorher über setPosition, setRotation usw. (Würg... das ist echt etwas was ich an sfml hasse... naja ich hab mal einen test gemacht, und man kommt auch noch an die Hundert frames ran, wenn man in einem frame ein sprite mehrere tausend mal verändert (der test war allerdings auch alles andere als aussagekräftig))

Was ich an dem aber jetzt noch nicht verstehe, warum bekomme ich den Fehler wenn ich einen leeren Vector in einen anderen Vector schieben will? Das Object als einzelnes kann ich ja wieder in einen Vector schieben ohne das ich Probleme bekomme. Aber warum ausgerechnet bei dem doppelten Vector?

Ob ein vector gefüllt oder leer ist, macht beim kompilieren keinen Unterschied. Hier geht es nur um die Typen die die einzelnen Variablen haben. Ohne ein bisschen Code kann ich dir da allerdings nicht weiter helfen.

Die vernünftigste Lösung wäre also, sollte ich die Referenz drin behalten mögen, die c_units per new auf den Heap zu erzeugen oder? Ich frag deswegen noch, weil ich mir mit dem Aufbau des Programms noch nicht sicher bin, weil ich noch garnicht weiß was ich alles drin haben will. Also könnte es durchaus sein das ich später wieder einen Zugriff auf das Framework in der c_unit bräuchte. Oder der Fall im ersten Absatz trifft zu.

Du kannst ruhig einen Zeiger auf das framework in c_unit rein machen. Das Problem mit der Referenz vorher war ja, dass du deine einheit kopieren wolltest und eine Referenz nicht zugewiesen werden kann. Deshalb hast du diesen komischen Fehler von oben bekommen. Wenn du aber aus der Referenz ein Pointer machst, ist das kein problem mehr. Ich würde dir trotzdem vorschlagen, die einheiten (in form von c_unit) auf dem heap zu erzeugen (mit new). Den fehler von oben Hast du ja nur, weil du eine c_unit kopieren wolltest. Du must dir aber vorstellen, was deine c_unit modelieren soll (!!!) und das ist ja etwas (nämlich ein Raumschiff oder ein Soldat oder so) was man gar nicht kopieren kann (bzw. können soll). Ich meine jetzt damit nicht, dass es auf dem pc nicht möglich wäre aber in echt kopierst du ja auch keine raumschiffe. Ok es gibt zwar Klonen aber das ist meiner meinung nach nicht wie kopierend Zuweisen, sondern wie kopierend Erzeugen (Siehe hier für den Unterschied in C++). Genau das modelierst du, indem du deine Objekte auf dem Heap erzeugst, und dann nur noch Zeiger auf sie benutzt. Ein weiterer wahrscheinlich viel wichtigerer Grund ist aber, dass du dir durch das direkte benutzen der Klassen als value-typen die Möglichkeit verbaust Polymorphie (Also Vererbung und so) einzusetzten! Und du willst (!) Polymorphie einsetzten.

Aja ein toller nebeneffekt von der ganzen Aktion ist, dass du dann wieder die referenz auf das framework benutzen kannst ;) Was eigentlich schöner ist als ein pointer.

Nachoman hat nämlich schon recht. Ein SmartPointer wäre hier fehl am platz (also es sei denn du hast wirklich schlaue pointer xD). Die frage ist doch wie die Abhängigkeiten, bezieungen und vor allem wie die Lebensspannen sind.
framework wird (und sollte ;)) auf jeden fall die Lebensdauer von jeder c_unit überstehen. Weiterhin gilt, dass die referenz auf framework eigentlich von anfang an vorhanden sein soll und sich auch niemals ändert (gibt ja keine zwei frameworks).
Da c_unit framework nicht zerstören darf/will/wird, ist ein smart_ptr überflüssig. Gerade im fall von shared_ptr kann es eher die gefahr von zyklen geben, wenn man einen smart_ptr benutzt um auf c_unit zu zeigen. das beste wäre also tatsächlich die referenz
bei zu behalten und ggf. den =operator zu definieren (was man nicht braucht, wenn man das Objekt nicht kopieren will). Für ein Framework wäre meiner Meinung nach auch eine globale Variable ok, obwohl ich es auch gerne vermeide.

PS: falls du doch den =operator überladen willst, dann kannst du die referenz einfach unberührt lassen, weil die zeigt ja schon auf das richtige und muss deshalb noch nochmal gesetzt werden.

17

28.07.2013, 15:37

@BlueCobold

Anscheinend. Ich dachte die beiden Pointer sind von Boost und Boost wird ja in den C++ Standard integriert oder teile davon soweit ich das verstanden hab oder? Dann dachte ich noch das erst mit Visual Studio 2012 was von C++ 11 unterstützt wird. Aber liegt wohl ganz einfach daran das ich mich damit auch nie befasst habe wie das wirklich ist, nur nebenbei in Foren immer etwas gelesen und den Rest selbst dazugereimt.


@Databyte

Wegen dem Sprite, ich hab mir einfach neben meinem Vector mit c_unit, einen Vector mit sf::Sprites erstellt, womit wieder für jede ein Sprite vorhanden ist. Aber das hatte ich vorher auch nicht genau so aufgeführt gehabt.

Wegen dem in den Vector schieben:

C-/C++-Quelltext

1
2
3
4
5
std::vector< c_unit >  test;

c_unit temp;

test.push_back( temp );


Der Code hier hat funktioniert, obwohl ich ja trotzdem eine Kopie von temp im Vector erstelle oder? Ich konnte ihn auch Problemlos mehrmals reinschieben.

Der Fehler ist erst hier aufgetreten, sobald ich einen doppelten Vector hatte:

C-/C++-Quelltext

1
2
3
4
5
std::vector< std::vector< c_unit >  >  test;

std::vector< c_unit > temp;

test.push_back( temp );


Warum hier das eine Funktioniert und das andere nicht meinte ich? Sieht man auch im Code auf der ersten Seite, da hatte ich auch kommentiert das das eine geht und das andere den Fehler produziert. Ich hatte zuerst den Code schon mit einem einfachen Vector wo er halt Problem los lief, hab ihn dann auf den doppelten Vector gewechselt, wegen verschiedenen Einheiten Gruppen ( Spieler , Verbündete, Gegner ) und schon hatte ich den Fehler.

Polymorphie, Vererbung werde ich wahrscheinlich garnicht brauchen. Ich habs in einem meiner aller ersten Programme schon mal verwendet, seit dem bin ich immer ohne ausgekommen. Um es etwas zu erklären warum ich es wahrscheinlich nicht brauchen werde. Bei meinem letzten Spiel was ich angefangen hatte, standen z.b. die Einheiten Daten alle in einer Text Datei. Jede Einheit die ich erstellt habe war die komplett gleiche Klasse, die Daten wurden einfach von der Text Datei dann eingelesen. Sie hatten zwar auch noch verschiedene Fertigkeiten, aber dafür gabs eine eigene Fertigkeiten Klasse die jede mögliche Fertigkeit darstellen konnte. Anhand des Textes den ich eingelesen hab, wurde festgelegt wie die Fertigkeit genau funktioniert. Dazu sollte ich sagen, das System hat auch Komplexe Fertigkeiten erlaubt, die sich durch beliebige Effekte, komplett ändern konnten und das ohne Vererbung oder Polymorphie.

Bei dem aktuellen Project, leben die c_unit Objecte solange wie der Kampf dauert. Ich lad sie am anfang einfach und erst sobald der Kampf zuende ist werden sie gelöscht, es werden aktuell auch keine neuen c_units während des Kampfes erstellt. Aber das kann sich alles noch ändern. Da ein Kampf so 30-60min dauert, ist ihre Lebensdauer auch ziemlich lange. Aber wegen manchen Ideen schwanke ich sehr schon es auf den Heap anzulegen. Sollte vielleicht dazu sagen ich vermeide meistens Pointer einsetzen zu müssen, wenn ich es irgendwie anders vernünftig lösen kann. Deswegen warte ich da immer relativ lange bis ich mich dazu Entscheide welche einzusetzen. Das Framework später wieder reinzusetzen, wenn ich sie auf den Heap erzeuge ist eine Kleinigkeit, aber zuerst will ich schauen wie sich das ganze Entwickelt und ob es auch Spass macht.

Für etwas mehr Einblick, die c_units bewegen sich auf Hexfeldern rundenweise. Was die lange Kampfdauer erklären dürfte. :D

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

18

28.07.2013, 17:01


Der Fehler ist erst hier aufgetreten, sobald ich einen doppelten Vector hatte:

C-/C++-Quelltext

1
2
3
4
5
std::vector< std::vector< c_unit >  >  test;

std::vector< c_unit > temp;

test.push_back( temp );


Warum hier das eine Funktioniert und das andere nicht meinte ich? Sieht man auch im Code auf der ersten Seite, da hatte ich auch kommentiert das das eine geht und das andere den Fehler produziert. Ich hatte zuerst den Code schon mit einem einfachen Vector wo er halt Problem los lief, hab ihn dann auf den doppelten Vector gewechselt, wegen verschiedenen Einheiten Gruppen ( Spieler , Verbündete, Gegner ) und schon hatte ich den Fehler.


Ja das Problem ist immer noch das gleiche: eine Referenz nach der Initialisierung zuzuweisen, geht nicht. Das problem ist, dass push_back das objekt welches du übergibst kopiert; das Kopieren macht in dem fall aber der copy-konstruktor und da wird die Referenz dann initialisiert. Wenn du aber den vector bei push_back benutzt, dann wird zwar auch der vector kopiert aber der widerum muss intern seine objekte kopieren und dazu benutzt er den assignment operator. Du könntest es eventuell umgehen, indem du std::move benutzt:

C-/C++-Quelltext

1
2
3
4
5
std::vector< std::vector< c_unit >  >  test;

std::vector< c_unit > temp;

test.push_back( std::move(temp) );


Ich bin mir aber nur zu 98% sicher, dass das geht. Außerdem ist es nicht schön und du musst dann darauf achten, das temp dann leer ist (!).


Polymorphie, Vererbung werde ich wahrscheinlich garnicht brauchen. Ich habs in einem meiner aller ersten Programme schon mal verwendet, seit dem bin ich immer ohne ausgekommen.


Einer meiner Profs sagt immer: Wenn sie Polymorphie in oo-sprachen nicht einsetzten, dann haben sie es nicht verstanden :)
Aber ich glaub dir das es auch ohne geht.

Dazu sollte ich sagen, das System hat auch Komplexe Fertigkeiten erlaubt, die sich durch beliebige Effekte, komplett ändern konnten und das ohne Vererbung oder Polymorphie.

Kann man dazu code sehen? ich glaub dir das du es so gemacht hast, ich bin nur neugierig wie :)

19

28.07.2013, 20:21

Das mit std::move probier ich noch mal obs dann gehen würde.


Code zu dem Beispiel mit den Fertigkeiten zu Posten ist mir etwas zu schwer, vorallem da er keine Kommentare hat und ich bin mir nicht sicher ob man den alleine versteht wenn man den darunter liegenden Code nicht kennt der die Fertigkeiten dann benützt und auf die Daten zugreift. Am einfachsten ist es vllt so zu erklären, mit der Datei die ich einlese.


attacker;Alyna
50;2
0;Angriff;0;data;physical;close;stab;5
0;MAIN;kind_attack;close;free
0;MAIN;kind_target;target;1;1
0;ADD;data;physical;close;stab;4
0;OR;effect;self;Schattenmantel;0;data;physical;close;stab;5
0;OPT;name_change;Durchbohren
0;ADD;data;physical;close;stab;4
0;OPT;armor_ignore;2
1;Doppelklinge;2;data;physical;close;stab;8
1;MAIN;kind_attack;close;free
1;MAIN;kind_target;target;1;1
1;OR;effect;self;Kriegsschrei;0;data;physical;close;stab;9
1;AND;0;1;#;effect;self;Schattenmantel;effect;Blutung;3
2;Durchstoßen;3;data;physical;close;stab;7
2;MAIN;kind_attack;close;free
2;MAIN;kind_target;target;1;1
2;OPT;armor_ignore;2
3;Schatten;10;effect;Schattenmantel;6
3;MAIN;kind_attack;self
3;MAIN;kind_target;all


attacker;Alyna
50;2

attacker ist die Rolle des Charackters, wird für manche Skill zuweisungen benützt, also wenn einer nur auf Attacker gehen soll. Alyna dann der Name des Chars. 50 sind dann die Lebenspunkte und 2 die Rüstung.


0;Angriff;0;data;physical;close;stab;5
0;MAIN;kind_attack;close;free
0;MAIN;kind_target;target;1;1

So sieht ein Standard Skill aus, 0 vorne gibt an welcher Skill es ist, alles was mit 0 Anfängt gehört zu diesem Skill. Für die erste Zeile wird ein struct angelegt namens execution wo die Daten enthalten sind.

Angriff = Fertigkeiten Name
0 = Dauer bis der Skill wieder bereit ist
data = Das es sich um einen einfachen Wert handelt, Schaden oder Heilung
physical;close;stab = die Art des Wertes
5 = höhe des Wertes

Die zweite Zeile gibt an, welche Ziele erreichbar sind, für jedes Schlachtfeld ist das schon vordefiniert in einer anderen Datei. Hier ist die Close Angriffsart gewählt, wodurch er alle Nahkampfziele in reichweite erwischt. Attack arten habe ich in einem weiteren Struct gespeichert.

Die dritte Zeile gibt an, wieviele Ziele man Angreifen kann. Das wurde auch in einem Struct gespeichert.

Für die drei Struct gibt es je immer einen Vector wo sie gespeichert werden. Der execution struct weis wo sein zugehöriger Attack und Target struct ist.

Weil mit denen hier:

1;OR;effect;self;Kriegsschrei;0;data;physical;close;stab;9
1;AND;0;1;#;effect;self;Schattenmantel;effect;Blutung;3

kann man Skills noch weiter verändern.

mit OR kann ich dann Bedingungen abfragen.

effect = Ich frage einen Bestimmten Effect ab
self = Ob er auf mir selber liegt, ansonsten könnte man auch das Ziel angeben.
Kriegsschrei = der Effect Name
0 = hier gebe ich an auf welche execution sich das OR bezieht, wenn jetzt z.b. 1 stehen würde, könnte diese Bedingung nur ausgelöst werden, wenn schon die Vorbedingung ausgelöst worden war.
rest = die Angaben die in einer neuen Execution landen

Die OR Daten werden in einem neuem Struct gespeichert Namens reaction, die auch wieder in einem Vector liegen, darin ist auch festgelegt auf welche Execution sie zugreifen muss.

will ich für die OR Werte dann eine andere Angriffsart, kann ich einfach mit:

1;OR;effect;self;Kriegsschrei;0;data;physical;close;stab;9
1;OPT;kind_attack;range;free

Einem OPT festlegen das sich diese ändern soll. In der Execution des ORs werden die Attack und Target Daten des normalen Skills hinterlegt, außer ich ändere sie. Dafür wird dann in den Attack oder Target Vectoren ein neues Struct angelegt und die Position im Vector in der Execution des OR hinterlegt.

1;OPT;name_change;Wurfmesser

Das hier würde den Namen des Skills ändern, macht nur sinn wenn die Bedingung den Effect auf einem selbst abfragt.


Mit AND könnte ich dann zusätzlich noch etwas dazuschalten:

1;AND;0;1

mit den 0;1 lege ich fest, diese Bedingung wird auf die Execution auf Position 0 angewandt und auf die Execution auf Position 1 ( was das erste OR wäre )

effect;Blutung;3

hier wird statt dem data Wert, ein effect erschaffen. Das Ziel würde also unter Blutung leiden. Der Wert 3 Gibt an, dass dieser Effect 3 Runden dauert, welche Werte man hier angeben muss sind in den Effect Dateien definiert, das heißt hier nur, der Blutungs Effect hat keine im Standard festgelegte Dauer, sondern ich kann den bei jedem Skill der diesen Effect Anwendet, anders starten.

Zu dem allen könnte ich noch mit 0;ADD;data oder effect zusätzliche Werte in eine execution Laden.


Also im Grunde nur viele structs mit Daten, die in Vectoren liegen. Wenn eine Fertigkeit gestartet wird, schaut er sich die ganzen OR und AND Befehle durch um zu schauen ob dort eine Bedingung erfüllt ist und führt diese dann aus, falls nicht wird einfach der normale Skill geladen und ausgeführt.

Ähnliches gibts nochmal für die Effekte und sogar für die KI habe ich mir was gebastelt, weil ich keine Automatische KI schreiben konnte die sich mit allen Möglichkeiten auskennt, die über das System möglich sind. Vorallem da die Effekte noch komplexer sind.

Mein Ziel war damit halt gewesen, dass man einfach in den Textdateien den Skill definieren kann und das Programm sich dann damit auskennt. Hoffe es ist etwas verständlich was ich da verbrochen habe. :D


Ich sollte vllt noch dazusagen, ich hab mir C++ selbst beigebracht, zuerst ein paar extrem einfache Tutorials, auf irgend einer Seite zu Allegro. Dann einfach das Buch von Heiko Kalista "nur" durchgelesen und dann einfach angefangen das zu machen was ich wollte. Wenn ich noch am mein erstes Project mit SFML zurückdenke, was eigentlich noch garnicht sooo lange her ist, ein Jahr vllt. Da habe ich noch mehrere Gameschleifen ineinander gemacht. Also für das Menü gabs eine Gameschleife, dann für die Karte usw. Wenn ich dann das Spiel beenden wollte musste ich im Code den Beenden Befehl über alle Gameschleifen zurückgeben. *g* Es hat zwar auch gut Funktioniert, aber war trotzdem schlimm. ^^ Vorallem hatte ich an die 10 Gameschleifen dann, immer mit eigener Event Abfrage. :dash:

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

20

28.07.2013, 21:44

Ok sieht gut aus^^ also scriptsprachenähnlich... naja etwas abgespeckt ;)

Werbeanzeige