Seite 1 von 2
Fehler beim Rendern meine Sprites
Verfasst: 13.04.2013, 22:31
von Ma_No
Guten Tag,
ich bin ziemlich neu in diesem Forum.
Erstmal möchte ich mich vorstellen ich heisse Matthias bin 17 jahre alt und gerade dabei
mir die Spieleprogrammierung zu lernen die ich später als Beruf ausüben möchte.
Ich stehe noch ziemlich am Anfang der 2D Programmierung und arbeite grade an einem kleinen
Projekt um mein frisch erworbenes Wissen zu festigen und auszubauen.
Und hier liegt das Problem ich komme einfach nicht weiter!
Ich bin in meinem Projekt jetzt soweit das ich ein Sprite rendern kann...theorethisch,
aber praktisch will das einfach nicht klappen!
ich habe mir einen header namens Render.h gemacht der das Rendern von den einzelnen Sprites
übernimmt indem ich die Sprite-Klassen wie z.B die Figur die man spielt von der klasse CRender erben lasse.
Aber irgentwas klappt da nicht!
Hier mal der Code vom Header Render.h:
Code: Alles auswählen
#ifndef RENDER_H
#define RENDER_H
#include <SDL.h>
class CRender
{
protected:
SDL_Surface *m_pScreen;
SDL_Surface *m_pImage;
SDL_Rect Pos;
SDL_Rect source;
int cur_frame = 1;
public:
void Render();
void Render(int framewidth, int frameheigth, int numframes);
~CRender(){}
};
void CRender::Render()
{
SDL_BlitSurface(m_pImage, &source, m_pScreen, &Pos);
}
void CRender::Render(int framewidth, int frameheigth, int numframes)
{
int numof_rows = frameheigth/source.h;
int row = numof_rows/(numframes/cur_frame);
source.x += source.w * (cur_frame-1);
source.y = frameheigth * row;
SDL_BlitSurface(m_pImage, &source, m_pScreen, &Pos);
cur_frame++;
if (cur_frame > numframes)
{
cur_frame = 1;
}
}
#endif // RENDER_H
und hier von der Figur die erben soll:
Code: Alles auswählen
#ifndef CMAN_H
#define CMAN_H
#include <SDL.h>
#include "Render.h"
class CMan : public CRender
{
public:
CMan();
~CMan();
void Man_Move(Uint8 *keystate);
};
CMan::CMan()
{
m_pImage = SDL_LoadBMP("Man.bmp");
Pos.x = 0;
Pos.y = 150;
source.x = 0;
source.y = 0;
source.h = 64;
source.w = 64;
cur_frame = 0;
}
CMan::~CMan()
{
}
void CMan::Man_Move(Uint8 *keystate)
{
if (keystate[SDLK_w] && Pos.y > 0)
{
Pos.y -=1;
}
if (keystate[SDLK_a] && Pos.x > 0)
{
Pos.x -=1;
}
if (keystate[SDLK_d] && Pos.x < 1000)
{
Pos.x +=1;
}
if (keystate[SDLK_s] && Pos.y < 800)
{
Pos.y +=1;
}
}
#endif // MAN_H
und hier nochmal die main():
Code: Alles auswählen
#include <SDL.h>
#include <fstream>
#include "CMan.h"
#include "CStone.h"
#include "CFramework.h"
using namespace std;
int main (int args, char *argv[])
{
g_pFramework -> Init(1024, 600, 32, false);
bool run = true;
CMan Man;
SDL_WM_SetCaption("Game project", NULL);
while (run)
{
Man.Render(256, 64, 4);
g_pFramework -> Flip();
g_pFramework -> Clear();
}
g_pFramework -> Quit();
return 0;
}
Bitte wundert euch nicht wenn ein paar Funktionen noch keinen Sinn haben mir geht es grade nur um das Rendern
und die Mechanik des Spiels kommt später.
Jedoch habe ich versucht ob ich manche Abläufe schon hinbekomme und wollte die ansätze nicht löschen
somit ist hier und da vielleicht etwas nutzloses drin.
Ich hoffe ihr könnt mir weiter Helfen denn ich komme einfach nicht vorran.
Danke schonmal :)
Re: Fehler beim Rendern meine Sprites
Verfasst: 13.04.2013, 23:13
von Niki
Hallo Ma_No :) Willkommen im Forum.
Also, von SDL habe ich keinen Plan, und auch habe ich grad sehr wenig Zeit. Aber auf die Schnelle erscheint mir folgende Zeile sehr merkwürdig:
Für mich sieht das so aus als würde source.x verflixt groß werden, wodurch dein Männchen sehr schnell verschwinden dürfte. Wollest du vielleicht "=" anstelle von "+=" nehmen?
EDIT: Ach, ja, wenn du BBCode "code=cpp" anstelle von "code" nimmst, dann passt auch die Einrückung. Und Syntax-Highlighting gibt's grats dazu. Ich musste das auch erst mal rausfinden :)
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 01:36
von Ma_No
Ah ja danke das hattich garnicht gesehen. :)
Mh aber leider hat das mein Problem auch nicht gelöst. :(
Ich versteh auch nicht wo der Fehler liegen könnte...
Und danke auch für den Tipp mit dem Code.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 03:13
von Niki
Also, ich glaube du solltest erstmal ein Männchen ohne Animation darstellen, um zu sehen ob das funktioniert. Auch würde es helfen wenn du erklären würdest wie sich dein Problem optisch bemerkbar macht.
Und dann solltest du bei der Animation deine Mathematik überprüfen. Momentan hast du da:
Code: Alles auswählen
int numof_rows = frameheigth/source.h;
int row = numof_rows/(numframes/cur_frame);
source.x += source.w * (cur_frame-1);
source.y = frameheigth * row;
Wenn ich das richtig sehe, dann hast du momentan ein Bild mit 4 Sprites. Jedes Sprite ist 64x64 Pixel groß. Und das Bild ist 256x64 Pixel groß. Ich komme auf ganz anderen Code:
Nichtsdestotrotz, ist bei deiner Rechnung
row = 0, wenn
1<=cur_frame<=3, und damit ist
source.y = 0. Für
cur_frame=4 ist
row=1, und damit ist
source.y = 64, was außerhalb des Sprite-Bildes ist. Dabei gehe ich jetzt davon aus, dass der Koordinatenursprung bei SDL in der linken oberen Ecke des Bildes ist, aber wissen tue ich das nicht wirklich. Wenn der Rest deines Codes funktioniert, dann würde das bedeuten das der letzte Frame nie gezeichnet wird, und dadurch ein Flackern entsteht.
Möglicherweise wolltest du etwas wie folgt erreichen:
Code: Alles auswählen
int numSpritesInX = spriteSheetWidth / source.w;
source.x = ((cur_frame-1) % numSpritesInX) * source.w;
source.y = ((cur_frame-1) / numSpritesInX) * source.h;
Hier habe ich spriteSheetWidth anstelle von frameWidth genommen, da die Namen frameWidth und frameHeight in diesem Kontext verwirrend sind.
Falls du vorher überhaupt nichts gesehen hast, dann nehme ich an, dass das nach diesen Änderungen immer noch so sein wird, und das irgendwo anders noch ein anderer Fehler ist.
Auch empfehle ich deine Frame-Nummerierung mit 0 anfangen zu lassen, und nicht mit 1. Dadurch ändert sich allerdings dein Code. Also erstmal A ans laufen bringen und dann B einbauen :)
EDIT: Habe den float-Kram aus dem letzten Stück Code rausgenommen. Aus irgendeinem, mir unbekannten Grund war ich davon ausgegangen, dass SDL_Rect floats benutzt. Ist aber nicht so.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 03:30
von Ma_No
Ja mit der linken oberen Ecke hast du Recht.
Aber das Problem liegt erstmal da das das Programm abstürtzt wenn diese Funktion aufgerufen wird.
Entschuldigung das hab ich nicht deutlich gemacht.
Das mit der Rechnung überprüfe ich gleich mal :)
Und das mit source.y = 0;
funktioniert ja nur so lange ich nur 1 reihe Animationsphasen habe denn wenn ich
16 Anim-Phasen habe möchte ich die doch gerne kompkat in 2-3 Reihen haben :)
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 03:38
von Niki
Abstürze können viele Gründe haben. Zum Beispiel, SDL falsch benutzt, oder Bild nicht geladen weil die Datei nicht gefunden wurde. Da ich keine SDL benutze kann ich das schwierig nachvollziehen.
So... und nun ist Zeit für die Heia. Ich penne hier schon im Sitzen.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 03:40
von Ma_No
Ok danke dir für deine Hilfe ich werd nochn bisl rumtüfteln :)
Gute Nacht wünsche ich.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 12:21
von Schrompf
Erzeugst Du denn irgendwo das m_pImage, was Du in CRender verwendest? Das kommt in Deinen Code-Ausschnitten nicht vor.
Allgemeiner Tipp: nimm eine Entwicklungsumgebung. Du hast leider nicht geschrieben, auf welchem Betriebssystem und mit welcher Umgebung Du bastelst, aber nahezu jede Entwicklungsumgebung hat einen Debugger. Und der zeigt Dir bei einem Absturz die exakte Zeile an, wo es passiert ist, und Du kannst in jeder Funktion bis zum Absturz nachschauen, welche Werte gerade in den Variablen stehen. Falls meine Vermutung richtig ist, dass m_pImage nie initialisiert wird, wirst Du es daran sehen, dass der Debugger Dir für m_pImage eine seltsame Zahl anzeigt - üblicherweise 0xcdcdcdcd oder so ähnlich. Und wenn Du dann versuchst, den Zeiger aufzuklappen, Dir also das Objekt anzuschauen, auf das der Zeiger verweist, dann siehst Du da nur Müll.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 12:40
von Niki
Schrompf hat geschrieben:Erzeugst Du denn irgendwo das m_pImage, was Du in CRender verwendest? Das kommt in Deinen Code-Ausschnitten nicht vor.
Das hast du nur übersehen, weil der Klassenaufbau bei einem Einsteiger natürlich noch nicht so ist wie bei einem alteingesessenen Hasen :) Schau mal im Konstruktor von CMan. Da ist allerdings keine Fehlerabfrage, und
m_pImage könnte evtl.
NULL sein und zu einem Crash führen. Aber halt nur eventuell.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 12:41
von Schrompf
Guter Einwand. Danke. Dann empfehle ich halt nur allgemein mal den Debugger :-)
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 12:54
von Niki
Schrompf, du warst aber schon verdammt nah dran, glaube ich :) Die Variable m_pScreen wird nämlich nirgendwo gesetzt und ist vollkommen uninitialisiert. Wie konnte ich das gestern nur übersehen....?!
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:39
von Ma_No
Ja der Fehler ist mir gestern noch aufgefallen aber danke.
Ähm ja der Absturz besteht leider immernoch und ich benutze Code::Blocks unter Windows 8.
Den Debugger habe ich schon oft gestartet aber die Zeile die angezeigt wird ist diese
glaube ich zumindest ich bin noch nicht so geübt im Umgang mit dem Debugger...
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:44
von Artificial Mind
Ma_No hat geschrieben:Ja der Fehler ist mir gestern noch aufgefallen aber danke.
Ähm ja der Absturz besteht leider immernoch und ich benutze Code::Blocks unter Windows 8.
Den Debugger habe ich schon oft gestartet aber die Zeile die angezeigt wird ist diese
glaube ich zumindest ich bin noch nicht so geübt im Umgang mit dem Debugger...
Gibt das nicht bei cur_frame == 0 Probleme?
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:46
von Ma_No
cur_frame kann nicht 0 werden ich weise der Variable immer den Anfangswert 1 zu.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:47
von Ma_No
Obwohl...moment
Also das habe ich auch noch nicht gesehen danke :)
Aber es stürtzt einfach immer wieder ab....
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:47
von Artificial Mind
Alternativ kann numframes == 0 sein und es knallt ;)
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:48
von Niki
Ma_No hat geschrieben:cur_frame kann nicht 0 werden ich weise der Variable immer den Anfangswert 1 zu.
Nein, tust du nicht :) Artificial Mind hat recht. Du hast mindestens eine Division durch 0, da der CMan Konstruktor cur_frame = 0 setzt.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 13:53
von Schrompf
Wenn Du im Debugger bist, der Dir gerade die Absturzstelle anzeigt, gibt es für Dich ein paar Sachen zu tun:
1) Schau Dir die Variableninhalte an. Meistens geht das durch Draufhalten der Maus auf die Code-Stelle, sonst gibt es auch meist ein "Watch"-Fenster.
2) Schau Dir den Callstack an. Besonders, wenn Du den Code nicht wiedererkennst, ist es sehr nützlich, sich die aufrufenden Funktionen anzuschauen, die zu dieser Stelle geführt haben. Im Callstack kannst Du Funktion für Funktion zurückgehen, bis Du in eigenem Code angekommen bist.
3) Manchmal zeigt der Debugger eine Zeile später als der eigentliche Absturzgrund. Studiere also auch die Zeilen rund um die angezeigte Zeile, prüfe die Variablenwerte und überlege, was das Ergebnis sein sollte.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:02
von Ma_No
@Niki Ja der Fehler ist mir schon aufgefallen und ich habe ihn behoben :)
Und die Watch List schliesst sich bei mir während des Debuggens und jetzt zeigt mir
der Call-Stack die Funktion
Code: Alles auswählen
void CRender::Render()
{
SDL_BlitSurface(m_pImage, NULL, m_pScreen, &Pos);
}
als Fehler an.
Also der zweite Parameter der NULL gesetzt ist steht für einen Bild ausschnitt und den brauche ich hier nicht.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:04
von Niki
Welche Werte haben denn m_pScreen und m_pImage im Debugger? (unter Autos und Locals nachschauen). Wie ich einige Posts weiter vorne geschrieben habe, ist mindestens dein m_pScreen nicht korrekt.
EDIT: Was das übrigens grad bedeutet ist das du schon einen Crash gefixt hast, nämlich die Division durch 0. Da du aber mehr als eine Crash-Stelle hast, bist du nun an der nächsten angekommen. Deshalb hält der Debugger jetzt auch an einer anderen Stelle. Es ist genau so wie Schrompf sagt... Debugger, Debugger, Debugger... das Teil ist ein super Kumpel.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:13
von Ma_No
Ihr habt Recht der Variable ist tatsächlich nicht Definiert...
Aber wie kann das sein als ich das bemerkt habe habe ich in den Konstruktor
von CMan noch diese Zeile eingefügt
Somit weise ich der Variable den Screen zu den die Klasse CFramework initialisiert und verwendet.
Oder nicht?
EDIT: Achso und die Funktion GetScreen() sieht folgendermaßen aaus:
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:25
von Niki
Aua! Da wird's jetzt schwierig. Erstmal überprüfen ob die Initialisierung des Frameworks überhaupt funktioniert:
Code: Alles auswählen
if (g_pFramework -> Init(1024, 600, 32, false) == false)
{
return 0;
}
Auf das "return 0;" setzt du einen Breakpoint. Einfach mit dem Cursor die Zeile anklicken und F9 drücken. Am linken Editorrand erscheint dann eine rote Kugel. Wenn die Initialisierung fehlschlägt, dann wird der Debugger an der roten Kugel anhalten.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:27
von Ma_No
Da läuft alles daas haabe ich schon auf anderem Wege abgefangen die Funktion Init
schreibt in eine Art Log ob aalles geklappt hat es wird also schon in der Funktion abgefangen.
EDIT: Tut mir leid wegen den ganzen doppel a's die Taste ist bei mir etwas Lediert.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:31
von Niki
Ma_No hat geschrieben:EDIT: Tut mir leid wegen den ganzen doppel a's die Taste ist bei mir etwas Lediert.
Mach die keine Gedanken. Aber ich würde mich freuen wenn du die Originalpost editieren würdest und "code" nach "code=cpp" änderst. Das macht's für uns auch einfacher :)
EDIT: Und vielleicht mal den aktuellen Quelltext posten. Der hast sich ja nun stark verändert.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 14:41
von Ma_No
Ok also der Header Render.h sieht jetzt so aus:
Code: Alles auswählen
#ifndef RENDER_H
#define RENDER_H
#include <SDL.h>
class CRender
{
protected:
SDL_Surface *m_pScreen;
SDL_Surface *m_pImage;
SDL_Rect Pos;
SDL_Rect source;
int cur_frame;
public:
void Render();
void Render(int framewidth, int frameheigth, int numframes);
virtual ~CRender(){}
};
void CRender::Render()
{
SDL_BlitSurface(m_pImage, NULL, m_pScreen, &Pos);
}
void CRender::Render(int framewidth, int frameheigth, int numframes)
{
int numof_rows = frameheigth/source.h;
int row = numof_rows/(numframes/cur_frame);
source.x = source.w * (cur_frame);
source.y = frameheigth * row;
SDL_BlitSurface(m_pImage, &source, m_pScreen, &Pos);
cur_frame++;
if (cur_frame > numframes)
{
cur_frame = 1;
}
}
#endif // RENDER_H
Der Header CMan:
Code: Alles auswählen
#ifndef CMAN_H
#define CMAN_H
#include <SDL.h>
#include "Render.h"
#include "CFramework.h"
class CMan : public CRender
{
public:
CMan();
~CMan();
void Man_Move(Uint8 *keystate);
};
CMan::CMan()
{
m_pScreen = g_pFramework->GetScreen();
m_pImage = SDL_LoadBMP("Man.bmp");
Pos.x = 0;
Pos.y = 150;
source.x = 0;
source.y = 0;
source.h = 64;
source.w = 64;
cur_frame = 1;
}
CMan::~CMan()
{
}
void CMan::Man_Move(Uint8 *keystate)
{
if (keystate[SDLK_w] && Pos.y > 0)
{
Pos.y -=1;
}
if (keystate[SDLK_a] && Pos.x > 0)
{
Pos.x -=1;
}
if (keystate[SDLK_d] && Pos.x < 1000)
{
Pos.x +=1;
}
if (keystate[SDLK_s] && Pos.y < 800)
{
Pos.y +=1;
}
}
#endif // MAN_H
und nu auch nochmal CFramework:
Code: Alles auswählen
#ifndef CFRAMEWORK_H
#define CFRAMEWORK_H
#include <SDL.h>
#include <fstream>
#include "CTime.h"
#include "Singleton.h"
#define g_pFramework CFramework::Get()
using namespace std;
class CFramework : public TSingleton<CFramework>
{
private:
SDL_Surface *m_pScreen;
Uint8 *m_pKeystate;
fstream Err;
public:
bool Init(int ScreenWidth, int ScreenHeigth, int colordepth, bool Fullscreen);
void Render();
void Clear();
void Flip();
void Update();
bool KeyDown(int ID);
void Quit();
SDL_Surface *GetScreen(){return (m_pScreen);}
};
bool CFramework::Init(int ScreenWidth, int ScreenHeigth, int colordepth, bool fullscreen)
{
Err.open("error.log", ios::out | ios::app);
if (SDL_Init(SDL_INIT_EVERYTHING) != 0 )
{
Err<<"\nCouldnt initialize SDL! ";
Err<<SDL_GetError();
}
else
{
Err<<"\nSuccessfuly initialized SDL!";
}
if (fullscreen == true)
{
m_pScreen = SDL_SetVideoMode(ScreenWidth, ScreenHeigth, colordepth, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN);
}
else
{
m_pScreen = SDL_SetVideoMode(ScreenWidth, ScreenHeigth, colordepth, SDL_HWSURFACE | SDL_DOUBLEBUF);
}
if (!m_pScreen)
{
Err<<"\nFailed to Set Video Mode\n";
Err<<SDL_GetError();
Quit();
}
else
{
Err<<"\nSuccessfuly Set Video Mode\n";
}
m_pKeystate = SDL_GetKeyState(NULL);
Err.close();
if (SDL_Init (SDL_INIT_EVERYTHING) > 0 && m_pScreen)
{
return (true);
}
else
{
return (false);
}
}
void CFramework::Clear()
{
SDL_FillRect(m_pScreen, NULL, 0);
}
void CFramework::Flip()
{
SDL_Flip(m_pScreen);
}
void CFramework::Update()
{
g_pTimer -> Update();
SDL_PumpEvents();
}
bool CFramework::KeyDown(int ID)
{
return (m_pKeystate[ID] ? true:false);
}
void CFramework::Quit()
{
SDL_Quit();
}
#endif // CFRAMEWORK_H
EDIT: Also das Problem scheint darin zu bestehen das m_pScreen nicht korrekt definiert wird.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 15:05
von Niki
Also, ich habe mittlerweile Probleme noch einen Absturzgrund zu finden.
Was mich aber interessieren würde... crasht es auch noch wenn du Man.Render(...) in der main() auskommentierst? (Clear und Flip aber drin lassen).
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 15:13
von Ma_No
Oh also:
Man.Render() ausgeklammert: Crash
g_pFramewor->Flip() und g_pFramework->Clear() ausgeklammert: crash
alles ausgeklammer: läuft
ergo:irgentwas stimmt mit der Klasse CFramework nicht oder?
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 15:16
von Niki
Ma_No hat geschrieben:ergo:irgentwas stimmt mit der Klasse CFramework nicht oder?
Möglich aber ungewiss. Ich gehe mal davon aus, das CFramework schon von tausend Leuten benutzt wurde. Kannst du mal im Build Menü deine Solution Cleanen und vollständig neu kompilieren? Sorry, aber ich kenne die deutschsprachigen Begriffe nicht. Solution ist glaube ich Arbeitsmappe oder was ähnlich seltsames.
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 15:26
von Ma_No
So habe ich gemacht und jetzt? :)
Re: Fehler beim Rendern meine Sprites
Verfasst: 14.04.2013, 15:32
von Niki
Ma_No hat geschrieben:So habe ich gemacht und jetzt? :)
Einfach nur schauen ob's was geändert hat. Es kommt selten mal vor, dass der Compiler Mist baut, wenn du schon länger keinen Rebuild hattest.
Eine allerletzte Sache würde ich jetzt gerne noch ausprobieren, und dann weiß ich auch nicht mehr weiter.
Kommentiere in deiner main() mal alles aus, was von dir ist. Es soll nur noch SDL Init, Flip, Clear, und Quit dableiben. Also SDL_WM_SetCaption auch auskommentieren. Die while-Schleife bleibt natürlich da.