authoreyes
Member
Hey all,
Was fixin' to get back to coding my pandora game, and I figured I'd throw the rendering portion to the mercy of the dev community.
See, I am only a C++/game programmer hobbyist (career is more java stuff), so I figured I'd see if anyone with some time could point out any inefficiencies here. Basically, this is doing a foreground/background 16x16 tile mapped scrolling engine. It runs fine, but a bit slow. I am sure there is room to optimize, so maybe someone has a few tips...Worst comes to worst, I can render a smaller area and scale up (but loose the high res look it has now)...
I know it may be hard to follow some of this as my commenting is lacking, so if something seems stupid, feel free to shout...
EDIT: added some optimizations.
	
	
	
		
				
			Was fixin' to get back to coding my pandora game, and I figured I'd throw the rendering portion to the mercy of the dev community.
See, I am only a C++/game programmer hobbyist (career is more java stuff), so I figured I'd see if anyone with some time could point out any inefficiencies here. Basically, this is doing a foreground/background 16x16 tile mapped scrolling engine. It runs fine, but a bit slow. I am sure there is room to optimize, so maybe someone has a few tips...Worst comes to worst, I can render a smaller area and scale up (but loose the high res look it has now)...
I know it may be hard to follow some of this as my commenting is lacking, so if something seems stupid, feel free to shout...
EDIT: added some optimizations.
		Code:
	
	class RenderUtils {
    public :
        //TODO: this needs to be pulled out into a main cycle loop
        //class since artificial intelligence and such is going in here now
        static void render(SDL_Surface *screen, GameState *state) {
            clear_screen(screen);
            pre_process_events(state);
            GameLifeManager::move_baddies(state);
            procedural_render(screen, state);
            post_process_events(state);
            SDL_Flip(screen);
        }
        static void procedural_render(SDL_Surface *screen, GameState *state) {
            //render_sprite_vector(screen, state, state->parallax_objs);
            render_backgrounds(screen, state);
            render_sprite_vector(screen, state, state->screen_stats);
            //TODO: attachedsprites needs to be below and check z depth
            render_sprite_vector(screen, state, state->player.attached_sprites);
            render_sprite(screen, state, state->player);
            render_sprite_vector(screen, state, state->sprites);
            render_sprite_vector(screen, state, state->baddies);
        }
        static void render_backgrounds(SDL_Surface *screen, GameState *state) {
            unsigned int x = (int)state->camera_x / LEVEL_TILE_WIDTH;
            unsigned int x_mod_tilewidth = (((int)state->camera_x) % LEVEL_TILE_WIDTH);
            render_parallax(screen, state, x, x_mod_tilewidth, true);
            render_parallax(screen, state, x, x_mod_tilewidth, false);
        }
        static void render_parallax(SDL_Surface *screen, GameState *state, unsigned int x, unsigned int x_mod_tilewidth, bool background) {
            DecoratedSurface *parallax_surface = (background == true ? &(state->background_surface) : &(state->foreground_surface));
            std::vector<std::vector<Tile*> > *grid = (background == true ? &(state->back_grid) : &(state->fore_grid));
            if (background) {
                calculate_background_parallax_offsets(state, &x, &x_mod_tilewidth, background);
            }
            unsigned int total_distance = x + (GAME_WINDOW_WIDTH / LEVEL_TILE_WIDTH) + 1;
            unsigned int scrolled_tile_width = LEVEL_TILE_WIDTH;
            //screen_x represents the absolute position of the start of the display tiles,
            //so we always repaint starting at 0,0
            unsigned int screen_x = 0;
            SDL_Rect tile_pos;
            tile_pos.y = 0;
            tile_pos.h = LEVEL_TILE_HEIGHT;
            //first x pass will be a shaved tile (possibly < 16 pixels on the left of screen)
            if ((int)state->camera_x >> 4 != 0) {
                scrolled_tile_width = LEVEL_TILE_WIDTH - x_mod_tilewidth;
                render_screen_y_tiles(screen, parallax_surface, grid, state, tile_pos, screen_x, x, scrolled_tile_width, x_mod_tilewidth, background);
                screen_x += scrolled_tile_width;
                x++;
            }
            for (x;x<total_distance; ++x) {
                scrolled_tile_width = LEVEL_TILE_WIDTH;
                render_screen_y_tiles(screen, parallax_surface, grid, state, tile_pos, screen_x, x, scrolled_tile_width, 0, background);
                screen_x += scrolled_tile_width;
           }
        }
        static void render_screen_y_tiles(SDL_Surface *screen, DecoratedSurface *parallax_surface, std::vector<std::vector<Tile*> > *grid, GameState *state,
            SDL_Rect tile_pos, unsigned int screen_x, unsigned int x, unsigned int scrolled_tile_width, unsigned int x_mod_tilewidth, bool background) {
            std::vector<Tile*> y_vector = (*grid)[x];
            for (unsigned int y=0;y<y_vector.size();++y) {
                unsigned int tile_id = y_vector[y]->id;
                unsigned int transparent_tile = (background ? state->transparent_tile_f : state->transparent_tile_B);
                if (tile_id != transparent_tile) {
                    //calc tile rip from tile strip
                    tile_pos.x = (tile_id << 4) + x_mod_tilewidth;
                    tile_pos.w = scrolled_tile_width;
                    unsigned int screen_y = (y << 4);
                    blit_tile(screen, state, parallax_surface, &tile_pos, screen_x, screen_y, false);
                }
            }
        }
        static void calculate_background_parallax_offsets(GameState *state, unsigned int *x, unsigned *x_mod, bool background) {
            if (state->background_scroll_offset == 0) {
                state->background_parallax_camera_x = ++state->background_parallax_camera_x;
                //TODO: this should not use the default, but the specific level impl
                state->background_scroll_offset = GameState::default_background_scroll_offset;
            }
            *x = state->background_parallax_camera_x / LEVEL_TILE_WIDTH;
            *x_mod = (((int)state->background_parallax_camera_x) % LEVEL_TILE_WIDTH);
        }
        static void render_sprite_vector(SDL_Surface *screen, GameState *state, std::vector<Sprite*> sprites) {
            for (std::vector<Sprite*>::iterator it = sprites.begin();it != sprites.end(); ++it) {
                render_sprite(screen, state, *(*it));
            }
        }
        static void render_sprite_vector(SDL_Surface *screen, GameState *state, std::vector<Sprite> sprites) {
             for (std::vector<Sprite>::iterator it = sprites.begin();it != sprites.end(); ++it) {
                render_sprite(screen, state, (*it));
            }
        }
        static void render_sprite(SDL_Surface *screen, GameState *state, Sprite sprite) {
            SDL_Rect tile_pos;
            if (sprite.descriptor->num_frames == 1) {
                tile_pos.x = tile_pos.y = 0;
                tile_pos.w = sprite.descriptor->width;
                tile_pos.h = sprite.descriptor->height;
            } else {
                tile_pos.x = sprite.get_current_frame() * sprite.descriptor->width;
                tile_pos.y = 0;
            }
            tile_pos.w = sprite.descriptor->width;
            tile_pos.h = sprite.descriptor->height;
            blit_tile(screen, state, sprite.descriptor->sprite_sheet, &tile_pos, sprite.x, sprite.y, sprite.heading == W);
        }
        static void blit_tile(SDL_Surface *screen, GameState *state, DecoratedSurface *surface, SDL_Rect *tile_pos, unsigned int x, unsigned int y, bool flip) {
           SDL_Rect offset;
           offset.x = x;
           offset.y = y;
           SDL_BlitSurface(surface->surface, tile_pos, screen, &offset);
        }
        static void pre_process_events(GameState *state) {
            for (std::vector<TriggeredEvent*>::iterator it = state->level->pre_process_triggered_events.begin();it != state->level->pre_process_triggered_events.end(); ++it) {
                if ((*it)->status == EXECUTING) {
                    (*it)->next_cycle(state);
                }
            }
        }
        static void post_process_events(GameState *state) {
            for (std::vector<TriggeredEvent*>::iterator it = state->level->post_process_triggered_events.begin();it != state->level->post_process_triggered_events.end(); ++it) {
                if ((*it)->status == EXECUTING) {
                    (*it)->next_cycle(state);
                }
            }
        }
        static void clear_screen(SDL_Surface *screen) {
            SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0, 0, 0));
        }
};
#endif 
	
 
 
		 
 
		 
 
		 
 
		 
 
		 
 
		 
 
		