Prechádzať zdrojové kódy

Weltweiter Bestscore und Spielwiederholung ansehen ist jetzt verfügbar

Kolja Strohm 6 rokov pred
rodič
commit
68b1550355
6 zmenil súbory, kde vykonal 786 pridanie a 332 odobranie
  1. 13 2
      Blöcke/Game.cpp
  2. 2 0
      Blöcke/Game.h
  3. 402 310
      Blöcke/Map.cpp
  4. 10 4
      Blöcke/Map.h
  5. 318 13
      Blöcke/Menü.cpp
  6. 41 3
      Blöcke/Menü.h

+ 13 - 2
Blöcke/Game.cpp

@@ -1,5 +1,6 @@
 #include "Game.h"
 #include <Bild.h>
+#include "../../../Include/KSGKlientV.h"
 
 // Inhalt der Game Klasse aus Game.h
 // Konstruktor
@@ -9,12 +10,15 @@ Game::Game()
 	screen = 0;
 	alpha = 0;
 	menü = 0;
+    client = 0;
 	ref = 1;
 }
 
 // Destruktor
 Game::~Game()
 {
+    if( client )
+        client->release();
 	if( schrift )
 		schrift->release();
 	if( screen )
@@ -29,6 +33,13 @@ bool Game::laden()
 	return 1;
 }
 
