C++ Programm mit der SDL: Hintergundbild wird nur auf andern Rechnern nicht angezeigt

Abcd12345

Lt. Junior Grade
Registriert
März 2006
Beiträge
483
Problem gelöst

PROBLEM WURDE GELÖST!


Hi,

Ich Programmiere grade ein kleines Spiel mit der SDL. Dabei habe ich schon seit Tagen ein schwerwiegenes Problem. Die ganze Spielwelt ist ein großes Hintergrundbild 3000x1200 Pixel, wovon je nachdem wo der Spieler grade ist der entsprechende 800x600 große Ausschnit angezeigt wird. Dies Funktioniert bei mir auch wunderbar ohne jegliche Fehler sowohl wenn ich mein Projekt aus der Entwiklungsumgebung Visual Studio 2008 oder aus dem Ordner direckt durch anklicken der Exe starte. Wenn ich jetzt jedoch mein Projekt kopiere und auf einem andern Rechner starte wird das Hintergrundbild nicht mehr angezeigt und man sieht nur noch einen schwarzen Bildschirm..

Hier sind die Funktionen zum Rendern/Laden und Ubdaten des Bildes bzw AUschnitt des Bildes:

Code:
#include "Backgroundmap.h"


void CBackgroundmap::ScreenLoad ()
{
	    //Lädt das Hintergrundbild..
	m_SpriteBackground.Load_Backgroundmap(m_MapPfad, 800, 600);
	
}


void CBackgroundmap :: ScreenUpdate (CPlayer &Koordinaten)
{
	// Bildschirmausschnitt je nach Figurbewegung berechnen

	//Für X Koordinate

	//Wenn Spieler am Ende der Map (Rechts) ist nicht mehr mit ziehen
	if (Koordinaten.XRueckgabe () > Koordinaten.MapWidthMaxRueckgabe()  -415)
	{

		m_MapArea.x = Koordinaten.MapWidthMaxRueckgabe()  -800;

	}
	//Muss groeser 385 sein damit Bildschirm mit gezogen wird
	else if (Koordinaten.XRueckgabe () > 385)
	{
		//Bild schirm wird mitgezogen allerdings reduziert um den Anfangswert
		m_MapArea.x = Koordinaten.XRueckgabe ()-385;
	}

	else
	{

		m_MapArea.x = 0;
	}

	//Für Y Koordinate

	//Wenn Y kleiner 300 ist dann nicht mit ziehen
	if (Koordinaten.YRueckgabe () < 300)
	{
		m_MapArea.y = 0;
	}
	//Wenn Spieler nicht an einem Rand dann mitziehen
	else if (Koordinaten.YRueckgabe () < Koordinaten.MapHeightMaxRueckgabe()-300)
	{
		//Bild schirm wird mitgezogen allerdings reduziert um den Anfangswert
		m_MapArea.y = Koordinaten.YRueckgabe ()-300;
	}
	//Ansonsten Bildausschnitt bleibt ganz unten auf der Map
	else
	{
		m_MapArea.y = Koordinaten.MapHeightMaxRueckgabe()-600;
	}

}

void CBackgroundmap :: ScreenRender() 
{
	m_SpriteBackground.Render_BackgroundMap(m_MapArea.x, m_MapArea.y);
	
}

Hier dann noch die Funktionen die zu ScreenRende und ScreenLoad gehören:

Code:
// Render_BackgroundMap
//
// Aufgabe: Rendern des Spielabschnittes (Nur für Hintergrundbild)
//
	void CSprite::Render_BackgroundMap (int X ,int Y )
	{
		m_FrameRect.x = X;
		m_FrameRect.y = Y;
		
		
		// Ausschnitt rendern
		SDL_BlitSurface (m_pImage, &m_FrameRect, m_pScreen, &m_Rect);
        }

// Load_Backgroundmap
//
// Aufgabe: Backgroundmap laden (Nur für Backgroundmap)
//
void CSprite::Load_Backgroundmap (const string sFilename,int FrameWidth, int FrameHeight)
{
	// Bitmap laden
	Load (sFilename);

	// Rect für Animationsphase initialisieren
	m_FrameWidth  = FrameWidth;
	m_FrameHeight = FrameHeight;

} 

