123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- #include "Welt2D.h"
- #include "Bild.h"
- using namespace Framework;
- Object2D::Object2D()
- {
- rSpeed = 0;
- rotation = 0;
- size = 1;
- collision = 1;
- ref = 1;
- }
- Object2D::~Object2D()
- {}
- void Object2D::explosion( Vertex worldPos, float intensity )
- {
- intensity /= ( position - worldPos ).getLengthSq();
- speed += ( position - worldPos ) * intensity;
- }
- void Object2D::impuls( Vertex start, Vertex speed, float strength )
- {}
- void Object2D::setSpeed( Vertex speed )
- {
- this->speed = speed;
- }
- void Object2D::setSpeed( float x, float y )
- {
- speed.x = x, speed.y = y;
- }
- void Object2D::setPosition( Vertex pos )
- {
- position = pos;
- }
- void Object2D::setPosition( float x, float y )
- {
- position = Vertex( x, y );
- }
- void Object2D::setDrehungSpeed( float ds )
- {
- rSpeed = ds;
- }
- void Object2D::setDrehung( float drehung )
- {
- rotation = drehung;
- while( rotation > PI * 2 )
- rotation -= (float)PI * 2;
- while( rotation < 0 )
- rotation += (float)PI * 2;
- }
- void Object2D::addDrehung( float drehung )
- {
- rotation += drehung;
- while( rotation > PI * 2 )
- rotation -= (float)PI * 2;
- while( rotation < 0 )
- rotation += (float)PI * 2;
- }
- void Object2D::setSize( float size )
- {
- this->size = size;
- }
- void Object2D::addSize( float size )
- {
- this->size += size;
- }
- void Object2D::setCollision( bool handle )
- {
- collision = handle;
- }
- bool Object2D::handleCollision( Object2D *obj )
- {
- Vertex hp;
- if( istModelInnen( obj, &hp ) ) // hp wird auf den aufprallpunkt gesetzt
- {
- // Geschwindigkeit von diesem objekt mit rotation
- Vertex v1 = getSpeed() + getWorldDir( getObjectPos( hp ).rotation( rSpeed ) - getObjectPos( hp ) );
- // Geschwindigkeit des anderen Objektes mit rotation
- Vertex v2 = obj->getSpeed() + getWorldDir( obj->getObjectPos( hp ).rotation( obj->getDrehungSpeed() ) - obj->getObjectPos( hp ) );
- if( ( hp - obj->getPosition() ).getLengthSq() > ( hp + v1 * 0.03f - obj->getPosition() ).getLengthSq() ||
- ( hp - getPosition() ).getLengthSq() > ( hp + v2 * 0.03f - getPosition() ).getLengthSq() )
- { // nur wenn sie sich aufeinander zu bewegen
- float m1 = getMasse() * v1.getLength(); // fläche von Objekt 1
- float m2 = obj->getMasse() * v2.getLength(); // fläche von Objekt 2
- if( m1 == 0 || m2 == 0 )
- return 0; // falls ein objekt keine masse hat ignoriere die kollision
- float nm1 = m1 / ( m1 + m2 ); // koeffizient für objekt 2
- float nm2 = m2 / ( m1 + m2 ); // koeffizient für Objekt 1
- //rSpeed *= nm1; // Drehgeschwindigkeit anpassen (objekt 1)
- //speed *= nm1; // Bewegungsgeschwindigkeit anpassen (objekt 1)
- //obj->setDrehungSpeed( obj->getDrehungSpeed() * nm2 ); // Drehgeschwindigkeit anpassen (objekt 2)
- //obj->setSpeed( obj->getSpeed() * nm2 ); // Bewegungsgeschwindigkeit anpassen (objekt 2)
- float speedSumLength = getSpeed().getLength() + obj->getSpeed().getLength();
- rSpeed = 0;
- speed = Vertex();
- obj->setDrehungSpeed( 0 );
- obj->setSpeed( Vertex() );
- if( v2.x || v2.y )
- impuls( hp - v2, v2 );
- if( getSpeed().getLength() > 0 )
- setSpeed( getSpeed().normalize() * speedSumLength * nm2 );
- if( v1.x || v1.y )
- obj->impuls( hp - v1, v1 );
- if( obj->getSpeed().getLength() > 0 )
- obj->setSpeed( obj->getSpeed().normalize() * speedSumLength * nm1 );
- return 1;
- }
- }
- return 0;
- }
- bool Object2D::tick( const WeltInfo &info, double zeit )
- {
- rotation += rSpeed * (float)zeit;
- while( rotation > PI * 2 )
- rotation -= (float)PI * 2;
- while( rotation < 0 )
- rotation += (float)PI * 2;
- position += speed * (float)zeit;
- while( zeit > 1 )
- {
- rSpeed -= rSpeed - ( rSpeed / ( 1 + info.airResistance * getLuftWiederstand() ) );
- speed -= speed - ( speed / ( 1 + info.airResistance * getLuftWiederstand() ) );
- zeit -= 1;
- }
- rSpeed -= ( rSpeed - ( rSpeed / ( 1 + info.airResistance * getLuftWiederstand() ) ) ) * (float)zeit;
- speed -= ( speed - ( speed / ( 1 + info.airResistance * getLuftWiederstand() ) ) ) * (float)zeit;
- if( info.circular && info.hasSize && info.size.x && info.size.y )
- {
- while( position.x > info.size.x )
- position.x -= (float)info.size.x;
- while( position.x < 0 )
- position.x += (float)info.size.x;
- while( position.y > info.size.y )
- position.y -= (float)info.size.y;
- while( position.y < 0 )
- position.y += (float)info.size.y;
- }
- return rSpeed != 0 || speed != Vertex( 0, 0 );
- }
- bool Object2D::istPunktInnen( Vertex p ) const
- {
- return 0;
- }
- bool Object2D::istLinieInnen( Vertex a, Vertex b ) const
- {
- return 0;
- }
- bool Object2D::istModelInnen( const Object2D *zObj, Vertex *sp, bool end ) const
- {
- return 0;
- }
- Mat3< float > Object2D::getObjectMatrix() const
- {
- return Mat3<float>::translation( position ) * Mat3<float>::rotation( rotation ) * Mat3<float>::scaling( size );
- }
- Mat3< float > Object2D::getInverseObjectMatrix() const
- {
- return Mat3<float>::scaling( 1 / size ) * Mat3<float>::rotation( -rotation ) * Mat3<float>::translation( -position );
- }
- Vertex Object2D::getObjectPos( Vertex worldPos ) const
- {
- return ( worldPos - position ).rotation( -rotation ) * ( 1 / size );
- }
- Vertex Object2D::getObjectDir( Vertex worldDir ) const
- {
- return Vertex( worldDir.x, worldDir.y ).rotation( -rotation ) * ( 1 / size );
- }
- Vertex Object2D::getWorldPos( Vertex objectPos ) const
- {
- return ( Vertex( objectPos ) * size ).rotation( rotation ) + position;
- }
- Vertex Object2D::getWorldDir( Vertex objectDir ) const
- {
- return ( Vertex( objectDir ) * size ).rotation( rotation );
- }
- Vertex Object2D::getSpeed() const
- {
- return speed;
- }
- Vertex Object2D::getPosition() const
- {
- return position;
- }
- float Object2D::getDrehungSpeed() const
- {
- return rSpeed;
- }
- float Object2D::getDrehung() const
- {
- return rotation;
- }
- float Object2D::getSize() const
- {
- return size;
- }
- bool Object2D::calcHitPoint( Vertex pos, Vertex dir, Vertex &hitpoint ) const
- {
- return 0;
- }
- float Object2D::getLuftWiederstand() const
- {
- return 0;
- }
- float Object2D::getMasse() const
- {
- return 0;
- }
- bool Object2D::canCollide()
- {
- return collision;
- }
- Object2D *Object2D::getThis()
- {
- ref++;
- return this;
- }
- Object2D *Object2D::release()
- {
- if( !--ref )
- delete this;
- return 0;
- }
- Welt2D::Welt2D()
- {
- objects = new RCArray< Object2D >();
- memset( &info, 0, sizeof( WeltInfo ) );
- ref = 1;
- }
- Welt2D::~Welt2D()
- {
- objects->release();
- }
- void Welt2D::setAirResistance( float resistance )
- {
- info.airResistance = resistance;
- }
- void Welt2D::setSize( int width, int height )
- {
- info.size.x = width;
- info.size.y = height;
- }
- void Welt2D::setSize( bool hasSize )
- {
- info.hasSize = hasSize;
- }
- void Welt2D::setCircular( bool circular )
- {
- info.circular = circular;
- }
- void Welt2D::addObject( Object2D *obj )
- {
- objects->add( obj );
- }
- void Welt2D::removeObject( Object2D *zObj )
- {
- int anz = objects->getEintragAnzahl();
- for( int i = 0; i < anz; i++ )
- {
- if( objects->z( i ) == zObj )
- {
- objects->remove( i );
- i--;
- }
- }
- }
- void Welt2D::removeAll()
- {
- objects->leeren();
- }
- void Welt2D::explosion( Vertex worldPos, float intensity, float maxRad )
- {
- maxRad = maxRad * maxRad;
- for( auto obj = objects->getIterator(); obj; obj++ )
- {
- if( info.circular && info.hasSize && info.size.x && info.size.y )
- {
- Vertex offsets[] = {
- Vertex( 0, 0 ),
- Vertex( (float)info.size.x, 0 ),
- Vertex( 0, (float)info.size.y ),
- Vertex( (float)info.size.x, (float)info.size.y ),
- Vertex( (float)-info.size.x, 0 ),
- Vertex( 0, (float)-info.size.y ),
- Vertex( (float)-info.size.x, (float)-info.size.y ),
- Vertex( (float)-info.size.x, (float)info.size.y ),
- Vertex( (float)info.size.x, (float)-info.size.y ) };
- Vertex offset;
- float minDist = INFINITY;
- for( Vertex p : offsets )
- {
- float dist = ( obj->getPosition() - (worldPos - p) ).getLengthSq();
- if( dist < minDist )
- {
- minDist = dist;
- offset = p;
- }
- }
- if( ( obj->getPosition() - (worldPos - offset) ).getLengthSq() < maxRad )
- obj->explosion( worldPos - offset, intensity );
- }
- else if( ( obj->getPosition() - worldPos ).getLengthSq() < maxRad )
- obj->explosion( worldPos, intensity );
- }
- }
- void Welt2D::impuls( Vertex worldPos, Vertex worldDir )
- {
- Vertex hitPoint;
- float dist = INFINITY;
- Object2D *o = 0;
- for( auto obj = objects->getIterator(); obj; obj++ )
- {
- if( obj->calcHitPoint( worldPos, worldDir, hitPoint ) )
- {
- if( ( hitPoint - worldPos ).getLengthSq() < dist )
- {
- dist = ( hitPoint - worldPos ).getLengthSq();
- o = obj;
- }
- }
- }
- if( o )
- o->impuls( worldPos, worldDir );
- }
- bool Welt2D::tick( double zeit )
- {
- bool ret = 0;
- for( auto obj = objects->getIterator(); obj; obj++ )
- {
- if( obj.hasNext() && obj->canCollide() )
- {
- for( auto obj2 = obj.next(); obj2; obj2++ )
- {
- if( obj2->canCollide() )
- obj->handleCollision( obj2 );
- }
- }
- ret |= obj->tick( info, zeit );
- }
- return ret;
- }
- void Welt2D::render( Mat3< float > &kamMat, Punkt size, Bild &zRObj, int xOffset, int yOffset, const char *kamName )
- {
- for( auto obj = objects->getIterator(); obj; obj++ )
- {
- Rect2< float > bnd = obj->getBoundingBox();
- Vertex topRight = Vertex( bnd.bottomRight.x, bnd.topLeft.y );
- Vertex bottomLeft = Vertex( bnd.topLeft.x, bnd.bottomRight.y );
- Mat3< float > km = kamMat * Mat3<float>::translation( Vertex( (float)xOffset, (float)yOffset ) );
- bnd.bottomRight = km * bnd.bottomRight;
- bnd.topLeft = km * bnd.topLeft;
- topRight = km * topRight;
- bottomLeft = km * bottomLeft;
- if( ( bnd.bottomRight.x >= 0 && bnd.bottomRight.x < size.x ) ||
- ( bnd.bottomRight.y >= 0 && bnd.bottomRight.y < size.y ) ||
- ( bnd.topLeft.x >= 0 && bnd.topLeft.x < size.x ) ||
- ( bnd.topLeft.y >= 0 && bnd.topLeft.y < size.y ) ||
- ( topRight.x >= 0 && topRight.x < size.x ) ||
- ( topRight.y >= 0 && topRight.y < size.y ) ||
- ( bottomLeft.x >= 0 && bottomLeft.x < size.x ) ||
- ( bottomLeft.y >= 0 && bottomLeft.y < size.y ) )
- obj->render( km, zRObj, kamName );
- }
- }
- void Welt2D::render( Mat3< float > &kamMat, Punkt size, Bild &zRObj, const char *kamName )
- {
- if( !info.hasSize || !info.circular )
- {
- for( auto obj = objects->getIterator(); obj; obj++ )
- {
- Rect2< float > bnd = obj->getBoundingBox();
- Vertex topRight = Vertex( bnd.topLeft.y, bnd.bottomRight.x );
- Vertex bottomLeft = Vertex( bnd.topLeft.x, bnd.bottomRight.y );
- bnd.bottomRight = kamMat * bnd.bottomRight;
- bnd.topLeft = kamMat * bnd.topLeft;
- topRight = kamMat * topRight;
- bottomLeft = kamMat * bottomLeft;
- if( ( bnd.bottomRight.x >= 0 && bnd.bottomRight.x < size.x ) ||
- ( bnd.bottomRight.y >= 0 && bnd.bottomRight.y < size.y ) ||
- ( bnd.topLeft.x >= 0 && bnd.topLeft.x < size.x ) ||
- ( bnd.topLeft.y >= 0 && bnd.topLeft.y < size.y ) ||
- ( topRight.x >= 0 && topRight.x < size.x ) ||
- ( topRight.y >= 0 && topRight.y < size.y ) ||
- ( bottomLeft.x >= 0 && bottomLeft.x < size.x ) ||
- ( bottomLeft.y >= 0 && bottomLeft.y < size.y ) )
- obj->render( kamMat, zRObj, kamName );
- }
- }
- else if( info.circular )
- {
- render( kamMat, size, zRObj, 0, 0, kamName );
- render( kamMat, size, zRObj, info.size.x, 0, kamName );
- render( kamMat, size, zRObj, 0, info.size.y, kamName );
- render( kamMat, size, zRObj, info.size.x, info.size.y, kamName );
- render( kamMat, size, zRObj, -info.size.x, 0, kamName );
- render( kamMat, size, zRObj, 0, -info.size.y, kamName );
- render( kamMat, size, zRObj, -info.size.x, -info.size.y, kamName );
- render( kamMat, size, zRObj, -info.size.x, +info.size.y, kamName );
- render( kamMat, size, zRObj, +info.size.x, -info.size.y, kamName );
- }
- }
- const WeltInfo &Welt2D::getWorldInfo() const
- {
- return info;
- }
- Welt2D *Welt2D::getThis()
- {
- ref++;
- return this;
- }
- Welt2D *Welt2D::release()
- {
- if( !--ref )
- delete this;
- return 0;
- }
|