game/sdlpp/sdlpp_scene.cpp
2021-03-07 14:06:55 +01:00

238 lines
8.0 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.first < leftmost_rect.first.first )
leftmost_obj = obj;
auto rightmost_rect = rightmost_obj->getDoubleRect();
if ( rect.first.first + rect.second.first >
rightmost_rect.first.first + rightmost_rect.second.first )
rightmost_obj = obj;
}
}
void Scene::setZIndex( const std::shared_ptr< RenderObject > &obj, int 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 );
}
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::shared_ptr< RenderObject > >
Scene::getCollisions( RenderObject &r ) {
if ( r.getHidden() )
return {};
std::vector< std::shared_ptr< RenderObject > > ret{};
for ( const auto &x : collision_objects ) {
if ( x->colidesWith( r ) ) {
ret.push_back( x );
}
}
return ret;
}
std::vector< std::shared_ptr< RenderObject > >
Scene::getCollisions( RenderObject &r,
const std::unordered_set< int > &objectIDs ) {
if ( r.getHidden() )
return {};
std::vector< std::shared_ptr< RenderObject > > ret{};
for ( const auto &x : collision_objects ) {
if ( objectIDs.find( x->getId() ) != objectIDs.end() &&
x->colidesWith( r ) ) {
ret.push_back( 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() );
}
}
}
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;
auto curPos = obj->getDoubleRect();
obj->setPos( curPos.first.first + x, curPos.first.second + y );
}
}
const std::shared_ptr< RenderObject > &Scene::leftmost() {
return leftmost_obj;
}
const std::shared_ptr< RenderObject > &Scene::rightmost() {
return rightmost_obj;
}
std::pair< int, 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::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