#include "SpielKlasse.h" #include #include #include #include #include #include #include "SpielerGUI/SpielerGUI.h" #include "Define.h" #include #include // Inhalt der SpielKlasse Klasse aus SpielKlasse.h // Konstruktor SpielKlasse::SpielKlasse() : ReferenceCounter() { this->uiFactory.initParam.schrift = 0; shieldBoost = 0; speedBoost = 0; spielZeit = -1; rZeit = 0; rendern = 0; stkn = new RCArray< STKNachricht >(); stkna = 0; time_t t; time( &t ); srand( (unsigned int)t ); infoKlient = 0; spielKlient = 0; spieler = new RCArray< Spieler >(); asteroids = new RCArray< Asteroid >(); teams = new RCArray< Team >(); objekte = new RCArray< SpielObjekt >(); deads = new RCArray< DeadPlayer >(); welt = new Welt2D(); welt->setCircular( 1 ); welt->setAirResistance( 0.001f ); kam = new Kamera2D(); kam->setWelt( dynamic_cast(welt->getThis()), 1 ); minimap = new Kamera2D(); minimap->setSize( 200, 200 ); minimap->setWelt( dynamic_cast(welt->getThis()), 0 ); minimap->setStyle( ZeichnungHintergrund::Style::Sichtbar | ZeichnungHintergrund::Style::Rahmen ); minimap->setRahmenFarbe( 0xFFFFFFFF ); minimap->setName( "minimap" ); spielerAnzahl = 0; karteId = 0; ladenProzent = 0; spielerNummer = 0; map = 0; end = 0; chat = 0; tasten = new char[ 256 ]; for( int i = 0; i < 256; i++ ) tasten[ i ] = 0; bestenliste = 0; schüsse = new RCArray< Laser >(); shipGUI = 0; spielPause = 1; setKam = 0; asteroidModels = new RCArray< Model2DData >(); asteroidTextures = new RCArray< Textur2D >(); pixel = new RCArray< Pixel >(); save(); } // Destruktor SpielKlasse::~SpielKlasse() { for( int i = 0; i < map->getMaxTeamAnzahl(); i++ ) { if( teams->z( i ) ) teams->z( i )->reset(); } map->release(); minimap->release(); welt->release(); deads->release(); stkn->release(); if( infoKlient ) infoKlient->release(); if( spielKlient ) spielKlient->release(); if( kam ) kam->release(); if( end ) end->release(); if( bestenliste ) bestenliste->release(); if( shipGUI ) shipGUI->release(); if( chat ) chat->release(); spieler->release(); asteroids->release(); asteroidModels->release(); asteroidTextures->release(); teams->release(); objekte->release(); schüsse->release(); pixel->release(); delete[] tasten; if( speedBoost ) speedBoost->release(); if( shieldBoost ) shieldBoost->release(); } // 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; } void SpielKlasse::goBackInTime( int zeit ) { if( zeit < last.spielZeit ) chat->addNachricht( "Fehler: Es wurde versucht das Spiel auf einen Zeitpunkt zurückzusetzen, welcher nicht mehr erreicht werden kann.", 0xFFFF0000 ); load(); while( spielZeit < zeit ) tick(); } void SpielKlasse::goToPresence( int zeit ) { save(); while( spielZeit < zeit ) tick(); } void SpielKlasse::load() { spielZeit = last.spielZeit; for( auto i : *spieler ) i->load(); for( auto i : *objekte ) i->load(); for( auto i : *schüsse ) i->load(); for( auto i : *asteroids ) i->load(); for( auto i : *pixel ) i->load(); for( auto i : *deads ) i->load(); } void SpielKlasse::save() { last.spielZeit = spielZeit; for( auto i : *spieler ) i->save(); for( auto i : *objekte ) i->save(); for( auto i : *schüsse ) i->save(); for( auto i : *asteroids ) i->save(); for( auto i : *pixel ) i->save(); for( auto i : *deads ) i->save(); } void SpielKlasse::tick() { spielZeit++; kam->tick( TICK ); int asteroidAnz = asteroids->getEintragAnzahl(); for( int i = 0; i < asteroidAnz; i++ ) { Asteroid* p = asteroids->z( i ); if( p->isDead() ) { welt->removeObject( p ); asteroids->remove( i-- ); asteroidAnz--; } } } // nicht constant void SpielKlasse::lock() { if( uiFactory.initParam.bildschirm ) uiFactory.initParam.bildschirm->lock(); } void SpielKlasse::unlock() { if( uiFactory.initParam.bildschirm ) uiFactory.initParam.bildschirm->unlock(); } void SpielKlasse::setUIFactory( UIInit& uiFactory ) { this->uiFactory = uiFactory; chat = new SpielChat( uiFactory ); if( !bestenliste ) bestenliste = new Bestenliste( uiFactory ); if( !shipGUI ) shipGUI = new SpielerGUI( uiFactory ); } 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() { Text path = "data/log/0.csv"; for( int i = 1; DateiExistiert( path ); i++ ) { path = "data/log/"; path += i; path += ".csv"; } csv.setDatei( path ); csv.erstellen(); csv.open( Datei::Style::schreiben ); csv.schreibe( "Spielernummer;Skill ID\n", 23 ); // load frame annimation Text* gamePath = infoKlient->getDateiGruppePfad( infoKlient->getDateiGruppeIdVonSpiel( infoKlient->getSpielId( karteId ) ) ); LTDBDatei flammenStartLTDB; Text* f_start = new Text( gamePath->getText() ); f_start->append( "/bilder/f_start.ltdb" ); flammenStartLTDB.setDatei( f_start ); flammenStartLTDB.leseDaten( 0 ); Animation2DData* flammenStart = new Animation2DData(); flammenStart->ladeAnimation( dynamic_cast(flammenStartLTDB.getThis()) ); flammenStart->setFPS( 75 ); flammenStart->setWiederhohlend( 0 ); spielKlient->setLadenProzent( 7 ); LTDBDatei flammenLTDB; Text* f_burn = new Text( gamePath->getText() ); f_burn->append( "/bilder/f_burn.ltdb" ); flammenLTDB.setDatei( f_burn ); Animation2DData* flammenBurn = new Animation2DData(); flammenBurn->ladeAnimation( dynamic_cast(flammenLTDB.getThis()) ); flammenBurn->setFPS( 60 ); flammenBurn->setWiederhohlend( 1 ); map = new Karte(); Text* mapPf = new Text( "data/tmp/Karten/" ); mapPf->append( karteId ); mapPf->append( "/spiel/data/data.sts" ); Datei* stsD = new Datei(); stsD->setDatei( mapPf->getText() ); stsD->open( Datei::Style::lesen ); map->ladeSts( stsD ); stsD->close(); stsD->release(); spielKlient->setLadenProzent( 15 ); mapPf->ersetzen( mapPf->getLength() - 3, mapPf->getLength(), "map" ); Datei* mapD = new Datei(); mapD->setDatei( mapPf->getText() ); mapD->open( Datei::Style::lesen ); map->ladeMap( mapD, karteId, spielKlient, gamePath ); mapD->close(); mapD->release(); mapPf->release(); for( int i = 0; i < map->getMaxSpielerAnzahl(); i++ ) { Spieler* s = map->createSpieler( i, uiFactory, infoKlient, flammenStart, flammenBurn ); spieler->set( s, i ); } flammenStart->release(); flammenBurn->release(); spielKlient->setLadenProzent( 75 ); int tAnz = map->getMaxTeamAnzahl(); for( int i = 0; i < tAnz; i++ ) teams->add( map->createTeam( i ) ); for( auto o = map->getObjekte(); o; o++ ) { SpielObjekt* obj = map->createObjekt( o->id, uiFactory ); obj->setTeam( teams->get( o->team - 1 ) ); welt->addObject( dynamic_cast(obj->getThis()) ); objekte->add( obj ); } bestenliste->setTeamAnzahl( map->getMaxTeamAnzahl() ); welt->setSize( map->getSize().x, map->getSize().y ); welt->setSize( 1 ); spielKlient->setLadenProzent( 80 ); M2Datei astroidModels; Text aModelPath = gamePath->getText(); aModelPath += "/models/asteroids.m2"; astroidModels.setPfad( aModelPath ); astroidModels.leseDaten(); int anz = astroidModels.getModelAnzahl(); for( int i = 0; i < anz; i++ ) { this->asteroidModels->add( astroidModels.ladeModel( astroidModels.zModelName( i )->getText() ) ); } spielKlient->setLadenProzent( 85 ); LTDBDatei asteroidTexturD; Text aTexturPfad = gamePath->getText(); aTexturPfad += "/bilder/asteroids.ltdb"; asteroidTexturD.setDatei( dynamic_cast(aTexturPfad.getThis()) ); asteroidTexturD.leseDaten( 0 ); for( int i = 0; i < anz; i++ ) { Text* name = new Text( astroidModels.zModelName( i )->getText() ); name->append( ".png" ); Textur2D* txt = new Textur2D(); txt->setTexturZ( asteroidTexturD.laden( 0, name ) ); asteroidTextures->add( txt ); } spielKlient->setLadenProzent( 98 ); LTDBDatei skillLTDB; Text* skillLTDBPfad = new Text( gamePath->getText() ); skillLTDBPfad->append( "/bilder/skills.ltdb" ); skillLTDB.setDatei( skillLTDBPfad ); skillLTDB.leseDaten( 0 ); speedBoost = skillLTDB.laden( 0, new Text( "speedboost.png" ) ); spielKlient->setLadenProzent( 99 ); shieldBoost = skillLTDB.laden( 0, new Text( "shieldboost.png" ) ); spielKlient->setLadenProzent( 100 ); gamePath->release(); } void SpielKlasse::doPublicMausEreignis( MausEreignis& me ) { if( end ) { end->doPublicMausEreignis( me ); return; } if( !istAmLeben() ) me.verarbeitet = 1; int skill = shipGUI->doPublicMausEreignis( me ); if( skill >= 0 ) { char bytes[ 2 ]; bytes[ 0 ] = 9; bytes[ 1 ] = (char)skill; spielKlient->spielNachricht( 2, bytes ); } chat->doPublicMausEreignis( me ); if( bestenliste ) bestenliste->doPublicMausEreignis( me ); } void SpielKlasse::doTastaturEreignis( TastaturEreignis& te ) { bestenliste->doTastaturEreignis( te ); if( end ) { end->doTastaturEreignis( te ); return; } if( !chat->istAktiv() ) { if( istAmLeben() ) { if( te.id == TE_Press ) { switch( te.taste ) { case 'w': case 'W': case T_Oben: if( !tasten[ T_Oben ] ) { tasten[ T_Oben ] = 1; char byte = 0; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case 'a': case 'A': case T_Links: if( !tasten[ T_Links ] ) { tasten[ T_Links ] = 1; char byte = 2; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case 'd': case 'D': case T_Rechts: if( !tasten[ T_Rechts ] ) { tasten[ T_Rechts ] = 1; char byte = 4; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case T_Space: if( !tasten[ T_Space ] ) { tasten[ T_Space ] = 1; char byte = 6; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; } } if( te.id == TE_Release ) { switch( te.taste ) { case 'w': case 'W': case T_Oben: if( tasten[ T_Oben ] ) { tasten[ T_Oben ] = 0; char byte = 1; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case 'a': case 'A': case T_Links: if( tasten[ T_Links ] ) { tasten[ T_Links ] = 0; char byte = 3; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case 'd': case 'D': case T_Rechts: if( tasten[ T_Rechts ] ) { tasten[ T_Rechts ] = 0; char byte = 5; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case T_Space: if( tasten[ T_Space ] ) { tasten[ T_Space ] = 0; char byte = 7; spielKlient->spielNachricht( 1, &byte ); te.verarbeitet = 1; } break; case '1': { char byte[ 2 ] = { 0xA, 0 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '2': { char byte[ 2 ] = { 0xA, 1 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '3': { char byte[ 2 ] = { 0xA, 2 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '4': { char byte[ 2 ] = { 0xA, 3 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '5': { char byte[ 2 ] = { 0xA, 4 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '6': { char byte[ 2 ] = { 0xA, 5 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '7': { char byte[ 2 ] = { 0xA, 6 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '8': { char byte[ 2 ] = { 0xA, 7 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '9': { char byte[ 2 ] = { 0xA, 8 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } case '0': { char byte[ 2 ] = { 0xA, 9 }; spielKlient->spielNachricht( 2, byte ); te.verarbeitet = 1; break; } } } } else { if( te.id == TE_Press ) { switch( te.taste ) { case T_Links: kam->setPosition( kam->getPosition() + Vertex( -2, 0 ) ); te.verarbeitet = 1; break; case T_Oben: kam->setPosition( kam->getPosition() + Vertex( 0, -2 ) ); te.verarbeitet = 1; break; case T_Rechts: kam->setPosition( kam->getPosition() + Vertex( 2, 0 ) ); te.verarbeitet = 1; break; case T_Unten: kam->setPosition( kam->getPosition() + Vertex( 0, 2 ) ); 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 ); int zeit = n->getSpielZeit(); while( zeit > spielZeit ) tick(); int län = n->getLength(); char* bytes = n->getNachricht(); län--; int sNum = 0; int presence = spielZeit; if( presence > zeit + 10 ) presence = zeit + 10; // maximale zeitdifferenz von client und server switch( bytes[ 0 ] ) { case 0: // spieler drückt gas bytes++; sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { if( i->getSpielerNummer() == sNum ) { i->setTastataturStatus( T_GAS, 1 ); } } goToPresence( presence ); break; case 1: // spieler lässt gas los bytes++; sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { if( i->getSpielerNummer() == sNum ) { i->setTastataturStatus( T_GAS, 0 ); } } goToPresence( presence ); break; case 2: // spieler drückt rotl bytes++; sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { if( i->getSpielerNummer() == sNum ) { i->setTastataturStatus( T_ROT_L, 1 ); } } goToPresence( presence ); break; case 3: // spieler lässt rotl los bytes++; sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { if( i->getSpielerNummer() == sNum ) { i->setTastataturStatus( T_ROT_L, 0 ); } } goToPresence( presence ); break; case 4: // spieler drückt rotr bytes++; sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { if( i->getSpielerNummer() == sNum ) { i->setTastataturStatus( T_ROT_R, 1 ); } } goToPresence( presence ); break; case 5: // spieler lässt rotr los bytes++; sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { if( i->getSpielerNummer() == sNum ) { i->setTastataturStatus( T_ROT_R, 0 ); } } goToPresence( presence ); break; case 6: // Init Spieler if( 1 ) { bytes++; spielerAnzahl = (int)*bytes; bytes++; län--; for( int i = 0; i < spielerAnzahl; i++ ) { int sNum = *(int*)bytes; Spieler* tmp = spieler->z( sNum - 1 ); tmp->addSkill( new ShieldBoost( dynamic_cast(shieldBoost->getThis()) ) ); tmp->addSkill( new SpeedBoost( dynamic_cast(speedBoost->getThis()) ) ); bytes += 4; län -= 4; tmp->setAccountId( *(int*)bytes ); bytes += 4; län -= 4; tmp->setTeam( teams->z( map->getTeamNummer( sNum ) ) ); tmp->zTeam()->spieler->add( dynamic_cast(tmp->getThis()) ); bestenliste->addSpieler( tmp ); bestenliste->updateSpieler( tmp ); bestenliste->updateTeam( tmp->zTeam() ); welt->addObject( dynamic_cast(tmp->getThis()) ); } int max = map->getMaxSpielerAnzahl(); for( int i = 0; i < max; i++ ) { if( !spieler->z( i )->zTeam() ) { spieler->remove( i ); i--; max--; } } } break; case 0x8: // 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 0x9: // Spieler Nummer bytes++; spielerNummer = *(int*)bytes; län -= 4; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) { shipGUI->update( spieler->z( i ) ); break; } } break; case 0xA: // Start spielPause = 0; rendern = 1; break; case 0xB: // Ende //chat->addNachricht( "Spiel beendet", 0xFF909090 ); csv.schreibe( "\n\nSpielernummer;Kills;Tode;Schaden gemacht;Schaden bekommen;Schüsse;Treffer\n", 2 ); for( int i = 0; i < spielerAnzahl; i++ ) { Spieler* s = spieler->z( i ); Text line = s->getSpielerNummer(); line += ";"; line += s->getKills(); line += ";"; line += s->getTode(); line += ";"; line += s->getSchadenGemacht(); line += ";"; line += s->getSchadenBekommen(); line += ";"; line += s->getSchüsse(); line += ";"; line += s->getTreffer(); line += "\n"; csv.schreibe( line, line.getLength() ); } csv.close(); end = new Ende( uiFactory ); bytes++; län--; end->setGewonnen( *bytes ); break; case 0xC: // Skill if( 1 ) { bytes++; sNum = *(int*)bytes; bytes += 4; län -= 4; char art = *bytes; län--; Text line = sNum; line += ";"; line += art; line += "\n"; csv.schreibe( line, line.getLength() ); goBackInTime( zeit ); for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) { Team* tmp = spieler->z( i )->zTeam(); spieler->z( i )->setSkill( art ); tmp->akkuLeistung = tmp->getAkkuLeistungBonus(); tmp->beschleunigung = tmp->getBeschleunigungBonus(); tmp->laserEffizienz = tmp->getLaserEffizienzBonus(); tmp->laserIntensität = tmp->getLaserIntensitätBonus(); tmp->laserTempo = tmp->getLaserTempoBonus(); tmp->maxEnergie = tmp->getMaxEnergieBonus(); tmp->maxStabilität = tmp->getMaxStabilitätBonus(); tmp->reparatur = tmp->getReperaturBonus(); tmp->wendigkeit = tmp->getWendigkeitBonus(); tmp->antriebEffizienz = tmp->getAntriebEffizienzBonus(); tmp->energieSchild = tmp->getEnergieSchildBonus(); tmp->energieSchildEffizienz = tmp->getEnergieSchildEffizienzBonus(); break; } } goToPresence( presence ); for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) { shipGUI->update( spieler->z( i ) ); break; } } } break; case 0xD: // Schuss if( 1 ) { bytes++; int id = *(int*)bytes; bytes += 4; län -= 4; sNum = *(int*)bytes; bytes += 4; län -= 4; float xPos = *(float*)bytes; bytes += 4; län -= 4; float yPos = *(float*)bytes; bytes += 4; län -= 4; float xSpeed = *(float*)bytes; bytes += 4; län -= 4; float ySpeed = *(float*)bytes; bytes += 4; län -= 4; double intensität = *(double*)bytes; län -= 8; int farbe = 0; goBackInTime( zeit ); for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == sNum ) { if( spieler->z( i )->getPosition() != Vertex( xPos, yPos ) ) chat->addNachricht( Text( "asynchrony detected difference: " ) += (spieler->z( i )->getPosition() - Vertex( xPos, yPos )).getLength(), 0xFFFF0000 ); spieler->z( i )->setPosition( Vertex( xPos, yPos ) ); spieler->z( i )->hatGeschossen(); farbe = spieler->z( i )->zTeam()->farbe; break; } } Laser* l = new Laser( id, Vertex( xPos, yPos ), Vertex( xSpeed, ySpeed ), sNum, intensität, farbe ); welt->addObject( dynamic_cast(l->getThis()) ); schüsse->add( l ); goToPresence( presence ); if( sNum == spielerNummer ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) { shipGUI->update( spieler->z( i ) ); bestenliste->updateSpieler( spieler->z( i ) ); break; } } } } break; case 0xE: // Treffer if( 1 ) { bytes++; int schuss = *(int*)bytes; bytes += 4; län -= 4; int sNum = *(int*)bytes; bytes += 4; län -= 4; float erf = *(float*)bytes; bytes += 4; län -= 4; int skillP = *(int*)bytes; län -= 4; goBackInTime( zeit ); int sAnz = schüsse->getEintragAnzahl(); for( int i = 0; i < sAnz; i++ ) { Laser* tmp = schüsse->z( i ); if( tmp && tmp->getId() == schuss ) { if( sNum >= 0 ) { double intens = 0; Spieler* attacker = 0; Spieler* attacked = 0; for( auto s : *spieler ) { if( s->getSpielerNummer() == tmp->getSpieler() ) attacker = s; if( s->getSpielerNummer() == sNum ) attacked = s; } if( attacked && attacker ) { intens = tmp->getIntensität( attacked->getSpeed() ); attacked->nimmSchaden( intens, attacker ? attacker->getLevel() : 1 ); if( tmp->getSpeed().getLengthSq() > 0 ) attacked->impuls( tmp->getPosition() - tmp->getSpeed(), tmp->getSpeed() * 0.3f ); attacked->calcDeadPlayerObject( schüsse->z( i ) ); bestenliste->updateSpieler( attacked ); attacker->machSchaden( intens, attacked->getLevel() ); if( attacker->getEp() != erf ) chat->addNachricht( Text( "asynchrony detected ep difference: " ) += (erf - attacker->getEp()), 0xFFFF0000 ); if( attacker->getSkillP() != skillP ) chat->addNachricht( Text( "asynchrony detected skillPunkte difference: " ) += (skillP - attacker->getSkillP()), 0xFFFF0000 ); bestenliste->updateSpieler( attacker ); } } welt->removeObject( tmp ); schüsse->remove( i ); break; } } goToPresence( presence ); if( sNum == spielerNummer ) { for( auto s : *spieler ) { if( s->getSpielerNummer() == spielerNummer ) { shipGUI->update( s ); break; } } } } break; case 0xF: // Wiederbelebung if( 1 ) { bytes++; int sNum = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto i : *spieler ) { for( auto s : *spieler ) { s->wiederbelebung(); break; } } goToPresence( presence ); if( sNum == spielerNummer ) { for( auto s : *spieler ) { if( s->getSpielerNummer() == spielerNummer ) { shipGUI->update( s ); break; } } } } break; case 0x10: // Tod if( 1 ) { bytes++; sNum = *(int*)bytes; bytes += 4; län -= 4; int killer = *(int*)bytes; län -= 4; goBackInTime( zeit ); Spieler* dead = 0; Spieler* kill = 0; for( auto s : *spieler ) { if( s->getSpielerNummer() == sNum ) dead = s; if( s->getSpielerNummer() == killer ) kill = s; } if( dead ) { DeadPlayer* dp = dead->sterben(); if( dp ) { welt->addObject( dynamic_cast(dp->getThis()) ); deads->add( dp ); } bestenliste->updateSpieler( dead ); } if( kill ) { kill->addKill( dead->getLevel() ); kill->zTeam()->punkte++; bestenliste->updateTeam( kill->zTeam() ); bestenliste->updateSpieler( kill ); } goToPresence( presence ); if( sNum == spielerNummer ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) { shipGUI->update( spieler->z( i ) ); break; } } } } break; case 0x11: // neuer Asteroid { Vertex pos, speed; float rot, rotS; bytes++; int id = *(int*)bytes; bytes += 4; län -= 4; pos.x = *(float*)bytes; bytes += 4; län -= 4; pos.y = *(float*)bytes; bytes += 4; län -= 4; speed.x = *(float*)bytes; bytes += 4; län -= 4; speed.y = *(float*)bytes; bytes += 4; län -= 4; rot = *(float*)bytes; bytes += 4; län -= 4; rotS = *(float*)bytes; bytes += 4; län -= 4; int index = *(int*)bytes; län -= 4; goBackInTime( zeit ); Asteroid* na = new Asteroid( id, pos, speed, rot, rotS, asteroidModels->get( index ), asteroidTextures->get( index ) ); welt->addObject( dynamic_cast(na->getThis()) ); asteroids->add( na ); goToPresence( presence ); break; } case 0x12: // Asteroid Treffer { Vertex pos; bytes++; int schuss = *(int*)bytes; bytes += 4; län -= 4; int asteroid = *(int*)bytes; bytes += 4; län -= 4; pos.x = *(float*)bytes; bytes += 4; län -= 4; pos.y = *(float*)bytes; bytes += 4; län -= 4; __int64 seed = *(__int64*)bytes; bytes += 8; län -= 8; int newAsteroid = *(int*)bytes; bytes += 4; län -= 4; float erf = *(float*)bytes; bytes += 4; län -= 4; int skillP = *(int*)bytes; län -= 4; goBackInTime( zeit ); int aAnz = asteroids->getEintragAnzahl(); for( int i = 0; i < aAnz; i++ ) { Asteroid* a = asteroids->z( i ); if( a->getId() == asteroid ) { int sAnz = schüsse->getEintragAnzahl(); for( int j = 0; j < sAnz; j++ ) { Laser* tmp = schüsse->z( j ); if( tmp && tmp->getId() == schuss ) { for( auto s : *spieler ) { if( s->getSpielerNummer() == tmp->getSpieler() ) { s->addTreffer( (float)tmp->getIntensität( a->getSpeed() ), 0 ); if( s->getEp() != erf ) chat->addNachricht( Text( "asynchrony detected ep difference: " ) += (erf - s->getEp()), 0xFFFF0000 ); if( s->getSkillP() != skillP ) chat->addNachricht( Text( "asynchrony detected skillPunkte difference: " ) += (skillP - s->getSkillP()), 0xFFFF0000 ); break; } } Asteroid* na = a->split( pos, tmp->getSpeed(), seed, newAsteroid ); welt->addObject( dynamic_cast(na->getThis()) ); asteroids->add( na ); welt->removeObject( tmp ); schüsse->remove( j ); } } break; } } goToPresence( presence ); break; } case 0x13: // Pixel { bytes++; int asteroid = *(int*)bytes; bytes += 4; län -= 4; int pixelId = *(int*)bytes; län -= 4; goBackInTime( zeit ); for( auto a : *asteroids ) { if( a->getId() == asteroid ) { Pixel* p = new Pixel( a->getPosition(), a->getSpeed(), a->getMasse() / 50, pixelId ); welt->addObject( dynamic_cast(p->getThis()) ); pixel->add( p ); a->setDead(); break; } } goToPresence( presence ); break; } case 0x14: // Pixel einsammeln { bytes++; int pixelId = *(int*)bytes; bytes += 4; län -= 4; int spielerId = *(int*)bytes; län -= 4; goBackInTime( zeit ); int pixelAnz = pixel->getEintragAnzahl(); for( int i = 0; i < pixelAnz; i++ ) { Pixel* p = pixel->z( i ); if( p->getId() == pixelId ) { if( spielerId >= 0 ) { for( auto s : *spieler ) { if( s->getSpielerNummer() == spielerId ) { s->addEp( p->getEp() ); if( s->getSpielerNummer() == spielerNummer ) shipGUI->update( s ); break; } } } welt->removeObject( p ); pixel->remove( i ); break; } } goToPresence( presence ); break; } case 0x15: // Use active Skill { bytes++; int sNum = *(int*)bytes; bytes += 4; län -= 4; char skillId = *bytes; län--; goBackInTime( zeit ); for( auto s : *spieler ) { if( s->getSpielerNummer() == sNum ) s->useSkill( skillId ); } goToPresence( presence ); break; } case 0x16: // Objekt treffer { bytes++; int schuss = *(int*)bytes; bytes += 4; län -= 4; int oId = *(int*)bytes; bytes += 4; län -= 4; float erf = *(float*)bytes; bytes += 4; län -= 4; int skillP = *(int*)bytes; län -= 4; goBackInTime( zeit ); int sAnz = schüsse->getEintragAnzahl(); for( int i = 0; i < sAnz; i++ ) { Laser* tmp = schüsse->z( i ); if( tmp && tmp->getId() == schuss ) { if( sNum >= 0 ) { double intens = 0; Spieler* attacker = 0; SpielObjekt* attacked = 0; for( auto s : *spieler ) { if( s->getSpielerNummer() == tmp->getSpieler() ) attacker = s; } for( auto o : *objekte ) { if( o->getObjektId() == oId ) attacked = o; } if( attacked && attacker ) { intens = tmp->getIntensität( attacked->getSpeed() ); attacked->nimmSchaden( intens, attacker ? attacker->getLevel() : 1 ); if( tmp->getSpeed().getLengthSq() > 0 ) attacked->impuls( tmp->getPosition() - tmp->getSpeed(), tmp->getSpeed() * 0.3f ); attacked->calcDeadPlayerObject( schüsse->z( i ) ); attacker->machSchaden( intens, attacked->getLevel(), attacked->doesShotAddEp() ); if( attacker->getEp() != erf ) chat->addNachricht( Text( "asynchrony detected ep difference: " ) += (erf - attacker->getEp()), 0xFFFF0000 ); if( attacker->getSkillP() != skillP ) chat->addNachricht( Text( "asynchrony detected skillPunkte difference: " ) += (skillP - attacker->getSkillP()), 0xFFFF0000 ); bestenliste->updateSpieler( attacker ); } } welt->removeObject( tmp ); schüsse->remove( i ); break; } } goToPresence( presence ); if( sNum == spielerNummer ) { for( auto s : *spieler ) { if( s->getSpielerNummer() == spielerNummer ) { shipGUI->update( s ); break; } } } break; } case 0x17: // Objekt Tod { bytes++; int oId = *(int*)bytes; bytes += 4; län -= 4; int killer = *(int*)bytes; län -= 4; goBackInTime( zeit ); SpielObjekt* dead = 0; Spieler* kill = 0; for( auto s : *spieler ) { if( s->getSpielerNummer() == killer ) kill = s; } for( auto o : *objekte ) { if( o->getObjektId() == oId ) dead = o; } if( dead ) { DeadPlayer* dp = dead->sterben(); if( dp ) { welt->addObject( dynamic_cast(dp->getThis()) ); deads->add( dp ); } } if( kill ) { kill->addKill( dead ? dead->getLevel() : 1, dead ? dead->doesShotAddEp() : 1 ); kill->zTeam()->punkte++; bestenliste->updateTeam( kill->zTeam() ); bestenliste->updateSpieler( kill ); } goToPresence( presence ); if( sNum == spielerNummer ) { for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) { shipGUI->update( spieler->z( i ) ); break; } } } 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 ) { stknVerarbeitung(); if( spielPause ) { zeit = 0; return 1; } rZeit += zeit; while( TICK <= rZeit ) { rZeit -= TICK; if( end ) return 1; lock(); if( spielZeit == -1 ) save(); // speichern // tote spieler int deadsCount = deads->getEintragAnzahl(); for( int i = 0; i < deadsCount; i++ ) { if( deads->z( i )->isFinished() ) { welt->removeObject( deads->z( i ) ); deads->remove( i-- ); deadsCount--; } } // spiel fortschritt tick(); minimap->tick( TICK ); // Kamera bewegen Vertex tPos; Vertex speed; bool setKam = 0; for( int i = 0; i < spielerAnzahl; i++ ) { if( spieler->z( i )->getSpielerNummer() == spielerNummer ) shipGUI->update( spieler->z( i ) ); if( spielerNummer == spieler->z( i )->getSpielerNummer() ) { tPos = spieler->z( i )->getPosition(); speed = spieler->z( i )->getSpeed(); setKam = spieler->z( i )->istAmLeben(); } } unlock(); if( setKam ) { if( !this->setKam || isnan( kam->getWorldPosition().x ) || isnan( kam->getWorldPosition().y ) ) kam->lookAtWorldPos( tPos ); Vertex str = (tPos - kam->getWorldPosition()); if( (tPos + welt->getWorldInfo().size - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + welt->getWorldInfo().size - kam->getWorldPosition()); if( (tPos - welt->getWorldInfo().size - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos - welt->getWorldInfo().size - kam->getWorldPosition()); if( (tPos + Punkt( welt->getWorldInfo().size.x, 0 ) - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + Punkt( welt->getWorldInfo().size.x, 0 ) - kam->getWorldPosition()); if( (tPos + Punkt( -welt->getWorldInfo().size.x, 0 ) - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + Punkt( -welt->getWorldInfo().size.x, 0 ) - kam->getWorldPosition()); if( (tPos + Punkt( 0, welt->getWorldInfo().size.y ) - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + Punkt( 0, welt->getWorldInfo().size.y ) - kam->getWorldPosition()); if( (tPos + Punkt( 0, -welt->getWorldInfo().size.y ) - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + Punkt( 0, -welt->getWorldInfo().size.y ) - kam->getWorldPosition()); if( (tPos + Punkt( welt->getWorldInfo().size.x, -welt->getWorldInfo().size.y ) - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + Punkt( welt->getWorldInfo().size.x, -welt->getWorldInfo().size.y ) - kam->getWorldPosition()); if( (tPos + Punkt( -welt->getWorldInfo().size.x, welt->getWorldInfo().size.y ) - kam->getWorldPosition()).getLengthSq() < str.getLengthSq() ) str = (tPos + Punkt( -welt->getWorldInfo().size.x, welt->getWorldInfo().size.y ) - kam->getWorldPosition()); float faktor = str.getLength() / 200.f; if( faktor > 1.f ) faktor = 1.f; kam->lookAtWorldPos( kam->getWorldPosition() + speed * faktor * (float)TICK ); kam->lookAtWorldPos( kam->getWorldPosition() + str * faktor * 0.1f * (float)TICK ); } this->setKam = setKam; chat->tick( !zeit ? 0.05 : zeit ); if( shipGUI ) shipGUI->tick( !zeit ? 0.05 : zeit ); } return 1; } void SpielKlasse::render( Bild& zRObj ) { if( !rendern ) return; lock(); kam->lookAtWorldArea( (float)zRObj.getBreite(), (float)zRObj.getHeight() ); kam->setSize( zRObj.getSize() ); kam->render( zRObj ); minimap->setPosition( zRObj.getSize() - Punkt( 210, 210 ) ); minimap->lookAtWorldPos( (float)welt->getWorldInfo().size.x / 2, (float)welt->getWorldInfo().size.y / 2 ); minimap->lookAtWorldArea( (float)welt->getWorldInfo().size.x, (float)welt->getWorldInfo().size.y ); minimap->render( zRObj ); chat->render( zRObj ); if( bestenliste ) bestenliste->render( zRObj ); if( shipGUI ) shipGUI->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; }