2011-12-22 44 views
3

好吧.. C++全新(我的意思是超級新)。我瞭解了很多PHP和JavaScript,所以我瞭解基本的代碼結構等。現在,我只是試圖掌握C++概念。我可以製作一個廣場,並使用我在網上找到的教程移動它。不要介意正方形大小與紋理(其175x55,它位於根目錄[texture.bmp])。但是我試圖獲取紋理,並且出現錯誤。我正在使用SDL和OpenGL。我得到的錯誤是:嘗試使用C++在OpenGL中獲取紋理時訪問違規

「未處理的0x0020fee9在Test1.exe例外:0x0000005:訪問衝突讀取位置0x00139000」

我在網上看了一下,從我的理解是什麼東西是越來越叫出來的順序(從我在網上找到的所有結果)。我想..

我的代碼如下:

//The headers 
#include "SDL.h" 
#include "SDL_opengl.h" 
#include "stdio.h" 
#pragma comment(lib, "opengl32.lib") 
#pragma comment(lib, "glu32.lib") 

//Screen attributes 
const int SCREEN_WIDTH = 640; 
const int SCREEN_HEIGHT = 480; 
const int SCREEN_BPP = 32; 

//The frame rate 
const int FRAMES_PER_SECOND = 60; 

//The attributes of the square 
const int SQUARE_WIDTH = 20; 
const int SQUARE_HEIGHT = 20; 

//Event handler 
SDL_Event event; 

//The square 
class Square 
{ 
    private: 
    //The offsets 
    int x, y; 

    //The velocity of the square 
    int xVel, yVel; 

    public: 
    //Initializes 
    Square(); 

    //Handles key presses 
    void handle_input(); 

    //Moves the square 
    void move(); 

    //Shows the square on the screen 
    void show(); 

    void getTexture(); 
}; 

//The timer 
class Timer 
{ 
    private: 
    //The clock time when the timer started 
    int startTicks; 

    //The ticks stored when the timer was paused 
    int pausedTicks; 

    //The timer status 
    bool paused; 
    bool started; 

    public: 
    //Initializes variables 
    Timer(); 

    //The various clock actions 
    void start(); 
    void stop(); 
    void pause(); 
    void unpause(); 

    //Gets the timer's time 
    int get_ticks(); 

    //Checks the status of the timer 
    bool is_started(); 
    bool is_paused(); 
}; 

bool init_GL() 
{ 
    //Set clear color 
    glClearColor(0, 0, 0, 0); 

    //Set projection 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1, 1); 

    //Initialize modelview matrix 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    //If there was any errors 
    if(glGetError() != GL_NO_ERROR) 
    { 
     return false; 
    } 

    //If everything initialized 
    return true; 
} 

bool init() 
{ 
    //Initialize SDL 
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) 
    { 
     return false; 
    } 

    //Create Window 
    if(SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL) == NULL) 
    { 
     return false; 
    } 

    //Initialize OpenGL 
    if(init_GL() == false) 
    { 
     return false; 
    } 

    //Set caption 
    SDL_WM_SetCaption("OpenGL Test", NULL); 

    return true; 
} 

void clean_up() 
{ 
    //Quit SDL 
    SDL_Quit(); 
} 

Square::Square() 
{ 
    //Initialize offsets 
    x = 0; 
    y = 0; 

    //Initialize velocity 
    xVel = 0; 
    yVel = 0; 
} 

void Square::handle_input() 
{ 
    //If a key was pressed 
    if(event.type == SDL_KEYDOWN) 
    { 
     //Adjust the velocity 
     switch(event.key.keysym.sym) 
     { 
      case SDLK_UP: yVel -= SQUARE_HEIGHT/2; break; 
      case SDLK_DOWN: yVel += SQUARE_HEIGHT/2; break; 
      case SDLK_LEFT: xVel -= SQUARE_WIDTH/2; break; 
      case SDLK_RIGHT: xVel += SQUARE_WIDTH/2; break; 
     } 
    } 
    //If a key was released 
    else if(event.type == SDL_KEYUP) 
    { 
     //Adjust the velocity 
     switch(event.key.keysym.sym) 
     { 
      case SDLK_UP: yVel += SQUARE_HEIGHT/2; break; 
      case SDLK_DOWN: yVel -= SQUARE_HEIGHT/2; break; 
      case SDLK_LEFT: xVel += SQUARE_WIDTH/2; break; 
      case SDLK_RIGHT: xVel -= SQUARE_WIDTH/2; break; 
     } 
    } 
} 