+void Game::setMinigameClientZ( MinigameKlientV *client )
+{
+    if( this->client )
+        this->client->release();
+    this->client = client;
+}
+
 void Game::doMausEreignis( MausEreignis &me )
 {
 	if( menü )
@@ -74,14 +85,14 @@ void Game::setSchriftZ( Schrift *schrift )
 {
 	this->schrift = schrift;
 	if( !menü && this->schrift && screen )
-		menü = new Menü( schrift, screen );
+		menü = new Menü( schrift, screen, client->getThis() );
 }
 
 void Game::setBildschirmZ( Bildschirm *screen )
 {
 	this->screen = screen;
 	if( !menü && schrift && screen )
-		menü = new Menü( schrift, screen );
+		menü = new Menü( schrift, screen, client->getThis() );
 }
 
 // constant

+ 2 - 0
Blöcke/Game.h

@@ -10,6 +10,7 @@ private:
 	Schrift *schrift;
 	Bildschirm *screen;
 	Menü *menü;
+    MinigameKlientV *client;
 	int alpha;
 	int ref;
 
@@ -20,6 +21,7 @@ public:
 	~Game();
 	// nicht constant
 	virtual bool laden() override;
+    virtual void setMinigameClientZ( MinigameKlientV *client ) override;
 	virtual void doMausEreignis( MausEreignis &me ) override;
 	virtual void doTastaturEreignis( TastaturEreignis &te ) override;
 	virtual bool tick( double zeit ) override;

+ 402 - 310
Blöcke/Map.cpp

@@ -6,369 +6,461 @@
 #include <Text.h>
 #include <TastaturEreignis.h>
 #include <MausEreignis.h>
+#include <AsynchronCall.h>
 
 // Inhalt der Map Klasse aus Map.h
 // Konstruktor
-Map::Map()
+Map::Map( MinigameKlientV *klient )
 {
-	map = new RCArray< Array< int > >();
-	score = 0;
-	breite = 0;
-	höhe = 0;
-	geschwindigkeit = 0;
-	bAnzahl = 0;
-	next = 0;
-	beendet = 1;
-	sr = 1;
-	rend = 0;
-	ref = 1;
+    this->klient = klient;
+    map = new RCArray< Array< int > >();
+    score = 0;
+    breite = 0;
+    höhe = 0;
+    geschwindigkeit = 0;
+    bAnzahl = 0;
+    next = 0;
+    beendet = 1;
+    rend = 0;
+    rGen = 0;
+    gameTime = 0;
+    ref = 1;
 }
 
 // Destruktor
 Map::~Map()
 {
-	speichern();
-	map->release();
+    speichern();
+    map->release();
+    if( rGen )
+        rGen->release();
+    if( klient )
+        klient->release();
 }
 
 // private
 void Map::remove( int x, int y )
 {
-	if( !map->z( x ) || !map->z( x )->hat( y ) || !map->z( x )->get( y ) )
-		return;
-	int f = map->z( x )->get( y );
-	map->z( x )->set( 0, y );
-	if( !f )
-		return;
-	if( map->z( x - 1 ) && map->z( x - 1 )->hat( y ) && map->z( x - 1 )->get( y ) == f )
-		remove( x - 1, y );
-	if( map->z( x + 1 ) && map->z( x + 1 )->hat( y ) && map->z( x + 1 )->get( y ) == f )
-		remove( x + 1, y );
-	if( map->z( x ) && map->z( x )->hat( y - 1 ) && map->z( x )->get( y - 1 ) == f )
-		remove( x, y - 1 );
-	if( map->z( x ) && map->z( x )->hat( y + 1 ) && map->z( x )->get( y + 1 ) == f )
-		remove( x, y + 1 );
+    if( !map->z( x ) || !map->z( x )->hat( y ) || !map->z( x )->get( y ) )
+        return;
+    int f = map->z( x )->get( y );
+    map->z( x )->set( 0, y );
+    if( !f )
+        return;
+    if( map->z( x - 1 ) && map->z( x - 1 )->hat( y ) && map->z( x - 1 )->get( y ) == f )
+        remove( x - 1, y );
+    if( map->z( x + 1 ) && map->z( x + 1 )->hat( y ) && map->z( x + 1 )->get( y ) == f )
+        remove( x + 1, y );
+    if( map->z( x ) && map->z( x )->hat( y - 1 ) && map->z( x )->get( y - 1 ) == f )
+        remove( x, y - 1 );
+    if( map->z( x ) && map->z( x )->hat( y + 1 ) && map->z( x )->get( y + 1 ) == f )
+        remove( x, y + 1 );
 }
 
 // nicht constant
-void Map::reset()
+void Map::reset( Text *zOptionen )
 {
-	next = 0;
-	beendet = 0;
-	score = 0;
-	map->leeren();
-	InitDatei *opd = new InitDatei( "data/Minigames/Blöcke/data/optionen.ini" );
-	if( !opd->laden() )
-		DateiPfadErstellen( "data/Minigames/Blöcke/data/optionen.ini" );
-	breite = 20;
-	if( opd->wertExistiert( "Breite" ) )
-		breite = (int)*opd->zWert( "Breite" );
-	else
-		opd->addWert( "Breite", "20" );
-	höhe = 12;
-	if( opd->wertExistiert( "Height" ) )
-		höhe = (int)*opd->zWert( "Height" );
-	else
-		opd->addWert( "Height", "12" );
-	bAnzahl = 5;
-	if( opd->wertExistiert( "Farben" ) )
-		bAnzahl = (int)*opd->zWert( "Farben" );
-	else
-		opd->addWert( "Farben", "5" );
-	geschwindigkeit = 4000;
-	if( opd->wertExistiert( "Geschwindigkeit" ) )
-		geschwindigkeit = (int)*opd->zWert( "Geschwindigkeit" );
-	else
-		opd->addWert( "Geschwindigkeit", "4000" );
-	bool fortsetzen = 0;
-	if( opd->wertExistiert( "Fortsetzen" ) )
-		fortsetzen = (int)*opd->zWert( "Fortsetzen" ) != 0;
-	else
-		opd->addWert( "Fortsetzen", "0" );
-	opd->speichern();
-	opd->release();
-	if( fortsetzen && DateiExistiert( "data/Minigames/Blöcke/data/game.save" ) )
-	{
-		Datei *save = new Datei();
-		save->setDatei( "data/Minigames/Blöcke/data/game.save" );
-		save->open( Datei::Style::lesen );
-		int br = 0;
-		int hö = 0;
-		save->lese( (char*)&br, 4 );
-		save->lese( (char*)&hö, 4 );
-		if( br == breite && hö == höhe )
-		{
-			save->lese( (char*)&score, 4 );
-			for( int x = 0; x < breite; x++ )
-			{
-				map->set( new Array< int >(), x );
-				for( int y = 0; y < höhe; y++ )
-				{
-					int f = 0;
-					save->lese( (char*)&f, 4 );
-					map->z( x )->set( f, y );
-				}
-			}
-			next = geschwindigkeit / 1000.0;
-		}
-		save->close();
-		save->release();
-		int xOff = 0;
-		for( int x = 0; x < breite; x++ )
-		{
-			if( !map->z( x - xOff ) )
-				continue;
-			Array< int > *row = map->z( x - xOff );
-			int yOff = 0;
-			for( int y = 0; y < höhe; y++ )
-			{
-				if( row->hat( y - yOff ) && !row->get( y - yOff ) )
-				{
-					row->remove( y - yOff );
-					yOff++;
-				}
-			}
-			bool del = 1;
-			for( int y = 0; y < höhe; y++ )
-				del &= !row->hat( y - yOff ) || !row->get( y - yOff );
-			if( del )
-			{
-				map->remove( x - xOff );
-				xOff++;
-			}
-		}
-	}
+    gameTime = 0;
+    next = 0;
+    beendet = 0;
+    score = 0;
+    map->leeren();
+    Text *tmp = zOptionen->getTeilText( zOptionen->positionVon( '=' ) + 1, zOptionen->positionVon( ',' ) );
+    breite = *tmp;
+    tmp->release();
+    tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 1 ) + 1, zOptionen->positionVon( ',', 1 ) );
+    höhe = *tmp;
+    tmp->release();
+    tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 2 ) + 1, zOptionen->positionVon( ',', 2 ) );
+    bAnzahl = *tmp;
+    tmp->release();
+    tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 3 ) + 1, zOptionen->positionVon( ',', 3 ) );
+    geschwindigkeit = *tmp;
+    tmp->release();
+    tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 4 ) + 1, zOptionen->positionVon( ',', 4 ) );
+    bool fortsetzen = (int)*tmp != 0;
+    tmp->release();
+    if( rGen )
+        rGen = rGen->release();
+    if( fortsetzen && DateiExistiert( "data/Minigames/Blöcke/data/game.save" ) && klient )
+    {
+        if( capture.istOffen() )
+            capture.close();
+        capture.setDatei( "data/Minigames/Blöcke/data/game.mgc" );
+        capture.open( Datei::Style::schreiben | Datei::Style::ende | Datei::Style::lesen );
+        Datei *save = new Datei();
+        save->setDatei( "data/Minigames/Blöcke/data/game.save" );
+        save->open( Datei::Style::lesen );
+        int br = 0;
+        int hö = 0;
+        __int64 seed;
+        save->lese( (char*)&seed, 8 );
+        rGen = new RandomGenerator();
+        rGen->setSeed( seed );
+        save->lese( (char*)&gameTime, 8 );
+        save->lese( (char*)&br, 4 );
+        save->lese( (char*)&hö, 4 );
+        if( br == breite && hö == höhe )
+        {
+            save->lese( (char*)&score, 4 );
+            for( int x = 0; x < breite; x++ )
+            {
+                map->set( new Array< int >(), x );
+                for( int y = 0; y < höhe; y++ )
+                {
+                    int f = 0;
+                    save->lese( (char*)&f, 4 );
+                    map->z( x )->set( f, y );
+                }
+            }
+            next = geschwindigkeit / 1000.0;
+        }
+        save->close();
+        save->release();
+        int xOff = 0;
+        for( int x = 0; x < breite; x++ )
+        {
+            if( !map->z( x - xOff ) )
+                continue;
+            Array< int > *row = map->z( x - xOff );
+            int yOff = 0;
+            for( int y = 0; y < höhe; y++ )
+            {
+                if( row->hat( y - yOff ) && !row->get( y - yOff ) )
+                {
+                    row->remove( y - yOff );
+                    yOff++;
+                }
+            }
+            bool del = 1;
+            for( int y = 0; y < höhe; y++ )
+                del &= !row->hat( y - yOff ) || !row->get( y - yOff );
+            if( del )
+            {
+                map->remove( x - xOff );
+                xOff++;
+            }
+        }
+    }
+    else
+    {
+        rGen = new RandomGenerator();
+        if( klient )
+        {
+            if( capture.istOffen() )
+                capture.close();
+            DateiRemove( "data/Minigames/Blöcke/data/game.mgc" );
+            capture.setDatei( "data/Minigames/Blöcke/data/game.mgc" );
+            capture.erstellen();
+            capture.open( Datei::Style::schreiben );
+            __int64 seed = rGen->getSeed();
+            capture.schreibe( (char*)&seed, 8 );
+        }
+        else
+        {
+            tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 5 ) + 1 );
+            rGen->setSeed( (__int64)*tmp );
+            tmp->release();
+        }
+    }
 }
 
 void Map::doMausEreignis( MausEreignis &me )
 {
-	if( beendet )
-		return;
-	if( me.id == ME_RRechts )
-		next = 0;
-	if( me.id != ME_RLinks )
-		return;
-	int x = (int)( me.mx / ( 800.0 / breite ) );
-	int y = (int)( höhe - ( me.my / ( 500.0 / höhe ) ) );
-	if( !map->z( x ) || !map->z( x )->hat( y ) || !map->z( x )->get( y ) )
-		return;
-	bool remove = 0;
-	int f = map->z( x )->get( y );
-	if( map->z( x - 1 ) && map->z( x - 1 )->hat( y ) && map->z( x - 1 )->get( y ) == f )
-		remove = 1;
-	if( map->z( x + 1 ) && map->z( x + 1 )->hat( y ) && map->z( x + 1 )->get( y ) == f )
-		remove = 1;
-	if( map->z( x ) && map->z( x )->hat( y - 1 ) && map->z( x )->get( y - 1 ) == f )
-		remove = 1;
-	if( map->z( x ) && map->z( x )->hat( y + 1 ) && map->z( x )->get( y + 1 ) == f )
-		remove = 1;
-	if( !remove )
-		return;
-	rend = 1;
-	this->remove( x, y );
-	int xOff = 0;
-	for( int x = 0; x < breite; x++ )
-	{
-		if( !map->z( x - xOff ) )
-			continue;
-		Array< int > *row = map->z( x - xOff );
-		int yOff = 0;
-		for( int y = 0; y < höhe; y++ )
-		{
-			if( row->hat( y - yOff ) && !row->get( y - yOff ) )
-			{
-				row->remove( y - yOff );
-				yOff++;
-			}
-		}
-		bool del = 1;
-		for( int y = 0; y < höhe; y++ )
-			del &= !row->hat( y - yOff ) || !row->get( y - yOff );
-		if( del )
-		{
-			score++;
-			map->remove( x - xOff );
-			xOff++;
-		}
-	}
+    if( beendet )
+        return;
+    cs.lock();
+    if( me.id == ME_RRechts )
+    {
+        next = 0;
+        if( klient )
+        {
+            capture.schreibe( (char*)&gameTime, 8 );
+            capture.schreibe( "\x1", 1 );
+        }
+    }
+    if( me.id != ME_RLinks )
+    {
+        cs.unlock();
+        return;
+    }
+    if( klient )
+    {
+        capture.schreibe( (char*)&gameTime, 8 );
+        capture.schreibe( "\x0", 1 );
+        capture.schreibe( (char*)&me.mx, 4 );
+        capture.schreibe( (char*)&me.my, 4 );
+    }
+    int x = (int)( me.mx / ( 800.0 / breite ) );
+    int y = (int)( höhe - ( me.my / ( 500.0 / höhe ) ) );
+    if( !map->z( x ) || !map->z( x )->hat( y ) || !map->z( x )->get( y ) )
+    {
+        cs.unlock();
+        return;
+    }
+    bool remove = 0;
+    int f = map->z( x )->get( y );
+    if( map->z( x - 1 ) && map->z( x - 1 )->hat( y ) && map->z( x - 1 )->get( y ) == f )
+        remove = 1;
+    if( map->z( x + 1 ) && map->z( x + 1 )->hat( y ) && map->z( x + 1 )->get( y ) == f )
+        remove = 1;
+    if( map->z( x ) && map->z( x )->hat( y - 1 ) && map->z( x )->get( y - 1 ) == f )
+        remove = 1;
+    if( map->z( x ) && map->z( x )->hat( y + 1 ) && map->z( x )->get( y + 1 ) == f )
+        remove = 1;
+    if( !remove )
+    {
+        cs.unlock();
+        return;
+    }
+    rend = 1;
+    this->remove( x, y );
+    int xOff = 0;
+    for( int x = 0; x < breite; x++ )
+    {
+        if( !map->z( x - xOff ) )
+            continue;
+        Array< int > *row = map->z( x - xOff );
+        int yOff = 0;
+        for( int y = 0; y < höhe; y++ )
+        {
+            if( row->hat( y - yOff ) && !row->get( y - yOff ) )
+            {
+                row->remove( y - yOff );
+                yOff++;
+            }
+        }
+        bool del = 1;
+        for( int y = 0; y < höhe; y++ )
+            del &= !row->hat( y - yOff ) || !row->get( y - yOff );
+        if( del )
+        {
+            score++;
+            map->remove( x - xOff );
+            xOff++;
+        }
+    }
+    cs.unlock();
 }
 
 void Map::doTastaturEreignis( TastaturEreignis &te )
 {
-	if( te.id == TE_Release )
-		next = 0;
+    cs.lock();
+    if( te.id == TE_Release )
+    {
+        next = 0;
+        if( klient )
+        {
+            capture.schreibe( (char*)&gameTime, 8 );
+            capture.schreibe( "\x1", 1 );
+        }
+    }
+    cs.unlock();
 }
 
 bool Map::tick( double tickVal )
 {
-	bool ret = rend;
-	rend = 0;
-	if( beendet )
-		return ret;
-	if( sr )
-		srand( (int)time( 0 ) );
-	sr = 0;
-	next -= tickVal;
-	if( next < 0 )
-	{
-		next = geschwindigkeit / 1000.0;
-		Array< int > *n = new Array< int >();
-		for( int i = 0; i < höhe; i++ )
-		{
-			int val = rand() % bAnzahl;
-			switch( val )
-			{
-			case 0:
-				n->set( 0xFFFF0000, i );
-				break;
-			case 1:
-				n->set( 0xFF00FF00, i );
-				break;
-			case 2:
-				n->set( 0xFF0000FF, i );
-				break;
-			case 3:
-				n->set( 0xFFFFFF00, i );
-				break;
-			case 4:
-				n->set( 0xFF00FFFF, i );
-				break;
-			case 5:
-				n->set( 0xFFFF00FF, i );
-				break;
-			case 6:
-				n->set( 0xFFFFFFFF, i );
-				break;
-			case 7:
-				n->set( 0xFFFF5555, i );
-				break;
-			case 8:
-				n->set( 0xFF55FF55, i );
-				break;
-			case 9:
-				n->set( 0xFF5555FF, i );
-				break;
-			default:
-				n->set( 0xFF000000, i );
-				break;
-			}
-		}
-		map->add( n, 0 );
-		if( map->z( breite ) )
-		{
-			Array< int > *row = map->z( breite );
-			for( int i = 0; i < höhe; i++ )
-			{
-				if( row->hat( i ) )
-					beendet |= row->get( i ) != 0;
-			}
-			if( beendet )
-			{
-				KSGTDatei *stb = new KSGTDatei( "data/Minigames/Blöcke/data/score.ksgt" );
-				if( !stb->laden() )
-					DateiPfadErstellen( "data/Minigames/Blöcke/data/score.ksgt" );
-				RCArray< Text > *zeile = new RCArray< Text >();
-				Zeit *zeit = getZeit();
-				zeile->add( zeit->getZeit( "y-m-d h:i:s" ) );
-				zeit->release();
-				Text *scoreT = new Text();
-				scoreT->append( score );
-				zeile->add( scoreT );
-				Text *breiteT = new Text();
-				breiteT->append( breite );
-				zeile->add( breiteT );
-				Text *höheT = new Text();
-				höheT->append( höhe );
-				zeile->add( höheT );
-				Text *geschwindigkeitT = new Text();
-				geschwindigkeitT->append( geschwindigkeit );
-				zeile->add( geschwindigkeitT );
-				Text *bAnzahlT = new Text();
-				bAnzahlT->append( bAnzahl );
-				zeile->add( bAnzahlT );
-				stb->addZeile( 6, zeile );
-				zeile->release();
-				stb->speichern();
-				stb->release();
+    bool ret = rend;
+    rend = 0;
+    if( beendet )
+        return ret;
+    cs.lock();
+    gameTime += tickVal;
+    next -= tickVal;
+    if( next < 0 )
+    {
+        next = geschwindigkeit / 1000.0;
+        Array< int > *n = new Array< int >();
+        for( int i = 0; i < höhe; i++ )
+        {
+            int val = (int)( rGen->rand() * bAnzahl );
+            switch( val )
+            {
+            case 0:
+                n->set( 0xFFFF0000, i );
+                break;
+            case 1:
+                n->set( 0xFF00FF00, i );
+                break;
+            case 2:
+                n->set( 0xFF0000FF, i );
+                break;
+            case 3:
+                n->set( 0xFFFFFF00, i );
+                break;
+            case 4:
+                n->set( 0xFF00FFFF, i );
+                break;
+            case 5:
+                n->set( 0xFFFF00FF, i );
+                break;
+            case 6:
+                n->set( 0xFFFFFFFF, i );
+                break;
+            case 7:
+                n->set( 0xFFFF5555, i );
+                break;
+            case 8:
+                n->set( 0xFF55FF55, i );
+                break;
+            case 9:
+                n->set( 0xFF5555FF, i );
+                break;
+            default:
+                n->set( 0xFF000000, i );
+                break;
+            }
+        }
+        map->add( n, 0 );
+        if( map->z( breite ) )
+        {
+            Array< int > *row = map->z( breite );
+            for( int i = 0; i < höhe; i++ )
+            {
+                if( row->hat( i ) )
+                    beendet |= row->get( i ) != 0;
+            }
+            if( beendet && klient )
+            {
+                capture.close();
+                DateiRemove( "data/Minigames/Blöcke/data/upload.mgc" );
+                DateiUmbenennen( "data/Minigames/Blöcke/data/game.mgc", "data/Minigames/Blöcke/data/upload.mgc" );
+                int tmpScore = score;
+                MinigameKlientV *tmpKlient = klient->getThis();
+                new AsynchronCall( [ tmpScore, tmpKlient ]()
+                {
+                    InitDatei *opd = new InitDatei( "data/Minigames/Blöcke/data/optionen.ini" );
+                    opd->laden();
+                    Text optionen = "Width=";
+                    optionen += opd->zWert( "Breite" )->getText();
+                    optionen += ",Height=";
+                    optionen += opd->zWert( "Höhe" )->getText();
+                    optionen += ",Farben=";
+                    optionen += opd->zWert( "Farben" )->getText();
+                    optionen += ",Speed=";
+                    optionen += opd->zWert( "Geschwindigkeit" )->getText();
+                    opd->release();
+                    int status = tmpKlient->reportEndOfGame( "Bloecke", optionen, tmpScore );
+                    if( status == 2 )
+                    {
+                        Datei d;
+                        d.setDatei( "data/Minigames/Blöcke/data/upload.mgc" );
+                        tmpKlient->uploadGameCapture( &d );
+                    }
+                    DateiRemove( "data/Minigames/Blöcke/data/upload.mgc" );
+                    tmpKlient->release();
+                } );
+                KSGTDatei *stb = new KSGTDatei( "data/Minigames/Blöcke/data/score.ksgt" );
+                if( !stb->laden() )
+                    DateiPfadErstellen( "data/Minigames/Blöcke/data/score.ksgt" );
+                RCArray< Text > *zeile = new RCArray< Text >();
+                Zeit *zeit = getZeit();
+                zeile->add( zeit->getZeit( "y-m-d h:i:s" ) );
+                zeit->release();
+                Text *scoreT = new Text();
+                scoreT->append( score );
+                zeile->add( scoreT );
+                Text *breiteT = new Text();
+                breiteT->append( breite );
+                zeile->add( breiteT );
+                Text *höheT = new Text();
+                höheT->append( höhe );
+                zeile->add( höheT );
+                Text *geschwindigkeitT = new Text();
+                geschwindigkeitT->append( geschwindigkeit );
+                zeile->add( geschwindigkeitT );
+                Text *bAnzahlT = new Text();
+                bAnzahlT->append( bAnzahl );
+                zeile->add( bAnzahlT );
+                stb->addZeile( 6, zeile );
+                zeile->release();
+                stb->speichern();
+                stb->release();
                 DateiRemove( "data/Minigames/Blöcke/data/game.save" );
-			}
-		}
-		map->remove( breite );
-		ret = 1;
-	}
-	return ret;
+            }
+        }
+        map->remove( breite );
+        ret = 1;
+    }
+    cs.unlock();
+    return ret;
 }
 
 void Map::render( Bild &zRObj )
 {
-	for( int x = 0; x < breite; x++ )
-	{
-		if( !map->z( x ) )
-			continue;
-		Array< int > *row = map->z( x );
-		for( int y = 0; y < höhe; y++ )
-		{
-			if( !row->hat( y ) )
-				continue;
-			int xs = (int)( x * ( 800.0 / breite ) );
-			int ys = (int)( ( höhe - y - 1 ) * ( 500.0 / höhe ) );
-			int xe = (int)( ( x + 1 ) * ( 800.0 / breite ) );
-			int ye = (int)( ( höhe - y ) * ( 500.0 / höhe ) );
-			zRObj.fillRegion( xs, ys, xe - xs, ye - ys, row->get( y ) );
-		}
-	}
+    for( int x = 0; x < breite; x++ )
+    {
+        if( !map->z( x ) )
+            continue;
+        Array< int > *row = map->z( x );
+        for( int y = 0; y < höhe; y++ )
+        {
+            if( !row->hat( y ) )
+                continue;
+            int xs = (int)( x * ( 800.0 / breite ) );
+            int ys = (int)( ( höhe - y - 1 ) * ( 500.0 / höhe ) );
+            int xe = (int)( ( x + 1 ) * ( 800.0 / breite ) );
+            int ye = (int)( ( höhe - y ) * ( 500.0 / höhe ) );
+            zRObj.fillRegion( xs, ys, xe - xs, ye - ys, row->get( y ) );
+        }
+    }
 }
 