// Load
//
// Aufgabe: Einfaches, nicht animiertes Sprite laden
//
void CSprite::Load (const string sFilename)
{
  // Bitmap laden
  m_pImage = SDL_LoadBMP (sFilename.c_str());

  // Prüfen, ob alles glatt ging
  if (m_pImage == NULL)
  {
    cout << "Fehler beim Laden von: " << sFilename.c_str();
    cout << endl;
    cout << "Fehlermeldung: " << SDL_GetError () << endl;

    // Framework herunterfahren
    g_pFramework->Quit ();

    // Gesamtes Spiel beenden
    exit (1);
  }

Ich versuche echt schon seit Tagen den Fehler zu finden und komme nicht weiter und habe die Hoffnung das hier vieleicht jemand eine Potenziele Fehlerquelle entdecken kann..

Gruß Ancd

Edit: Auf Wunsch bin ich gerne bereit weitere Informationen, Codeausschnitt oder Screenshot zu veröffentlichen, wenn das eine Hilfestellung erleichtert :)
 
Zuletzt bearbeitet:
Lass dir doch mal den Pfadnamen, der verwendet wird, ausgeben.
Ich denke dass du hier einen Fehler gemacht hast... Wie ermittelst du denn den Pfadnamen des Hintergrundbildes?
Du solltest auch mit FileMon ausgeben lassen, auf welche Dateien dein Spiel zugreifen will.

Gruß
 
Der Pfad wird in der Main FUnktion bei der Erstellung der Instanz an die entsprechende Variabel übergeben:

Code:
#include <windows.h>
#include "framework.h"
#include "Sprite.h"
#include "Player.h"
#include "Enemy.h"
#include <iostream>
#include "timer.h"
#include "AreaScanning.h"
#include "Backgroundmap.h"
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")

int main (int argc, char *argv[])
{
	// Framework initialisieren	
	if (g_pFramework->Init (800, 600, 16, false) == false)
    return (0);


	CPlayer Player;
	CEnemy Enemy;
	CAreaScanning test(1136, 0, 0, 3000);
	CBackgroundmap Level1("Data/test.bmp");


	for (int i = 0; i != 10000; i++)
	{

		Level1.ScreenLoad();

		g_pFramework->Update ();
		cout << g_pTimer->GetElapsed () << endl;
		g_pFramework->Clear (); 

		
		Player.Update_Movement();


	if (Player.StatusRueckgabe() != 3)
	{
		if (test.Abfrage_Oben(Player) == true)
		{
			Player.StatusAnpassen(1);

		}
		else
		{
			
			Player.StatusAnpassen(2);
		}
	}

		Player.Update_Screen();

		Level1.ScreenUpdate(Player);
		Level1.ScreenRender();
		
		Player.Render();
		Enemy.Render(Player);


		g_pFramework->Flip ();

		//g_pFramework->Flip ();
	}




	

  
	return (0);

}

Hier wird ein lokaler Pfad übergeben der meiner Meinung nach absoult richtig ist, da sich die Map direckt im Projektverzeichnis im Ordner Daten befindet. Wenn der Pfad nicht richtig wäre würde das Bild ja auch bei mir nicht geladen werden, da ich ja "bewusst" mit lokalen und nicht absoluten Pfaden arbeite.

Hier nochmal die Erstellung der Klasseninstanz:
Code:
CBackgroundmap Level1("Data/test.bmp");

Und hier nochmal der Konstruktor der bei der Instanz erstellung aufgerufen wird:

Code:
CBackgroundmap (string Mappfad) {m_MapPfad = Mappfad; }

Hier wird dann der Mappfad in der Stringvariabel gespeichert damit man ihn später verwenden kann.


Ich hab jetzt auch mal versucht mir die Variablen und den Rückgabewert der SDL_BlitSurface Renderfunktion per Cout Befehle ausgeben zu lassen:

