Browse Source

Game loop und nachrichtenverarbeitung

Kolja Strohm 6 years ago
parent
commit
673768de59

+ 1 - 1
StickmanWorldOnline/Bariere.h

@@ -39,7 +39,7 @@ public:
     void setAutoSchaltungMaxTime( int seconds );
     void startAutoSchaltung();
     void setTeam( Team *team );
-    void tick( float time );
+    void tick( double time );
     bool hatStyle( int style ) const;
     int getVerschiebungAnzahl() const;
     int getSchaltungAnzahl() const;

+ 3 - 1
StickmanWorldOnline/Base.h

@@ -3,6 +3,8 @@
 #include "GameObject.h"
 #include "Team.h"
 
+class Spiel;
+
 class Base : public GameObject
 {
 private:
@@ -18,7 +20,7 @@ public:
     Base( int x, int y, int width, int height, int maxTime = 10, Team *team = 0 );
     ~Base();
     void setTeam( Team *team );
-    void tick( float time );
+    void tick( double time, Spiel *zSpiel );
     void startChange( Team *team );
     Team *getTeam() const;
     Team *zTeam() const;

+ 4 - 2
StickmanWorldOnline/Drop.h

@@ -3,6 +3,8 @@
 #include "Variablen.h"
 #include "Gegenstand.h"
 
+class Spiel;
+
 class Drop : public Variable
 {
 private:
@@ -24,8 +26,8 @@ public:
     void setMinY( int y );
     void setMaxY( int y );
     void setMaxTime( int seconds );
-    void doDrop();
-    void tick( float time );
+    void doDrop( Spiel *zSpiel );
+    void tick( double time, Spiel *zSpiel );
     int getNumDrops() const;
     int getMinX() const;
     int getMaxX() const;

+ 1 - 0
StickmanWorldOnline/GameObject.h

@@ -22,6 +22,7 @@ public:
     void setY( int y );
     void setWidth( int width );
     void setHeight( int height );
+    bool intersectsWith( GameObject *zObj );
     int getX() const;
     int getY() const;
     int getWidth() const;

+ 6 - 1
StickmanWorldOnline/Geschoss.h

@@ -19,16 +19,21 @@ private:
     Spieler *besitzer;
     GeschossTyp typ;
     int tunnelBenutzt;
-    bool alive;
     int umgelenkt;
     int geschosseGetroffen;
 
 public:
     Geschoss( float speed, GeschossTyp typ, Richtung r, int x, int y, Spieler *besitzer );
     ~Geschoss();
+    void invertDirection();
+    void setRichtung( Richtung r );
     void tick( double zeit );
+    GeschossTyp getTyp() const;
+    Spieler *zBesitzer() const;
+    Spieler *getBesitzer() const;
 };
 
+// size: 150x150
 class FeuerballTreffer : public GameObject
 {
 private:

+ 7 - 0
StickmanWorldOnline/Reader.cpp

@@ -566,6 +566,12 @@ void MapReader::ladeKarte( Spiel *zSpiel )
     if( !mapFile.existiert() || mapFile.istOrdner() )
         return;
     mapFile.open( Datei::Style::lesen );
+    // map Size
+    int width;
+    int height;
+    mapFile.lese( (char *)& width, 4 );
+    mapFile.lese( (char *)& height, 4 );
+    zSpiel->setMapSize( width, height );
     // teams
     int anz = 0;
     mapFile.lese( (char *)& anz, 4 );
@@ -679,6 +685,7 @@ void MapReader::ladeKarte( Spiel *zSpiel )
         mapFile.lese( (char *)& maxX, 4 );
         mapFile.lese( (char *)& maxY, 4 );
         mapFile.lese( (char *)& maxTime, 4 );
+        mapFile.lese( (char *)& numDrops, 4 );
         for( int j = KEIN_GEGENSTAND; j < ITEMANZAHL; j++ )
             mapFile.lese( (char *)& wahrscheinlichkeit[ j ], 4 );
         char len;

+ 1 - 0
StickmanWorldOnline/Schalter.h

@@ -17,4 +17,5 @@ public:
     void press();
     int getAnzahlAktivierungen() const;
     bool isAktive() const;
+    int getId() const;
 };

+ 330 - 7
StickmanWorldOnline/Spiel.cpp

@@ -201,7 +201,7 @@ void Spiel::klientOffline( int accountId )
     }
 }
 
