#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() { spielZeit = -1; rZeit = 0; 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 >(); asteroids = new RCArray< Asteroid >(); teams = new RCArray< Team >(); objekte = new RCArray< SpielObjekt >(); deads = new RCArray< DeadPlayer >(); screen = 0; welt = new Welt2D(); welt->setCircular( 1 ); welt->setAirResistance( 0.001f ); kam = new Kamera2D(); kam->setWelt( welt->getThis(), 1 ); minimap = new Kamera2D(); minimap->setSize( 200, 200 ); minimap->setWelt( 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 = new SpielChat(); 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 >(); ref = 1; 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( schrift ) schrift->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(); chat->relese(); spieler->release(); asteroids->release(); asteroidModels->release(); asteroidTextures->release(); teams->release(); objekte->release(); schüsse->release(); pixel->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; } 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->getIterator(); i; i++ ) i->load(); for( auto i = schüsse->getIterator(); i; i++ ) i->load(); for( auto i = asteroids->getIterator(); i; i++ ) i->load(); for( auto i = pixel->getIterator(); i; i++ ) i->load(); for( auto i = deads->getIterator(); i; i++ ) i->load(); } void SpielKlasse::save() { last.spielZeit = spielZeit; for( auto i = spieler->getIterator(); i; i++ ) i->save(); for( auto i = schüsse->getIterator(); i; i++ ) i->save(); for( auto i = asteroids->getIterator(); i; i++ ) i->save(); for( auto i = pixel->getIterator(); i; i++ ) i->save(); for( auto i = deads->getIterator(); i; i++ ) 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( 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( schrift->getThis() ); if( !shipGUI ) shipGUI = new SpielerGUI( 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() { 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( 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( 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, schrift, infoKlient, flammenStart, flammenBurn ); spieler->set( s, i ); } flammenStart->release(); flammenBurn->release(); spielKlient->setLadenProzent( 75 ); for( int i = 0; i < map->getZeichnungAnzahl(); i++ ) { SpielObjekt *obj = map->createObjekt( i, schrift ); welt->addObject( obj->getThis() ); objekte->set( obj, i ); } 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( 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( 100 ); } void SpielKlasse::doMausEreignis( MausEreignis &me ) { if( end ) { end->doMausEreignis( me ); return; } if( !istAmLeben() ) me.verarbeitet = 1; int skill = shipGUI->doMausEreignis( me ); if( skill >= 0 ) { char *bytes = new char[ 2 ]; bytes[ 0 ] = 9; bytes[ 1 ] = (char)skill; spielKlient->spielNachricht( 2, bytes ); } chat->doMausEreignis( me ); if( bestenliste ) bestenliste->doMausEreignis( 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; } } } 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->getIterator(); i; i++ ) { 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->getIterator(); i; i++ ) { 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->getIterator(); i; i++ ) { 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->getIterator(); i; i++ ) { 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->getIterator(); i; i++ ) { 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->getIterator(); i; i++ ) { 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 ); bytes += 4; län -= 4; tmp->setAccountId( *(int*)bytes ); bytes += 4; län -= 4; if( !teams->z( map->getTeamNummer( sNum ) ) ) teams->set( map->createTeam( map->getTeamNummer( sNum ) ), map->getTeamNummer( sNum ) ); tmp->setTeam( teams->z( map->getTeamNummer( sNum ) ) ); tmp->zTeam()->spieler->add( (Spieler*)tmp->getThis() ); bestenliste->addSpieler( tmp ); bestenliste->updateSpieler( tmp ); bestenliste->updateTeam( tmp->zTeam() ); welt->addObject( 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( schrift ); 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( 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; for( auto s = spieler->getIterator(); s; s++ ) { if( s->getSpielerNummer() == sNum ) { intens = tmp->getIntensität( s->getSpeed() ); s->nimmSchaden( intens ); if( tmp->getSpeed().getLengthSq() > 0 ) s->impuls( tmp->getPosition() - tmp->getSpeed(), tmp->getSpeed() * 0.3f ); s->calcDeadPlayerObject( schüsse->z( i ) ); bestenliste->updateSpieler( s ); break; } } for( auto s = spieler->getIterator(); s; s++ ) { if( s->getSpielerNummer() == tmp->getSpieler() ) { s->machSchaden( intens ); 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 ); bestenliste->updateSpieler( s ); break; } } } welt->removeObject( tmp ); schüsse->remove( i ); break; } } goToPresence( presence ); if( sNum == spielerNummer ) { for( auto s = spieler->getIterator(); s; s++ ) { 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 s = spieler->getIterator(); s; s++ ) { if( s->getSpielerNummer() == sNum ) { s->wiederbelebung(); break; } } goToPresence( presence ); if( sNum == spielerNummer ) { for( auto s = spieler->getIterator(); s; s++ ) { 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 ); for( auto s = spieler->getIterator(); s; s++ ) { if( s->getSpielerNummer() == sNum ) { DeadPlayer *dp = s->sterben(); if( dp ) { welt->addObject( dp->getThis() ); deads->add( dp ); } bestenliste->updateSpieler( s ); } if( s->getSpielerNummer() == killer ) { s->addKill(); s->zTeam()->punkte++; bestenliste->updateTeam( s->zTeam() ); bestenliste->updateSpieler( s ); } } 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( 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->getIterator(); s; s++ ) { if( s->getSpielerNummer() == tmp->getSpieler() ) { s->addTreffer( (float)tmp->getIntensität( a->getSpeed() ) ); 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( 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->getIterator(); a; a++ ) { if( a->getId() == asteroid ) { Pixel *p = new Pixel( a->getPosition(), a->getSpeed(), a->getMasse() / 50, pixelId ); welt->addObject( 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->getIterator(); s; s++ ) { 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; } 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( zRObj.getBreite(), zRObj.getHeight() ); kam->setSize( zRObj.getSize() ); kam->render( zRObj ); minimap->setPosition( zRObj.getSize() - Punkt( 210, 210 ) ); minimap->lookAtWorldPos( welt->getWorldInfo().size.x / 2, welt->getWorldInfo().size.y / 2 ); minimap->lookAtWorldArea( welt->getWorldInfo().size.x, 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; } // Reference Counting SpielV *SpielKlasse::getThis() { ref++; return this; } SpielV *SpielKlasse::release() { ref--; if( !ref ) delete this; return 0; }