#include "graphic.h" #include "utils.h" int mySDLInit(char title[], SDL_Rect win_pos, Uint32 init_flags, Uint32 win_flags, Uint32 rend_flags, SDL_Window **win, SDL_Renderer **rend, SDL_RendererInfo *rend_info, SDL_Rect *viewport) { int res, i; Uint32 tf; res=SDL_Init(init_flags); MPL_CHECK( res==0, // Expression to evaluate {return 1;} , // Code to execute if expression is not true SDL_LOG_PRIORITY_CRITICAL, // SDL_LogPriority (_CRITICAL, _ERROR, _WARN, _INFO, DEBUG, _VERBOSE) "SDL_Init failed (%i)",res // var args list starting with a fmt string like in printf() ); *win=SDL_CreateWindow(title,win_pos.x,win_pos.y,win_pos.w,win_pos.h,win_flags); MPL_CHECK( *win, // Just put the pointer if you want to check if it's not NULL {SDL_Quit(); return 2;}, SDL_LOG_PRIORITY_CRITICAL, "SDL_CreateWindow failed" ); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "SDL_GetWindowPixelFormat() returns %s", SDL_GetPixelFormatName(SDL_GetWindowPixelFormat(*win)) ); *rend=SDL_CreateRenderer(*win,-1, rend_flags); MPL_CHECK( *rend, {SDL_DestroyWindow(*win);SDL_Quit(); return 3;}, SDL_LOG_PRIORITY_CRITICAL, "SDL_CreateRenderer(...,SDL_RENDERER_ACCELERATED) failed" ); SDL_SetRenderDrawColor(*rend, 0xA0, 0xA0, 0xA0, 0xFF); res=SDL_GetRendererInfo(*rend, rend_info); MPL_CHECK( res==0, {SDL_DestroyRenderer(*rend);SDL_DestroyWindow(*win);SDL_Quit(); return 4;}, SDL_LOG_PRIORITY_CRITICAL, "res=SDL_GetRendererInfo() failed" ); tf=1; for(i=0;i<16 && tf!=0;i++) { tf=rend_info->texture_formats[i]; SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "rend_info->texture_formats[%i] == %s", i, SDL_GetPixelFormatName(tf) ); } SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "rend_info->flags==%i", rend_info->flags ); if ( (rend_info->flags & SDL_RENDERER_SOFTWARE) == SDL_RENDERER_SOFTWARE) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "rend_info->flags contains SDL_RENDERER_SOFTWARE"); } if ( (rend_info->flags & SDL_RENDERER_ACCELERATED) == SDL_RENDERER_ACCELERATED) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "rend_info->flags contains SDL_RENDERER_ACCELERATED"); } if ( (rend_info->flags & SDL_RENDERER_PRESENTVSYNC) == SDL_RENDERER_PRESENTVSYNC) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "rend_info->flags contains SDL_RENDERER_PRESENTVSYNC"); } if ( (rend_info->flags & SDL_RENDERER_TARGETTEXTURE) == SDL_RENDERER_TARGETTEXTURE) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,SDL_LOG_PRIORITY_INFO, "rend_info->flags contains SDL_RENDERER_TARGETTEXTURE"); } // Remarks : When the window is resized, the current viewport is automatically centered within the new window size. SDL_RenderGetViewport(*rend, viewport); return 0; } #define PIXEL32(s,x,y) (((Uint32 *)s->pixels)[y*s->w + x]) int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameState_t *gState) { int res, res2, bpp; int i, modifier; int x,y,xmin,xmax,ymin,ymax,y2,xdst,ydst; Uint32 srcPixel, dstPixel, dstStencil; Uint32 cc_nothing, cc_terrain, cc_background, rmask, gmask, bmask, amask; SDL_Surface *tile; res=SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, &bpp, &rmask, &gmask, &bmask, &amask); MPL_CHECK( res==SDL_TRUE, { return 1; }, SDL_LOG_PRIORITY_CRITICAL, "paintTerrain(), SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, ...) failed" ); gState->terrain=SDL_CreateRGBSurface(0, LEVEL_WIDTH, LEVEL_HEIGHT, bpp, rmask, gmask, bmask, amask); gState->stencil=SDL_CreateRGBSurface(0, LEVEL_WIDTH, LEVEL_HEIGHT, bpp, rmask, gmask, bmask, amask); MPL_CHECK( gState->terrain && gState->stencil, { return 2; }, SDL_LOG_PRIORITY_CRITICAL, "paintTerrain(), SDL_CreateRGBSurface() failed" ); cc_nothing=0xFF000000; /* Make it portable (big endian) */ cc_terrain=0xFFFFAAAA; /* Make it portable (big endian) */ cc_background = gIni->style.bgColor | amask; /* Fill the entire surfaces with default color */ res =SDL_FillRect(gState->terrain, NULL, cc_background); res2=SDL_FillRect(gState->stencil, NULL, cc_nothing); MPL_CHECK( res==0 && res2==0, { return 3; }, SDL_LOG_PRIORITY_CRITICAL, "paintTerrain(), SDL_FillRect() failed" ); for(i=0 ; i < gIni->level.terrainCount ; i++) { int tid=gIni->level.terrains[i].id; MPL_CHECK( tid >= 0 && tid < MAX_TILES_COUNT, { return 4; }, SDL_LOG_PRIORITY_CRITICAL, "paintTerrain(), gIni->level.terrains[%i].id == %i and it is out of range", i, tid ); tile=gRess->tiles[tid]; MPL_CHECK( tile, { return 5; }, SDL_LOG_PRIORITY_CRITICAL, "paintTerrain(), tile %i was not loaded", tid ); // Special modifier values : // 15 : Hidden : Lemini hack. Seems to be the same as NO_OVERRIDE // Combinable modifier : // 8 : NO_OVERRIDE : Don't change pixels that already set on destination // 4 : Upside Down // 2 : REMOVE : oublier (rendre transparent) tous les pixels qu'on a déjà plaqué modifier=gIni->level.terrains[i].modifier; // If we match the Lemini hack, change the value to NO_OVERRIDE if (modifier == 15) { modifier=8; } // If both REMOVE and NO_OVERRIDE is enabled, prefer NO_OVERRIDE (turn off REMOVE flag) if ( (modifier & 10) == 10) { modifier &= ~2; } // For each tile pixel, without going outside of the terrain ymin=(gIni->level.terrains[i].ypos>=0)?0:-gIni->level.terrains[i].ypos; ymax=SDL_min(tile->clip_rect.h, gState->terrain->clip_rect.h - gIni->level.terrains[i].ypos); xmin=(gIni->level.terrains[i].xpos>=0)?0:-gIni->level.terrains[i].xpos; xmax=SDL_min(tile->clip_rect.w, gState->terrain->clip_rect.w - gIni->level.terrains[i].xpos); for (y=ymin; yclip_rect.h-1-y; } else { y2=y; } ydst=gIni->level.terrains[i].ypos+y; xdst=gIni->level.terrains[i].xpos+x; srcPixel = PIXEL32(tile, x, y2); // Act only if current pixel in tile is not transparent if ( (srcPixel & amask) != 0 ) { // Always paint pixel, except in one case: // If we are in NO_OVERRIDE mode and there is already a terrain on the current (source) pixel if ( !( (modifier & 8) == 8 && PIXEL32(gState->stencil, xdst, ydst) == cc_terrain ) ) { // If we have REMOVE modifier, dstPixel will be rolled back to cc_background, else, it will be identical to the source pixel. We have to update stencil consistenly. if ( (modifier & 2) == 2 ) { dstPixel=cc_background; dstStencil=cc_nothing; } else { dstPixel=srcPixel; dstStencil=cc_terrain; } PIXEL32(gState->terrain,xdst,ydst)=dstPixel; PIXEL32(gState->stencil,xdst,ydst)=dstStencil; } } } } } return 0; } int renderTerrainToTextures(SDL_Renderer *rend, SDL_Surface *terrain, gameUI_t *gUI) { int res, pitch; SDL_Rect src_rect, dst_rect; SDL_Surface *tmp_surf; SDL_PixelFormat *pf = terrain->format; Uint32 *pixels; tmp_surf = SDL_CreateRGBSurface(0,MPL_WIN_W, LEVEL_HEIGHT, pf->BitsPerPixel, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask); MPL_CHECK( tmp_surf, { return 1; }, SDL_LOG_PRIORITY_CRITICAL, "Can't SDL_CreateRGBSurface() for converting terrain" ); src_rect.x=gUI->cameraX; src_rect.y=0; src_rect.w=MPL_WIN_W; src_rect.h=LEVEL_HEIGHT; dst_rect=src_rect; dst_rect.x=0; res = SDL_BlitSurface(terrain, &src_rect, tmp_surf, &dst_rect); MPL_CHECK( res==0, { SDL_FreeSurface(tmp_surf); return 2; }, SDL_LOG_PRIORITY_CRITICAL, "Can't SDL_BlitSurface(terrain,...)" ); if (gUI->terrainSprite.t == NULL) { gUI->terrainSprite.t = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dst_rect.w, dst_rect.h); MPL_CHECK( gUI->terrainSprite.t, { SDL_FreeSurface(tmp_surf); return 3; }, SDL_LOG_PRIORITY_CRITICAL, "Can't SDL_CreateTexture for terrainSprite" ); gUI->terrainSprite.size = dst_rect; gUI->terrainSprite.frames = 1; } res=SDL_LockTexture(gUI->terrainSprite.t, NULL, (void **)&pixels, &pitch); MPL_CHECK( (res==0) && (pitch == dst_rect.w * sizeof(Uint32)), { SDL_FreeSurface(tmp_surf); SDL_UnlockTexture(gUI->terrainSprite.t); return 3; }, SDL_LOG_PRIORITY_CRITICAL, "Can't SDL_CreateTexture for terrainSprite" ); (void) SDL_memcpy(pixels, tmp_surf->pixels, dst_rect.h * pitch); SDL_UnlockTexture(gUI->terrainSprite.t); SDL_FreeSurface(tmp_surf); // SDL_DestroyTexture(gUI->terrainSprite.t); //TODO mais pas ici !! //TODO : faire le rendu de la minimap aussi return 0; } int renderSprites(SDL_Renderer *rend, gameUI_t *gUI) { int i, res; SDL_Rect src,dst; renderItem_t *it; for(i=0,res=0 ; i < MAX_RENDERLIST_SIZE && res==0 ; i++) { it = &gUI->renderList[i]; if (it->sprite == NULL) continue; src = dst = it->sprite->size; src.y = src.h * it->currframe; if ( it->absolute ) { dst.x = it->x; } else { dst.x = it->x - gUI->cameraX; } dst.y = it->y; it->lastDstRect = dst; res=SDL_RenderCopy(rend, it->sprite->t, &src, &dst); } return res; }