-void Spiel::klientOnline( int accountId, SSKlientV *zKlient )
+void Spiel::klientOnline( int accountId, SSKlientV * zKlient )
 {
     for( int i = 0; i < spielerAnzahl; i++ )
     {
@@ -220,7 +220,111 @@ void Spiel::klientOnline( int accountId, SSKlientV *zKlient )
 
 void Spiel::nachricht( int accountId, int len, char *bytes )
 {
-
+    if( !isRunning )
+        return;
+    c.lock();
+    if( ende )
+    {
+        c.unlock();
+        return;
+    }
+    char *msgBeg = bytes;
+    int msgLen = len;
+    int msgAccount = accountId;
+    bool saveMSG = 1;
+    len--;
+    switch( *bytes )
+    {
+    case 0: // key press
+        bytes++;
+        len--;
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            Spieler *tmp = spieler.z( i );
+            if( tmp && tmp->getAccountId() == accountId )
+            {
+                if( !tmp->setTastenStand( *bytes, 1 ) )
+                {
+                    saveMSG = 0;
+                    break;
+                }
+                for( int j = 0; j < spielerAnzahl; j++ )
+                {
+                    Spieler *s = spieler.z( j );
+                    if( s && s->zKlient() )
+                        s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), *bytes, 1, gameTicks );
+                }
+                break;
+            }
+        }
+        break;
+    case 1: // key release
+        bytes++;
+        len--;
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            Spieler *tmp = spieler.z( i );
+            if( tmp && tmp->getAccountId() == accountId )
+            {
+                if( !tmp->setTastenStand( *bytes, 0 ) )
+                {
+                    saveMSG = 0;
+                    break;
+                }
+                for( int j = 0; j < spielerAnzahl; j++ )
+                {
+                    Spieler *s = spieler.z( j );
+                    if( s && s->zKlient() )
+                        s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), *bytes, 0, gameTicks );
+                }
+                break;
+            }
+        }
+        break;
+    case 3: // chat Nachricht
+        if( 1 )
+        {
+            bytes++;
+            Text *txt = psqldb->getAccountRufName( accountId );
+            txt->append( ": " );
+            txt->append( bytes, len );
+            for( int i = 0; i < spielerAnzahl; i++ )
+            {
+                Spieler *tmp = spieler.z( i );
+                if( tmp && tmp->zKlient() )
+                    tmp->zKlient()->sendeChatNachricht( txt->getText(), gameTicks );
+            }
+            txt->release();
+            len = 0;
+        }
+        break;
+    default:
+        saveMSG = 0;
+    }
+    if( len )
+    {
+        // error
+    }
+    if( log && log->istOffen() && saveMSG )
+    {
+        char c = 1;
+        log->schreibe( &c, 1 );
+        int spielerNum = 0;
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            Spieler *tmp = spieler.z( i );
+            if( tmp && tmp->getAccountId() == msgAccount )
+            {
+                spielerNum = tmp->getSpielerNummer();
+                break;
+            }
+        }
+        log->schreibe( (char *)& spielerNum, 4 );
+        short l = (short)msgLen;
+        log->schreibe( (char *)& l, 2 );
+        log->schreibe( msgBeg, l );
+    }
+    c.unlock();
 }
 
 void Spiel::setPausiert( bool pausiert )
@@ -230,10 +334,159 @@ void Spiel::setPausiert( bool pausiert )
 
 void Spiel::tick( double zeit )
 {
-
+    // spieler bewegungen
+    for( auto s = spieler.getIterator(); s; s++ )
+    {
+        s->tick( zeit );
+        for( auto b = barieren.getIterator(); b; b++ )
+        { // spieler - bariere intersection
+            if( b->hatStyle( Bariere::Style::Aktiv ) && ( b->zTeam() != s->zTeam() ) && b->intersectsWith( s ) )
+                s->tick( -zeit );
+            else if( s->getX() < 0 || s->getY() < 0 || s->getX() + s->getWidth() >= mapSize.x || s->getY() + s->getHeight() >= mapSize.y )
+                s->tick( -zeit );
+        }
+    }
+    // barieren bewegung
+    for( auto b = barieren.getIterator(); b; b++ )
+        b->tick( zeit );
+    // geschoss bewegung
+    for( int i = 0; i < shots.getEintragAnzahl(); i++ )
+    {
+        Geschoss *g = shots.z( i );
+        g->tick( zeit );
+        bool removed = 0;
+        // geschoss - bariere intersection
+        bool intersectsWithBariere = 0;
+        for( auto b = barieren.getIterator(); b; b++ )
+        {
+            if( b->hatStyle( Bariere::Style::Aktiv ) && b->intersectsWith( g ) )
+            {
+                intersectsWithBariere = 1;
+                break;
+            }
+        }
+        if( intersectsWithBariere || g->getX() < 0 || g->getY() < 0 || g->getX() + g->getWidth() >= mapSize.x || g->getY() + g->getHeight() >= mapSize.y )
+        {
+            g->tick( -zeit );
+            switch( g->getTyp() )
+            {
+            case GESCHOSS_PFEIL:
+                shots.remove( i );
+                i--;
+                removed = 1;
+                break;
+            case GESCHOSS_KUGEL:
+            case GESCHOSS_DRACHENAUGE:
+                g->invertDirection();
+                break;
+            case GESCHOSS_FEUERBALL:
+                if( intersectsWithBariere )
+                {
+                    feuer.add( new FeuerballTreffer( g->getX() - 70, g->getY() - 70, g->getBesitzer(), 10 ) );
+                    shots.remove( i );
+                    i--;
+                    removed = 1;
+                }
+                else
+                    g->invertDirection();
+                break;
+            }
+        }
+        if( !removed )
+        { // geschoss - tunnel intersection
+            for( auto t = tunnel.getIterator(); t; t++ )
+            {
+                if( t->istAktiv() && t->intersectsWith( g ) )
+                {
+                    g->setX( g->getX() + t->getZielX() - t->getX() );
+                    g->setY( g->getY() + t->getZielY() - t->getY() );
+                }
+            }
+            // geschoss - schalter intersection
+            if( g->getTyp() == GESCHOSS_PFEIL )
+            {
+                for( auto s = schalter.getIterator(); s; s++ )
+                {
+                    if( s->isAktive() && s->intersectsWith( g ) )
+                    {
+                        shots.remove( i );
+                        i--;
+                        removed = 1;
+                        activateShalter( s->getId() );
+                    }
+                }
+            }
+            if( !removed )
+            {
+                // geschoss - umlenkung intersection
+                if( g->getTyp() != GESCHOSS_PFEIL )
+                {
+                    for( auto u = umlenkungen.getIterator(); u; u++ )
+                    {
+                        if( u->isAktive() && g->getTyp() != GESCHOSS_PFEIL && u->intersectsWith( g ) )
+                        {
+                            g->setRichtung( u->getRichtung() );
+                            u->addBenutzt();
+                        }
+                    }
+                }
+                // geschoss - spieler intersection
+                for( auto s = spieler.getIterator(); s; s++ )
+                {
+                    if( s->istAmLeben() && s != g->zBesitzer() )
+                    {
+                        switch( g->getTyp() )
+                        {
+                        case GESCHOSS_PFEIL:
+                        case GESCHOSS_KUGEL:
+                            s->nimmSchaden( 100 + ( g->zBesitzer() ? g->zBesitzer()->getSchadenBonus() : 0 ) );
+                            if( g->zBesitzer() )
+                            {
+                                g->zBesitzer()->addGemachterSchaden( 100 + g->zBesitzer()->getSchadenBonus() );
+                                if( !s->istAmLeben() )
+                                    g->zBesitzer()->addKill();
+                            }
+                        case GESCHOSS_DRACHENAUGE:
+                            s->addEffekt( new DrachenAugeEffekt( g->zBesitzer(), s._, 10 ) );
+                            break;
+                        case GESCHOSS_FEUERBALL:
+                            feuer.add( new FeuerballTreffer( g->getX() - 70, g->getY() - 70, g->getBesitzer(), 10 ) );
+                        }
+                        if( g->zBesitzer() )
+                            g->zBesitzer()->addTreffer();
+                        s->addGetroffen();
+                        shots.remove( i );
+                        i--;
+                        removed = 1;
+                    }
+                }
+            }
+        }
+    }
+    // Drop Ticks
+    for( auto d = drops.getIterator(); d; d++ )
+        d->tick( zeit, this );
+    // Timer Ticks
+    for( auto t = timer.getIterator(); t; t++ )
+        t->tick( zeit, this );
+    // Umlenkung Ticks
+    for( auto u = umlenkungen.getIterator(); u; u++ )
+        u->tick( zeit );
+    // Base Ticks
+    for( auto b = basen.getIterator(); b; b++ )
+        b->tick( zeit, this );
+    // aktive trigger Ticks
+    for( int i = 0; i < triggerRuns.getEintragAnzahl(); i++ )
+    {
+        if( !triggerRuns.z( i )->runNext( zeit ) )
+        {
+            triggerRuns.remove( i );
+            i--;
+        }
+    }
 }
 
