作者:龙飞
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 阅读(2907)
评论(2) 编辑 收藏 引用 所属分类:
SDL入门教程