void Square::move() 
{ 
    //Move the square left or right 
    x += xVel; 

    //If the square went too far 
    if((x < 0) || (x + SQUARE_WIDTH > SCREEN_WIDTH)) 
    { 
     //Move back 
     x -= xVel; 
    } 

    //Move the square up or down 
    y += yVel; 

    //If the square went too far 
    if((y < 0) || (y + SQUARE_HEIGHT > SCREEN_HEIGHT)) 
    { 
     //Move back 
     y -= yVel; 
    } 
} 

void getTexture() 
{ 
    GLuint texture; // Texture object handle 

    SDL_Surface *surface; // Gives us the information to make the texture 

    if ((surface = SDL_LoadBMP("image.bmp"))) { 

     // Check that the image's width is a power of 2 
     if ((surface->w & (surface->w - 1)) != 0) { 
      printf("warning: image.bmp's width is not a power of 2\n"); 
     } 

     // Also check if the height is a power of 2 
     if ((surface->h & (surface->h - 1)) != 0) { 
      printf("warning: image.bmp's height is not a power of 2\n"); 
     } 

     // Have OpenGL generate a texture object handle for us 
     glGenTextures(1, &texture); 

     // Bind the texture object 
     glBindTexture(GL_TEXTURE_2D, texture); 

     // Set the texture's stretching properties 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

     // Edit the texture object's image data using the information SDL_Surface gives us 
     glTexImage2D(GL_TEXTURE_2D, 0, 3, surface->w, surface->h, 0, 
         GL_BGR, GL_UNSIGNED_BYTE, surface->pixels); 
    }  

    // Free the SDL_Surface only if it was successfully created 
    if (surface) { 
     SDL_FreeSurface(surface); 
    } 

    // Bind the texture to which subsequent calls refer to 
    glBindTexture(GL_TEXTURE_2D, texture); 

} 

void Square::show() 
{ 
    //Move to offset 
    glTranslatef(x, y, 0); 

    //Start quad 
    glBegin(GL_QUADS); 
     // Top-left vertex (corner) 
     glTexCoord2i(0, 0); 
     glVertex3f(100, 100, 0); 

     // Bottom-left vertex (corner) 
     glTexCoord2i(1, 0); 
     glVertex3f(228, 100, 0); 

     // Bottom-right vertex (corner) 
     glTexCoord2i(1, 1); 
     glVertex3f(228, 228, 0); 

     // Top-right vertex (corner) 
     glTexCoord2i(0, 1); 
     glVertex3f(100, 228, 0); 
    glEnd(); 

    //Reset 
    glLoadIdentity(); 
} 

Timer::Timer() 
{ 
    //Initialize the variables 
    startTicks = 0; 
    pausedTicks = 0; 
    paused = false; 
    started = false; 
} 

void Timer::start() 
{ 
    //Start the timer 
    started = true; 

    //Unpause the timer 
    paused = false; 

    //Get the current clock time 
    startTicks = SDL_GetTicks(); 
} 

void Timer::stop() 
{ 
    //Stop the timer 
    started = false; 

    //Unpause the timer 
    paused = false; 
} 

void Timer::pause() 
{ 
    //If the timer is running and isn't already paused 
    if((started == true) && (paused == false)) 
    { 
     //Pause the timer 
     paused = true; 

     //Calculate the paused ticks 
     pausedTicks = SDL_GetTicks() - startTicks; 
    } 
} 

void Timer::unpause() 
{ 
    //If the timer is paused 
    if(paused == true) 
    { 
     //Unpause the timer 
     paused = false; 

     //Reset the starting ticks 
     startTicks = SDL_GetTicks() - pausedTicks; 

     //Reset the paused ticks 
     pausedTicks = 0; 
    } 
} 

