简体   繁体   English

SDL渲染为新纹理

[英]SDL render to a new texture

I'm making a 2d game with SDL library. 我正在使用SDL库制作2D游戏。

I'm trying to draw the map for each frame over and over again, because I'm moving the map, according to the player's movement to achieve illusion that the camera follows the player. 我试图一遍又一遍地绘制每个帧的地图,因为我正在根据玩家的移动来移动地图,以实现相机跟随玩家的错觉。

So basically, if the player moves, I'm moving all the blocks ( those two , player movement and update blocks positions , are handled in a separate thread ) and rendering the map texture over again , in the main thread. 因此,基本上,如果玩家移动了,我将移动所有块(这两个,玩家移动和更新块的位置,在单独的线程中处理),然后在主线程中再次渲染地图纹理。

Although, it is really not efficient to draw all the blocks each frame, and it lags the window rendering, so what I want to do is to make another thread, that will create a blank texture that the blocks could be rendered there. 虽然,实际上每帧绘制所有块的效率并不高,并且滞后于窗口渲染,所以我要做的是制作另一个线程,这将创建一个空白纹理,可以在此处渲染块。

The question is : Is it possible to do so without a renderer ? 问题是:在没有渲染器的情况下是否可以这样做? to draw all the blocks to a new texture without actually stuck the main renderer that draws the window and prevent it from going over all the blocks each frame ? 将所有块绘制为新纹理而没有实际卡住绘制窗口的主渲染器,并防止每帧遍历所有块?

This is the code that goes throgh the map blocks and drawing them to a new texture : 这是遍历地图块并将其绘制到新纹理的代码:

SDL_Texture* GraphicsDrawer::drawMap() {
    map = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, WINDOW_WIDTH, WINDOW_HEIGHT);
    SDL_SetTextureBlendMode(map, SDL_BLENDMODE_BLEND); // set texture to be transparent
    SDL_SetRenderTarget(renderer, map);
    for (Block block : blocks) {
        std::cout << block.getTexture() << std::endl;
        SDL_RenderCopy(renderer, block.getTexture(), NULL, &block.getPosition());
        SDL_RenderPresent(renderer);
    }
    SDL_SetRenderTarget(renderer, NULL);
    return map;
}

This is the code that draws textures to the window : 这是将纹理绘制到窗口的代码:

void Game::render() {
    SDL_RenderClear(renderer);
    //map
    SDL_RenderCopy(renderer, map, NULL, NULL);
    //player
    SDL_RenderCopy(renderer, player->getAnimation(player->getFlipImageFlag()), NULL, &player->getPosition());

    SDL_SetRenderDrawColor(renderer, BG_R, BG_G, BG_B, BG_A);
    SDL_RenderPresent(renderer);
}


If I understand what you're asking, you'd want to update only SOME blocks/tiles on the map at each time? 如果我了解您的要求,那么您每次只想更新地图上的一些街区/瓷砖吗? That's not possible unless you divide your map texture into pieces, which could create more overhead than you're saving. 除非将地图纹理分成几部分,否则这是不可能的,这可能会产生比您节省的更多开销。 You can't SDL_RenderClear only part of a texture without some potentially undesired side effects. 您不能仅对部分纹理进行SDL_RenderClear清除,而没有一些潜在的不良副作用。

What I would do is break the map texture up into layers (map_floors, map_walls, etc.) and cache each layer. 我要做的是将地图纹理分解为几层(map_floors,map_walls等)并缓存每层。 So instead of calling GraphicsDrawer::drawMap() every frame, only call it on frames in which a layer changes. 因此,与其在每一帧都调用GraphicsDrawer :: drawMap(),不如在层发生变化的帧上调用它。 So if a NPC moves, only redraw the layer which has NPC's on it. 因此,如果NPC移动,则仅重绘具有NPC的图层。 You'd still call SDL_RenderCopy() every frame but the texture for each layer doesn't have to be regenerated every frame. 您仍然会在每帧调用SDL_RenderCopy(),但不必在每一帧都重新生成每一层的纹理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM