#include "Aufzeichnung.h" #include #include // Inhalt der Aufzeichnung Klasse auf Aufzeichnung.h // Konstruktor Aufzeichnung::Aufzeichnung() : ReferenceCounter() { nMsg = 0; nMsgVorwärts = 0; nachrichten = 0; bestenliste = 0; chat = 0; steuerung = 0; kam = 0; map = 0; ende = 0; spieler = new RCArray< VideoSpieler >(); spielZeit = 0; rSpielZeit = new Array< double >(); spielPause = 1; spielerAnzahl = 0; teamAnzahl = 0; kamSpielerNummer = -1; mx = -1; my = -1; geladen = 0; pauseZeit = -1; time = 0; } // Destruktor Aufzeichnung::~Aufzeichnung() { spieler->release(); if( ende ) ende->release(); if( map ) map->release(); if( kam ) kam->release(); if( steuerung ) steuerung->release(); if( chat ) chat->release(); if( bestenliste ) bestenliste->release(); if( nachrichten ) nachrichten->release(); rSpielZeit->release(); } // nicht constant void Aufzeichnung::setUIFactory( UIInit &factory ) { uiFactory = factory; } bool Aufzeichnung::ladeSpiel( int id ) { nachrichten = new SpielNachricht( id ); bestenliste = new VideoBestenliste( uiFactory ); chat = new VideoChat( uiFactory ); steuerung = new VideoSteuerung( uiFactory ); kam = new VideoKamera(); map = new VideoKarte(); ende = new VideoEnde( uiFactory ); Text f; if( nachrichten->hatFehler( &f ) ) { ende->setText( f ); ende->setSichtbar( 1 ); geladen = 1; return 1; } spielerAnzahl = nachrichten->getSVD()->spielerAnzahl; teamAnzahl = 0; for( int i = 0; i < spielerAnzahl; i++ ) { SpielerVideoDaten *dat = nachrichten->getSPVD( i ); if( !i ) kam->setSize( dat->kamBreite, dat->kamHöhe ); VideoSpieler *tmp = new VideoSpieler( dat ); bestenliste->addSpieler( tmp ); spieler->set( tmp, i ); teamAnzahl = teamAnzahl < dat->team ? dat->team : teamAnzahl; } teamAnzahl++; bestenliste->setTeamAnzahl( teamAnzahl ); for( int i = 0; i < nachrichten->getTeamAnzahl(); i++ ) { TeamVideoDaten *dat = nachrichten->getTVD( i ); bestenliste->setTeamMaxPunkte( dat->teamNummer, dat->maxPunkte ); bestenliste->setTeamPunkte( dat->teamNummer, dat->punkte ); } RundeVideoDaten *rDat = nachrichten->getRVD(); map->setSize( rDat->mapBreite, rDat->mapHöhe ); for( int i = 0; i < spielerAnzahl; i++ ) { RundeSpielerVideoDaten *dat = nachrichten->getRSVD( i ); spieler->z( i )->neuRunde( 1, dat, 1 ); bestenliste->updateSpielerStatus( spieler->z( i ) ); } pauseZeit = 3; ende->setText( "Die Aufzeichnung des Spiels wird geladen.\nRunde 1 beginnt in kürze." ); ende->setSichtbar( 1 ); geladen = 1; return 1; } void Aufzeichnung::doPublicMausEreignis( MausEreignis &me ) { if( !geladen ) return; if( kam->istMausIn( me.mx, me.my ) ) { if( me.id == ME_PLinks ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->istMausIn( kam->getLinks() + me.mx - kam->getRX( kam->getLinks() ), kam->getOben() + me.my - kam->getRY( kam->getOben() ) ) ) { kamSpielerNummer = spieler->z( i )->getSpielerNummer(); me.verarbeitet = 1; break; } } } 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 && !me.verarbeitet ) { mx = me.mx; my = me.my; kamSpielerNummer = -1; } me.verarbeitet = 1; } else { mx = -1; my = -1; } bestenliste->doPublicMausEreignis( me ); steuerung->doPublicMausEreignis( me ); } void Aufzeichnung::doTastaturEreignis( TastaturEreignis &te ) { if( !geladen ) return; 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 ) kamSpielerNummer = -1; } } bool Aufzeichnung::spielTick( double spielZeit ) { this->spielZeit += spielZeit; bool setKam = kamSpielerNummer >= 0; int x = 0; int y = 0; bool rEnd = 0; for( int i = 0; i < spielerAnzahl; i++ ) { VideoSpieler *tmp = spieler->z( i ); if( tmp ) { if( tmp->getSpielerNummer() == kamSpielerNummer ) { x = (int)( tmp->getX() + 0.5 ); y = (int)( tmp->getY() + 0.5 ); } bool amLeben = tmp->istAmLeben(); tmp->tick( map->zMap(), spielZeit ); if( amLeben != tmp->istAmLeben() ) { bestenliste->updateSpielerStatus( tmp ); for( int j = 0; j < spielerAnzahl; j++ ) { VideoSpieler *s = spieler->z( j ); if( s && s != tmp && s->istAmLeben() ) bestenliste->addPunkt( s->getTeam(), s->getSpielerNummer(), spielZeit > 0 ); } } if( amLeben && !tmp->istAmLeben() ) { // gestorben int team = tmp->getTeam(); bool teamLebt = 0; for( int k = 0; k < spielerAnzahl; k++ ) { if( spieler->z( k ) && spieler->z( k )->getTeam() == team ) teamLebt |= spieler->z( k )->istAmLeben(); } if( !teamLebt ) { int teamAmLebenAnzahl = 0; for( int k = 0; k < teamAnzahl; k++ ) { if( !bestenliste->teamExistiert( k ) ) continue; bool amLeben = 0; for( int l = 0; l < spielerAnzahl; l++ ) { if( spieler->z( l ) && spieler->z( l )->getTeam() == k ) amLeben |= spieler->z( l )->istAmLeben(); } if( amLeben ) { teamAmLebenAnzahl++; bestenliste->addPunkt( k, 1 ); } else bestenliste->addPunkt( k, 0 ); if( !bestenliste->getTeamPunkte( k ) ) bestenliste->setTeamStatus( k, "tod", 0xFFFF0000 ); } if( teamAmLebenAnzahl <= 1 ) rEnd = 1; } } if( !amLeben && tmp->istAmLeben() ) { // Wiederbelebt int team = tmp->getTeam(); bool teamLebt = 0; for( int k = 0; k < spielerAnzahl; k++ ) { if( k != i && spieler->z( k ) && spieler->z( k )->getTeam() == team ) teamLebt |= spieler->z( k )->istAmLeben(); } if( !teamLebt ) { for( int k = 0; k < teamAnzahl; k++ ) { if( !bestenliste->teamExistiert( k ) ) continue; bool amLeben = 0; for( int l = 0; l < spielerAnzahl; l++ ) { if( l != i && spieler->z( l ) && spieler->z( l )->getTeam() == k ) amLeben |= spieler->z( l )->istAmLeben(); } if( amLeben ) bestenliste->addPunkt( k, 0 ); else bestenliste->addPunkt( k, 1 ); if( bestenliste->getTeamPunkte( k ) ) bestenliste->setTeamStatus( k, "lebt", 0xFF00FF00 ); } } } } } if( setKam ) { double z = spielZeit < 0 ? -spielZeit : spielZeit; double px = ( ( x - kam->getX() ) / 100.0 ) * ( 50 * z ); double py = ( ( y - kam->getY() ) / 100.0 ) * ( 50 * z ); kam->addPosition( (int)px, (int)py, map ); } chat->tick( spielZeit ); steuerung->tick( spielZeit ); if( rEnd && spielZeit > 0 ) { // Runden Ende int nAnz = 0; int nAnz2 = 0; for( int i = 0; i < teamAnzahl; i++ ) { if( bestenliste->teamExistiert( i ) ) { nAnz += bestenliste->hatTeamGewonnen( i ); nAnz2 += bestenliste->getTeamPunkte( i ) >= 0; } } if( nAnz || nAnz2 <= 1 || nachrichten->getRunde() >= 9 ) { // Spiel Ende steuerung->pause( 1 ); return 1; } spielPause = 1; pauseZeit = 2; ende->setText( "Die nächste Runde beginnt in kürze." ); ende->setSichtbar( 1 ); int r = nachrichten->setRundenEnde( 1 ); rSpielZeit->set( spielZeit, r - 1 ); this->spielZeit = 0; time = 0; bestenliste->updatePunkte(); kam->nextRunde( 1 ); map->nextRunde( 1 ); RundeVideoDaten *dat = nachrichten->getRVD(); map->setSize( dat->mapBreite, dat->mapHöhe ); for( int i = 0; i < spielerAnzahl; i++ ) { spieler->z( i )->neuRunde( 1, nachrichten->getRSVD( i ), bestenliste->getTeamPunkte( spieler->z( i )->getTeam() ) != 0 ); bestenliste->updateSpielerStatus( spieler->z( i ) ); } return 1; } return 0; } bool Aufzeichnung::tick( double tickVal ) { if( !geladen ) return 0; if( spielPause ) { if( pauseZeit >= 0 ) { pauseZeit -= tickVal; if( pauseZeit < 0 ) { pauseZeit = 0; spielPause = 0; ende->setSichtbar( 0 ); } } chat->tick( 0 ); steuerung->tick( 0 ); return 1; } if( ( steuerung->istVorwärts() || nMsg && nMsgVorwärts ) && !( nMsg && !nMsgVorwärts ) ) { if( steuerung->istZeitlupe() ) time += tickVal / steuerung->getSpeed(); else time += tickVal * steuerung->getSpeed(); while( steuerung->getSpeed() != 0 ) { while( !nMsg || nMsg->typ && steuerung->getSpeed() != 0 ) { if( !nMsg ) nMsg = nachrichten->GetNextNachricht(); if( !nMsg ) break; nMsgVorwärts = 1; if( !nMsg->typ ) break; VideoAktionMSG *ak = (VideoAktionMSG *)nMsg; switch( ak->aktion ) { case 0: // T_Links Press for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setLinksKurve( 1 ); break; } } break; case 1: // T_Links Release for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setLinksKurve( 0 ); break; } } break; case 2: // T_Rechts Press for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setRechtsKurve( 1 ); break; } } break; case 3: // T_Rechts Release for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setRechtsKurve( 0 ); break; } } break; case 4: // Chat Nachricht if( 1 ) { VideoChatMSG *msg = (VideoChatMSG *)ak; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { Text txt = spieler->z( i )->zName()->getText(); txt += ": "; txt += msg->msg.getText(); chat->addNachricht( txt ); break; } } } break; case 5: // Linien Unterbrechung if( 1 ) { VideoLinieMSG *lMsg = (VideoLinieMSG *)ak; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setLinienUnterbrechung( lMsg->unterbrechung != 0 ); break; } } } break; } nMsg = 0; } if( !nMsg ) break; if( time > spielZeit + TICK ) { bool end = spielTick( TICK ); nMsg = 0; if( !steuerung->istVorwärts() || end ) break; } else break; } } else { if( steuerung->istZeitlupe() ) time -= tickVal / steuerung->getSpeed(); else time -= tickVal * steuerung->getSpeed(); while( 1 ) { while( !nMsg || nMsg->typ ) { if( !nMsg ) { nMsg = nachrichten->GetLastNachricht(); nMsgVorwärts = 0; if( !nMsg ) { int r = nachrichten->setRundenEnde( 0 ); if( r < 0 ) { // Spiel Beginn steuerung->pause( 0 ); return 1; } bestenliste->updatePunkte( 0 ); kam->nextRunde( 0 ); map->nextRunde( 0 ); for( int i = 0; i < spielerAnzahl; i++ ) spieler->z( i )->neuRunde( 0, 0, 1 ); spielPause = 1; pauseZeit = 2; ende->setText( "Vorherige Runde beginnt in kürze." ); ende->setSichtbar( 1 ); spielZeit = rSpielZeit->get( r ); time = spielZeit; return 1; } } if( !nMsg->typ ) break; VideoAktionMSG *ak = (VideoAktionMSG *)nMsg; switch( ak->aktion ) { case 0: // T_Links Press for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setLinksKurve( 0 ); break; } } break; case 1: // T_Links Release for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setLinksKurve( 1 ); break; } } break; case 2: // T_Rechts Press for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setRechtsKurve( 0 ); break; } } break; case 3: // T_Rechts Release for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setRechtsKurve( 1 ); break; } } break; case 4: // Chat Nachricht if( 1 ) { VideoChatMSG *msg = (VideoChatMSG *)ak; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { Text txt = spieler->z( i )->zName()->getText(); txt += ": "; txt += msg->msg.getText(); chat->removeNachricht( txt ); break; } } } break; case 5: // Linien Unterbrechung if( 1 ) { VideoLinieMSG *lMsg = (VideoLinieMSG *)ak; if( 1 ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer ) { spieler->z( i )->setLinienUnterbrechung( lMsg->unterbrechung == 0 ); break; } } } } break; } nMsg = 0; } if( time <= spielZeit - TICK ) { spielTick( -TICK ); nMsg = 0; if( steuerung->istVorwärts() ) break; } else break; } } return 1; } void Aufzeichnung::render( Bild &zRObj ) { if( !geladen ) return; bestenliste->render( zRObj ); chat->render( zRObj ); steuerung->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( ende ) ende->render( zRObj ); } // constant bool Aufzeichnung::hatVerlassen( bool jetzt ) const { if( !geladen ) return 0; return steuerung->istBeendet( jetzt ); }