int Timer::get_ticks() 
{ 
    //If the timer is running 
    if(started == true) 
    { 
     //If the timer is paused 
     if(paused == true) 
     { 
      //Return the number of ticks when the timer was paused 
      return pausedTicks; 
     } 
     else 
     { 
      //Return the current time minus the start time 
      return SDL_GetTicks() - startTicks; 
     } 
    } 

    //If the timer isn't running 
    return 0; 
} 

bool Timer::is_started() 
{ 
    return started; 
} 

bool Timer::is_paused() 
{ 
    return paused; 
} 

int main(int argc, char *argv[]) 
{ 
    //Quit flag 
    bool quit = false; 

    //Initialize 
    if(init() == false) 
    { 
     return 1; 
    } 

    //Our square object 
    Square square; 

    getTexture(); 

    //The frame rate regulator 
    Timer fps; 

    //Wait for user exit 
    while(quit == false) 
    { 
     //Start the frame timer 
     fps.start(); 

     //While there are events to handle 
     while(SDL_PollEvent(&event)) 
     { 
      //Handle key presses 
      square.handle_input(); 

      if(event.type == SDL_QUIT) 
      { 
       quit = true; 
      } 
     } 

     //Move the square 
     square.move(); 

     //Clear the screen 
     glClear(GL_COLOR_BUFFER_BIT); 

     //Show the square 
     square.show(); 

     //Update screen 
     SDL_GL_SwapBuffers(); 

     //Cap the frame rate 
     if(fps.get_ticks() < 1000/FRAMES_PER_SECOND) 
     { 
      SDL_Delay((1000/FRAMES_PER_SECOND) - fps.get_ticks()); 
     } 
    } 

    //Clean up 
    clean_up(); 

    return 0; 
} 

您可以粘貼到微軟的Visual C++ 2010(我正在使用)。請給我建議,如果它更好地做它不同或任何其他建議,你可能有。謝謝。

+1

C++新手?我有義務推薦[一本好的介紹性C++書](http://stackoverflow.com/q/388242/46642)。 :) – 2011-12-22 02:38:52

+5

您是否嘗試過使用調試器來確定異常被拋出的位置? – 2011-12-22 02:40:33

+0

Visual C中的「Disassembly」說:0020FEE9 movzx ebx,byte ptr [esi + 2]。不知道這是否有幫助。 – ALF 2011-12-22 02:56:53

回答

1

我不能真正重現您的問題。該程序執行得很好,並添加glEnable(GL_TEXTURE_2D)它甚至顯示一個紋理正方形。請注意,您不應該在對象的類中輸入處理,而應該使用專用的輸入處理程序,將輸入事件的結果委託給對象。這不是Java,你不必把所有東西都放在一個類中,特別是像類不可知的類似SDL的庫。 getTextures在您的代碼中被聲明爲成員函數,但沒有定義它。

做出這4個更改後,http://pastebin.com/c58Hmw9Z中的代碼按預期執行。順便說一下:因爲OpenGL-2紋理可能有任意的分辨率。

+0

好的,從你幫助我,看起來像東西配置不正確。當我推f10(運行到光標),並把我帶到WinMainCRTStartup(無效)?我試過禁用/ GS,但我仍然得到完全相同的錯誤。 – ALF 2011-12-22 17:26:23

+0

謝謝。必須重新啓動項目配置一切,並重新下載所有的DLL。在某些時候,我一定已經改變了一些東西......但不知道。 – ALF 2011-12-22 17:46:52

1

看起來你打電話glBindTexture()兩次對相同的紋理;我不能說這是問題的根源,但我認爲你應該刪除第二個實例(如果if()分支沒有被採用,那麼 可能會被初始化爲)。

+0

好的。在相同紋理上調用兩次是沒有問題的(這是多餘的,但不應該成爲問題)。可悲的是,用一個不確定的價值來調用它也是可行的。在OpenGL 3之前(這裏就是這種情況),使用未生成的紋理對象句柄會自動生成它。所以,這可能會導致一些問題,但我認爲這不會導致例外。無論如何。 – 2011-12-22 03:12:29

+0

因爲它只是一個整數,所以在做real_real_「indeterminate」檢查時無論如何都會做太多事情,但至少可以確保該值是早先發布的值。 (映射紋理真的發生多少次,刪除錯誤檢查性能是否合理?)感謝您的警告。 :) – sarnold 2011-12-22 03:19:01