-// constant
-void Map::speichern() const
+void Map::speichern()
 {
-	if( !beendet )
-	{
-		Datei *d = new Datei();
-		d->setDatei( "data/Minigames/Blöcke/data/game.save" );
-		d->erstellen();
-		d->open( Datei::Style::schreiben );
-		d->schreibe( (char*)&breite, 4 );
-		d->schreibe( (char*)&höhe, 4 );
-		d->schreibe( (char*)&score, 4 );
-		for( int x = 0; x < breite; x++ )
-		{
-			for( int y = 0; y < höhe; y++ )
-			{
-				int f = 0;
-				if( map->z( x ) && map->z( x )->hat( y ) )
-					f = map->z( x )->get( y );
-				d->schreibe( (char*)&f, 4 );
-			}
-		}
-		d->close();
-		d->release();
-	}
-	else
-		DateiRemove( "data/Minigames/Blöcke/data/game.save" );
+    if( !beendet && klient )
+    {
+        if( capture.istOffen() )
+            capture.close();
+        Datei *d = new Datei();
+        d->setDatei( "data/Minigames/Blöcke/data/game.save" );
+        d->erstellen();
+        d->open( Datei::Style::schreiben );
+        __int64 seed = rGen->getSeed();
+        d->schreibe( (char*)&seed, 8 );
+        d->schreibe( (char*)&gameTime, 8 );
+        d->schreibe( (char*)&breite, 4 );
+        d->schreibe( (char*)&höhe, 4 );
+        d->schreibe( (char*)&score, 4 );
+        for( int x = 0; x < breite; x++ )
+        {
+            for( int y = 0; y < höhe; y++ )
+            {
+                int f = 0;
+                if( map->z( x ) && map->z( x )->hat( y ) )
+                    f = map->z( x )->get( y );
+                d->schreibe( (char*)&f, 4 );
+            }
+        }
+        d->close();
+        d->release();
+    }
+    else if( klient )
+        DateiRemove( "data/Minigames/Blöcke/data/game.save" );
 }
 
