Tag 2 Look-up-Tabellen, Zufallszahlen, Listen, Speichermanagement und Dateiverwaltung 17.10.2007 Quelle: 3D-Spiele mit C++ und DirectX in 21 Tagen, Alexander.

Slides:



Advertisements
Ähnliche Präsentationen
Imperative Programmierung
Advertisements

der Universität Oldenburg
Klassen - Verkettete Liste -
Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste falls n=0 Listenelemente besitzen.
der Universität Oldenburg
Datenstrukturen Look-Up Tabellen, Zufallszahlen, Listen, Speichermanagement und Dateiverwaltung.
Ultris Version 8: Erzeugen der Formen und Anzeigen der Vorschau
Java: Objektorientierte Programmierung
Sortierverfahren Richard Göbel.
Java: Dynamische Datentypen
Listen Richard Göbel.
Indirekte Adressierung
Java: Grundlagen der Sprache
Java: Referenzen und Zeichenketten
Dynamischer Speicher und Struktur
Polymorphie (Vielgestaltigkeit)
Polymorphie (Vielgestaltigkeit)
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (13 – Offenes Hashing) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (05 – Elementare Datenstrukturen) Prof. Th. Ottmann.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 6 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 9 Claudio Moraga; Gisbert Dittrich FBI Unido
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 7 Claudio Moraga, Gisbert Dittrich FBI Unido
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
Zusammenfassung Vorwoche
Einführung in Visual C++
Arrays,Strings&Pointer in C/C++
Wir müssen also überlegen: Implementierung der Knoten, Implementierung der Kanten, daraus: Implementierung des Graphen insgesamt. Annahme: die Knoteninhalte.
Einfach verkettete Listen
Einfach verkettete Listen (OOP)
PRJ 2007/1 Stefan Dissmann Verkettete datenstruktur: Liste Problem: Liste, die eine beliebige Zahl von Elementen verwaltet Operationen: Erzeugen, Anfügen,
Einführung in die Programmierung
Informatik 1 Übung 8. NACHBESPRECHUNG Übung 8 Rekursion Existiert Weg von A nach B?
Programmieren in C Zeichen-/Stringfunktionen Dynamischer Speicher
Abteilung für Telekooperation Übung Softwareentwicklung 1 für Wirtschaftsinformatik Dr. Wieland Schwinger
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung
Einführung in die Programmiersprache C 3.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
EPROG Tutorium Einheit 4 Klassen und Objekte. Wiederholung Schleifen do... while while for break/continue Strings String char Methoden für Strings Arrays.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fakultät.
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2011/12 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung
Einführung in die Programmiersprache C 4
Informatik 1 Letzte Übung.
Dynamische Datentypen
Einfach und doppelt verkettete Listen in JAVA by Jens Weibler
Arrays / Felder Themen: Arrays / Felder / Vektoren Was soll das eigentlich? Erstellen von Arrays Arrays auslesen. Wie sie verwaltet werden.
EPROG Tutorium #3 Philipp Effenberger
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
CuP - Java Achte Vorlesung Entspricht ungefähr Kapitel 4.1 des Skriptums Montag, 28. Oktober 2002.
Java-Kurs - 3. Übung Hausaufgabe Arrays For-Schleifen.
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
1 // Verkettete Liste 2 // demonstriert verkettete Listen und // Rekursion // (Einfügen am "Fuß") // #include struct Liste { int Element; Liste *weiter;
Java Programme nur ein bisschen objektorientiert.
Pointer, Arrays und verkettete Listen. Mehrdimensionale Arrays  Pointer auf ein Array von Pointern  int32 **matrix = new int32*[3];  matrix: Zeiger.
Tutorium Software-Engineering SS14 Florian Manghofer.
Pointer. * und &  Bei der Definition int var1; ○ // „normale“ Variable int *var2; ○ // Zeiger auf einen Integer int *var2 = NULL; ○ // … incl. Initialisierung.
 Präsentation transkript:

Tag 2 Look-up-Tabellen, Zufallszahlen, Listen, Speichermanagement und Dateiverwaltung Quelle: 3D-Spiele mit C++ und DirectX in 21 Tagen, Alexander Rudolph, Markt+Technik Verlag

2.1 Look-up-Tabelle Besonders kritisch für die Performance bei Computerspielen: Berechnungen für die grafische Darstellung und die Simulation von KI Daher unser Ziel: optimierter Programmcode Rechenzeit sparen kann eine Look-up-Tabelle Zeitaufwendige Berechnungen, die sich im Programmablauf häufig wiederholen, werden bereits zum Spielstart (oder Start einer bestimmten Sequenz/Szene) durchgeführt und in eine Tabelle geschrieben Vor dem Erstellen einer Look-up-Tabelle muss festgestellt werden, für welche Funktionen dies Sinn macht und welche Genauigkeit die Tabelle einmal haben wird Beispiele für Funktionen, aus denen eine Look-up-Tabelle bestehen könnte: Sinus, Kosinus, Arkuskosinus, Quadratwurzel...

Auszug Beispiel LookUp 1 #include #define SAFE_DELETE(p) {if(p) {delete (p); (p)=NULL;}} #define SAFE_DELETE_ARRAY(p) {if(p) {delete[] (p); (p)=NULL;}} float* SinLookUp = NULL; float* CosLookUp = NULL; float* ArcCosLookUp = NULL; float* WurzelLookUp = NULL; inline void Berechne_LookUpTabellen(void) { for(long winkel = 0; winkel < 360; winkel++) { SinLookUp[winkel] = sinf(winkel* f/180.0f); CosLookUp[winkel] = cosf(winkel* f/180.0f); } for(long i = 0; i < 2001; i++) { WurzelLookUp[i] = sqrtf(i/1000.0f); ArcCosLookUp[i] = 180.0f/ f*acosf((i f)/1000.0f); } inline float ReturnSineValue(float winkel) { return(SinLookUp[(long)winkel]); }

int main(void) { SinLookUp = new float[360]; CosLookUp = new float[360]; ArcCosLookUp = new float[2001]; WurzelLookUp = new float[2001]; Berechne_LookUpTabellen(); cout << "sin(45 DEG) = " << ReturnSineValue(45.0f) << endl; SAFE_DELETE_ARRAY(SinLookUp) SAFE_DELETE_ARRAY(CosLookUp) SAFE_DELETE_ARRAY(WurzelLookUp) SAFE_DELETE_ARRAY(ArcCosLookUp) return 0; }

Klassische Funktion: Beim Funktionsaufruf springt der Compiler an die Stelle im Code, an der die gesuchte Funktion steht und führt sie dort aus. Sämtliche Parameter und die Rücksprungadresse müssen solang festgehalten werden. Inline-Funktion: Statt zur Funktion zu springen, ersetzt der Compiler den Funktionsaufruf im Code direkt durch den Funktionsinhalt. Vergrößert den Code, daher vor allem für kurze Funktionen geeignet. Kann dafür kleine Zeitersparnis bringen. Cast: (long)winkel wandelt die Variable vom Typ float in den Typ long um. Vorsicht geboten, C++ muss die Typenumwandlung auch wirklich durchführen können!

Klassen für Look-up-Tabellen Wünschenswert wäre eine Klasse für Look-up-Tabellen, die es erlaubt, dass ihre Genauigkeit flexibel bestimmt werden kann und die überwacht, dass nur zulässige Werte abgefragt werden Beispiel für Sinusfunktionen, im Beispielprogramm LookUp2 auch für Kosinus/Arkuskosinus/Quadratwurzel:

