2012-07-20 41 views
0

我用C++编写了一个简单的SDL程序,以查看究竟是什么。除了运行速度非常缓慢(尽管我在上网本上运行它,所以也许是这样),并且不会在窗口中绘制更多的两行像素,我将它带入(主要)工作状态。SDL:程序运行应该很好;只绘制两行像素

此问题在软件和硬件模式下都存在。

//colorizer.h 
#include <iostream> 
#include "SDL.h" 
#include "math.h" 

class Colorizer 
{ 
    public: 
     Colorizer(int width, int height, int bpp); 
     ~Colorizer(); 
     void frame(int rx, int ry, int gx, int gy, int bx, int by); 

    protected: 
     SDL_Surface* screen; 
     SDL_Surface* canvas; 
     void set_pixel(int x, int y, int r, int g, int b); 
     double distance(int from_x, int from_y, int to_x, int to_y); 
     int canvasW; 
     int canvasH; 
     int canvasBPP; 
     long framenumber; 
}; 

//------------------------------------------------------------------------------------------- 
//colorizer.cpp 
#include "colorizer.h" 

Colorizer::Colorizer(int width, int height, int bpp) 
{ 
    screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE); 
    if(!screen) 
    { 
     throw(SDL_GetError()); 
    } 
    canvasW = width; 
    canvasH = height; 
    canvasBPP = bpp; 
    framenumber = 0; 
} 

void Colorizer::frame(int rx, int ry, int gx, int gy, int bx, int by) 
{ 
    if(SDL_LockSurface(screen) < 0){ 
     std::cerr << "Can't lock screen: " << SDL_GetError() << std::endl; 
    } 

    for(int pix = 0; pix < screen->h; pix++) //Per column 
    { 
     for(int row = 0; row < screen->w; row++) //Per pixel 
     { 
      double src_r = sin(0.5*distance(row, pix, rx, ry)*framenumber); 
      double src_g = cos(0.5*distance(row, pix, gx, gy)*framenumber); 
      double src_b = sin(0.5*distance(row, pix, bx, by)*framenumber); 
      int dst_r = static_cast<int> (fabs(floor(255*src_r))); 
      int dst_g = static_cast<int> (fabs(floor(255*src_g))); 
      int dst_b = static_cast<int> (fabs(floor(255*src_b))); 
      if(dst_r > 255 or dst_g > 255 or dst_b > 255 or dst_r < 0 or dst_g < 0 or dst_b < 0){ 
       std::cerr << "Error: Pixel: (" << row << "," << pix << ") r=" << dst_r << " g=" << dst_g << " b=" << dst_b << std::endl; 
       throw ("One of the colours is invalid."); 
      } 
      set_pixel(row, pix, dst_r, dst_g, dst_b); 
     } 
    } 

    SDL_UnlockSurface(screen); 
    SDL_Flip(screen); 
    framenumber++; 
} 

double Colorizer::distance(int from_x, int from_y, int to_x, int to_y) 
{ 
    double triW = static_cast<double> (from_x) - static_cast<double> (to_x); 
    double triH = static_cast<double> (from_y) - static_cast<double> (to_y); 
    double distSq = triW*triW + triH*triH; 
    return sqrt(distSq); 
} 

void Colorizer::set_pixel(int x, int y, int r, int g, int b) 
{ 
    if(x > 640 or y > 480){ 
     std::cerr << "Invalid pixel: " << x << "," << y << std::endl; 
     return; 
    } 
    int color; 
    color = SDL_MapRGB(screen->format, r, g, b); 

    int *pixel; 
    pixel = (int*) screen->pixels + x + y; 
    *pixel = color; 
} 

Colorizer::~Colorizer() 
{ 
    SDL_FreeSurface(screen); 
} 

//------------------------------------------------------------------------------------------- 
//main.cpp 
#include <iostream> 
#include "SDL.h" 
#include "colorizer.h" 

/*snip pretty bash colour functions*/ 

int main (int argc, char* argv[]) 
{ 
    int sdlinit = SDL_Init(SDL_INIT_EVERYTHING); 
    if(sdlinit < 0){ 
     std::cerr << "Cannot initialize SDL: " << SDL_GetError() << std::endl; 
     return 1; 
    } 

    try{ 
     Colorizer app(640, 480, 32); 
     bool keypress = false; 

     SDL_Event evt; 
     while(!keypress){ 
      std::cerr << "."; //per frame 
      app.frame(100, 230, 25, 40, 200, 100); //default points 
      while(SDL_PollEvent(&evt)){ 
       std::cerr << "!"; //per event 
       if (evt.type == SDL_QUIT or evt.type == SDL_KEYDOWN) 
       { 
        keypress = true; 
       } 
      } 
     } 
     std::cout << std::endl; 
     return 0; 
    }catch(const char* &ex){ 
     SDL_Quit(); 
     return 1; 
    } 
} 
//------------------------------------------------------------------------------------------- 
// compile with: g++ *.cpp -O2 -o colorizer `pkg-config --cflags --libs sdl` 
//------------------------------------------------------------------------------------------- 
+0

请包括足够的代码在你的问题它是没有外部链接有用。 – meagar 2012-07-20 15:19:25

回答

2

与@Paul Tomblin指出的一样,您假定typedef int Uint32,这不是便携式和不良做法。亦可服用C++风格的考虑,

int color; 
color = SDL_MapRGB(screen->format, r, g, b); 

int *pixel; 
pixel = (int*) screen->pixels + x + y; 
*pixel = color; 

大概应该是:

Uint32* pixels = reinterpret_cast<Uint32*>(screen->pixels); 
pixels[screen->w * y + x] = SDL_MapRGB(screen->format, r, g, b); 
+0

感谢您的建议,尤其是C++风格。我对C++比较新,所以我仍然有很多东西需要了解它。 – FLamparski 2012-07-20 18:45:14

2

不宜pixel = (int*) screen->pixels + x + y;是这样pixel = (int*) screen->pixels + x + y * screen->w;?我实际上不知道像素是如何排列在SDL中的,但如果你不乘以x或y,那么(2,1)将与(1,2)相同的字节,并且显然不会工作。

+0

[来自FriedSpace的C代码](http://friedspace.com/SDLTest.c)我正在使用作为我的'set_pixel()'的参考,正是这样做,事实上工作。不过,我会给你一个建议。 – FLamparski 2012-07-20 18:20:38

+0

你试过他们的C代码吗?你为什么认为这是正确的? – 2012-07-20 18:24:20

+0

那么,现在我看着它,我看到他们使用了一个不同的y坐标,这是在其他地方计算出来的。我一定错过了,傻了我。无论如何,我确实改变了我的代码,现在它可以正常工作。非常感谢! – FLamparski 2012-07-20 18:34:20