+// constant
 int Map::getScore() const
 {
-	return score;
+    return score;
 }
 
 bool Map::istBeendet() const
 {
-	return beendet;
+    return beendet;
 }
 
 // Reference Counting
 Map *Map::getThis()
 {
-	ref++;
-	return this;
+    ref++;
+    return this;
 }
 
 Map *Map::release()
 {
-	ref--;
-	if( !ref )
-		delete this;
-	return 0;
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
 }

+ 10 - 4
Blöcke/Map.h

@@ -2,6 +2,8 @@
 #define Map_H
 
 #include <Bild.h>
+#include <Random.h>
+#include "../../../Include/KSGKlientV.h"
 
 using namespace Framework;
 
@@ -16,25 +18,29 @@ private:
 	int bAnzahl;
 	double next;
 	bool beendet;
-	bool sr;
 	bool rend;
+    double gameTime;
+    Datei capture;
+    Critical cs;
+    MinigameKlientV *klient;
+    RandomGenerator *rGen;
 	int ref;
 	// private
 	void remove( int x, int y );
 
 public:
 	// Konstruktor
-	Map();
+	Map( MinigameKlientV *klient );
 	// Destruktor
 	~Map();
 	// nicht constant
-	void reset();
+	void reset( Text *zOptionen );
 	void doMausEreignis( MausEreignis &me );
 	void doTastaturEreignis( TastaturEreignis &te );
 	bool tick( double tickVal );
 	void render( Bild &zRObj );