Auszug Beispiel LookUp2 class CSinLookUp { private: long AnzElements; float Genauigkeit; float* Tabelle; public: CSinLookUp(float Schrittweite = 1.0f) { Genauigkeit = 1.0f/Schrittweite; AnzElements = (long)(360*Genauigkeit); Tabelle = new float[AnzElements]; for(long winkel = 0; winkel < AnzElements; winkel++) { // Berechnung der Sinus Look-Up Tabelle Tabelle[winkel] = sinf(winkel*Schrittweite* f/180.0f); } ~CSinLookUp() { SAFE_DELETE_ARRAY(Tabelle) }

2.2 Zufallszahlen Zufallszahlen dienen vor allem dazu, den Spielablauf abwechslungsreich zu gestalten Zufallszahlengenerator muss zunächst initialisiert werden: Funktion srand() Als Argument dient Funktion GetTickCount() oder time() Srand(time(0)) startet den Generator auf Basis der Zeit in Millisekunden, die seit dem Systemstart vergangen ist Anschließend Zufallszahl generieren mit rand() bzw. long(rand())

Auszug Beispiel Zufallszahlen #include // Header für die Funktionen rand() und srand() #include float tempFrnd; inline float frnd(float low, float high) { tempFrnd = low + ( high - low ) * ( (long)rand() ) / RAND_MAX; if(tempFrnd < high) return tempFrnd; else return low; } int main(void) { // Initialisierung des Zufallsgenerators srand(time(0)); cout << frnd(-5.0f,5.0f) << endl;

Verknüpfen der Konzepte: Look-up-Tabelle mit Zufallszahlen füllen Auszug Beispiel ZufallszahlenKlasse class CLongRandomNumberList { private: long counter; // Diese Variable enthält das aktuelle Element der Zufallszahlen-Tabelle long AnzElements; long SmallestNumber; // kleinste Zufallszahl long HighestNumber; // größte Zufallszahl long* ZahlenListe; // Zeiger auf das Array ZahlenListe public: ~CLongRandomNumberList() { SAFE_DELETE_ARRAY(ZahlenListe) }

CLongRandomNumberList(long Anzahl, long s, long h) { srand(time(0)); // Initialisierung des Zufallsgenerators AnzElements = Anzahl; SmallestNumber = s; HighestNumber = h; ZahlenListe = new long[AnzElements]; // Erzeugung der Zufallszahlen: for(counter = 0; counter < AnzElements; counter++ ) ZahlenListe[counter] = lrnd(SmallestNumber, HighestNumber); counter = 0; //Variable wird auf das erste Element der Zufallszahlen-Tabelle gesetzt. } long NeueZufallsZahl() { if(counter < AnzElements-1) counter++; // counter wird auf das nächste Element der Tabelle gesetzt. else counter = 0; // falls counter schon auf letztem Element return ZahlenListe[counter]; }

2.3 Einfach verkettete Listen Struktur einer EvL: Head -> Node -> Node ->... -> Node -> Tail (-> NULL) Jedes Element der Liste besteht aus einem Objekt und einem Zeiger auf das jeweils nächste Objekt Das Objekt kann ein Klassenobjekt sein, aber auch eine mit struct erzeugte Strukturvariable Wichtige Operationen zum Verwalten einer verketteten Liste: - Initialisieren der Liste - neuen Knoten hinzufügen - einen Knoten löschen - die Liste durchlaufen (z.B. suchen) - die Liste löschen Beispiele für die Implementierung dieser Operationen im Programm SimpleLinkedList

2.4 Ein eigener Memory-Manager Verkettete Listen für Spieleprogrammierung nicht unbedingt optimal, da häufig die ganze Liste durchlaufen werden muss und die Spielobjekte selten in der Reihenfolge gebraucht werden, in der sie in der Liste liegen Alternative Array Nachteil: statische Größe, eventuell Speicherverschwendung Vorteil: schneller Zugriff auf einzelne Elemente, der Größe des Arrays sollten ohnehin Grenzen gesetzt sein (z. B. maximale Anzahl darstellbarer Objekte) Nicht mehr benötigten Speicherplatz unbedingt wieder freigeben, Speicherfragmentierung vermeiden! Speicherverwaltung bei 3D-Anwendungen besonders kritisch

Auszug Beispiel MemoryManager class CObject_Memory_Manager { private: CObject* pObject; long Element_Unbenutzt; long NoMore_Element; long* pReadingOrder; // Zeiger auf pReadingOrder-Array long* pUsedElements; // Zeiger auf pUsedElements-Array long ActiveElements; // Anzahl der aktiven Elemente long Size; // Arraygröße

In diesem Modell stehen drei Arrays im Mittelpunkt: -ein Array aus Objekten der Klasse CObject pObject = new CObject[Size]; Dort sollen die tatsächlichen Spielobjekte, in der Reihenfolge ihrer Erstellung, abgelegt werden. -ein Array aus long-Integern pReadingOrder = new long[Size+1]; Dieses Array hält die Reihenfolge fest, in der die Objekte – wie auch immer – verarbeitet werden sollen (pReadingOrder[0] enthält also die ID-Nummer des Objektes, das gerade die höchste Priorität besitzt). -ein weiteres Array aus long-Integern pUsedElements = new long[Size] Listet auf, welche Elemente des pObject-Arrays mit welcher ID belegt sind, oder enthält einen bestimmten Wert (Element_Unbenutzt), falls das Element noch frei ist.

Mithilfe dieser 3 Arrays wesentlich dynamischere Speicherverwaltung: -direktes Ansprechen eines Objektes im Speicher möglich, kein Durchlaufen der verketteten Liste mehr nötig -Objekte können entweder mit ihrer Index-Nummer angesprochen werden (Position 0, 1, 2 im Array pObjects...) oder nach ihrer Position in der ReadingOrder -effektiver für Spieleprogrammierung Beispielprogramm MemoryManager enthält Routinen zum Initialisieren der Objekte, Durchlaufen nach ReadingOrder, Löschen einer bestimmten Position in der Reading Order, Löschen einer bestimmten Index-Nr. und Löschen aller Objekte Destruktor der Klasse muss alle erstellen Arrays löschen!

2.5 Dateiverwaltung Auszug aus Beispiel Dateiverwaltung, Ziel: eine Datei finden und den Dateinamen einlesen #include struct _finddata_t c_file; long hFile; long pos = 0; const long MaxLength = 100; char TempStrategisches_ScenarioName[MaxLength]; char Strategisches_ScenarioName[2*MaxLength]; void Select_Spielvariante(long Strategische_ScenarioNr = 1 );

int main(void) { Select_Spielvariante(1); printf("%s\n", Strategisches_ScenarioName); Select_Spielvariante(2); printf("%s\n", Strategisches_ScenarioName); Select_Spielvariante(3); printf("%s\n", Strategisches_ScenarioName); return 0; } void Select_Spielvariante(long Strategische_ScenarioNr) { long SavedStrategicScenarioDateiNr = 0; memset(Strategisches_ScenarioName, '\0', 2*MaxLength); if( (hFile = _findfirst( "Szenarien/*.*", &c_file )) != -1) {

while( _findnext( hFile, &c_file ) == 0 ) { if( SavedStrategicScenarioDateiNr == Strategische_ScenarioNr) { memset(TempStrategisches_ScenarioName, '\0', MaxLength); for(pos = 0; pos < MaxLength; pos++) { if( c_file.name[pos] == '.') break; TempStrategisches_ScenarioName[pos] = c_file.name[pos]; } } // string der zu ladenen Datei zusammensetzen: strcpy(Strategisches_ScenarioName,"Szenarien/"); strcat(Strategisches_ScenarioName,TempStrategisches_ScenarioName); strcat(Strategisches_ScenarioName,".txt"); SavedStrategicScenarioDateiNr++; } _findclose(hFile); }

Strcpy(y,x)kopiert String x in String y Strcat(y,x)hängt String x an String y an Memset()sauberes Reinitialisieren eines Strings Struct _finddata_tenthält alle wichtigen Informationen für die Dateiarbeit _findfirst()testet, ob eine Datei oder ein Ordner existiert _findnext()wählt die nächste Datei im Ordner an _findclose() beendet die Interaktion mit dem Dateisystem