286 lines
9.6 KiB
C++
286 lines
9.6 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() {
|
|
if(paused) {
|
|
return;
|
|
}
|
|
// 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;
|
|
}
|
|
void Scene::pauseScene() {
|
|
paused = true;
|
|
diff_ticks = SDL_GetTicks() - prev_ticks;
|
|
}
|
|
void Scene::unpauseScene() {
|
|
paused = false;
|
|
prev_ticks = SDL_GetTicks() - diff_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 ) {
|
|
if(x.get() == &r) {
|
|
continue;
|
|
}
|
|
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
|