+    void speichern();
 	// constant
-	void speichern() const;
 	int getScore() const;
 	bool istBeendet() const;
 	// Reference Counting

+ 318 - 13
Blöcke/Menü.cpp

@@ -10,6 +10,8 @@
 #include <Schrift.h>
 #include <DateiSystem.h>
 #include <Rahmen.h>
+#include <Bildschirm.h>
+#include <AsynchronCall.h>
 
 // Inhalt der MenüVerloren Klasse aus Menü.h
 // Kontruktor
@@ -83,12 +85,13 @@ Men
 
 // Inhalt der MenüSpiel Klasse aus Menü.h
 // Konstruktor
-MenüSpiel::MenüSpiel( Schrift *zSchrift, Bildschirm *zScreen )
+MenüSpiel::MenüSpiel( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient )
 {
 	scoreT = initTextFeld( 690, 10, 100, 20, zSchrift, TextFeld::Style::Text, "Score: 0" );
 	beenden = initKnopf( 690, 40, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Beenden" );
-	map = new Map();
+	map = new Map( klient );
 	verloren = new MenüVerloren( zSchrift );
+    timePuffer = 0;
 	beendet = 0;
 	ref = 1;
 }
@@ -105,7 +108,56 @@ Men
 // nicht constant
 void MenüSpiel::reset()
 {
-	map->reset();
+    timePuffer = 0;
+    Text optionen = "Width=";
+    InitDatei *opd = new InitDatei( "data/Minigames/Blöcke/data/optionen.ini" );
+    if( !opd->laden() )
+        DateiPfadErstellen( "data/Minigames/Blöcke/data/optionen.ini" );
+    if( opd->wertExistiert( "Breite" ) )
+        optionen += (int)*opd->zWert( "Breite" );
+    else
+    {
+        opd->addWert( "Breite", "20" );
+        optionen += 20;
+    }
+    optionen += ",Height=";
+    if( opd->wertExistiert( "Height" ) )
+        optionen += (int)*opd->zWert( "Height" );
+    else
+    {
+        opd->addWert( "Height", "12" );
+        optionen += 12;
+    }
+    optionen += ",Farben=";
+    if( opd->wertExistiert( "Farben" ) )
+        optionen += (int)*opd->zWert( "Farben" );
+    else
+    {
+        opd->addWert( "Farben", "5" );
+        optionen += 5;
+    }
+    optionen += ",Speed=";
+    if( opd->wertExistiert( "Geschwindigkeit" ) )
+        optionen += (int)*opd->zWert( "Geschwindigkeit" );
+    else
+    {
+        opd->addWert( "Geschwindigkeit", "4000" );
+        optionen += 4000;
+
+    }
+    optionen += ",Fortsetzen=";
+    if( opd->wertExistiert( "Fortsetzen" ) )
+        optionen += (int)*opd->zWert( "Fortsetzen" ) != 0;
+    else
+    {
+        opd->addWert( "Fortsetzen", "0" );
+        optionen += 0;
+
+    }
+    optionen += ",Seed=0";
+    opd->speichern();
+    opd->release();
+	map->reset( &optionen );
 	beendet = 0;
 	scoreT->setText( "Score: " );
 	scoreT->zText()->append( map->getScore() );
@@ -149,6 +201,12 @@ void Men
 bool MenüSpiel::tick( double tickVal )
 {
 	bool ret = beenden->tick( tickVal );
+    timePuffer += tickVal;
+    while( timePuffer >= 0.01 )
+    {
+        ret |= map->tick( 0.01 );
+        timePuffer -= 0.01;
+    }
 	ret |= map->tick( tickVal );
 	if( map->istBeendet() )
 		ret |= verloren->tick( tickVal );
@@ -186,20 +244,140 @@ Men
 }
 
 
+// Inhalt der MenüWiederhohlung Klasse
+// Konstruktor
+MenüWiederhohlung::MenüWiederhohlung( Schrift *zSchrift, Bildschirm *zScreen, Datei *datei, Text *zOptionen )
+{
+    scoreT = initTextFeld( 690, 10, 100, 20, zSchrift, TextFeld::Style::Text, "Score: 0" );
+    beenden = initKnopf( 690, 40, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Beenden" );
+    this->datei = datei;
+    if( !datei->istOffen() )
+        datei->open( Datei::Style::lesen );
+    __int64 seed;
+    datei->lese( (char*)&seed, 8 );
+    zOptionen->append( ",Fortsetzen=0,Seed=" );
+    zOptionen->append( seed );
+    map = new Map( 0 );
+    map->reset( zOptionen );
+    beendet = 0;
+    nowTime = 0;
+    nextTime = 0;
+    datei->lese( (char*)&nextTime, 8 );
+    timePuffer = 0;
+    ref = 1;
+}
+
+// Destruktor
+MenüWiederhohlung::~MenüWiederhohlung()
+{
+    scoreT->release();
+    beenden->release();
+    map->release();
+    datei->close();
+    datei->release();
+}
+
+// nicht constant
+void MenüWiederhohlung::doMausEreignis( MausEreignis &me )
+{
+    bool vera = me.verarbeitet;
+    beenden->doMausEreignis( me );
+    if( !vera && me.verarbeitet && me.id == ME_RLinks )
+        beendet = 1;
+    if( map->istBeendet() )
+        beendet = 1;
+}
+
+void MenüWiederhohlung::doTastaturEreignis( TastaturEreignis &te )
+{}
+
+bool MenüWiederhohlung::tick( double tickVal )
+{
+    bool ret = beenden->tick( tickVal );
+    // TODO Replay Activity
+    while( nextTime >= 0 && nowTime + tickVal >= nextTime )
+    {
+        while( nowTime < nextTime )
+        {
+            ret |= map->tick( 0.01 );
+            tickVal -= 0.01;
+            nowTime += 0.01;
+        }
+        char ak;
+        MausEreignis me;
+        datei->lese( &ak, 1 );
+        me.id = ME_RRechts;
+        if( ak == 0 )
+        {
+            datei->lese( (char*)&me.mx, 4 );
+            datei->lese( (char*)&me.my, 4 );
+            me.id = ME_RLinks;
+        }
+        if( datei->istEnde() )
+            nextTime = -1;
+        else
+            datei->lese( (char*)&nextTime, 8 );
+        me.verarbeitet = 0;
+        map->doMausEreignis( me );
+    }
+    timePuffer += tickVal;
+    while( timePuffer > 0 )
+    {
+        ret |= map->tick( 0.01 );
+        nowTime += 0.01;
+        timePuffer -= 0.01;
+    }
+    scoreT->setText( "Score: " );
+    scoreT->zText()->append( map->getScore() );
+    return ret;
+}
+
+void MenüWiederhohlung::render( Bild &zRObj )
+{
+    map->render( zRObj );
+    scoreT->render( zRObj );
+    beenden->render( zRObj );
+}
+
+// constant
+bool MenüWiederhohlung::istBeendet() const
+{
+    return beendet;
+}
+
+// Reference Counting
+MenüWiederhohlung *MenüWiederhohlung::getThis()
+{
+    ref++;
+    return this;
+}
+
+MenüWiederhohlung *MenüWiederhohlung::release()
+{
+    if( !--ref )
+        delete this;
+    return 0;
+}
+
 // Inhalt der MenüStatistik Klasse aus Menü.h
 // Konstruktor
-MenüStatistik::MenüStatistik( Schrift *zSchrift, Bildschirm *zScreen )
+MenüStatistik::MenüStatistik( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient )
 {
+    this->klient = klient;
+    wiederH = 0;
 	ansichtT = initTextFeld( 245, 10, 50, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Ansicht:" );
 	ansicht = initAuswahlBox( 295, 10, 120, 20, zSchrift, AuswahlBox::Style::Normal | AuswahlBox::Style::Hintergrund, { "Tabelle", "Diagramm" } );
 	optionen = initKontrollKnopf( 425, 10, 130, 20, zSchrift, KontrollKnopf::Style::Normal, "Optionen beachten" );
-	gesammtT = initObjTabelle( 150, 40, 500, 420, zSchrift, ObjTabelle::Style::normal, { { "Score", 70, 0, 0 }, { "Datum", 145, 0, 0 }, { "Breite", 70, 0, 0 }, { "Height", 70, 0, 0 }, { "Farben", 70, 0, 0 }, { "Tempo", 70, 0, 0 } }, 20 );
-	optionenT = initObjTabelle( 150, 40, 500, 420, zSchrift, ObjTabelle::Style::normal, { { "Score", 70, 0, 0 }, { "Datum", 145, 0, 0 }, { "Breite", 70, 0, 0 }, { "Height", 70, 0, 0 }, { "Farben", 70, 0, 0 }, { "Tempo", 70, 0, 0 } }, 20 );
-	gesammtD = initLinienDiagramm( 100, 40, 600, 420, zSchrift, LDiag::Style::DatenRahmen, 0 );
-	optionenD = initLinienDiagramm( 100, 40, 600, 420, zSchrift, LDiag::Style::DatenRahmen, 0 );
+    worldBestT = initObjTabelle( 150, 40, 500, 120, zSchrift, ObjTabelle::Style::normal | ObjTabelle::Style::VScroll, { { "Score", 60, 0, 0 }, { "Spieler", 100, 0, 0 }, { "Ansehen", 55, 0, 0 }, { "Breite", 70, 0, 0 },{ "Height", 70, 0, 0 },{ "Farben", 65, 0, 0 },{ "Tempo", 60, 0, 0 } }, 20 );
+	gesammtT = initObjTabelle( 150, 170, 500, 290, zSchrift, ObjTabelle::Style::normal | ObjTabelle::Style::VScroll, { { "Score", 70, 0, 0 }, { "Datum", 145, 0, 0 }, { "Breite", 70, 0, 0 }, { "Height", 70, 0, 0 }, { "Farben", 65, 0, 0 }, { "Tempo", 60, 0, 0 } }, 20 );
+	optionenT = initObjTabelle( 150, 170, 500, 290, zSchrift, ObjTabelle::Style::normal | ObjTabelle::Style::VScroll, { { "Score", 70, 0, 0 }, { "Datum", 145, 0, 0 }, { "Breite", 70, 0, 0 }, { "Height", 70, 0, 0 }, { "Farben", 65, 0, 0 }, { "Tempo", 60, 0, 0 } }, 20 );
+	gesammtD = initLinienDiagramm( 100, 170, 600, 290, zSchrift, LDiag::Style::DatenRahmen, 0 );
+	optionenD = initLinienDiagramm( 100, 170, 600, 290, zSchrift, LDiag::Style::DatenRahmen, 0 );
 	removen = initKnopf( 10, 470, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Zurücksetzen" );
 	zurück = initKnopf( 350, 470, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Zurück" );
 	schrift = zSchrift->getThis();
+    screen = zScreen->getThis();
+    asyncFinished = 1;
 }
 
 // Destruktor
@@ -214,6 +392,23 @@ Men
 	}
 	for( int j = 0; j < 6; j++ )
 		( (TextFeld*)optionenT->zZeichnung( j, 0 ) )->release();
+    while( !asyncFinished )
+    {
+        Sleep( 100 );
+    }
+    anz = worldBestT->getZeilenAnzahl();
+    for( int i = 0; i < anz; i++ )
+    {
+        for( int j = 0; j < 7; j++ )
+        {
+            if( j == 2 )
+                ( (Knopf*)worldBestT->zZeichnung( j, 0 ) )->release();
+            else
+                ( (TextFeld*)worldBestT->zZeichnung( j, 0 ) )->release();
+        }
+        worldBestT->removeZeile( 0 );
+    }
+    worldBestT->release();
 	ansichtT->release();
 	ansicht->release();
 	optionen->release();
@@ -224,6 +419,10 @@ Men
 	removen->release();
 	zurück->release();
 	schrift->release();
+    klient->release();
+    if( wiederH )
+        wiederH->release();
+    screen->release();
 }
 
 // nicht constant
@@ -239,6 +438,77 @@ void Men
 	anz = optionenT->getZeilenAnzahl();
 	for( int i = 1; i < anz; i++ )
 		optionenT->removeZeile( 1 );
+    anz = worldBestT->getZeilenAnzahl();
+    for( int i = 1; i < anz; i++ )
+    {
+        for( int j = 0; j < 7; j++ )
+        {
+            if( j == 2 )
+                ( (Knopf*)worldBestT->zZeichnung( j, 1 ) )->release();
+            else
+                ( (TextFeld*)worldBestT->zZeichnung( j, 1 ) )->release();
+        }
+        worldBestT->removeZeile( 1 );
+    }
+    ObjTabelle *tmpWBT = worldBestT->getThis();
+    MinigameKlientV *tmpKlient = klient->getThis();
+    Schrift *tmpSchrift = schrift->getThis();
+    new AsynchronCall( [ this, tmpWBT, tmpKlient, tmpSchrift ]()
+    {
+        Array< int > score;
+        RCArray< Text > player;
+        RCArray< Text > option;
+        int anz = tmpKlient->getMinigameBestscoreList( "Bloecke", &score, &player, &option );
+        for( int i = 0; i < anz; i++ )
+        {
+            TextFeld *scoreT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, Text( score.get( i ) ) );
+            TextFeld *spielerT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, player.z( i )->getText() );
+            Text optionen = option.z( i )->getText();
+            Text *breite = optionen.getTeilText( optionen.positionVon( '=' ) + 1, optionen.positionVon( ',' ) );
+            Text *höhe = optionen.getTeilText( optionen.positionVon( '=', 1 ) + 1, optionen.positionVon( ',', 1 ) );
+            Text *farben = optionen.getTeilText( optionen.positionVon( '=', 2 ) + 1, optionen.positionVon( ',', 2 ) );
+            Text *geschwindigkeit = optionen.getTeilText( optionen.positionVon( '=', 3 ) + 1 );
+            TextFeld *breiteT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, breite->getText() );
+            breite->release();
+            TextFeld *höheT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, höhe->getText() );
+            höhe->release();
+            TextFeld *farbenT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, farben->getText() );
+            farben->release();
+            TextFeld *geschwindigkeitT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, geschwindigkeit->getText() );
+            geschwindigkeit->release();
+            Knopf *ansehenK = initKnopf( 0, 0, 0, 0, tmpSchrift, Knopf::Style::Normal, "Ansehen" );
+            ansehenK->setMausEreignis( [ this, optionen ]( void *p, void *obj, MausEreignis me ) -> bool
+            {
+                if( me.id == ME_RLinks && !me.verarbeitet )
+                {
+                    ( (Knopf*)obj )->removeStyle( Knopf::Style::Erlaubt );
+                    getThis();
+                    new AsynchronCall( [ this, optionen, obj ]()
+                    {
+                        Datei *d = klient->downloadGameCapture( "Bloecke", optionen );
+                        ( (Knopf*)obj )->addStyle( Knopf::Style::Erlaubt );
+                        if( wiederH )
+                            wiederH = wiederH->release();
+                        Text options = optionen.getText();
+                        wiederH = new MenüWiederhohlung( schrift, screen, d, &options );
+                        release();
+                    } );
+                }
+                return 1;
+            } );
+            tmpWBT->addZeile( optionen.getText() );
+            tmpWBT->setZeichnungZ( 0, i + 1, scoreT );
+            tmpWBT->setZeichnungZ( 1, i + 1, spielerT );
+            tmpWBT->setZeichnungZ( 2, i + 1, ansehenK );
+            tmpWBT->setZeichnungZ( 3, i + 1, breiteT );
+            tmpWBT->setZeichnungZ( 4, i + 1, höheT );
+            tmpWBT->setZeichnungZ( 5, i + 1, farbenT );
+            tmpWBT->setZeichnungZ( 6, i + 1, geschwindigkeitT );
+        }
+        tmpKlient->release();
+        tmpWBT->release();
+        tmpSchrift->release();
+    }, &asyncFinished );
 	InitDatei *opd = new InitDatei( "data/Minigames/Blöcke/data/optionen.ini" );
 	opd->laden();
 	if( !opd->wertExistiert( "Breite" ) )
