|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 14.06.2007, 14:03 Titel: Screenshots mit individuellem Namen |
|
|
-------------------------------
Einleitung
-------------------------------
Ich habe die Funktion zum Screenshots erstellen aus dem Buch so erweitert, dass man jetzt nicht immer nur den Screenshot in einer Datei ablegt, sondern das man die Screenshots unter eigenen Namen in ein extra Unterverzeichnis ablegt.
Das bedeutet, das man so viele Screenshots machen kann, wie man mag, ohne das die alten überschrieben werden.
Im Beispiel werden die Dateien als PNG gespeichert.
-------------------------------
Entwicklungsumgebung
-------------------------------
Da ich hier die Klasse Direct3D aus dem Buch editiere, setze ich die Grundstruktur der Klasse vorraus. Des weiteren arbeite ich mit Visual C++ EE und dem DirectX SDK April 2007, dementsprechend also unter Windows (XP).
-------------------------------
Klassenheader
-------------------------------
Als erstes modifiziert man die Headerdatei der Klasse.
Dort fügt man einen optionalen Paramter hinzu, falls man den Screenshot unter einem bestimmten Namen speichern möchte:
CPP: | // Screenshot erstellen
void CreateScreenshot(char* name = NULL); |
-------------------------------
Die Methode
-------------------------------
Dann zur Funktion selber:
CPP: | // Screenshot erzeugen
void Cdirect3d::CreateScreenshot(char* name)
{
char Dateiname[100]; |
Als erstes wird überprüft, ob der Optionale Parameter immernoch NULL ist, oder ob er gesetzt wurde:
Wurde er nicht gesetzt, sit er also NULL. Nun gilt es, einen würdigen Dateinamen für den Screenshot zu erstellen.
Hierbei gebe ich dem Screenshot einen Namen in der Form: datum-zeit.png.
Dieser Dateiname enthält auch die Millisekunden, damit die Dateien sich nicht überschreiben, wenn man 2x in einer Sekunde einen Screenshot erstellen will.
Also fülle ich zuerst die Struktur systemtime mit den aktuellen Zeitdaten und hole mir Informationen über die aktuelle Zeitzone, damit anschließend die Zeit auf die aktuellen Zeitzonenoptionen angepasst wird (d.h.: Sommer- / Winterzeit, etc.).
Mit sprintf_s wird dann der Name erzeugt und in der Variablen Dateiname gespeichert:
CPP: | {
SYSTEMTIME systemtime; // Zeitstruktur mit Systemzeit
GetSystemTime(&systemtime);
TIME_ZONE_INFORMATION timezone; // Informationen über die Zeitzone
GetTimeZoneInformation(&timezone);
SYSTEMTIME time; // Zeitstruktur mit lokaler UTC-Zeit
SystemTimeToTzSpecificLocalTime(&timezone, &systemtime, &time);
// Dateiname festlegen (Datum + Zeit, für individuelle Dateinamen)
sprintf_s(Dateiname, sizeof(Dateiname),
"%d-%d-%d-%d-%d-%d-%d.png",
time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);
} |
Ist der name jedoch nicht NULL, wurde ein Dateiname übergeben. Dieser wird dann alternativ verwendet:
CPP: | else
{
strcpy_s(Dateiname, sizeof(Dateiname), name);
} |
Nun muss das Bildschirmfoto irgendwo gespeichert werden.
Dazu wird hier ein unterverzeichnis namens screenshots definiert.
Anschließend wird überprüft ob es existiert, oder noch neu angelegt werden muss:
CPP: | char* Verzeichnisname = "./screenshots/";
// Verzeichnis ./screenshots/ erstellen, falls nicht vorhanden
if(GetFileAttributes(Verzeichnisname) != FILE_ATTRIBUTE_DIRECTORY)
CreateDirectory("screenshots", NULL); |
Nun müssen noch der Pfad und Dateiname zusammengefügt werden, damit sie später an die Funktion zum erstellen der Datei übergeben werden können. Dies habe ich einfach mit Strings gelöst. Wenn man bei char bleiben mag, kann man die char Variablen auch mit der Funktion strcnt_s(erste_var, sizeof(erste_var), anzuhaengende_var); aneinanderhängen.
CPP: | // Verzeichnispfad und Dateiname zusammenhängen
string DirAndFilename = Verzeichnisname;
DirAndFilename += Dateiname; |
Hier folgt dann der aus dem Buch bekannte Code. Es wird ein Surface erstellt, in das der aktuelle Inhalt des Frontbuffers gespeichert wird. SCR_WIDTH und SCR_HEIGHT sind bei mir Konstanten mit der Breite und Höhe des Fensters.
CPP: | // Surface für den Screenshot anlegen
LPDIRECT3DSURFACE9 lpScreenshotSurface;
this->m_lpD3DDevice->CreateOffscreenPlainSurface(
SCR_WIDTH, SCR_HEIGHT,
D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM,
&lpScreenshotSurface,0);
// Inhalt des Frontbuffers in das Surface kopieren
this->m_lpD3DDevice->GetFrontBufferData(0, lpScreenshotSurface); |
Nun wird dieses Surface als Datei gespeichert. Hier muss beachtet werden, das man den String (falls man Strings verwendet) mit c_str() in den Typ char konvertiert:
CPP: | // Surface in Datei speichern
D3DXSaveSurfaceToFile(DirAndFilename.c_str(), D3DXIFF_PNG, lpScreenshotSurface, NULL, NULL); |
Jetzt noch das Surface freigeben. Fertig.
CPP: | // Freigeben
lpScreenshotSurface->Release();
} |
-------------------------------
Aufrufen
-------------------------------
Nun kann man, nach dem man ein Objekt der Klasse erstellt und ggf. initialisiert hat, einen Screenshot wie folgt erstellen:
CPP: | Direct3D.CreateScreenshot(); |
Möchte man einen eigenen Dateinamen festlegen, dann so:
CPP: | Game.Direct3D.CreateScreenshot("moo.png"); |
-------------------------------
Schlussworte
-------------------------------
Ich hoffe es war verständlich, wenn nicht: bitte nicht hauen
Nehme gerne Verbesserungsvorschläge entgegen. _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt
Zuletzt bearbeitet von Asto am 14.06.2007, 16:05, insgesamt 5-mal bearbeitet |
|
Nach oben |
|
|
fast hawk Senior JLI'ler
Anmeldedatum: 15.07.2005 Beiträge: 237 Wohnort: Freiburg Medaillen: Keine
|
Verfasst am: 14.06.2007, 14:21 Titel: |
|
|
gute arbeit, nur würde ich millisekunde rausnehmen sonst wird der datei nahme zulang und UNICODE rein..... aber sonst STIFTUNG CODETEST: GUT^^ _________________ Jetziges Projekt: The Ring War
Status: 40%
-----------------------------------
Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.
--
Lucius Annaeus Seneca (4)
röm. Philosoph, Dramatiker und Staatsmann |
|
Nach oben |
|
|
Chriss Senior JLI'ler
Anmeldedatum: 18.08.2004 Beiträge: 267
Medaillen: Keine
|
Verfasst am: 14.06.2007, 14:23 Titel: Re: Screenshots mit individuellem Namen |
|
|
GreatFlo hat Folgendes geschrieben: | sondern das man die Screenshots unter eigenen Namen ... ablegt. |
Kann ich hier nciht finden
CPP: | char Dateiname[100];
// Dateiname festlegen (Datum + Zeit, für individuelle Dateinamen)
sprintf_s(Dateiname, sizeof(Dateiname),
"screens_%d%d%d-%d%d%d%d.png",
time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);
|
Eventuell noch die Übergabe eines optionalen Dateinames einbauen.
Ich finde deinen optimistischen Einsatz ja bewundernswert aber ein klein wenig mehr hätte es, für ein Tut., sein können. Vieleicht Erklärungen und mehr Funktionen.
EDIT: Wurde mittlerweile ja angepasst
Zuletzt bearbeitet von Chriss am 15.06.2007, 07:05, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 14.06.2007, 14:30 Titel: |
|
|
Nun okay, hätte eher in eine Funktionssammlung gehört, so wie ich es gepostet habe. :X
Werde es später mal eher in Richtung Tutorial editieren.
Die Millisekunden sind eingebaut, da man sonst nur einmal pro Sekunde ein Foto machen könnte _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
David Super JLI'ler
Alter: 39 Anmeldedatum: 13.10.2005 Beiträge: 315
Medaillen: Keine
|
Verfasst am: 14.06.2007, 15:20 Titel: |
|
|
Nummerier die Fotos doch pro Sekunde durch... Und ja, das ist egtl wirklich kein Tutorial. |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 14.06.2007, 15:28 Titel: |
|
|
hmm naja ich hoffe jetzt ist es eines
Pro Sekunde durchnummerieren == [...]_1.png, [...]_2.png, oder wie meinst du das? Könnte man machen... hmm, evt. baue ich es später ein.
was ich halt erstmal erreichen wollte, ist, dass man nicht immer nur eine datei hat, sondern das man so viele screens machen kann, wie man will.
Edit: Habe oben den Dateinamen etwas humaner gemacht ^^ _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
fast hawk Senior JLI'ler
Anmeldedatum: 15.07.2005 Beiträge: 237 Wohnort: Freiburg Medaillen: Keine
|
Verfasst am: 14.06.2007, 19:17 Titel: |
|
|
naja du könntest ja die millisekunden weglassen und stattdessen denn namen vor dem speicher überprüfen.
nach dem motto
CPP: | int Durchaehler = 0;
sprintf_s(Dateiname, sizeof(Dateiname),
"screens_%d%d%d-%d%d.png",
time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute);
while(!CheckDatei(Dateiname))
{
Durchaehler++;
sprintf_s(Dateiname, sizeof(Dateiname),
"screens_%d%d%d-%d%d_%d.png",
time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute, Durchzaehler);
}
| [/code] _________________ Jetziges Projekt: The Ring War
Status: 40%
-----------------------------------
Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.
--
Lucius Annaeus Seneca (4)
röm. Philosoph, Dramatiker und Staatsmann |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 17.06.2007, 18:19 Titel: |
|
|
also ich finde den jetzigen Stand des Tutorials gut. Es gibt zwar weite Umfangsspannen von Tutorials, und dieses gehört sicherlich zu einer etwas kleineren davon. Aber da du nun alles bis ins kleinste Detail ausführlich erläutert hast, denke ich dass es insb. für Programmieranfänger sehr gut geeignet ist, da du eben so detailliert vorgegangen bist und die einzelnen kleinen Schritte sehr umfangreich eingefasst hast
Gruß DXer |
|
Nach oben |
|
|
Kronos Senior JLI'ler
Anmeldedatum: 19.03.2004 Beiträge: 290
Medaillen: Keine
|
Verfasst am: 17.06.2007, 19:20 Titel: |
|
|
David hat Folgendes geschrieben: | Nummerier die Fotos doch pro Sekunde durch... Und ja, das ist egtl wirklich kein Tutorial. |
sagt wer? du? find ich amüsant.
nur weil du (wahrscheinlich) stundenlang an tutorials hockst und versuchst irgendwas perfektes rauszubringen, um respekt, genügend dankeschoens oder sonstwas zu ernten, um dein ego zu befriedigen..
das waere ja noch das beste, wenn du hier irgendwelche massstaebe fuer tutorials festlegst.
im prinzip geht es doch darum, dass wir von anderen noch was lernen koennen. das leute einfach mittels etwas text und code loesungen fuer probleme angeben, die wir alle sicherlich schonmal hatten oder die uns gerade beschaeftigen. dabei kommt es ueberhaupt nicht auf die komplexitaet des themas oder des codes an, oder auf irgendwelche anderen massstaebe. jeder, der denkt, etwas interessantes und hilfreiches hier beitragen zu koennen, soll es bitteschoen posten.
soweit kommts noch, dass du oder andere hier irgendwelche qualitativen und quantitativen bedingungen stellst, die jemand hier zu erfuellen haben muss.
in diesem sinne: danke fuer das tutorial, ich bin sicher damit ist hier einigen anfaengern oder kommenden leuten geholfen.
immer wieder schoen zu sehen, wenn leute mit anderen code, ideen und gedanken austauschen. _________________
David hat Folgendes geschrieben: | Solang meine Beiträge konstruktiver sind als deiner bin ich zufrieden... |
Kein Kommentar notwendig. :rolleyes: |
|
Nach oben |
|
|
David Super JLI'ler
Alter: 39 Anmeldedatum: 13.10.2005 Beiträge: 315
Medaillen: Keine
|
Verfasst am: 17.06.2007, 19:35 Titel: |
|
|
Kronos hat Folgendes geschrieben: | David hat Folgendes geschrieben: | Nummerier die Fotos doch pro Sekunde durch... Und ja, das ist egtl wirklich kein Tutorial. |
sagt wer? du? find ich amüsant.
nur weil du (wahrscheinlich) stundenlang an tutorials hockst und versuchst irgendwas perfektes rauszubringen, um respekt, genügend dankeschoens oder sonstwas zu ernten, um dein ego zu befriedigen..
das waere ja noch das beste, wenn du hier irgendwelche massstaebe fuer tutorials festlegst.
im prinzip geht es doch darum, dass wir von anderen noch was lernen koennen. das leute einfach mittels etwas text und code loesungen fuer probleme angeben, die wir alle sicherlich schonmal hatten oder die uns gerade beschaeftigen. dabei kommt es ueberhaupt nicht auf die komplexitaet des themas oder des codes an, oder auf irgendwelche anderen massstaebe. jeder, der denkt, etwas interessantes und hilfreiches hier beitragen zu koennen, soll es bitteschoen posten.
soweit kommts noch, dass du oder andere hier irgendwelche qualitativen und quantitativen bedingungen stellst, die jemand hier zu erfuellen haben muss.
in diesem sinne: danke fuer das tutorial, ich bin sicher damit ist hier einigen anfaengern oder kommenden leuten geholfen.
immer wieder schoen zu sehen, wenn leute mit anderen code, ideen und gedanken austauschen. |
Komm erstmal runter. Als ich das geschrieben habe war das Tutorial nurmehr ein Codefetzen und zwei Zeilen Text. Das ist maximal ein Codeschnippsel für eine Codedatenbank, oder sonstiges... So wie das Tutorial JETZT aufgebaut ist hab ich überhaupt keine Einwände mehr...
Also, erstmal langsam mit den Vorurteilen. |
|
Nach oben |
|
|
xardias JLI Master
Alter: 38 Anmeldedatum: 28.12.2003 Beiträge: 804 Wohnort: Palo Alto, CA Medaillen: Keine
|
Verfasst am: 17.06.2007, 19:42 Titel: |
|
|
Falls es da noch diskussionsbedarf gibt sollte man das von hier an am besten als private message fortführen.. das gibt doch nur wieder stress |
|
Nach oben |
|
|
Kronos Senior JLI'ler
Anmeldedatum: 19.03.2004 Beiträge: 290
Medaillen: Keine
|
Verfasst am: 17.06.2007, 19:59 Titel: |
|
|
David hat Folgendes geschrieben: |
Komm erstmal runter. Als ich das geschrieben habe war das Tutorial nurmehr ein Codefetzen und zwei Zeilen Text. Das ist maximal ein Codeschnippsel für eine Codedatenbank, oder sonstiges... So wie das Tutorial JETZT aufgebaut ist hab ich überhaupt keine Einwände mehr...
Also, erstmal langsam mit den Vorurteilen. |
ich habe sogar noch wahrscheinlich dazu geschrieben. also bitte nicht wieder irgendwo was reininterpretieren.
das ganze aendert nichts daran, dass du (und mMn. kein anderer hier) irgendwelche bestimmungen festlegen kannst, die ein beitrag hier zu erfuellen hat. 2 zeilen text und code koennen manchmal mehr helfen als irgendwelche z.B. langatmig, pseudolustige tutorials.
also lass doch das naechste mal einfach deine persoenlichen kommentare zum beitrag an sich, und trag lieber was konstruktives bei. dann ist auch alles in ordnung (und man demotiviert keine anfaenger, neulinge hier, auch wenn das nur eine vermutung ist)
schoenen abend dir noch. _________________
David hat Folgendes geschrieben: | Solang meine Beiträge konstruktiver sind als deiner bin ich zufrieden... |
Kein Kommentar notwendig. :rolleyes: |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 17.06.2007, 20:02 Titel: |
|
|
Nehmt euch (eigentlich nur kronos bisher) ein beispiel an den Worten von xardias, ansosten wird der Thread geschlossen und erst auf bitten des TE wieder eröffnet. _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
Maxim Senior JLI'ler
Anmeldedatum: 28.03.2004 Beiträge: 249
Medaillen: Keine
|
Verfasst am: 17.06.2007, 20:08 Titel: |
|
|
Déjà-vu |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 17.06.2007, 23:23 Titel: |
|
|
evt. ich noch zur aufklärung:
@kronos: habe es nicht kenntlich gemacht im 1. beitrag, sry, aber danke für deinen einsatz
an sich hatte david mit dem post ja recht, wobei du ansatzweise ja auch: ich ging halt davon aus, das es sich mehr oder weniger mit den kommentaren selbst erklärt, da ich ja nur ne funktion aus dem buch modifizierte.
ich habe zu beginn als er es geschrieben hatte nur die Einleitung gepostet, mit der gesamten funktion darunter, ohne die erläuterrungen.
daher wäre es eher was für eine funktionssammlung gewesen, als ein tutorial. insofern hatte er recht =)
aber nicht zanken _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|