Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Sortowanie obiektów do renderowania - czyli sortowanie względem typu i pozycji y

Ostatnio zmodyfikowano dzisiaj: 4h » 26 min
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
Sortowanie obiektów do renderowania - czyli sortowanie względem typu i pozycji y
» 2026-09-03 22:00:41
Cześć. Mam różne obiekty do renderowania. Chciałbym je posortować względem typu,a potem względem pozycji y.
Czy optymalnie napisałem sortowanie względem typu?

C/C++
void GameObjectsOnMap::sort() {
   
   
std::vector < ObjectType > types = {
       
ObjectType::BuildingSkeleton,
       
ObjectType::WallMounted,
       
ObjectType::Window,
       
ObjectType::Door,
       
ObjectType::Roof,
   
};
   
   
auto getIndex =[ & types ]( ObjectType type )->int {
       
auto it = std::find( types.begin(), types.end(), type );
       
if( it != types.end() )
           
 return it - types.begin();
       
       
return - 1; // other types
   
};
   
   
std::sort( _visibleGameObjectsOnMap.begin(), _visibleGameObjectsOnMap.end(),[ & types, getIndex ]( const std::shared_ptr < GameObjectOnMap > & a, const std::shared_ptr < GameObjectOnMap > & b ) {
       
       
int aIndex = getIndex( a->_type );
       
int bIndex = getIndex( b->_type );
       
       
if( aIndex < bIndex ) return true;
       
       
if( aIndex > bIndex ) return false;
       
       
// OBJECT A - POSITION
       
sf::Vector2i posA = a->_position;
       
       
if( a->_prefab.lock()->_collider->_type == ColliderType::Rectangular ) {
           
std::shared_ptr < RectangularCollider > collider = std::dynamic_pointer_cast < RectangularCollider >( a->_prefab.lock()->getCollider() );
           
posA += collider->_rect.position + collider->_rect.size / 2;
       
}
       
else if( !dynamic_pointer_cast < MonsterPrefab >( a->_prefab.lock() ) ) {
           
posA += a->_prefab.lock()->getOrigin();
       
}
       
       
// OBJECT B - POSITION
       
sf::Vector2i posB = b->_position;
       
       
if( b->_prefab.lock()->_collider->_type == ColliderType::Rectangular ) {
           
std::shared_ptr < RectangularCollider > collider = std::dynamic_pointer_cast < RectangularCollider >( b->_prefab.lock()->getCollider() );
           
posB += collider->_rect.position + collider->_rect.size / 2;
       
}
       
else if( !dynamic_pointer_cast < MonsterPrefab >( b->_prefab.lock() ) ) {
           
posB += b->_prefab.lock()->getOrigin();
       
}
       
       
       
if( posA.y == posB.y )
           
 return posA.x < posB.x;
       
       
return posA.y < posB.y;
   
} );
}
P-184522
DejaVu
» 2026-09-03 22:45:55
Sortowanie wygląda sensownie tj. najpierw ify na index true/false jak masz, a potem druga część. Natomiast na Twoim miejscu lockowałbym cały kontener z obiektami (o ile tak masz kod zorganizowany), bo robić 2*N*log(N) locków jest bardzo nieefektywne i niewydajne.
P-184523
tBane
Temat założony przez niniejszego użytkownika
» 2026-09-03 22:49:13
W sensie utworzyć listę obiektów z użyciem object.lock() i dopiero na niej wykonywać operacje?
P-184524
DejaVu
» 2026-09-03 22:54:06
Generalnie chodzi o to, że jeżeli tworzysz wielowątkową grę, to powinieneś mieć listę obiektów, którą lockujesz, wykonujesz operacje na całej liście i zdejmujesz locka. Lockowanie pojedynczych obiektów jest nieefektywne. Chyba, że to są lockiczegoś innego (nie widzę czym jest _prefab).

W każdym razie dążyłbym też do upraszczania kodu tak, aby unikać dynamic_pointer_cast. Czyli:

C/C++
auto typeA = a->getType();
auto typeB = b->getType();
if( typeA < typeB ) return true;

if( typeA > typeB ) return false;

auto positionAY = a->getPosition().y;
auto positionBY = b->getPosition().y;
if( positionAY < positionBY ) return true;

if( positionAY > positionBY ) return false;

//... inne warunki
return false; //lub true

Innymi słowy: metoda ma zwrócić Ci przygotowaną cząstkową informację, aby złożoność sortowania była prosta do implementacji.
P-184525
tBane
Temat założony przez niniejszego użytkownika
» 2026-09-03 23:06:33
Dobra. Dynamic pointery cast da się zastąpić porównaniem typu.
P-184526
« 1 »
  Strona 1 z 1