game/sdlpp/sdlpp_scene.cpp

272 lines
9.3 KiB
C++

#include "sdlpp_scene.hpp"
namespace SDLPP {
Scene::Scene( std::shared_ptr< Renderer > &r ) : renderer( r ) {
SDL_SetRenderDrawColor( renderer->getRendererPtr(), 0xFF, 0xFF, 0xFF,
0xFF );
prev_ticks = SDL_GetTicks();
}
void Scene::addObject( const std::shared_ptr< RenderObject > &obj ) {
std::lock_guard< std::mutex > lock( render_mutex );
render_objects.push_back( obj );
obj->setSceneID( ++max_object_id );
if ( obj->hasCollisions() ) {
collision_objects.push_back( obj );
}
if ( render_objects.size() == 1 ) {
leftmost_obj = obj;
rightmost_obj = obj;
} else {
auto rect = obj->getDoubleRect();
auto leftmost_rect = leftmost_obj->getDoubleRect();
if ( ( rect.first.getX() < leftmost_rect.first.getX() &&
!obj->getPermanent() ) ||
( leftmost_obj->getPermanent() && !obj->getPermanent() ) )
leftmost_obj = obj;
auto rightmost_rect = rightmost_obj->getDoubleRect();
if ( ( rect.first.getX() + rect.second.getX() >
rightmost_rect.first.getX() + rightmost_rect.second.getX() &&
!obj->getPermanent() ) ||
( rightmost_obj->getPermanent() && !obj->getPermanent() ) )
rightmost_obj = obj;
}
}
void Scene::setZIndex( const std::shared_ptr< RenderObject > &obj, uint64_t index ) {
std::lock_guard< std::mutex > guard( render_mutex );
int original_index = 0;
for ( long unsigned int i = 0; i < render_objects.size(); i++ ) {
if ( render_objects[i] == obj ) {
original_index = i;
}
}
if ( original_index == index )
return;
if ( original_index > index )
original_index++;
render_objects.insert( render_objects.begin() + index, obj );
render_objects.erase( render_objects.begin() + original_index );
}
void Scene::moveDownZ( const std::shared_ptr< RenderObject > &obj ) {
moveZ( obj, -1 );
}
void Scene::moveUpZ( const std::shared_ptr< RenderObject > &obj ) {
moveZ( obj, 1 );
}
void Scene::moveZ( const std::shared_ptr< RenderObject > &obj, int addition ) {
int original_index = 0;
for ( long unsigned int i = 0; i < render_objects.size(); i++ ) {
if ( render_objects[i] == obj ) {
original_index = i;
}
}
std::iter_swap( render_objects.begin() + original_index,
render_objects.begin() + original_index + addition );
}
void Scene::moveZTop( const std::shared_ptr< RenderObject > &obj ) {
setZIndex( obj, render_objects.size() - 1 );
}
void Scene::moveZBottom( const std::shared_ptr< RenderObject > &obj ) {
setZIndex( obj, 0 );
}
void Scene::moveZJustAboveBackground( const std::shared_ptr< RenderObject > &obj ) {
setZIndex( obj, first_non_background_index );
}
std::shared_ptr< RenderObject > Scene::getObject( int index ) {
return render_objects[index];
}
std::vector< std::shared_ptr< RenderObject > > Scene::getObjects() {
return render_objects;
}
std::vector< std::shared_ptr< RenderObject > >
Scene::getObjects( const std::unordered_set< int > &objectIDs ) {
std::vector< std::shared_ptr< RenderObject > > ret{};
for ( const auto &x : render_objects ) {
// check if object exists because of possible race condition
if ( x && objectIDs.find( x->getId() ) != objectIDs.end() ) {
ret.push_back( x );
}
}
return ret;
}
void Scene::updateScene() {
// check for objects that should be removed
checkKilled();
std::lock_guard< std::mutex > lock( render_mutex );
int now_ticks = SDL_GetTicks();
for ( const auto &x : render_objects ) {
// move objects that should be moved
x->move( now_ticks - prev_ticks );
// animate objects that should be animated
x->animate( now_ticks - prev_ticks );
}
prev_ticks = now_ticks;
}
std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > >
Scene::getCollisions( RenderObject &r ) {
if ( r.getHidden() )
return {};
std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > > ret{};
for ( const auto &x : collision_objects ) {
for ( auto id : r.colidesWith( *x ) ) {
ret.emplace_back( id, x );
}
}
return ret;
}
void Scene::visitCollisions( RenderObject &r, Visitor &v ) {
for ( auto &collision : getCollisions( r ) ) {
v.setFromId( collision.first );
collision.second->visit( v );
}
}
std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > >
Scene::getCollisions( RenderObject &r,
const std::unordered_set< int > &objectIDs ) {
if ( r.getHidden() )
return {};
std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > > ret{};
for ( const auto &x : collision_objects ) {
if ( objectIDs.find( x->getId() ) != objectIDs.end() ) {
for ( auto id : r.colidesWith( *x ) ) {
ret.push_back( { id, x } );
}
}
}
return ret;
}
void Scene::renderScene( bool clear_renderer ) {
checkKilled();
std::lock_guard< std::mutex > lock( render_mutex );
if ( clear_renderer )
SDL_RenderClear( renderer->getRendererPtr() );
if ( background && background->getTexturePtr() )
SDL_RenderCopy( renderer->getRendererPtr(), background->getTexturePtr(),
NULL, NULL );
for ( const auto &x : render_objects ) {
x->render();
}
}
void Scene::presentScene() {
SDL_RenderPresent( renderer->getRendererPtr() );
}
void Scene::setBackground( std::shared_ptr< Texture > bg ) {
background = bg;
}
void Scene::setBackground( const std::string &img_path ) {
background = std::make_shared< Texture >( renderer, img_path );
}
void Scene::updateSizeAndPosition() {
checkKilled();
std::lock_guard< std::mutex > lock( render_mutex );
for ( auto &x : render_objects ) {
x->updateSizeAndPosition();
for ( auto &col : x->getCollisions() ) {
col->updateCollision( x->collisionPushX(), x->collisionPushY(),
x->collisionWidth(), x->collisionHeight(),
x->getId() );
}
}
}
void Scene::moveEverything( double x, double y ) {
checkKilled();
std::lock_guard< std::mutex > lock( render_mutex );
for ( auto &obj : render_objects ) {
if ( obj->getPermanent() )
continue;
obj->setPos( obj->getDoubleRect().first + Vec2D< double >( x, y ) );
}
}
const std::shared_ptr< RenderObject > &Scene::leftmost() {
return leftmost_obj;
}
const std::shared_ptr< RenderObject > &Scene::rightmost() {
return rightmost_obj;
}
Vec2D< int > Scene::getDimensions() const {
return renderer->getDimensions();
}
int Scene::getWidth() const {
return renderer->getWidth();
}
int Scene::getHeight() const {
return renderer->getHeight();
}
Renderer &Scene::getRenderer() {
return *renderer;
}
std::shared_ptr< Renderer > Scene::getRendererShared() {
return renderer;
}
void Scene::setPrevTicks( int ticks ) {
prev_ticks = ticks;
}
void Scene::saveScene() {
saved_render_objects.clear();
saved_collision_objects.clear();
for ( auto &obj : render_objects ) {
if ( !obj->isStatic() )
saved_render_objects.push_back( obj->copySelf() );
else
saved_render_objects.push_back( obj );
}
for ( auto &obj : collision_objects ) {
if ( !obj->isStatic() )
saved_collision_objects.push_back( obj->copySelf() );
else
saved_collision_objects.push_back( obj );
}
}
void Scene::resetScene() {
render_objects.clear();
collision_objects.clear();
for ( auto &obj : saved_render_objects ) {
if ( !obj->isStatic() )
render_objects.push_back( obj->copySelf() );
else
render_objects.push_back( obj );
}
for ( auto &obj : saved_collision_objects ) {
if ( !obj->isStatic() )
collision_objects.push_back( obj->copySelf() );
else
collision_objects.push_back( obj );
}
}
void Scene::setBackgroundObjectIDs(const std::unordered_set<uint64_t> &ids) {
background_ids = ids;
}
void Scene::updateBackgroundObjectZIndex() {
first_non_background_index = 1;
for(uint64_t i = 1; i < render_objects.size(); i++) {
if(background_ids.find(render_objects[i]->getId()) != background_ids.end()) {
setZIndex(render_objects[i], 1);
first_non_background_index++;
}
}
}
void Scene::checkKilled() {
std::lock_guard< std::mutex > lock( render_mutex );
std::vector< int > killed;
std::vector< int > killed_collisions;
for ( long unsigned int i = 0; i < render_objects.size(); i++ ) {
if ( render_objects[i]->getKilled() )
killed.push_back( i );
if ( i < collision_objects.size() && collision_objects[i]->getKilled() )
killed_collisions.push_back( i );
}
// reverse so we don't screw up indexing while going thorugh the kill
// indices
std::reverse( killed.begin(), killed.end() );
std::reverse( killed_collisions.begin(), killed_collisions.end() );
for ( auto &index : killed ) {
render_objects.erase( render_objects.begin() + index );
}
for ( auto &index : killed_collisions ) {
collision_objects.erase( collision_objects.begin() + index );
}
}
} // namespace SDLPP