Pārlūkot izejas kodu

realistischere asteroiden (Aufsplitten wenn getroffen)

Kolja Strohm 6 gadi atpakaļ
vecāks
revīzija
2aa57ac9f4
7 mainītis faili ar 271 papildinājumiem un 96 dzēšanām
  1. 49 13
      Asteroids/Asteroid.cpp
  2. 8 2
      Asteroids/Asteroid.h
  3. 28 2
      Asteroids/Map.cpp
  4. 10 2
      Asteroids/Schuss.cpp
  5. 1 1
      Asteroids/Schuss.h
  6. 168 76
      Asteroids/Ship.cpp
  7. 7 0
      Asteroids/Ship.h

+ 49 - 13
Asteroids/Asteroid.cpp

@@ -5,11 +5,13 @@
 #include "Schuss.h"
 #include <iostream>
 #include <Textur2D.h>
+#include "Schuss.h"
 
 // Inhalt der Asteroid Klasse aus Asteroid.h
 // Konstruktor
 Asteroid::Asteroid( Model2DData *data, Bild *textur, Vec2< float > p, Vec2< float > s, float rS, float r, float gr, char num )
 {
+    txt = textur->getThis();
 	asteroid = new Model2D();
 	asteroid->setStyle( Model2D::Style::Sichtbar | Model2D::Style::Textur );
 	asteroid->setModel( data );
@@ -18,7 +20,6 @@ Asteroid::Asteroid( Model2DData *data, Bild *textur, Vec2< float > p, Vec2< floa
 	asteroid->setTextur( txt );
 	asteroid->setDrehung( r );
 	asteroid->setSize( gr );
-	mGröße = 0;
 	pos = p;
 	speed = s;
 	rSpeed = rS;
@@ -29,6 +30,7 @@ Asteroid::Asteroid( Model2DData *data, Bild *textur, Vec2< float > p, Vec2< floa
 // Destruktor
 Asteroid::~Asteroid()
 {
+    txt->release();
 	asteroid->release();
 }
 
@@ -46,17 +48,14 @@ bool Asteroid::tick( double zeit, int breite, int h
 	if( minP.y > höhe && speed.y > 0 )
 		pos.y -= höhe + asteroid->zModel()->maxP.y * asteroid->getSize();
 	asteroid->setPosition( pos );
-	if( mGröße )
-	{
-		float gr = mGröße > zeit ? (float)zeit : mGröße;
-		if( asteroid->getSize() < gr )
-			asteroid->setSize( 0 );
-		else
-			asteroid->addSize( -gr );
-		mGröße -= gr;
-	}
 	if( rSpeed )
 		asteroid->addDrehung( rSpeed * (float)zeit );
+    if( ( asteroid->zModel()->maxP - asteroid->zModel()->minP ).x < 50 || ( asteroid->zModel()->maxP - asteroid->zModel()->minP ).y < 50 )
+    {
+        asteroid->setSize( asteroid->getSize() - (float)zeit * 3 );
+        if( asteroid->getSize() < 0 )
+            asteroid->setSize( 0 );
+    }
 	if( speed.x || speed.y )
 	{
 		pos += speed * (float)zeit;
@@ -70,16 +69,33 @@ void Asteroid::render( Bild &zRObj )
 	asteroid->render( zRObj );
 }
 
-bool Asteroid::istGetroffen( Schuss *zSchuss )
+bool Asteroid::istGetroffen( Schuss *zSchuss, Polygon2D &a, Polygon2D &b, Punkt &pa, Punkt &pb, RandomGenerator *zRand )
 {
-	if( zSchuss->istInM2( *asteroid ) )
+    if( ( asteroid->zModel()->maxP - asteroid->zModel()->minP ).x < 50 || ( asteroid->zModel()->maxP - asteroid->zModel()->minP ).y < 50 )
+        return 0;
+    Vertex sp( 0, 0);
+    float r = 0;
+    Vertex hp;
+	if( zSchuss->istInM2( *asteroid, sp, r, hp ) )
 	{
-		mGröße += 0.4f;
+        asteroid->zModel()->split( hp, sp.rotation( -asteroid->getDrehung() ) * 0.1f, "", a, b, pa, pb, [ zRand ]()
+        {
+            return zRand->rand();
+        } );
+        hp = ( hp * asteroid->getSize() ).rotation( asteroid->getDrehung() ) + asteroid->getPosition();
+        speed += sp * 0.1f;
+        rSpeed += r * 0.1f;
+        zSchuss->getPos();
 		return 1;
 	}
 	return 0;
 }
 
+void Asteroid::setDead()
+{
+    asteroid->setSize( 0 );
+}
+
 // constant
 void Asteroid::save( Datei *zD ) const
 {
@@ -110,6 +126,26 @@ Punkt Asteroid::getPos() const
 	return (Punkt)pos;
 }
 
+Bild *Asteroid::getTextur() const
+{
+    return txt->getThis();
+}
+
+Vec2< float > Asteroid::getSpeed() const
+{
+    return speed;
+}
+
+float Asteroid::getRSpeed() const
+{
+    return rSpeed;
+}
+
+char Asteroid::getId() const
+{
+    return id;
+}
+
 // Refernece Counting
 Asteroid *Asteroid::getThis()
 {

+ 8 - 2
Asteroids/Asteroid.h

@@ -3,6 +3,7 @@
 
 #include <Model2D.h>
 #include <Datei.h>
+#include <Random.h>
 
 using namespace Framework;
 
@@ -14,7 +15,7 @@ private:
 	Model2D *asteroid;
 	Vec2< float > pos;
 	Vec2< float > speed;
-	float mGröße;
+    Bild *txt;
 	float rSpeed;
 	char id;
 	int ref;
@@ -27,12 +28,17 @@ public:
 	// nicht constant
 	bool tick( double zeit, int breite, int höhe );
 	void render( Bild &zRObj );
-	bool istGetroffen( Schuss *zSchuss );
+	bool istGetroffen( Schuss *zSchuss, Polygon2D &a, Polygon2D &b, Punkt &pa, Punkt &pb, RandomGenerator *zRand );
+    void setDead();
 	// constant
 	void save( Datei *zD ) const;
 	bool amLeben() const;
 	Model2D *zModel() const;
 	Punkt getPos() const;
+    Bild *getTextur() const;
+    Vec2< float > getSpeed() const;
+    float getRSpeed() const;
+    char getId() const;
 	// Refernece Counting
 	Asteroid *getThis();
 	Asteroid *release();

+ 28 - 2
Asteroids/Map.cpp

@@ -129,7 +129,10 @@ Map::~Map()
 // nicht constant
 void Map::reset( Text *zOptionen )
 {
-    gameTime = 0;
+    flammenL->setAnimation( -1 );
+    flammenR->setAnimation( -1 );
+    flammenM->setAnimation( -1 );
+    gameTime = 0;;
     timer = 0;
     beendet = 0;
     score = 0;
@@ -405,7 +408,28 @@ bool Map::tick( double tickVal )
         Schuss *zs = schuss->z( i );
         bool b = 0;
         for( int j = 0; j < aAnz; j++ )
-            b |= asteroid->z( j )->istGetroffen( zs );
+        {
+            Polygon2D ap;
+            Polygon2D bp;
+            Punkt pa;
+            Punkt pb;
+            if( asteroid->z( j )->istGetroffen( zs, ap, bp, pa, pb, rGen ) )
+            {
+                Array< Polygon2D > *npaA = new Array< Polygon2D >();
+                npaA->add( ap );
+                Model2DData *npdA = new Model2DData();
+                npdA->erstelleModell( npaA );
+                float rot = asteroid->z( j )->zModel()->getDrehung();
+                asteroid->add( new Asteroid( npdA, asteroid->z( j )->getTextur(), pa.rotation( rot ) + asteroid->z( j )->getPos(), asteroid->z( j )->getSpeed(), asteroid->z( j )->getRSpeed(), rot, asteroid->z( j )->zModel()->getSize() ) );
+                Array< Polygon2D > *npaB = new Array< Polygon2D >();
+                npaB->add( bp );
+                Model2DData *npdB = new Model2DData();
+                npdB->erstelleModell( npaB );
+                asteroid->add( new Asteroid( npdB, asteroid->z( j )->getTextur(), pb.rotation( rot ) + asteroid->z( j )->getPos(), asteroid->z( j )->getSpeed(), asteroid->z( j )->getRSpeed(), rot, asteroid->z( j )->zModel()->getSize() ) );
+                b = 1;
+                asteroid->z( j )->setDead();
+            }
+        }
         if( b )
         {
             schuss->remove( i );
@@ -486,6 +510,7 @@ bool Map::tick( double tickVal )
 
 void Map::render( Bild &zRObj )
 {
+    cs.lock();
     Punkt kamP = ship->getKamPos( breite, höhe );
     zRObj.addScrollOffset( kamP.x, kamP.y );
     int aAnz = asteroid->getEintragAnzahl();
@@ -513,6 +538,7 @@ void Map::render( Bild &zRObj )
             kam->setSize( kam->getBreite(), 200 );
         kam->render( zRObj );
     }
+    cs.unlock();
 }
 
 void Map::speichern()

+ 10 - 2
Asteroids/Schuss.cpp

@@ -22,9 +22,17 @@ void Schuss::render( Bild &zRObj )
 }
 
 // constant
-bool Schuss::istInM2( const Model2D &mdl ) const
+bool Schuss::istInM2( const Model2D &mdl, Vertex &speed, float &rot, Vertex &hp ) const
 {
-	return mdl.istPunktInnen( pos ) || mdl.istPunktInnen( pos - speed / 10 );
+    if( mdl.istPunktInnen( pos ) )
+    {
+        if( mdl.zModel()->calcHitPoint( ( ( pos - this->speed / 10 ) - mdl.getPosition() ).rotation( -mdl.getDrehung() ) / mdl.getSize(), Vertex( this->speed / 10 ).rotation( -mdl.getDrehung() ), "", hp, speed, rot ) )
+        {
+            speed = speed.rotation( mdl.getDrehung() );
+            return 1;
+        }
+    }
+    return 0;
 }
 
 void Schuss::save( Datei *zD ) const

+ 1 - 1
Asteroids/Schuss.h

@@ -21,7 +21,7 @@ public:
 	bool tick( double zeit );
 	void render( Bild &zRObj );
 	// constant
-	bool istInM2( const Model2D &mdl ) const;
+	bool istInM2( const Model2D &mdl, Vertex &speed, float &rot, Vertex &hp ) const;
 	void save( Datei *zD ) const;
 	Vec2< float > getPos() const;
 	// Reference Counting

+ 168 - 76
Asteroids/Ship.cpp

@@ -12,131 +12,223 @@
 // Konstruktor
 Ship::Ship( Model2DData *data, Textur2D *zFlammenM, Textur2D *zFlammenL, Textur2D *zFlammenR, Bild *textur, Vec2< float > p, Vec2< float > s, float r )
 {
-	ship = new Model2D();
-	ship->setStyle( Model2D::Style::Sichtbar | Model2D::Style::Textur );
+    for( auto i = data->polygons->getArray(); i.set; i++ )
+    {
+        if( i.var.name->istGleich( "engine_l" ) )
+        {
+            stL = *i.var.schwerpunkt;
+            Vertex l, r;
+            for( int j = 0; j < 4; j++ )
+            {
+                if( i.var.tKordinaten->get( j ).y == 1.f )
+                {
+                    if( i.var.tKordinaten->get( j ).x == 0.f )
+                        l = i.var.vertex->get( j );
+                    if( i.var.tKordinaten->get( j ).x == 1.f )
+                        r = i.var.vertex->get( j );
+                }
+            }
+            kL = ( ( l + ( r - l ) * 0.5 ) - stL );
+        }
+        if( i.var.name->istGleich( "engine_r" ) )
+        {
+            stR = *i.var.schwerpunkt;
+            Vertex l, r;
+            for( int j = 0; j < 4; j++ )
+            {
+                if( i.var.tKordinaten->get( j ).y == 1.f )
+                {
+                    if( i.var.tKordinaten->get( j ).x == 0.f )
+                        l = i.var.vertex->get( j );
+                    if( i.var.tKordinaten->get( j ).x == 1.f )
+                        r = i.var.vertex->get( j );
+                }
+            }
+            kR = ( ( l + ( r - l ) * 0.5 ) - stR );
+        }
+        if( i.var.name->istGleich( "engine_m" ) )
+        {
+            stM = *i.var.schwerpunkt;
+            Vertex l, r;
+            for( int j = 0; j < 4; j++ )
+            {
+                if( i.var.tKordinaten->get( j ).y == 1.f )
+                {
+                    if( i.var.tKordinaten->get( j ).x == 0.f )
+                        l = i.var.vertex->get( j );
+                    if( i.var.tKordinaten->get( j ).x == 1.f )
+                        r = i.var.vertex->get( j );
+                }
+            }
+            kM = ( ( l + ( r - l ) * 0.5 ) - stM );
+        }
+    }
+    rSpeed = 0;
+    ship = new Model2D();
+    ship->setStyle( Model2D::Style::Sichtbar | Model2D::Style::Textur | Model2D::Style::Alpha );
     ship->setModel( data );
+    ship->setFarbe( 0x00000000 );
     Textur2D *txt = new Textur2D();
     txt->setTexturZ( textur );
-	ship->setTextur( txt, "ship" );
+    ship->setTextur( txt, "ship" );
     ship->setTextur( zFlammenL->getThis(), "engine_l" );
     ship->setTextur( zFlammenR->getThis(), "engine_r" );
     ship->setTextur( zFlammenM->getThis(), "engine_m" );
-	ship->setDrehung( r );
-	pos = p;
-	speed = s;
-	ref = 1;
+    ship->setDrehung( r );
+    pos = p;
+    speed = s;
+    ref = 1;
 }
 
 // Destruktor
 Ship::~Ship()
 {
-	ship->release();
+    ship->release();
 }
 
+#define sgn( x ) x < 0 ? -1 : 1
+
 // nicht constant
 bool Ship::tick( double zeit, int breite, int höhe, char tastenStände )
 {
-	Vertex minP = (Vertex)ship->zModel()->minP * ship->getSize() + ship->getPosition();
-	Vertex maxP = (Vertex)ship->zModel()->maxP * ship->getSize() + ship->getPosition();
-	if( maxP.x < 0 && speed.x < 0 )
-		pos.x += breite + ship->zModel()->maxP.x * ship->getSize();
-	if( maxP.y < 0 && speed.y < 0 )
+    Vertex minP = (Vertex)ship->zModel()->minP * ship->getSize() + ship->getPosition();
+    Vertex maxP = (Vertex)ship->zModel()->maxP * ship->getSize() + ship->getPosition();
+    if( maxP.x < 0 && speed.x < 0 )
+        pos.x += breite + ship->zModel()->maxP.x * ship->getSize();
+    if( maxP.y < 0 && speed.y < 0 )
         pos.y += höhe + ship->zModel()->maxP.y * ship->getSize();
-	if( minP.x > breite && speed.x > 0 )
-		pos.x -= breite + ship->zModel()->maxP.x * ship->getSize();
-	if( minP.y > höhe && speed.y > 0 )
-		pos.y -= höhe + ship->zModel()->maxP.y * ship->getSize();
-	ship->setPosition( pos );
-	if( ( tastenStände | 1 ) == tastenStände )
-	{
-		speed.x += (float)( 4.2 * cos( ship->getDrehung() ) ) * (float)zeit * 30;
-		speed.y += (float)( 4.2 * sin( ship->getDrehung() ) ) * (float)zeit * 30;
-	}
-	else
-	{
-		float movementAngle = atan2( speed.y, speed.x );
-		if( speed.x != 0 )
-			speed.x += 1.2f * cos( movementAngle + (float)PI ) * (float)zeit * 30;
-		if( speed.y != 0 )
-			speed.y += 1.2f * sin( movementAngle + (float)PI ) * (float)zeit * 30;
-		if( speed.x < 6.f && speed.x > -6.f )
-			speed.x = 0;
-		if( speed.y < 6.f && speed.y > -6.f )
-			speed.y = 0;
-	}
-	if( ( tastenStände | 8 ) != tastenStände )
-	{
-		if( ( tastenStände | 2 ) == tastenStände )
-			ship->addDrehung( (float)zeit * 2 );
-		if( ( tastenStände | 4 ) == tastenStände )
-			ship->addDrehung( (float)-zeit * 2 );
-	}
-	if( speed.x || speed.y )
-	{
-		pos += speed * (float)zeit;
-		ship->setPosition( pos );
-	}
-	return ship->tick( zeit );
+    if( minP.x > breite && speed.x > 0 )
+        pos.x -= breite + ship->zModel()->maxP.x * ship->getSize();
+    if( minP.y > höhe && speed.y > 0 )
+        pos.y -= höhe + ship->zModel()->maxP.y * ship->getSize();
+    ship->setPosition( pos );
+    if( ( tastenStände | 1 ) == tastenStände )
+    {
+        Vertex hp;
+        Vertex mv;
+        float r;
+        if( ship->zModel()->calcHitPoint( stM, kM, "ship", hp, mv, r ) )
+        {
+            rSpeed += r * (float)zeit;
+            speed += mv.rotation( ship->getDrehung() ) * (float)zeit;
+        }
+    }
+    else
+    {
+        float movementAngle = atan2( speed.y, speed.x );
+        int ix = sgn( speed.x ), iy = sgn( speed.y );
+        if( speed.x != 0 )
+            speed.x += 1.2f * cos( movementAngle + (float)PI ) * (float)zeit * 10;
+        if( speed.y != 0 )
+            speed.y += 1.2f * sin( movementAngle + (float)PI ) * (float)zeit * 10;
+        if( ix * sgn( speed.x ) < 0 )
+            speed.x = 0;
+        if( iy * sgn( speed.y ) < 0 )
+            speed.y = 0;
+        if( rSpeed > 0 )
+        {
+            rSpeed -= (float)zeit;
+            if( rSpeed < 0 )
+                rSpeed = 0;
+        }
+        if( rSpeed < 0 )
+        {
+            rSpeed += (float)zeit;
+            if( rSpeed > 0 )
+                rSpeed = 0;
+        }
+    }
+    ship->addDrehung( (float)zeit * rSpeed );
+    if( ( tastenStände | 2 ) == tastenStände )
+    {
+        Vertex hp;
+        Vertex mv;
+        float r;
+        if( ship->zModel()->calcHitPoint( stL, kL, "ship", hp, mv, r ) )
+        {
+            rSpeed += r * (float)zeit;
+            speed += mv.rotation( ship->getDrehung() ) * (float)zeit;
+        }
+        //ship->addDrehung( (float)zeit * 2 );
+    }
+    if( ( tastenStände | 4 ) == tastenStände )
+    {
+        Vertex hp;
+        Vertex mv;
+        float r;
+        if( ship->zModel()->calcHitPoint( stR, kR, "ship", hp, mv, r ) )
+        {
+            rSpeed += r * (float)zeit;
+            speed += mv.rotation( ship->getDrehung() ) * (float)zeit;
+        }
+        //ship->addDrehung( (float)-zeit * 2 );
+    }
+    if( speed.x || speed.y )
+    {
+        pos += speed * (float)zeit;
+        ship->setPosition( pos );
+    }
+    return ship->tick( zeit );
 }
 
 void Ship::render( Bild &zRObj )
 {
-	ship->render( zRObj );
+    ship->render( zRObj );
 }
 
 // constant
 void Ship::save( Datei *zD ) const
 {
-	zD->schreibe( (char*)&pos.x, 4 );
-	zD->schreibe( (char*)&pos.y, 4 );
-	zD->schreibe( (char*)&speed.x, 4 );
-	zD->schreibe( (char*)&speed.y, 4 );
-	float r = ship->getDrehung();
-	zD->schreibe( (char*)&r, 4 );
+    zD->schreibe( (char*)&pos.x, 4 );
+    zD->schreibe( (char*)&pos.y, 4 );
+    zD->schreibe( (char*)&speed.x, 4 );
+    zD->schreibe( (char*)&speed.y, 4 );
+    float r = ship->getDrehung();
+    zD->schreibe( (char*)&r, 4 );
 }
 
 Schuss *Ship::getSchuss() const
 {
-	return new Schuss( pos, Vec2<float>( cos( ship->getDrehung() ), sin( ship->getDrehung() ) ) * 200 );
+    return new Schuss( pos, Vec2<float>( cos( ship->getDrehung() ), sin( ship->getDrehung() ) ) * 200 );
 }
 
 bool Ship::istTod( Asteroid *zA ) const
 {
-	return ship->istModelInnen( zA->zModel() );
+    return ship->istModelInnen( zA->zModel() );
 }
 
 Punkt Ship::getKamPos( int breite, int höhe ) const
 {
-	Punkt ret;
-	ret.x = (int)pos.x - 400;
-	ret.y = (int)pos.y - 250;
-	if( ret.x < 0 )
-		ret.x = 0;
-	if( ret.y < 0 )
-		ret.y = 0;
-	if( ret.x > breite - 800 )
-		ret.x = breite - 800;
-	if( ret.y > höhe - 500 )
-		ret.y = höhe - 500;
-	return ret;
+    Punkt ret;
+    ret.x = (int)pos.x - 400;
+    ret.y = (int)pos.y - 250;
+    if( ret.x < 0 )
+        ret.x = 0;
+    if( ret.y < 0 )
+        ret.y = 0;
+    if( ret.x > breite - 800 )
+        ret.x = breite - 800;
+    if( ret.y > höhe - 500 )
+        ret.y = höhe - 500;
+    return ret;
 }
 
 Punkt Ship::getPos() const
 {
-	return (Punkt)pos;
+    return (Punkt)pos;
 }
 
 // Reference Counting
 Ship *Ship::getThis()
 {
-	ref++;
-	return this;
+    ref++;
+    return this;
 }
 
 Ship *Ship::release()
 {
-	ref--;
-	if( !ref )
-		delete this;
-	return 0;
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
 }

+ 7 - 0
Asteroids/Ship.h

@@ -15,6 +15,13 @@ private:
 	Model2D *ship;
 	Vec2< float > pos;
 	Vec2< float > speed;
+    Vertex stL;
+    Vertex kL;
+    Vertex stR;
+    Vertex kR;
+    Vertex stM;
+    Vertex kM;
+    float rSpeed;
 	int ref;
 
 public: