#include "SpielKlasse.h" #include #include #include #include // Inhalt der SpielKlasse Klasse aus SpielKlasse.h // Konstruktor SpielKlasse::SpielKlasse() { spielZeit = 0; rZeit = 0; spielPause = 1; rendern = 0; stkn = new RCArray< STKNachricht >(); stkna = 0; schrift = 0; time_t t; time( &t ); srand( (unsigned int)t ); infoKlient = 0; spielKlient = 0; spieler = new RCArray< Spieler >(); screen = 0; kam = 0; spielerAnzahl = 0; karteId = 0; spielerNummer = 0; map = 0; rEnd = 0; end = 0; chat = new SpielChat(); tasten = new char[ 256 ]; for( int i = 0; i < 256; i++ ) tasten[ i ] = 0; mx = -1; my = -1; bestenliste = 0; ref = 1; } // Destruktor SpielKlasse::~SpielKlasse() { stkn->release(); if( schrift ) schrift->release(); if( infoKlient ) infoKlient->release(); if( spielKlient ) spielKlient->release(); if( kam ) kam->release(); if( map ) map->release(); if( rEnd ) rEnd->release(); if( end ) end->release(); if( bestenliste ) bestenliste->release(); chat->relese(); spieler->release(); delete[] tasten; } // privat bool SpielKlasse::istAmLeben() const { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) return spieler->z( i )->istAmLeben(); } return 0; } // nicht constant void SpielKlasse::lock() { if( screen ) screen->lock(); } void SpielKlasse::unlock() { if( screen ) screen->unlock(); } void SpielKlasse::setSchrift( Schrift *schrift ) { if( this->schrift ) this->schrift->release(); this->schrift = schrift; chat->setSchrift( schrift ); if( !bestenliste ) bestenliste = new Bestenliste( dynamic_cast( schrift->getThis() ) ); if( !rEnd ) rEnd = new RundenEnde( schrift ); } void SpielKlasse::setBildschirm( Bildschirm *zScreen ) { screen = zScreen; } void SpielKlasse::nachricht( int län, char *bytes ) { if( !län ) return; lock(); stkn->add( new STKNachricht( län, bytes ), stkna ); stkna++; unlock(); } void SpielKlasse::setKlients( KSGClient::InformationServerClient *infoKlient, KSGClient::SpielServerClient *spielKlient ) { if( this->infoKlient ) this->infoKlient->release(); this->infoKlient = infoKlient; if( this->spielKlient ) this->spielKlient->release(); this->spielKlient = spielKlient; } void SpielKlasse::setKarteId( int karteId ) { this->karteId = karteId; } void SpielKlasse::ladeDaten() { kam = new Kamera(); kam->setSize( 400, 400 ); map = new Karte(); map->setId( karteId ); for( int i = 1; i <= 100; i++ ) { Sleep( 100 + ( rand() % 100 ) ); spielKlient->setLadenProzent( i ); } } void SpielKlasse::doPublicMausEreignis( MausEreignis &me ) { if( end ) { end->doPublicMausEreignis( me ); return; } if( !istAmLeben() && kam->istMausIn( me.mx, me.my ) ) { if( ( me.id == ME_RLinks || me.id == ME_RRechts ) && mx >= 0 ) { mx = -1; my = -1; } if( me.id == ME_Bewegung && mx >= 0 ) { kam->addPosition( mx - me.mx, my - me.my, map ); mx = me.mx; my = me.my; } if( ( me.id == ME_PLinks || me.id == ME_PRechts ) && mx < 0 ) { mx = me.mx; my = me.my; } me.verarbeitet = 1; } else { mx = -1; my = -1; } chat->doPublicMausEreignis( me ); if( bestenliste ) bestenliste->doPublicMausEreignis( me ); } void SpielKlasse::doTastaturEreignis( TastaturEreignis &te ) { if( end ) return; if( istAmLeben() ) { if( te.id == TE_Press ) { switch( te.taste ) { case T_Links: if( !tasten[ T_Links ] ) { tasten[ T_Links ] = 1; char byte = 0; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case T_Rechts: if( !tasten[ T_Rechts ] ) { tasten[ T_Rechts ] = 1; char byte = 2; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; } } if( te.id == TE_Release ) { switch( te.taste ) { case T_Links: if( tasten[ T_Links ] ) { tasten[ T_Links ] = 0; char byte = 1; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case T_Rechts: if( tasten[ T_Rechts ] ) { tasten[ T_Rechts ] = 0; char byte = 3; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; } } } else { if( te.id == TE_Press ) { switch( te.taste ) { case T_Links: kam->addPosition( -2, 0, map ); te.verarbeitet = 1; break; case T_Oben: kam->addPosition( 0, -2, map ); te.verarbeitet = 1; break; case T_Rechts: kam->addPosition( 2, 0, map ); te.verarbeitet = 1; break; case T_Unten: kam->addPosition( 0, 2, map ); te.verarbeitet = 1; break; } } } if( !te.verarbeitet ) chat->doTastaturEreignis( te, spielKlient ); } void SpielKlasse::stknVerarbeitung() { lock(); for( int i = 0; i < stkna; i++ ) { STKNachricht *n = stkn->z( i ); double zeit = n->getSpielZeit(); if( zeit > spielZeit && ( !rEnd || !rEnd->istSichtbar() ) ) break; int län = n->getLength(); char *bytes = n->getNachricht(); län--; switch( bytes[ 0 ] ) { case 0: // set Spieler Nummer bytes++; spielerNummer = *(int *)bytes; län -= 4; break; case 1: // init Spieler if( 1 ) { bytes++; spielerAnzahl = *(int *)bytes; län -= 4; bytes += 4; int maxTeam = 0; for( int i = 0; i < spielerAnzahl; i++ ) { Spieler *tmp = new Spieler( infoKlient ); int sNum = *(int *)bytes; län -= 4; bytes += 4; tmp->setSpielerNummer( sNum ); int team = *(int *)bytes; län -= 4; bytes += 4; maxTeam = maxTeam < team ? team : maxTeam; tmp->setTeam( team ); int sFarbe = *(int *)bytes; län -= 4; bytes += 4; tmp->setSpielerFarbe( sFarbe ); int tFarbe = *(int *)bytes; län -= 4; bytes += 4; tmp->setTeamFarbe( tFarbe ); int accId = *(int *)bytes; län -= 4; bytes += 4; tmp->setAccountId( accId ); bestenliste->addSpieler( tmp ); bestenliste->updateSpielerStatus( tmp ); spieler->set( tmp, i ); } bestenliste->setTeamAnzahl( maxTeam + 1 ); } break; case 2: // setze Spieler Position if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; bytes += 4; double posX = *(double *)bytes; län -= 8; bytes += 8; double posY = *(double *)bytes; län -= 8; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setPos( posX, posY ); } if( spielerNummer == sNum ) kam->setPosition( (int)posX, (int)posY ); } break; case 3: // setzt kammera größe if( 1 ) { bytes++; int br = *(int *)bytes; län -= 4; bytes += 4; int hö = *(int *)bytes; län -= 4; kam->setSize( br, hö ); } break; case 4: // Zeit Beginn spielPause = 0; spielZeit = 0; rZeit = 0; rendern = 1; break; case 5: // spieler ist tod if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; Text *zName = 0; for( int i = 0; i < spielerAnzahl; i++ ) { int team = spieler->z( i )->getTeam(); int player = spieler->z( i )->getSpielerNummer(); if( player == sNum ) { spieler->z( i )->sterben( map->zMap(), zeit, spielZeit ); bestenliste->updateSpielerStatus( spieler->z( i ) ); zName = spieler->z( i )->zName(); bool teamLebt = 0; for( int j = 0; j < spielerAnzahl; j++ ) { if( spieler->z( j ) && spieler->z( j )->getTeam() == team ) teamLebt |= spieler->z( j )->istAmLeben(); } if( !teamLebt ) { for( int j = 0; j < bestenliste->getTeamAnzahl(); j++ ) { if( bestenliste->teamExistiert( j ) ) { bool amLeben = 0; for( int k = 0; k < spielerAnzahl; k++ ) { if( spieler->z( k ) && spieler->z( k )->getTeam() == j ) amLeben |= spieler->z( k )->istAmLeben(); } if( amLeben ) bestenliste->addPunkt( j, 1 ); else bestenliste->addPunkt( j, 0 ); if( bestenliste->getTeamPunkte( j ) <= 0 ) bestenliste->setTeamStatus( j, "tot", 0xFFFF0000 ); } } } } else { if( spieler->z( i )->istAmLeben() ) bestenliste->addPunkt( team, player, 1 ); } } if( sNum == spielerNummer ) chat->addNachricht( "Du bist gestorben.", 0xFFFFFF00 ); else if( zName ) { Text *txt = new Text( zName->getText() ); txt->append( " ist gestorben." ); chat->addNachricht( txt->getText(), 0xFFFFFF00 ); txt->release(); } } break; case 6: // spiel Ende if( 1 ) { bestenliste->updatePunkte(); bytes++; char gewonnen = *bytes; län--; end = new Ende( schrift ); end->setGewonnen( gewonnen ); } break; case 7: // set Spieler Geschwindigkeit if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; bytes += 4; double xSpeed = *(double *)bytes; län -= 8; bytes += 8; double ySpeed = *(double *)bytes; län -= 8; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setSpeed( xSpeed, ySpeed ); } } break; case 8: // set Spieler Wendigkeit if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; bytes += 4; double kurve = *(double *)bytes; län -= 8; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setKurveSpeed( kurve ); } } break; case 9: // set Spieler Kurve if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; bytes += 4; char k = *bytes; län--; if( k == 0 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) { spieler->z( i )->setLinksKurve( map->zMap(), 0, zeit, spielZeit ); spieler->z( i )->setRechtsKurve( map->zMap(), 0, zeit, spielZeit ); } } } else if( k == 1 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setLinksKurve( map->zMap(), 1, zeit, spielZeit ); } } else if( k == 2 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setLinksKurve( map->zMap(), 0, zeit, spielZeit ); } } else if( k == 3 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setRechtsKurve( map->zMap(), 1, zeit, spielZeit ); } } else if( k == 4 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) spieler->z( i )->setRechtsKurve( map->zMap(), 0, zeit, spielZeit ); } } else if( k == 5 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) { spieler->z( i )->setLinksKurve( map->zMap(), 1, zeit, spielZeit ); spieler->z( i )->setRechtsKurve( map->zMap(), 1, zeit, spielZeit ); } } } } break; case 0xA: // set Karte Größe if( 1 ) { bytes++; int br = *(int *)bytes; län -= 4; bytes += 4; int hö = *(int *)bytes; län -= 4; map->setSize( br, hö ); } break; case 0xB: // chat Nachricht if( 1 ) { bytes++; Text *txt = new Text( "" ); txt->append( bytes, län ); chat->addNachricht( txt->getText() ); txt->release(); län = 0; } break; case 0xC: // Spieler Linien Unterbrechung if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; bytes += 4; char unterbrechung = *bytes; län--; for( int i = 0; i < spielerAnzahl; i++ ) { Spieler *tmp = spieler->z( i ); if( tmp && tmp->getSpielerNummer() == sNum ) tmp->setLinienUnterbrechung( map->zMap(), unterbrechung != 0, zeit, spielZeit ); } } break; case 0xD: // Max Team Punkte if( 1 ) { bytes++; int team = *(int *)bytes; län -= 4; bytes += 4; int mP = *(int *)bytes; län -= 4; bestenliste->setTeamMaxPunkte( team, mP ); } break; case 0xE: // Team Punkte if( 1 ) { bytes++; int team = *(int *)bytes; län -= 4; bytes += 4; int p = *(int *)bytes; län -= 4; bestenliste->setTeamPunkte( team, p ); if( !p ) bestenliste->setTeamStatus( team, "tot", 0xFFFF0000 ); } break; case 0xF: // Spieler Punkte if( 1 ) { bytes++; int sNum = *(int *)bytes; län -= 4; bytes += 4; int p = *(int *)bytes; län -= 4; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i ) && spieler->z( i )->getSpielerNummer() == sNum ) { bestenliste->setSpielerPunkte( spieler->z( i )->getTeam(), sNum, p ); break; } } } break; case 0x10: // Team Tod if( 1 ) { bytes++; int team = *(int *)bytes; län -= 4; bestenliste->setTeamPunkte( team, 0 ); bestenliste->setTeamStatus( team, "tot", 0xFFFF0000 ); for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i ) && spieler->z( i )->getTeam() == team ) { spieler->z( i )->sterben(); bestenliste->updateSpielerStatus( spieler->z( i ) ); } } } break; case 0x11: // Runden Ende if( 1 ) { spielPause = 1; bytes++; int team = *(int *)bytes; län -= 4; bool gewonnen = 0; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) { gewonnen = spieler->z( i )->getTeam() == team; break; } } rEnd->setGewonnen( gewonnen ); bestenliste->updatePunkte(); rEnd->setSichtbar( 1 ); } break; case 0x12: // Verbleibende Zeit if( 1 ) { bytes++; int sek = *(int *)bytes; län -= 4; rEnd->setZeit( sek ); if( !sek ) { if( rEnd && rEnd->istSichtbar() ) { rEnd->setSichtbar( 0 ); rEnd->setZeit( 6 ); for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i ) ) { spieler->z( i )->neuRunde(); if( !bestenliste->getTeamPunkte( spieler->z( i )->getTeam() ) ) spieler->z( i )->sterben(); bestenliste->updateSpielerStatus( spieler->z( i ) ); } } } } } break; case 0x13: // Team Name if( 1 ) { bytes++; int team = *(int *)bytes; län -= 4; bytes += 4; char *n = new char[ län + 1 ]; n[ län ] = 0; memcpy( n, bytes, län ); län -= län; bestenliste->setTeamName( team, n ); delete[] n; } break; default: // Fehler beim verarbeiten break; } if( län != 0 ) { // Fehler beim verarbeiten chat->addNachricht( "Es ist ein Fehler beim verarbeiten einer Nachricht aufgetreten.", 0xFFFF0000 ); } n->setVerarbeitet(); } for( int i = stkna; i > 0; i-- ) { if( !stkn->z( 0 ) || !stkn->z( 0 )->istVerarbeitet() ) break; stkna--; stkn->remove( 0 ); } unlock(); } bool SpielKlasse::tick( double zeit ) { if( spielPause ) { zeit = 0; stknVerarbeitung(); } rZeit += zeit; while( spielZeit + TICK < rZeit ) { spielZeit += TICK; stknVerarbeitung(); if( end ) return 1; if( !rEnd->istSichtbar() ) { int x = 0; int y = 0; bool setKam = 0; lock(); for( int i = 0; i < spielerAnzahl; i++ ) { spieler->z( i )->tick( map->zMap(), TICK ); if( spielerNummer == spieler->z( i )->getSpielerNummer() ) { x = (int)spieler->z( i )->getX(); y = (int)spieler->z( i )->getY(); setKam = spieler->z( i )->istAmLeben(); } } unlock(); if( setKam ) { double px = ( ( x - kam->getX() ) / 100.0 ) * ( 50 * TICK ); double py = ( ( y - kam->getY() ) / 100.0 ) * ( 50 * TICK ); kam->addPosition( (int)px, (int)py, map ); } } chat->tick( !zeit ? 0.05 : zeit ); } return 1; } void SpielKlasse::render( Bild &zRObj ) { if( !rendern ) return; lock(); chat->render( zRObj ); if( bestenliste ) bestenliste->render( zRObj ); kam->render( zRObj ); int x = kam->getRX( kam->getLinks() ) + 1, y = kam->getRY( kam->getOben() ) + 1; if( zRObj.setDrawOptions( x, y, kam->getRechts() - kam->getLinks() - 2, kam->getUnten() - kam->getOben() - 2 ) ) { zRObj.addScrollOffset( x, y ); map->render( kam, zRObj ); for( int i = 0; i < spielerAnzahl; i++ ) spieler->z( i )->render( kam, zRObj ); zRObj.releaseDrawOptions(); } if( rEnd ) rEnd->render( zRObj ); if( end ) end->render( zRObj ); unlock(); } // constant int SpielKlasse::läuft() const { if( !rendern ) return 3; if( !end ) return 2; if( end && !end->getWeiter() ) return 1; if( end && end->getWeiter() ) return 0; return 0; } // Reference Counting SpielV *SpielKlasse::getThis() { ref++; return this; } SpielV *SpielKlasse::release() { ref--; if( !ref ) delete this; return 0; }