SDL入门教程(十三):3、封装多线程

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
跳转到指定楼层
楼主
发表于 2017-12-19 09:55:49 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
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;
}


分享到:  QQ好友和群QQ好友和群
收藏收藏
回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表