Code:
		// Ausschnitt rendern
		// Ausschnitt rendern
		if (SDL_BlitSurface (m_pImage, &m_FrameRect, m_pScreen, &m_Rect)== -1)
		{
			cout << "Fehler beim Rendern -> Unbekannter Fehler" << endl;
			cout << "Y Abschnitt des Bildes welcher gerendert wird: " << m_FrameRect.y << endl;
			cout << "X Abschnitt des Bildes welcher gerendert wird: " << m_FrameRect.x << endl;
			cout << "Y Abschnitt wo das Bild angezeigt wird: " << m_Rect.y << endl;
			cout << "X Abschnitt wo das Bild angezeigt wird: " << m_Rect.x << endl;
			if (m_pImage == NULL)
			{
				cout << "Kein Daten mehr in dem Zeiger für das  HintergrundBild gepeichert" << endl;
			}
			else
			{
				cout << "Hintergrundbild Adresse ist noch im Zeiger Gespeichert" << endl;

			}
			if (m_pScreen == NULL)
			{
				cout << "Zeiger für Bildschirm ist lehr" << endl;
			}
			else
			{
				cout << "Zeiger für Bildschirm zeigt noch auf Daten" << endl;

			}


		}
		else if (SDL_BlitSurface (m_pImage, &m_FrameRect, m_pScreen, &m_Rect)== 0)
		{
			cout << "Rendern erbrachte keinen Fehler" << endl;
			cout << "Y Abschnitt des Bildes welcher gerendert wird: " << m_FrameRect.y << endl;
			cout << "X Abschnitt des Bildes welcher gerendert wird: " << m_FrameRect.x << endl;
			cout << "Y Abschnitt wo das Bild angezeigt wird: " << m_Rect.y << endl;
			cout << "X Abschnitt wo das Bild angezeigt wird: " << m_Rect.x << endl;
			if (m_pImage == NULL)
			{
				cout << "Kein Daten mehr in dem Zeiger für das  HintergrundBild gepeichert" << endl;
			}
			else
			{
				cout << "Hintergrundbild Adresse ist noch im Zeiger Gespeichert" << endl;

			}
			if (m_pScreen == NULL)
			{
				cout << "Zeiger für Bildschirm ist lehr" << endl;
			}
			else
			{
				cout << "Zeiger für Bildschirm zeigt noch auf Daten" << endl;

			}
		}
		else if (SDL_BlitSurface (m_pImage, &m_FrameRect, m_pScreen, &m_Rect)== -2)
		{
			cout << "Fehler beim Rendern -> Zugriff auf den Viedospeicher verloren" << endl;
			cout << "Y Abschnitt des Bildes welcher gerendert wird: " << m_FrameRect.y << endl;
			cout << "X Abschnitt des Bildes welcher gerendert wird: " << m_FrameRect.x << endl;
			cout << "Y Abschnitt wo das Bild angezeigt wird: " << m_Rect.y << endl;
			cout << "X Abschnitt wo das Bild angezeigt wird: " << m_Rect.x << endl;
			if (m_pImage == NULL)
			{
				cout << "Kein Daten mehr in dem Zeiger für das  HintergrundBild gepeichert" << endl;
			}
			else
			{
				cout << "Hintergrundbild Adresse ist noch im Zeiger Gespeichert" << endl;

			}
			if (m_pScreen == NULL)
			{
				cout << "Zeiger für Bildschirm ist lehr" << endl;
			}
			else
			{
				cout << "Zeiger für Bildschirm zeigt noch auf Daten" << endl;

			}
		}

Die Cout ausgaben werden komischerweiße auch nur dann gemacht wenn ich das Projekt aus der Entwiklungsumgebung heraus teste. Wenn ich es per Exe starte dann werden sie auch nicht gemacht.. Ähnlich verhällt es sich auch mit einer Logfileklasse die ich erstellt habe um die selbe Funktion auf Herz und Nieren zu prüfen. Auch diese erstellt das Logfile nur wenn ich sie aus der Entwiklungsumgebung heraus starte..



Okey nach mehreren Tagen fehlersuche hab ich das Problem gefunden:

Ich muss die Exe aus dem Debugverzeichnis ins Hauptverzeichnis kopieren um das Programm mit der Exe starten zu können. Jetzt habe ich fälschlicherweiße angenomen, dass sich eben diese Exe auch immer automatisch updatet, wenn ich etwas am Programm verändere. Deswegen hab ich immer diese Exe auf einen andern Rechner kopiert und mich gewundert warum sich Anderungen immer nur bei mir auswirken..
 
Zuletzt bearbeitet:
Denk dran dass du das Programm auch als Release kompilieren kannst und das einen nicht unerheblichen Performancegewinn bringt ;) Aber weißt du ja wahrscheinlich
 
Zurück
Oben