Thread: Making an efficient tiling engine

  1. #1
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288

    Making an efficient tiling engine

    I don't usually like to post questions about my game for competition, but I haven't been able to think about a way to render tiles efficiently. Currently, I have a system set up where I parse digits from a file, store them in a 2-D integer array, and then use hardware acceleration to fill rectangles on the screen( clipping when necessary ). It greatly reduces the maximum frame rate of my game, which is what I'm measuring efficiency by, with a decrease of ~70 frames to a total of ~210 frames. This concerns me, since I will need to render actual images and more detailed tiles later on.


    This is what my tiling engine looks like currently :

    Code:
    static void draw_game_background( game_data * game )
    {
        if ( game->camera.x < 0 || game->camera.y < 0 )
            return;
    
    
        /* Get the block location of the camera */
        const int MIN_X = game->camera.x / BLOCK_WIDTH;
        const int MIN_Y = game->camera.y / BLOCK_HEIGHT;
    
    
        int x = 0;
        int y = 0;
    
    
        /* Predefine the invariants to prevent unessecary computation of values */
        const int STARTING_WIDTH = BLOCK_WIDTH - ( game->camera.x % BLOCK_WIDTH );
        const int STARTING_HEIGHT = BLOCK_HEIGHT - ( game->camera.y % BLOCK_HEIGHT );
        const int ENDING_WIDTH = ( ( game->viewport.w - STARTING_WIDTH ) % BLOCK_WIDTH );
        const int ENDING_HEIGHT = ( ( game->viewport.h - STARTING_HEIGHT ) % BLOCK_HEIGHT );
        const int BLOCK_AMOUNT_ACROSS = ( ( game->viewport.w - STARTING_WIDTH ) - ENDING_WIDTH ) / BLOCK_WIDTH;
        const int BLOCK_AMOUNT_DOWN = ( ( game->viewport.h - STARTING_HEIGHT ) - ENDING_HEIGHT ) / BLOCK_HEIGHT;
    
    
        /* Initialize the strucuture we will use to fill in the game map on the screen */
        SDL_Rect box = { 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT };
    
    
        for ( y = MIN_Y; y < game->current_level->height; y++, box.y = ( BLOCK_HEIGHT * ( ( y - MIN_Y ) - 1 ) ) + STARTING_HEIGHT )
        {
            if ( y - MIN_Y > BLOCK_AMOUNT_DOWN + 1 )
                break; /* Exit the loop completely */
    
    
            for ( x = MIN_X, box.x = 0; x < game->current_level->width; x++, box.x = ( BLOCK_WIDTH * ( ( x - MIN_X ) - 1 ) ) + STARTING_WIDTH )
            {
                if ( !( x - MIN_X ) )
                    box.w = STARTING_WIDTH;
                else
                    box.w = BLOCK_WIDTH;
    
    
                if ( !( y - MIN_Y ) )
                    box.h = STARTING_HEIGHT;
                else
                    box.h = BLOCK_HEIGHT;
    
    
                if ( x - MIN_X == BLOCK_AMOUNT_ACROSS + 1 )
                    box.w = ENDING_WIDTH;
                if ( y - MIN_Y == BLOCK_AMOUNT_DOWN + 1 )
                    box.h = ENDING_HEIGHT;
    
    
                if ( x - MIN_X > BLOCK_AMOUNT_ACROSS + 1 )
                    break; /* Exit out of the nested loop */
    
    
                switch ( game->current_level->level_data[y][x] )
                {
                    /* Fills in the color or object for each type */
                    case WHITE_BOX :
                        SDL_SetRenderDrawColor( game->renderer, 0xFF, 0xFF, 0xFF, 0xFF );
                        SDL_RenderFillRect( game->renderer, &box );
                    break;
    
    
                    case BLACK_BOX :
                        SDL_SetRenderDrawColor( game->renderer, 0x00, 0x00, 0x00, 0xFF );
                        SDL_RenderFillRect( game->renderer, &box );
                    break;
    
    
                    case STARTING_BOX :
                        SDL_SetRenderDrawColor( game->renderer, 0x00, 0xFF, 0x00, 0xFF );
                        SDL_RenderFillRect( game->renderer, &box );
                    break;
    
    
                    case ENDING_BOX :
                        SDL_SetRenderDrawColor( game->renderer, 0xFF, 0x00, 0x00, 0xFF );
                        SDL_RenderFillRect( game->renderer, &box );
                    break;
    
    
                    default :
                        SDL_SetRenderDrawColor( game->renderer, 0x00, 0xFF, 0x00, 0xFF );
                        SDL_RenderFillRect( game->renderer, &box );
                    break;
                }
            }
        }
    
    
        return;
    }
    I would think there is a more efficient way to do that than how I did it, but I couldn't find any sample code online for ideas. The code works well for handling different viewport sizes and clipping everything properly, but it's pretty expensive to call. Any suggestions are appreciated.

    If you need a small program to test my code, I can make one. Just notify me( I may not respond soon ).

    Edit :
    I probably need to define the constant values better for you guys.

    A BLOCK is just my word I used for a tile.
    The BLOCK_WIDTH and BLOCK_HEIGHT is the same as 300x325.
    Last edited by HelpfulPerson; 11-27-2013 at 10:19 PM.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

  2. #2
    Registered User ~Kyo~'s Avatar
    Join Date
    Jun 2004
    Posts
    320
    Try loading the image into video ram and passing pointers to the draw function? Similar to my game at the moment. I only load a texture the first time I see it and I only ever load it once. It also allows for different sized "tiles", in fact the engine doesn't really care what size your tile is as long as it isn't bigger than 1024 by 1024. I don't know if you are using actual graphics for the tiles or not I assumed you are. If not it still may be slightly faster drawing them into video memory and copying from there instead of from RAM.

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Since most tile games use repetition you can create larger quads and set the u,v's to values larger than 1.0f. Turn texture wrapping on for U and V and you have a fast way to render multiple identical tiles.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Suggestions for making my code more efficient?
    By HelpfulPerson in forum C Programming
    Replies: 27
    Last Post: 08-13-2013, 12:29 PM
  2. Making my own gfx engine
    By jverkoey in forum Game Programming
    Replies: 4
    Last Post: 06-07-2003, 02:06 PM
  3. Making Engine in C...
    By Unregistered in forum C Programming
    Replies: 1
    Last Post: 05-04-2002, 12:30 AM
  4. Making a search engine.
    By sean in forum C++ Programming
    Replies: 1
    Last Post: 01-27-2002, 11:44 AM