0

何が何であるかを確認するために、単純な SDL プログラムを C++ で作成しました。私はそれを(ほとんど)動作状態にしましたが、実行が非常に遅く(ネットブックで実行しているので、おそらくそれが原因かもしれません)、ウィンドウに2行以上のピクセルを描画しません。

この問題は、ソフトウェア モードとハードウェア モードの両方で発生します。

//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`
//-------------------------------------------------------------------------------------------
4

2 に答える 2

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);
于 2012-07-20T16:24:00.377 に答える
2

pixel = (int*) screen->pixels + x + y;のようなものであってはなりませんpixel = (int*) screen->pixels + x + y * screen->w;か?SDLでピクセルがどのように配置されているかは実際にはわかりませんが、xまたはyのいずれかを乗算しない場合、(2,1)は(1,2)と同じバイトになり、明らかにそうではありません仕事。

于 2012-07-20T15:37:08.217 に答える