-void Spiel::addVariable( const char *name, Variable *var )
+void Spiel::addVariable( const char *name, Variable * var )
 {
     bool found = 0;
     for( auto v = variablen.getIterator(); v; v++ )
@@ -250,7 +503,7 @@ void Spiel::addVariable( const char *name, Variable *var )
         var->release();
 }
 
-void Spiel::setVariable( const char *name, Variable *var )
+void Spiel::setVariable( const char *name, Variable * var )
 {
     bool found = 0;
     for( auto v = variablen.getIterator(); v; v++ )
@@ -265,16 +518,86 @@ void Spiel::setVariable( const char *name, Variable *var )
         var->release();
 }
 
-void Spiel::addTeam( Team *team )
+void Spiel::addTeam( Team * team )
 {
     teams.add( team );
 }
 
-void Spiel::addSpieler( Spieler *spieler )
+void Spiel::addSpieler( Spieler * spieler )
 {
     this->spieler.add( spieler );
 }
 
+void Spiel::addBariere( Bariere * bariere )
+{
+    barieren.add( bariere );
+}
+
+void Spiel::addBase( Base * base )
+{
+    basen.add( base );
+}
+
+void Spiel::addDrop( Drop * drop )
+{
+    drops.add( drop );
+}
+
+void Spiel::addGegenstand( Gegenstand * gegenstand )
+{
+    items.add( gegenstand );
+}
+
+void Spiel::addGeschoss( Geschoss * geschoss )
+{
+    shots.add( geschoss );
+}
+
+void Spiel::addSchalter( Schalter * schalter )
+{
+    this->schalter.add( schalter );
+}
+
+void Spiel::addSchiene( Schiene * schiene )
+{
+    schienen.add( schiene );
+}
+
+void Spiel::addTimer( Timer * timer )
+{
+    this->timer.add( timer );
+}
+
+void Spiel::addTunnel( Tunnel * tunnel )
+{
+    this->tunnel.add( tunnel );
+}
+
+void Spiel::addUmlenkung( Umlenkung * umlenkung )
+{
+    umlenkungen.add( umlenkung );
+}
+
+void Spiel::addTrigger( Trigger * trigger )
+{
+    this->trigger.add( trigger );
+}
+
+void Spiel::addTriggerRun( TriggerRun * tRun )
+{
+    triggerRuns.add( tRun );
+}
+
+Team *Spiel::getTeam( int id ) const
+{
+    for( auto t = teams.getIterator(); t; t++ )
+    {
+        if( t->getTeamNummer() == id )
+            return (Team *)t->getThis();
+    }
+    return 0;
+}
+
 Variable *Spiel::getVariable( const char *name ) const
 {
     for( auto v = variablen.getIterator(); v; v++ )

+ 9 - 4
StickmanWorldOnline/Spiel.h

@@ -16,6 +16,7 @@
 #include <Critical.h>
 #include <Datei.h>
 #include <Random.h>
+#include <Punkt.h>
 
 class Statistik;
 class StatistikV;
@@ -30,16 +31,17 @@ private:
     RCArray< VarPointer > variablen;
     RCArray< Spieler > spieler;
     RCArray< Team > teams;
-    RCArray< Bariere > bariere;
+    RCArray< Bariere > barieren;
     RCArray< Base > basen;
     RCArray< Drop > drops;
-    RCArray< Gegenstand > gegenstand;
+    RCArray< Gegenstand > items;
     RCArray< Geschoss > shots;
+    RCArray< FeuerballTreffer > feuer;
     RCArray< Schalter > schalter;
-    RCArray< Schiene > schiene;
+    RCArray< Schiene > schienen;
     RCArray< Timer > timer;
     RCArray< Tunnel > tunnel;
-    RCArray< Umlenkung > umlenkung;
+    RCArray< Umlenkung > umlenkungen;
     RCArray< Trigger > trigger;
     RCArray< TriggerRun > triggerRuns;
     Array< int > *zAccounts;
@@ -47,6 +49,7 @@ private:
     Text mapPfad;
     Critical c;
     Datei *log;
+    Punkt mapSize;
     bool ende;
     int spielerAnzahl;
     int spielId;
@@ -73,6 +76,7 @@ public:
     void klientOnline( int accountId, SSKlientV *zKlient ) override;
     void nachricht( int accountId, int len, char *bytes ) override;
 
+    void setMapSize( int width, int height );
     void setPausiert( bool pausiert );
     void tick( double zeit );
     void addVariable( const char *name, Variable *var );
@@ -91,6 +95,7 @@ public:
     void addUmlenkung( Umlenkung *umlenkung );
     void addTrigger( Trigger *trigger );
     void addTriggerRun( TriggerRun *tRun );
+    void activateShalter( int id );
     Team *getTeam( int id ) const;
     Variable *getVariable( const char *name ) const;
     Variable *zVariable( const char *name ) const;

+ 39 - 0
StickmanWorldOnline/Spieler.h

@@ -4,6 +4,30 @@
 #include "Gegenstand.h"
 #include "SSKlient.h"
 
+class Effekt
+{
+private:
+    Spieler *zSpieler;
+    double timeLeft;
+    int ref;
+
+public:
+    Effekt( Spieler *zSpieler, int maxTime );
+    virtual bool tick( double time );
+    Effekt *getThis();
+    Effekt *release();
+};
+
+class DrachenAugeEffekt : public Effekt
+{
+private:
+    Spieler *zVerursacher;
+
+public:
+    DrachenAugeEffekt( Spieler *zVerursacher, Spieler *zOpfer, int maxTime );
+    bool tick( double time ) override;
+};
+
 class Spieler : public GameObject
 {
 public:
@@ -19,6 +43,7 @@ public:
         const static int ENTERHAKEN_UNVERWUNDBAR = 0x40;
     };
 private:
+    RCArray< Effekt > effekte;
     Klient *klient;
     int accountId;
     int spielerNummer;
@@ -57,6 +82,7 @@ private:
     int tunnelBenutzt;
     int schalterAktiviert;
     int geschosseGeschossen;
+    char *tastenStand;
 
 public:
     Spieler( int id, Team *team, int spawnX, int spawnY, int breite, int height, 
@@ -64,13 +90,26 @@ public:
              int armor, int schadenBonus, int lebensraub, int lebensReg,
              int abkVerringerung, int level );
     ~Spieler();
+    bool setTastenStand( char taste, bool pressed );
     void setTeam( Team *team );
     void setAccount( int id );
     void setKlient( Klient *klient );
+    void addEffekt( Effekt *e );
+    // aktualisiert auch die team statistik
+    void addKill();
+    void addTreffer();
+    void addGetroffen();
+    void tick( double zeit );
+    // heilt auch um den lebensraub prozentsatz
+    void addGemachterSchaden( double schaden );
+    // zieht die rüstung ab
+    void nimmSchaden( double schaden );
+    int getSchadenBonus() const;
     Klient *zKlient() const;
     int getSpielerNummer() const;
     Team *zTeam() const;
     int getFarbe() const;
     int getAccountId() const;
     int getPunkte() const;
+    bool istAmLeben() const;
 };

+ 3 - 1
StickmanWorldOnline/Timer.h

@@ -2,6 +2,8 @@
 
 #include "GameObject.h"
 
+class Spiel;
+
 class Timer : public GameObject
 {
 private:
@@ -24,7 +26,7 @@ public:
     void setAutoWiederhohlung( bool wiederhohlung );
     void setSichtbar( bool visible );
     void setFarbe( int farbe );
-    bool tick( double time );
+    void tick( double time, Spiel *zSpiel );
     bool istSichtbar() const;
     int getFarbe() const;
     bool isRunning() const;