#include "SceneRenderer.h" using namespace graphic; // constructor SceneRenderer::SceneRenderer(Sint16 x, Sint16 y, Uint16 w, Uint16 h, bool graphic_mode) { // set initial view _view = new SDL_Rect; _view->x = x; _view->y = y; _view->w =w; _view->h = h; // set default limits _u_limit = 0; _b_limit = h; _l_limit = 0; _r_limit = w; // create buffer in SDL mode if(graphic_mode == SDL_GRAPHIC) { _use_buffer = true; _buffer = new Surface(w, h); } // GL mode, no buffer needed else { _use_buffer = false; _buffer = NULL; } // default fill color is black _fill_color.r = 0; _fill_color.g = 0; _fill_color.b = 0; // no scrolling at the beginning _scrolling = false; _scroll_speed = SCROLL_SPEED; _scrolling_dir.reset(); _need_buf_refresh = false; _need_blit = false; _need_buf_blit = false; } // blit the current scene on the dest surface void SceneRenderer::BlitScene(Surface * dest) { if(_need_buf_refresh && _use_buffer) RefreshBuffer(); if(_need_blit || !_use_buffer) DirectBlitScene(dest); else if(_need_buf_blit) BufferedBlitScene(dest); }; // blit the current scene on the dest surface void SceneRenderer::DirectBlitScene(Surface * dest) { int num_layers = _layers.size(); // clear the dest if(dest != NULL) dest->Fill(_fill_color); else screen->Clear(); // blit layers for(int i = 0; i < num_layers; i++) { if(_layers[i]->IsActive()) _layers[i]->BlitLayer(*_view, dest); } _need_blit = false; } // blit the current scene, using the buffer, on the dest surface void SceneRenderer::BufferedBlitScene(Surface * dest) { int num_layers = _layers.size(); // clear the dest if(dest != NULL) dest->Fill(_fill_color); else screen->Clear(); // blit the buffer blitter->Blit(_buffer, dest); // blit other layers for(int i = 0; i < num_layers; i++) { if(_layers[i]->IsActive() && !_layers[i]->IsBuffered()) _layers[i]->BlitLayer(*_view, dest); } _need_buf_blit = false; } // refresh the buffer void SceneRenderer::RefreshBuffer() { int num_layers = _layers.size(); // clear the buffer _buffer->Fill(_fill_color); // buffer layers for(int i = 0; i < num_layers; i++) if(_layers[i]->IsActive() && _layers[i]->IsBuffered()) _layers[i]->BlitLayer(* _view, _buffer); _need_buf_refresh = false; } // add a layer to the blit vector void SceneRenderer::AddLayer(Layer * layer) { // set layer id layer->SetLevel(_layers.size()); _layers.push_back(layer); } // move a layer up in the blit vector void SceneRenderer::MoveLayerUp(int id) { int num_layers = _layers.size(); int i; Layer * layer; for(i = 0; i < num_layers; i++) { if(_layers[i]->GetLevel() == id) break; } // last layer => do nothing if(i == (num_layers - 1)) return ; // swap layers layer = _layers[i]; _layers[i] = _layers[i + 1]; _layers[i + 1] = layer; // update level id _layers[i]->DownLevel(); _layers[i + 1]->UpLevel(); } // move a layer down in the blit vector void SceneRenderer::MoveLayerDown(int id) { int num_layers = _layers.size(); int i; Layer * layer; for(i = 0; i < num_layers; i++) { if(_layers[i]->GetLevel() == id) break; } // first layer => do nothing if(!i) return ; // swap layers layer = _layers[i]; _layers[i] = _layers[i - 1]; _layers[i - 1] = layer; // update level id _layers[i]->UpLevel(); _layers[i - 1]->DownLevel(); } // update view position void SceneRenderer::UpdateViewPosition(Sint16 x, Sint16 y) { _view->x = x; _view->y = y; // check for horizontal limits exceeded if(_view->x < _l_limit) _view->x = _l_limit; if(_view->x > _r_limit) _view->x = _r_limit; // check for vertical limits exceeded if(_view->y < _u_limit) _view->y = _u_limit; if(_view->y > _b_limit) _view->y = _b_limit; } /// manage scrolling in according to user input (keyboard and mouse) void SceneRenderer:: ManageScrolling(std::bitset<4> arrows, Sint16 x, Sint16 y) { if(arrows.test(LEFT) || (x < SCROLLING_H_LIMIT && x >= 0)) _scrolling_dir.set(LEFT); else _scrolling_dir.set(LEFT, 0); if(arrows.test(RIGHT) || (x > _view->w - SCROLLING_H_LIMIT && x <= _view->w)) _scrolling_dir.set(RIGHT); else _scrolling_dir.set(RIGHT, 0); if(arrows.test(UP) ||( y < SCROLLING_V_LIMIT && y >= 0)) _scrolling_dir.set(UP); else _scrolling_dir.set(UP, 0); if(arrows.test(DOWN) || (y >_view->h - SCROLLING_V_LIMIT && y <=_view->h)) _scrolling_dir.set(DOWN); else _scrolling_dir.set(DOWN, 0); // scrolling if(_scrolling_dir.any()) _scrolling = true; // end scrolling -> refresh the buffer else if(_scrolling) { _need_buf_refresh = true; _need_buf_blit = true; _scrolling = false; } } // manage the scrolling each frame void SceneRenderer::Scrolling(int time_diff) { int _scroll_mov = (int)ceil(_scroll_speed * time_diff); _need_blit = true; // scrolling up if(_scrolling_dir.test(UP)) { _view->y -= _scroll_mov; if(_view->y < _u_limit) _view->y = _u_limit; } // scrolling down if(_scrolling_dir.test(DOWN)) { _view->y += _scroll_mov; if(_view->y > _b_limit) _view->y = _b_limit; } // scrolling left if(_scrolling_dir.test(LEFT)) { _view->x -= _scroll_mov; if(_view->x < _l_limit) _view->x = _l_limit; } // scrolling right if(_scrolling_dir.test(RIGHT)) { _view->x += _scroll_mov; if(_view->x > _r_limit) _view->x = _r_limit; } } // update view dimensions void SceneRenderer::UpdateViewDimensions(Uint16 w, Uint16 h) { _view->w = w; _view->h = h; if(_use_buffer) { delete _buffer; // recreate buffer _buffer = new Surface(w, h); _need_buf_refresh = true; _need_buf_blit = true; } }; // tell to the SceneRenderer if use a buffer surface or not void SceneRenderer::UseBuffer(bool use) { if(use && !_use_buffer) { _use_buffer = true; _buffer = new Surface(_view->w, _view->h); _need_buf_refresh = true; _need_buf_blit = true; } else if(_use_buffer) { _use_buffer = false; delete _buffer; _buffer = NULL; } }