打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SDL入门教程(十三):3、封装多线程
作者:龙飞

        SDL创建多线程的函数SDL_CreateThread()所调用的是函数指针,这意味着我们不可以传入(非静态)成员函数的指针。关于两种函数指针我们之前已经讨论过:函数指针与成员函数指针,我们可以有两种方法能让具有普通函数指针(函数指针以及静态成员函数指针)的函数调用类的私有成员,一是友元函数,另外就是静态成员函数。而能够受到类私有保护的,只有静态成员函数。所以,我们可以通过静态成员函数调用一个对象数据的形式,实现对于创建多线程函数的封装。
        另外,我们希望测试在主线程中读写线程数据的效果,所以添加了两个方法show() 和reset(),多线程演示的类源代码如下:
#include <iostream>
#include "SurfaceClass.hpp"

class AmnArg
{
private:
    int beginX;
    int beginY;
    int endX;
    int endY;
    const ScreenSurface& screen;
    //
    static int amn(void* pThat);
public:
    AmnArg(int begin_x, int begin_y, int end_x, int end_y, const ScreenSurface& _screen);
    SDL_Thread* createThrd();
    void show() const;
    void reset();
};
其中SurfaceClass.hpp请参考:
http://www.cppblog.com/lf426/archive/2008/04/14/47038.html
实现函数如下:
#include "amn.hpp"

AmnArg::AmnArg(int begin_x, int begin_y, int end_x, int end_y, const ScreenSurface& _screen):
beginX(begin_x), beginY(begin_y), endX(end_x), endY(end_y), screen(_screen)
{}

SDL_Thread* AmnArg::createThrd()
{
    return SDL_CreateThread(amn, (void*)this);
}

void AmnArg::show() const
{
    std::cout << "Now x at: " << beginX << std::endl;
}

void AmnArg::reset()
{
    beginX = 0;
}

int AmnArg::amn(void* pThat)
{
    AmnArg* pData = (AmnArg*)pThat;
    PictureSurface stand("./images/am01.png", pData->screen);
    stand.colorKey();
    PictureSurface bg("./images/background.png", pData->screen);

    const int SPEED_CTRL = 300;
    int speedX = (pData->endX - pData->beginX) / SPEED_CTRL;
    int speedY = (pData->endY - pData->beginY) / SPEED_CTRL;

    for ( int i = 0; i < SPEED_CTRL; i++ ){
        pData->beginX += speedX;
        pData->beginY += speedY;
        bg.blit(pData->beginX, pData->beginY, pData->beginX, pData->beginY, stand.point()->w, stand.point()->h, 2, 2);
        stand.blit(pData->beginX, pData->beginY);
        pData->screen.flip();
        SDL_Delay(10);
    }

    return 0;
}
最后,我们修改了主演示程序,并测试了show()和reset()的效果。我们可以看到,直接修改线程数据的reset()的结果也是不可预知的,所以,我们似乎更应该通过改变线程“流”的效果,而不是直接对数据进行修改。这个我们以后再讨论了。
#include "SurfaceClass.hpp"
#include "amn.hpp"

int game(int argc ,char* argv[]);
int main(int argc ,char* argv[])
{
    int mainRtn = 0;
    try {
        mainRtn = game(argc, argv);
    }
    catch ( const ErrorInfo& info ) {
        info.show();
        return -1;
    }
    catch ( const char* s ) {
        std::cerr << s << std::endl;
        return -1;
    }
    
    return mainRtn;
}

int game(int argc ,char* argv[])
{
    //Create a SDL screen.
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    const Uint32 SCREEN_FLAGS = 0; //SDL_FULLSCREEN | SDL_DOUBLEBUF | SDL_HWSURFACE
    const std::string WINDOW_NAME = "Amn Test";
    ScreenSurface screen(SCREEN_WIDTH, SCREEN_HEIGHT, WINDOW_NAME, 0, SCREEN_FLAGS);

    PictureSurface bg("./images/background.png", screen);
    bg.blit(0);
    screen.flip();

    AmnArg test1(0, 250, 600, 250, screen);
    SDL_Thread* thread1 = test1.createThrd();
    
    AmnArg test2(0, 0, 400, 0, screen);
    SDL_Thread* thread2 = test2.createThrd();

    SDL_Event gameEvent;
    bool gameOver = false;
    while ( gameOver == false ){
        while ( SDL_PollEvent(&gameEvent) != 0 ){
            if ( gameEvent.type == SDL_QUIT ){
                gameOver = true;
            }
            if ( gameEvent.type == SDL_KEYDOWN ){
                if ( gameEvent.key.keysym.sym == SDLK_ESCAPE ){
                    gameOver = true;
                }
                if ( gameEvent.key.keysym.sym == SDLK_SPACE ){
                    test1.show();
                    test2.show();
                }
            }
            screen.flip();
        }
        SDL_Delay(100);
    }

    SDL_KillThread(thread1);
    SDL_KillThread(thread2);

    return 0;
}
posted on 2008-04-28 14:24 lf426 阅读(2252) 评论(2)  编辑 收藏 引用 所属分类: SDL入门教程
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
string类实现(C++)
V4L2视频采集技术
SDL使用
SDL历程--课程设计之写字
为什么不要在构造函数中调用虚函数
C 超详细讲解模板的使用
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服