Уроки по SDL 2: Урок 15 Многопоточность и Тиллинг
В этом уроке мы научимся запускать программу в несколько потоков, создавать полноценные уровни из мини изображения, так же научимся открывать несколько окон, скрывать и выводить вперед.
Приступим к коду:
static int TestThread(void *ptr)
{
SDL_Window *gWindow = SDL_CreateWindow("gamesBond",0,0,300,300,SDL_WINDOW_SHOWN);
;
SDL_Surface *imageThreadSurface = SDL_LoadBMP("hw.bmp");
int cnt;
SDL_Surface *windowSurface = SDL_GetWindowSurface(gWindow);
SDL_BlitSurface(imageThreadSurface,NULL, windowSurface,NULL);
SDL_UpdateWindowSurface( gWindow );
for (cnt = 0; cnt < 10; ++cnt) {
printf("Thread counter: %d\n", cnt);
SDL_Delay(50);
}
SDL_Delay(4000);
SDL_FreeSurface(windowSurface);
SDL_FreeSurface(imageThreadSurface);
SDL_DestroyWindow(gWindow);
return cnt;
}
Эта функция будет нашим вторым потоком, она создает окно(gWindow), подгружает изображения в(imageThreadSurface), подключаем windowSurface к нашему окну, и в него выводим изображение.
После этого выводим в консоль числа от 1 до 9, и добавляем 4 секунды ожидания,
и закрываем окно.
void writeMap(int *i,SDL_Renderer* gRenderer, SDL_Surface* mapSurface)
{
int yMap = 0;int xMap = 0;
int xSize = 80; int ySize = 80;
SDL_Rect coubPositionRect = {xMap,yMap,xSize,ySize};
SDL_Rect coubColorRect = {xMap,yMap,xSize,ySize };
SDL_Texture* mapTexture = SDL_CreateTextureFromSurface(gRenderer,mapSurface);
SDL_RenderClear;
while (xMap < 640)
{
if ( *i == REDSQUARE ) {
coubColorRect.x = 0;
coubColorRect.y = 0;
}else if ( *i == GREENSQUARE ) {
coubColorRect.y = 80;
coubColorRect.x = 0;
}else if ( *i == BLUESQUARE ) {
coubColorRect.y = 160;
coubColorRect.x = 0;
}else if ( *i == BLACKLEFTMID ) {
coubColorRect.y = 80;
coubColorRect.x = xSize;
}else if ( *i == BLACKLEFTTOP ) {
coubColorRect.y = 0;
coubColorRect.x = 80;
}else if ( *i == BLACKLEFTBOT ) {
coubColorRect.x = 80;
coubColorRect.y = 160;
}else if (*i == BLACKRIGHTTOP) {
coubColorRect.x = 240;
coubColorRect.y = 0;
}else if (*i == BLACKRIGHTMID) {
coubColorRect.x = 240;
coubColorRect.y = 80;
}else if (*i == BLACKRIGHTBOT) {
coubColorRect.x = 240;
coubColorRect.y = 160;
}
coubPositionRect.x = xMap;
coubPositionRect.y = yMap;
SDL_RenderCopy(gRenderer,mapTexture,&coubColorRect,&coubPositionRect);
yMap+=ySize;
if (yMap>=480) {
xMap+=xSize;
yMap = 0;
}
i++;
}
SDL_RenderPresent(gRenderer);
return;
}
Из этого маленького изображения и массива чисел от 0 до 8, мы отрисуем полноценную карту, через функцию, описанную выше, хоть она и большая, в ней нет ничего сложного, она принимает массив, переменную отображения, и изображение, находит соответствие между числом и квадратом на картинке, и отрисовывает его последовательно.
int main(void)
{
int mWidth = 640, mHeight = 480;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("tilling",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,mWidth,mHeight,SDL_WINDOW_SHOWN);
SDL_Renderer* gRenderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
SDL_Surface* imageSurface = IMG_Load("tiles.png");
SDL_Texture* imageTexture = SDL_CreateTextureFromSurface(gRenderer,imageSurface);
SDL_Rect imageRect = {0,0,80,80};
SDL_Event e;
SDL_RenderCopy(gRenderer,imageTexture,&imageRect,&imageRect);
SDL_RenderPresent(gRenderer);
int quit = 0;
int *k; k =(int*)calloc(50,4);
int threadReturnValue;
readData(k);
Стандартно задаем окно, подгружаем мини изображение, объявляем массив k.
И заполняем этот массив цифрами из файла readData(k), которые будут эквивалентом цвета квадратов на карте.
writeMap( k, gRenderer, imageSurface);
free(k);
Отображаем в окне(window). нашу карту через функцию(writeMap)
освобождаем память массива k
SDL_Thread *thread;
thread = SDL_CreateThread(TestThread,"testMultiThread",(void *)NULL);
SDL_WaitThread(thread, &threadReturnValue);
Создаем второй поток, SDL_CreateThread принимает три переменные, первая это функция(TestThread), вторая это имя потока, и третья данные подставляемые в функцию, в нашем случае это NULL.
Запускаем наш поток через SDL_WaitThread и результат функции записываем в переменную threadReturnValue
SDL_RaiseWindow(window);
SDL_ShowWindow(window);
SDL_RenderPresent(gRenderer);
untilPressKey (quit, e);
Первая функция SDL_RaiseWindow выводит окно поверх всех окон, вторая функция SDL_ShowWindow, показывает окно, если оно скрыто отображаем изображение и запускаем функцию выхода из приложения untilPressKey:
SDL_FreeSurface(imageSurface);
SDL_DestroyTexture(imageTexture);
SDL_RenderClear(gRenderer);
SDL_DestroyWindow(window);
SDL_Quit();