SDL_Thread Problem
-
Hi
Ich habe ein kleines Problem mit SDL_Thread. Für mich ist C++ und SDL ziemlich neu Land!
Nicht das ihr jetzt denkt ich sei einer von denen die noch nie programmiert haben, ich hab bis jetzt eben nur JAVA, C, PHP, C# programmiert und dort verwendet man keine Pointer/Referenzen ausser bei C.Also zum Problem, ich habe eine Engine Kopiert von einer Website und ich wollte sie erweitern mit einem Thread und dem Handling, etc.
In der Klasse CMyEngine (Main.cpp), will ich in der main Methode den Thread erstellen und die Funktion Move von der Klasse CPlayer im Thread laufen lassen.
Dann erscheint dieser Fehler:
argument of type `int*(CPlayer::)(void*)' does not match `int ()(void)'Aus dem Fehler kann ich lesen das es kein Pointer/Referenz ist, falsche Definition von mir..
Kann mir bitte einer helfen oder ein Tipp geben, ich habe bis jetzt ziemlich alles was ich aus den anderen Programmiersprachen kenne ausprobiert, aber nix funktioniert.
Ich danke schon mal im voraus.Player.h
#ifndef PLAYER_H #define PLAYER_H class CPlayer { private: // Constants, Speed des Panzers int Drive_x_speed; int Drive_y_speed; //int Variablen, Koordinaten des Spielers int x_pos_left; int x_pos_right; int y_pos_up; int y_pos_down; // boolean Variablen, ist der Spieler am Fahren bool driving_left; bool driving_right; bool driving_up; bool driving_down; bool checkValue; public: bool getcheckValie(); /** Gibt die X Position Left zurück **/ int getXPosLeft(); /** Gibt die X Position Right zurück **/ int getXPosRight(); /** Gibt die Y Position Up zurück **/ int getYPosUp(); /** Gibt die Y Position Down zurück**/ int getYPosDown(); /** DriveLeft Variable wird gesetzt @param value true = "pressed" false = "released" **/ virtual void DriveLeft(bool value); /** DriveRight Variable wird gesetzt @param value true = "pressed" false = "released" **/ virtual void DriveRight(bool value); /** Berechnet das komplette Movement **/ int Move(void *nichtVerwendet); /** Default Constructor **/ CPlayer(); }; #endif // PLAYER_HPlayer.cpp
#include <iostream> #include "Player.h" using namespace std; /** Default constructor. **/ CPlayer::CPlayer() { Drive_x_speed = 2; Drive_y_speed = 2; driving_left = false; driving_right = false; checkValue = true; } int CPlayer::getXPosLeft() { return x_pos_left; } int CPlayer::getXPosRight() { return x_pos_right; } int CPlayer::getYPosUp() { return y_pos_up; } int CPlayer::getYPosDown() { return y_pos_down; } void CPlayer::DriveLeft(bool value) { driving_left = value; } void CPlayer::DriveRight(bool value) { driving_right = value; } int CPlayer::Move(void *nichtVerwendet) { cout << "move" << endl; while(checkValue) { //player drives left if(driving_left) { cout << "links" << endl; } // player drives right else if(driving_right) { cout << "right" << endl; } } return 0; }Main.cpp
#include <iostream> #include "Engine.h" #include <stdlib.h> #include "SDL_thread.h" using namespace std; class CMyEngine: public CEngine { public: void AdditionalInit (); void Think ( const int& iElapsedTime ); void Render ( SDL_Surface* pDestSurface ); void KeyUp (const int& iKeyEnum); void KeyDown (const int& iKeyEnum); void MouseMoved (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY); void MouseButtonUp (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY); void MouseButtonDown(const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY); void WindowInactive(); void WindowActive(); void End(); }; // Entry point int main(int argc, char* argv[]) // <- this must match exactly, since SDL rewrites it { CMyEngine Engine; Engine.SetTitle( "Loading..." ); Engine.Init(); Engine.SetTitle( "SDL Testing!" ); Engine.Start(); SDL_Thread *thread; thread = SDL_CreateThread(Engine.player.Move, NULL); if ( thread == NULL ) { cout << (stderr ,"Thread konnte nicht gestartet werden: %s\n", SDL_GetError()) << endl; } SDL_KillThread (thread); Engine.SetTitle( "Quitting..." ); } void CMyEngine::AdditionalInit() { // Load up additional data } void CMyEngine::Think( const int& iElapsedTime ) { // Do time-based calculations } void CMyEngine::Render( SDL_Surface* pDestSurface ) { // Display slick graphics on screen } void CMyEngine::KeyDown(const int& iKeyEnum) { switch (iKeyEnum) { case SDLK_LEFT: // Left pressed player.DriveLeft(true); break; case SDLK_RIGHT: // Right pressed player.DriveRight(true); break; case SDLK_UP: // Up pressed break; case SDLK_DOWN: // Down pressed break; } } void CMyEngine::KeyUp(const int& iKeyEnum) { switch (iKeyEnum) { case SDLK_LEFT: // Left arrow released player.DriveLeft(false); break; case SDLK_RIGHT: // Right arrow released player.DriveRight(false); break; case SDLK_UP: // Up arrow released break; case SDLK_DOWN: // Down arrow released break; } } void CMyEngine::MouseMoved(const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY) { // Handle mouse movement // iX and iY are absolute screen positions // iRelX and iRelY are screen position relative to last detected mouse movement } void CMyEngine::MouseButtonUp(const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY) { // Handle mouse button released } void CMyEngine::MouseButtonDown(const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY) { // Handle mouse button pressed } void CMyEngine::WindowInactive() { // Pause game } void CMyEngine::WindowActive() { // Un-pause game } void CMyEngine::End() { // Clean up }Engine.cpp
#include "Engine.h" #include <windows.h> // For the WaitMessage() function. /** Default constructor. **/ CEngine::CEngine() { m_lLastTick = 0; m_iWidth = 800; m_iHeight = 600; m_czTitle = 0; m_pScreen = 0; m_iFPSTickCounter = 0; m_iFPSCounter = 0; m_iCurrentFPS = 0; m_bMinimized = false; } /** Destructor. **/ CEngine::~CEngine() { SDL_Quit(); } /** Sets the height and width of the window. @param iWidth The width of the window @param iHeight The height of the window **/ void CEngine::SetSize(const int& iWidth, const int& iHeight) { m_iWidth = iWidth; m_iHeight = iHeight; m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_SWSURFACE ); } /** Initialize SDL, the window and the additional data. **/ void CEngine::Init() { // Register SDL_Quit to be called at exit; makes sure things are cleaned up when we quit. atexit( SDL_Quit ); // Initialize SDL's subsystems - in this case, only video. if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { fprintf( stderr, "Unable to init SDL: %s\n", SDL_GetError() ); exit( 1 ); } // Attempt to create a window with the specified height and width. SetSize( m_iWidth, m_iHeight ); // If we fail, return error. if ( m_pScreen == NULL ) { fprintf( stderr, "Unable to set up video: %s\n", SDL_GetError() ); exit( 1 ); } AdditionalInit(); } /** The main loop. **/ void CEngine::Start() { m_lLastTick = SDL_GetTicks(); m_bQuit = false; // Main loop: loop forever. while ( !m_bQuit ) { // Handle mouse and keyboard input HandleInput(); if ( m_bMinimized ) { // Release some system resources if the app. is minimized. WaitMessage(); // pause the application until focus in regained } else { // Do some thinking DoThink(); // Render stuff DoRender(); } } End(); } /** Handles all controller inputs. @remark This function is called once per frame. **/ void CEngine::HandleInput() { // Poll for events, and handle the ones we care about. SDL_Event event; while ( SDL_PollEvent( &event ) ) { switch ( event.type ) { case SDL_KEYDOWN: // If escape is pressed set the Quit-flag if (event.key.keysym.sym == SDLK_ESCAPE) { m_bQuit = true; break; } KeyDown( event.key.keysym.sym ); break; case SDL_KEYUP: KeyUp( event.key.keysym.sym ); break; case SDL_QUIT: m_bQuit = true; break; case SDL_MOUSEMOTION: MouseMoved( event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel); break; case SDL_MOUSEBUTTONUP: MouseButtonUp( event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel); break; case SDL_MOUSEBUTTONDOWN: MouseButtonDown( event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel); break; case SDL_ACTIVEEVENT: if ( event.active.state & SDL_APPACTIVE ) { if ( event.active.gain ) { m_bMinimized = false; WindowActive(); } else { m_bMinimized = true; WindowInactive(); } } break; } // switch } // while (handling input) } /** Handles the updating routine. **/ void CEngine::DoThink() { long iElapsedTicks = SDL_GetTicks() - m_lLastTick; m_lLastTick = SDL_GetTicks(); Think( iElapsedTicks ); m_iFPSTickCounter += iElapsedTicks; } /** Handles the rendering and FPS calculations. **/ void CEngine::DoRender() { ++m_iFPSCounter; if ( m_iFPSTickCounter >= 1000 ) { m_iCurrentFPS = m_iFPSCounter; m_iFPSCounter = 0; m_iFPSTickCounter = 0; } SDL_FillRect( m_pScreen, 0, SDL_MapRGB( m_pScreen->format, 0, 0, 0 ) ); // Lock surface if needed if ( SDL_MUSTLOCK( m_pScreen ) ) if ( SDL_LockSurface( m_pScreen ) < 0 ) return; Render( GetSurface() ); // Unlock if needed if ( SDL_MUSTLOCK( m_pScreen ) ) SDL_UnlockSurface( m_pScreen ); // Tell SDL to update the whole gScreen SDL_Flip( m_pScreen ); } /** Sets the title of the window @param czTitle A character array that contains the text that the window title should be set to. **/ void CEngine::SetTitle(const char* czTitle) { m_czTitle = czTitle; SDL_WM_SetCaption( czTitle, 0 ); } /** Retrieve the title of the application window. @return The last set windows title as a character array. @remark Only the last set title is returned. If another application has changed the window title, then that title won't be returned. **/ const char* CEngine::GetTitle() { return m_czTitle; } /** Retrieve the main screen surface. @return A pointer to the SDL_Surface surface @remark The surface is not validated internally. **/ SDL_Surface* CEngine::GetSurface() { return m_pScreen; } /** Get the current FPS. @return The number of drawn frames in the last second. @remark The FPS is only updated once each second. **/ int CEngine::GetFPS() { return m_iCurrentFPS; }Engine.h
#ifndef ENGINE_H #define ENGINE_H #include "Player.h" #include "SDL.h" /** The base engine class. **/ class CEngine { private: /** Last iteration's tick value **/ long m_lLastTick; /** Window width **/ int m_iWidth; /** Window height **/ int m_iHeight; /** Has quit been called? **/ bool m_bQuit; /** The title of the window **/ const char* m_czTitle; /** Screen surface **/ SDL_Surface* m_pScreen; /** Is the window minimized? **/ bool m_bMinimized; /** Variables to calculate the frame rate **/ /** Tick counter. **/ int m_iFPSTickCounter; /** Frame rate counter. **/ int m_iFPSCounter; /** Stores the last calculated frame rate. **/ int m_iCurrentFPS; protected: void DoThink(); void DoRender(); void SetSize(const int& iWidth, const int& iHeight); void HandleInput(); public: CEngine(); virtual ~CEngine(); void Init(); void Start(); /** OVERLOADED - Data that should be initialized when the application starts. **/ virtual void AdditionalInit () {} /** OVERLOADED - All the games calculation and updating. @param iElapsedTime The time in milliseconds elapsed since the function was called last. **/ virtual void Think ( const int& iElapsedTime ) {} /** OVERLOADED - All the games rendering. @param pDestSurface The main screen surface. **/ virtual void Render ( SDL_Surface* pDestSurface ) {} /** OVERLOADED - Allocated data that should be cleaned up. **/ virtual void End () {} /** OVERLOADED - Window is active again. **/ virtual void WindowActive () {} /** OVERLOADED - Window is inactive. **/ virtual void WindowInactive () {} /** OVERLOADED - Keyboard key has been released. @param iKeyEnum The key number. **/ virtual void KeyUp (const int& iKeyEnum) {} /** OVERLOADED - Keyboard key has been pressed. @param iKeyEnum The key number. **/ virtual void KeyDown (const int& iKeyEnum) {} /** OVERLOADED - The mouse has been moved. @param iButton Specifies if a mouse button is pressed. @param iX The mouse position on the X-axis in pixels. @param iY The mouse position on the Y-axis in pixels. @param iRelX The mouse position on the X-axis relative to the last position, in pixels. @param iRelY The mouse position on the Y-axis relative to the last position, in pixels. @bug The iButton variable is always NULL. **/ virtual void MouseMoved (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY) {} /** OVERLOADED - A mouse button has been released. @param iButton Specifies if a mouse button is pressed. @param iX The mouse position on the X-axis in pixels. @param iY The mouse position on the Y-axis in pixels. @param iRelX The mouse position on the X-axis relative to the last position, in pixels. @param iRelY The mouse position on the Y-axis relative to the last position, in pixels. **/ virtual void MouseButtonUp (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY) {} /** OVERLOADED - A mouse button has been pressed. @param iButton Specifies if a mouse button is pressed. @param iX The mouse position on the X-axis in pixels. @param iY The mouse position on the Y-axis in pixels. @param iRelX The mouse position on the X-axis relative to the last position, in pixels. @param iRelY The mouse position on the Y-axis relative to the last position, in pixels. **/ virtual void MouseButtonDown (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY) {} void SetTitle (const char* czTitle); const char* GetTitle (); SDL_Surface* GetSurface (); int GetFPS (); CPlayer player; }; #endif // ENGINE_H
-
Dein Problem ist, dass du in C++ nicht einfach Methoden- mit Funktionszeigern mischen kannst, da die Signatur eines Methodenzeigers immer noch (unsichtbar) den Zeiger auf die jeweilige KLasseninstanz enthält:
int Foo::Move(int);würde also intern so aussehen:
int Foo_Move(Foo*, int);Näher dazu hier
Abhilfe kannst du mit einer statischen Memberfunktion schaffen:
class CMyEngine : public CEngine { ... static int ThreadFunction(void* who) { return reinterpret_cast<CMyEngine*>(who)->player.Move(); } }Angelegt wird der Thread dann so:
thread = SDL_CreateThread(Engine::ThreadFunction, (void*)&Engine);BTW, dass nächste mal bitte den Code eingrenzen und cpp-Tags benutzen, ich hatte jetzt wenig Lust das alles zu lesen...
Grüße
Martin
-
Danke für die schnelle Antwort.
Sry ich hab mir gedacht ich Poste den ganzen Code, weil ich mir nicht ganz sicher war wo ich den Fehler gemacht habe.Ich werde am Nachmittag mal dein Link anschauen und dementsprechend den Code anpassen. Merci viel mal.
-
du könntest ja deinen thread nochmal editieren. die tags in [cpp] statt [code]
-
Done. Hab ihn editiert und die Tags geändert.