@@ -366,8 +636,16 @@ void Men
 
 void MenüStatistik::doMausEreignis( MausEreignis &me )
 {
+    if( wiederH )
+    {
+        wiederH->doMausEreignis( me );
+        return;
+    }
 	ansicht->doMausEreignis( me );
 	optionen->doMausEreignis( me );
+    gesammtT->doMausEreignis( me );
+    optionenT->doMausEreignis( me );
+    worldBestT->doMausEreignis( me );
 	bool vera = me.verarbeitet;
 	removen->doMausEreignis( me );
 	if( !vera && me.verarbeitet && me.id == ME_RLinks )
@@ -407,6 +685,13 @@ void Men
 
 bool MenüStatistik::tick( double tickVal )
 {
+    if( wiederH )
+    {
+        bool ret = wiederH->tick( tickVal );
+        if( wiederH->istBeendet() )
+            wiederH = wiederH->release();
+        return ret;
+    }
 	bool ret = ansicht->tick( tickVal );
 	ret |= optionen->tick( tickVal );
 	ret |= removen->tick( tickVal );
@@ -415,11 +700,25 @@ bool Men
 	ret |= optionenT->tick( tickVal );
 	ret |= gesammtD->tick( tickVal );
 	ret |= optionenD->tick( tickVal );
+    ret |= worldBestT->tick( tickVal );
 	return ret;
 }
 
 void MenüStatistik::render( Bild &zRObj )
 {
+    if( wiederH )
+    {
+        wiederH->render( zRObj );
+        return;
+    }
+    schrift->setSchriftSize( 12 );
+    Text weltScore = "Welt Score:";
+    schrift->setDrawPosition( 10, 40 );
+    schrift->renderText( &weltScore, zRObj, 0xFFFFFFFF );
+    Text localScore = "Dein Score:";
+    schrift->setDrawPosition( 10, 170 );
+    schrift->renderText( &localScore, zRObj, 0xFFFFFFFF );
+    worldBestT->render( zRObj );
 	if( !ansicht->getAuswahl() )
 	{
 		if( optionen->hatStyle( KontrollKnopf::Style::Selected ) )
@@ -447,6 +746,11 @@ bool Men
 	return beendet;
 }
 
+bool MenüStatistik::istWiederhohlung() const
+{
+    return wiederH != 0;
+}
+
 // Reference Counting
 MenüStatistik *MenüStatistik::getThis()
 {
@@ -656,14 +960,14 @@ Men
 
 // Inhalt der Menü Klasse aus Menü.h
 // Konstruktor
-Menü::Menü( Schrift *zSchrift, Bildschirm *zScreen )
+Menü::Menü( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient )
 {
 	spielen = initKnopf( 350, 180, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Spielen" );
-	spielenF = new MenüSpiel( zSchrift, zScreen );
+	spielenF = new MenüSpiel( zSchrift, zScreen, klient->getThis() );
 	optionen = initKnopf( 350, 220, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Optionen" );
 	optionenF = new MenüOptionen( zSchrift, zScreen );
 	statistik = initKnopf( 350, 260, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Statistik" );
-	statistikF = new MenüStatistik( zSchrift, zScreen );
+	statistikF = new MenüStatistik( zSchrift, zScreen, klient );
 	beenden = initKnopf( 350, 300, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Beenden" );
 	ram = new LRahmen();
 	ram->setFarbe( 0xFFFFFFFF );
@@ -792,7 +1096,7 @@ bool Men
 
 void Menü::render( Bild &zRObj )
 {
-	if( status != 3 )
+	if( status != 3 && ( status != 2 || !statistikF->istWiederhohlung() ) )
 		zRObj.drawBild( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), *hintergrund );
 	switch( status )
 	{
@@ -814,7 +1118,8 @@ void Men
 		optionenF->render( zRObj );
 		break;
 	case 2:
-		zRObj.alphaRegion( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), 0xD0000000 );
+        if( !statistikF->istWiederhohlung() )
+            zRObj.alphaRegion( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), 0xD0000000 );
 		statistikF->render( zRObj );
 		break;
 	case 3:

+ 41 - 3
Blöcke/Menü.h

@@ -5,6 +5,7 @@
 #include <Tabelle.h>
 #include <Diagramm.h>
 #include <AuswahlBox.h>
+#include <Datei.h>
 #include "Map.h"
 
 using namespace Framework;
@@ -39,12 +40,13 @@ private:
 	Knopf *beenden;
 	Map *map;
 	MenüVerloren *verloren;
+    double timePuffer;
 	bool beendet;
 	int ref;
 
 public:
 	// Konstruktor
-	MenüSpiel( Schrift *zSchrift, Bildschirm *zScreen );
+	MenüSpiel( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient );
 	// Destruktor
 	~MenüSpiel();
 	// nicht constant
@@ -60,6 +62,36 @@ public:
 	MenüSpiel *release();
 };
 
+class MenüWiederhohlung
+{
+private:
+    TextFeld *scoreT;
+    Knopf *beenden;
+    Map *map;
+    Datei *datei;
+    double nowTime;
+    double nextTime;
+    bool beendet;
+    double timePuffer;
+    int ref;
+
+public:
+    // Konstruktor
+    MenüWiederhohlung( Schrift *zSchrift, Bildschirm *zScreen, Datei *datei, Text *zOptionen );
+    // Destruktor
+    ~MenüWiederhohlung();
+    // nicht constant
+    void doMausEreignis( MausEreignis &me );
+    void doTastaturEreignis( TastaturEreignis &te );
+    bool tick( double tickVal );
+    void render( Bild &zRObj );
+    // constant
+    bool istBeendet() const;
+    // Reference Counting
+    MenüWiederhohlung *getThis();
+    MenüWiederhohlung *release();
+};
+
 class MenüStatistik
 {
 private:
@@ -68,17 +100,22 @@ private:
 	KontrollKnopf *optionen;
 	ObjTabelle *gesammtT;
 	ObjTabelle *optionenT;
+    ObjTabelle *worldBestT;
 	LDiag *gesammtD;
 	LDiag *optionenD;
 	Knopf *removen;
 	Knopf *zurück;
 	Schrift *schrift;
+    MinigameKlientV *klient;
+    MenüWiederhohlung *wiederH;
+    Bildschirm *screen;
+    bool asyncFinished;
 	bool beendet;
 	int ref = 1;
 
 public:
 	// Konstruktor
-	MenüStatistik( Schrift *zSchrift, Bildschirm *zScreen );
+	MenüStatistik( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient );
 	// Destruktor
 	~MenüStatistik();
 	// nicht constant
@@ -88,6 +125,7 @@ public:
 	void render( Bild &zRObj );
 	// constant
 	bool istBeendet() const;
+    bool istWiederhohlung() const;
 	// Reference Counting
 	MenüStatistik *getThis();
 	MenüStatistik *release();
@@ -146,7 +184,7 @@ private:
 
 public:
 	// Konstruktor
-	Menü( Schrift *zSchrift, Bildschirm *zScreen );
+	Menü( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient );
 	// Destruktor
 	~Menü();
 	// nicht constant