Pārlūkot izejas kodu

Weltweiter Bestscore und Spielwiederholung ansehen ist jetzt verfügbar

Kolja Strohm 6 gadi atpakaļ
vecāks
revīzija
b25c2f6757
6 mainītis faili ar 752 papildinājumiem un 319 dzēšanām
  1. 13 2
      Tetris/Game.cpp
  2. 2 0
      Tetris/Game.h
  3. 375 297
      Tetris/Map.cpp
  4. 10 3
      Tetris/Map.h
  5. 312 14
      Tetris/Menü.cpp
  6. 40 3
      Tetris/Menü.h

+ 13 - 2
Tetris/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
Tetris/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;

+ 375 - 297
Tetris/Map.cpp

@@ -7,126 +7,152 @@
 #include <TastaturEreignis.h>
 #include <Zeit.h>
 #include <Rahmen.h>
+#include <AsynchronCall.h>
 
 // Inhalt der Map Klasse aus Map.h
 // Konstruktor
-Map::Map()
+Map::Map( MinigameKlientV *klient )
 {
-	map = new RCArray< Array< int > >();
-	feld = new LRahmen();
-	feld->setFarbe( 0xFFFFFFFF );
-	t = { 0, 0, 0, 0 };
-	beendet = 1;
-	sr = 1;
-	rend = 0;
-	ref = 1;
+    this->klient = klient;
+    map = new RCArray< Array< int > >();
+    feld = new LRahmen();
+    feld->setFarbe( 0xFFFFFFFF );
+    t = { 0, 0, 0, 0 };
+    beendet = 1;
+    sr = 1;
+    rend = 0;
+    gameTime = 0;
+    rGen = 0;
+    ref = 1;
 }
 
 // Destruktor
 Map::~Map()
 {
-	speichern();
-	map->release();
-	feld->release();
+    speichern();
+    map->release();
+    feld->release();
+    if( rGen )
+        rGen->release();
+    if( klient )
+        klient->release();
 }
 
 // nicht constant
-void Map::reset()
+void Map::reset( Text *zOptionen )
 {
-	next = 0;
-	score = 0;
-	map->leeren();
-	t = { -1, 0, 0, 0 };
-	InitDatei *opd = new InitDatei( "data/Minigames/tetris/data/optionen.ini" );
-	if( !opd->laden() )
-		DateiPfadErstellen( "data/Minigames/Tetris/data/optionen.ini" );
-	breite = 15;
-	if( opd->wertExistiert( "Breite" ) )
-		breite = (int)*opd->zWert( "Breite" );
-	else
-		opd->addWert( "Breite", "15" );
-	höhe = 25;
-	if( opd->wertExistiert( "Höhe" ) )
-		höhe = (int)*opd->zWert( "Höhe" );
-	else
-		opd->addWert( "Höhe", "25" );
-	neuTempo = 50;
-	if( opd->wertExistiert( "+Geschwindigkeit" ) )
-		neuTempo = (int)*opd->zWert( "+Geschwindigkeit" );
-	else
-		opd->addWert( "+Geschwindigkeit", "50" );
-	geschwindigkeit = 1000;
-	if( opd->wertExistiert( "Geschwindigkeit" ) )
-		geschwindigkeit = (int)*opd->zWert( "Geschwindigkeit" );
-	else
-		opd->addWert( "Geschwindigkeit", "1000" );
-	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/Tetris/data/game.save" ) )
-	{
-		Datei *save = new Datei();
-		save->setDatei( "data/Minigames/Tetris/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 );
-			save->lese( (char*)&t, sizeof( Tile ) );
-			for( int y = 0; y < höhe; y++ )
-			{
-				map->set( new Array< int >(), y );
-				for( int x = 0; x < breite; x++ )
-				{
-					int f = 0;
-					save->lese( (char*)&f, 4 );
-					map->z( y )->set( f, x );
-				}
-			}
-			geschwindigkeit -= score * neuTempo;
-			if( geschwindigkeit < 100 )
-				geschwindigkeit = 100;
-			next = geschwindigkeit / 1000.0;
-		}
-		save->close();
-		save->release();
-	}
-	if( t.id < 0 )
-	{
-		t.id = rand() % 7;
-		t.grad = rand() % 4;
-		t.xPos = breite / 2 - 2;
-		t.yPos = 0;
-	}
-	if( !map->getEintragAnzahl() )
-	{
-		for( int i = 0; i < höhe; i++ )
-		{
-			Array< int > *line = new Array< int >();
-			for( int j = 0; j < breite; j++ )
-				line->add( 0 );
-			map->add( line );
-		}
-	}
-	if( breite < 40 || höhe < 25 )
-	{
-		int br = breite * 20;
-		if( br > 800 )
-			br = 800;
-		int hö = höhe * 20;
-		if( hö > 500 )
-			hö = 500;
-		feld->setPosition( 400 - br / 2, 250 - hö / 2 );
-		feld->setSize( br, hö );
-	}
-	beendet = 0;
+    gameTime = 0;
+    if( rGen )
+        rGen = rGen->release();
+    next = 0;
+    score = 0;
+    map->leeren();
+    t = { -1, 0, 0, 0 };
+    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 ) );
+    neuTempo = *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( fortsetzen && DateiExistiert( "data/Minigames/Tetris/data/game.save" ) && klient )
+    {
+        if( capture.istOffen() )
+            capture.close();
+        capture.setDatei( "data/Minigames/Tetris/data/game.mgc" );
+        capture.open( Datei::Style::schreiben | Datei::Style::ende | Datei::Style::lesen );
+        Datei *save = new Datei();
+        save->setDatei( "data/Minigames/Tetris/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 );
+            save->lese( (char*)&t, sizeof( Tile ) );
+            for( int y = 0; y < höhe; y++ )
+            {
+                map->set( new Array< int >(), y );
+                for( int x = 0; x < breite; x++ )
+                {
+                    int f = 0;
+                    save->lese( (char*)&f, 4 );
+                    map->z( y )->set( f, x );
+                }
+            }
+            geschwindigkeit -= score * neuTempo;
+            if( geschwindigkeit < 100 )
+                geschwindigkeit = 100;
+            next = geschwindigkeit / 1000.0;
+        }
+        save->close();
+        save->release();
+    }
+    else
+    {
+        rGen = new RandomGenerator();
+        if( klient )
+        {
+            if( capture.istOffen() )
+                capture.close();
+            DateiRemove( "data/Minigames/Tetris/data/game.mgc" );
+            capture.setDatei( "data/Minigames/Tetris/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();
+        }
+    }
+    if( t.id < 0 )
+    {
+        t.id = (int)( rGen->rand() * 7 );
+        t.grad = (int)( rGen->rand() * 4 );
+        t.xPos = breite / 2 - 2;
+        t.yPos = 0;
+    }
+    if( !map->getEintragAnzahl() )
+    {
+        for( int i = 0; i < höhe; i++ )
+        {
+            Array< int > *line = new Array< int >();
+            for( int j = 0; j < breite; j++ )
+                line->add( 0 );
+            map->add( line );
+        }
+    }
+    if( breite < 40 || höhe < 25 )
+    {
+        int br = breite * 20;
+        if( br > 800 )
+            br = 800;
+        int hö = höhe * 20;
+        if( hö > 500 )
+            hö = 500;
+        feld->setPosition( 400 - br / 2, 250 - hö / 2 );
+        feld->setSize( br, hö );
+    }
+    beendet = 0;
 }
 
 void Map::doMausEreignis( MausEreignis &me )
@@ -136,223 +162,275 @@ void Map::doMausEreignis( MausEreignis &me )
 
 void Map::doTastaturEreignis( TastaturEreignis &te )
 {
-	if( beendet )
-		return;
-	if( te.id == TE_Press )
-	{
-		int g = t.grad;
-		int xPos = t.xPos;
-		int yPos = t.yPos;
-		if( te.taste == T_Oben )
-		{
-			g++;
-			if( g >= 4 )
-				g = 0;
-		}
-		if( te.taste == T_Links )
-			xPos--;
-		if( te.taste == T_Rechts )
-			xPos++;
-		if( te.taste == T_Unten )
-			yPos++;
-		bool ok = 1;
-		for( int x = xPos; x < xPos + 4; x++ )
-		{
-			for( int y = yPos; y < yPos + 4; y++ )
-			{
-				if( tiles[ t.id ][ g ][ y - yPos ][ x - xPos ] )
-				{
-					ok &= x >= 0 && x < breite && y >= 0 && y < höhe;
-					ok &= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) == 0;
-				}
-			}
-		}
-		if( ok )
-		{
-			t.grad = g;
-			t.xPos = xPos;
-			t.yPos = yPos;
-			rend = 1;
-		}
-	}
+    if( beendet )
+        return;
+    cs.lock();
+    bool ok = 1;
+    if( !beendet && te.id == TE_Press )
+    {
+        int g = t.grad;
+        int xPos = t.xPos;
+        int yPos = t.yPos;
+        bool save = 0;
+        if( te.taste == 'w' || te.taste == 'W' || te.taste == T_Oben )
+        {
+            g++;
+            if( g >= 4 )
+                g = 0;
+            save = 1;
+        }
+        if( te.taste == 'd' || te.taste == 'D' || te.taste == T_Rechts )
+        {
+            xPos++;
+            save = 1;
+        }
+        if( te.taste == 'a' || te.taste == 'A' || te.taste == T_Links )
+        {
+            xPos--;
+            save = 1;
+        }
+        if( te.taste == 's' || te.taste == 'S' || te.taste == T_Unten )
+        {
+            yPos++;
+            save = 1;
+        }
+        if( save && klient )
+        {
+            capture.schreibe( (char*)&gameTime, 8 );
+            capture.schreibe( (char*)&te.taste, 1 );
+        }
+        bool ok = 1;
+        for( int x = xPos; x < xPos + 4; x++ )
+        {
+            for( int y = yPos; y < yPos + 4; y++ )
+            {
+                if( tiles[ t.id ][ g ][ y - yPos ][ x - xPos ] )
+                {
+                    ok &= x >= 0 && x < breite && y >= 0 && y < höhe;
+                    ok &= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) == 0;
+                }
+            }
+        }
+        if( ok )
+        {
+            t.grad = g;
+            t.xPos = xPos;
+            t.yPos = yPos;
+            rend = 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;
-		bool ok = 1;
-		for( int x = t.xPos; x < t.xPos + 4; x++ )
-		{
-			for( int y = t.yPos + 1; y < t.yPos + 5; y++ )
-			{
-				if( tiles[ t.id ][ t.grad ][ y - t.yPos - 1 ][ x - t.xPos ] )
-				{
-					ok &= x >= 0 && x < breite && y >= 0 && y < höhe;
-					ok &= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) == 0;
-				}
-			}
-		}
-		if( ok )
-			t.yPos++;
-		else
-		{
-			for( int x = t.xPos; x < t.xPos + 4; x++ )
-			{
-				for( int y = t.yPos; y < t.yPos + 4; y++ )
-				{
-					if( tiles[ t.id ][ t.grad ][ y - t.yPos ][ x - t.xPos ] )
-						map->z( y )->set( tileFarbe[ t.id ], x );
-				}
-			}
-			for( int y = 0; y < höhe; y++ )
-			{
-				bool rm = 1;
-				for( int x = 0; x < breite; x++ )
-					rm &= map->z( y )->get( x ) != 0;
-				if( rm )
-				{
-					Array< int > *line = new Array< int >();
-					for( int i = 0; i < breite; i++ )
-						line->add( 0 );
-					map->remove( y );
-					map->add( line, 0 );
-					score++;
-					geschwindigkeit -= neuTempo;
-				}
-			}
-			t.id = rand() % 7;
-			t.grad = rand() % 4;
-			t.xPos = breite / 2 - 2;
-			t.yPos = 0;
-			for( int x = t.xPos; x < t.xPos + 4; x++ )
-			{
-				for( int y = t.yPos; y < t.yPos + 4; y++ )
-				{
-					if( tiles[ t.id ][ t.grad ][ y - t.yPos ][ x - t.xPos ] )
-						beendet |= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) != 0;
-				}
-			}
-			if( beendet )
-			{
+    bool ret = rend;
+    rend = 0;
+    if( beendet )
+        return ret;
+    cs.lock();
+    gameTime += tickVal;
+    next -= tickVal;
+    if( next < 0 )
+    {
+        next = geschwindigkeit / 1000.0;
+        bool ok = 1;
+        for( int x = t.xPos; x < t.xPos + 4; x++ )
+        {
+            for( int y = t.yPos + 1; y < t.yPos + 5; y++ )
+            {
+                if( tiles[ t.id ][ t.grad ][ y - t.yPos - 1 ][ x - t.xPos ] )
+                {
+                    ok &= x >= 0 && x < breite && y >= 0 && y < höhe;
+                    ok &= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) == 0;
+                }
+            }
+        }
+        if( ok )
+            t.yPos++;
+        else
+        {
+            for( int x = t.xPos; x < t.xPos + 4; x++ )
+            {
+                for( int y = t.yPos; y < t.yPos + 4; y++ )
+                {
+                    if( tiles[ t.id ][ t.grad ][ y - t.yPos ][ x - t.xPos ] )
+                        map->z( y )->set( tileFarbe[ t.id ], x );
+                }
+            }
+            for( int y = 0; y < höhe; y++ )
+            {
+                bool rm = 1;
+                for( int x = 0; x < breite; x++ )
+                    rm &= map->z( y )->get( x ) != 0;
+                if( rm )
+                {
+                    Array< int > *line = new Array< int >();
+                    for( int i = 0; i < breite; i++ )
+                        line->add( 0 );
+                    map->remove( y );
+                    map->add( line, 0 );
+                    score++;
+                    geschwindigkeit -= neuTempo;
+                }
+            }
+            t.id = (int)( rGen->rand() * 7 );
+            t.grad = (int)( rGen->rand() * 4 );
+            t.xPos = breite / 2 - 2;
+            t.yPos = 0;
+            for( int x = t.xPos; x < t.xPos + 4; x++ )
+            {
+                for( int y = t.yPos; y < t.yPos + 4; y++ )
+                {
+                    if( tiles[ t.id ][ t.grad ][ y - t.yPos ][ x - t.xPos ] )
+                        beendet |= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) != 0;
+                }
+            }
+            if( beendet && klient )
+            {
+                capture.close();
+                DateiRemove( "data/Minigames/Tetris/data/upload.mgc" );
+                DateiUmbenennen( "data/Minigames/Tetris/data/game.mgc", "data/Minigames/Tetris/data/upload.mgc" );
+                int tmpScore = score;
+                MinigameKlientV *tmpKlient = klient->getThis();
+                new AsynchronCall( [ tmpScore, tmpKlient ]()
+                {
+                    InitDatei *opd = new InitDatei( "data/Minigames/Tetris/data/optionen.ini" );
+                    opd->laden();
+                    Text optionen = "Width=";
+                    optionen += opd->zWert( "Breite" )->getText();
+                    optionen += ",Height=";
+                    optionen += opd->zWert( "Höhe" )->getText();
+                    optionen += ",NSpeed=";
+                    optionen += opd->zWert( "+Geschwindigkeit" )->getText();
+                    optionen += ",Speed=";
+                    optionen += opd->zWert( "Geschwindigkeit" )->getText();
+                    opd->release();
+                    int status = tmpKlient->reportEndOfGame( "Tetris", optionen, tmpScore );
+                    if( status == 2 )
+                    {
+                        Datei d;
+                        d.setDatei( "data/Minigames/Tetris/data/upload.mgc" );
+                        tmpKlient->uploadGameCapture( &d );
+                    }
+                    DateiRemove( "data/Minigames/Tetris/data/upload.mgc" );
+                    tmpKlient->release();
+                } );
                 DateiRemove( "data/Minigames/Tetris/data/game.save" );
-				KSGTDatei *stb = new KSGTDatei( "data/Minigames/Tetris/data/score.ksgt" );
-				if( !stb->laden() )
-					DateiPfadErstellen( "data/Minigames/Tetris/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 *neuTempoT = new Text();
-				neuTempoT->append( neuTempo );
-				zeile->add( neuTempoT );
-				stb->addZeile( 6, zeile );
-				zeile->release();
-				stb->speichern();
-				stb->release();
-			}
-		}
-		ret = 1;
-	}
-	return ret;
+                KSGTDatei *stb = new KSGTDatei( "data/Minigames/Tetris/data/score.ksgt" );
+                if( !stb->laden() )
+                    DateiPfadErstellen( "data/Minigames/Tetris/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 *neuTempoT = new Text();
+                neuTempoT->append( neuTempo );
+                zeile->add( neuTempoT );
+                stb->addZeile( 6, zeile );
+                zeile->release();
+                stb->speichern();
+                stb->release();
+            }
+        }
+        ret = 1;
+    }
+    cs.unlock();
+    return ret;
 }
 
 void Map::render( Bild &zRObj )
 {
-	int xS = feld->getX();
-	int yS = feld->getY();
-	int blockBr = 800 / breite;
-	if( blockBr > 20 )
-		blockBr = 20;
-	int blockHö = 500 / höhe;
-	if( blockHö > 20 )
-		blockHö = 20;
-	for( int x = 0; x < breite; x++ )
-	{
-		for( int y = 0; y < höhe; y++ )
-			zRObj.fillRegion( xS + x * blockBr, yS + y * blockHö, blockBr - 1, blockHö - 1, map->z( y )->get( x ) );
-	}
-	for( int x = 0; x < 4; x++ )
-	{
-		for( int y = 0; y < 4; y++ )
-		{
-			if( tiles[ t.id ][ t.grad ][ y ][ x ] )
-				zRObj.fillRegion( xS + ( x + t.xPos ) * blockBr, yS + ( y + t.yPos ) * blockHö, blockBr - 1, blockHö - 1, tileFarbe[ t.id ] );
-		}
-	}
-	feld->render( zRObj );
+    int xS = feld->getX();
+    int yS = feld->getY();
+    int blockBr = 800 / breite;
+    if( blockBr > 20 )
+        blockBr = 20;
+    int blockHö = 500 / höhe;
+    if( blockHö > 20 )
+        blockHö = 20;
+    for( int x = 0; x < breite; x++ )
+    {
+        for( int y = 0; y < höhe; y++ )
+            zRObj.fillRegion( xS + x * blockBr, yS + y * blockHö, blockBr - 1, blockHö - 1, map->z( y )->get( x ) );
+    }
+    for( int x = 0; x < 4; x++ )
+    {
+        for( int y = 0; y < 4; y++ )
+        {
+            if( tiles[ t.id ][ t.grad ][ y ][ x ] )
+                zRObj.fillRegion( xS + ( x + t.xPos ) * blockBr, yS + ( y + t.yPos ) * blockHö, blockBr - 1, blockHö - 1, tileFarbe[ t.id ] );
+        }
+    }
+    feld->render( zRObj );
 }
 
-// constant
-void Map::speichern() const
+void Map::speichern()
 {
-	if( !beendet )
-	{
-		Datei *d = new Datei();
-		d->setDatei( "data/Minigames/Tetris/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 );
-		d->schreibe( (char*)&t, sizeof( Tile ) );
-		for( int y = 0; y < höhe; y++ )
-		{
-			for( int x = 0; x < breite; x++ )
-			{
-				int f = map->z( y )->get( x );
-				d->schreibe( (char*)&f, 4 );
-			}
-		}
-		d->close();
-		d->release();
-	}
-	else
-		DateiRemove( "data/Minigames/Tetris/data/game.save" );
+    if( !beendet )
+    {
+        if( capture.istOffen() )
+            capture.close();
+        Datei *d = new Datei();
+        d->setDatei( "data/Minigames/Tetris/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 );
+        d->schreibe( (char*)&t, sizeof( Tile ) );
+        for( int y = 0; y < höhe; y++ )
+        {
+            for( int x = 0; x < breite; x++ )
+            {
+                int f = map->z( y )->get( x );
+                d->schreibe( (char*)&f, 4 );
+            }
+        }
+        d->close();
+        d->release();
+    }
+    else if( klient )
+        DateiRemove( "data/Minigames/Tetris/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 - 3
Tetris/Map.h

@@ -2,6 +2,8 @@
 #define Map_H
 
 #include <Bild.h>
+#include <Random.h>
+#include "../../../Include/KSGKlientV.h"
 
 using namespace Framework;
 
@@ -28,21 +30,26 @@ private:
 	bool beendet;
 	bool sr;
 	bool rend;
+    double gameTime;
+    Datei capture;
+    Critical cs;
+    MinigameKlientV *klient;
+    RandomGenerator *rGen;
 	int ref;
 
 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

+ 312 - 14
Tetris/Menü.cpp

@@ -10,6 +10,8 @@
 #include <Schrift.h>
 #include <DateiSystem.h>
 #include <Rahmen.h>
+#include <AsynchronCall.h>
+#include <Bildschirm.h>
 
 // Inhalt der MenüVerloren Klasse aus Menü.h
 // Kontruktor
@@ -83,13 +85,14 @@ 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 );
 	beendet = 0;
+    timePuffer = 0;
 	ref = 1;
 }
 
@@ -105,7 +108,53 @@ Men
 // nicht constant
 void MenüSpiel::reset()
 {
-	map->reset();
+    InitDatei *opd = new InitDatei( "data/Minigames/tetris/data/optionen.ini" );
+    if( !opd->laden() )
+        DateiPfadErstellen( "data/Minigames/Tetris/data/optionen.ini" );
+    Text optionen = "Width=";
+    if( opd->wertExistiert( "Breite" ) )
+        optionen += (int)*opd->zWert( "Breite" );
+    else
+    {
+        opd->addWert( "Breite", "15" );
+        optionen += 15;
+    }
+    optionen += ",Height=";
+    if( opd->wertExistiert( "Höhe" ) )
+        optionen += (int)*opd->zWert( "Höhe" );
+    else
+    {
+        opd->addWert( "Höhe", "25" );
+        optionen += 25;
+    }
+    optionen += ",NSpeed=";
+    if( opd->wertExistiert( "+Geschwindigkeit" ) )
+        optionen += (int)*opd->zWert( "+Geschwindigkeit" );
+    else
+    {
+        opd->addWert( "+Geschwindigkeit", "50" );
+        optionen += 50;
+    }
+    optionen += ",Speed=";
+    if( opd->wertExistiert( "Geschwindigkeit" ) )
+        optionen += (int)*opd->zWert( "Geschwindigkeit" );
+    else
+    {
+        opd->addWert( "Geschwindigkeit", "1000" );
+        optionen += 1000;
+    }
+    optionen += ",Fortsetzen=";
+    if( opd->wertExistiert( "Fortsetzen" ) )
+        optionen += (int)*opd->zWert( "Fortsetzen" ) != 0;
+    else
+    {
+        opd->addWert( "Fortsetzen", "0" );
+        optionen += 0;
+    }
+    opd->speichern();
+    opd->release();
+    optionen += ",Seed=0";
+	map->reset( &optionen );
 	beendet = 0;
 	scoreT->setText( "Score: " );
 	scoreT->zText()->append( map->getScore() );
@@ -146,8 +195,13 @@ void Men
 
 bool MenüSpiel::tick( double tickVal )
 {
+    timePuffer += tickVal;
 	bool ret = beenden->tick( tickVal );
-	ret |= map->tick( tickVal );
+    while( timePuffer >= 0.01 )
+    {
+        ret |= map->tick( 0.01 );
+        timePuffer -= 0.01;
+    }
 	scoreT->setText( "Score: " );
 	scoreT->zText()->append( map->getScore() );
 	if( map->istBeendet() )
@@ -186,17 +240,132 @@ 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 taste;
+        datei->lese( &taste, 1 );
+        if( datei->istEnde() )
+            nextTime = -1;
+        else
+            datei->lese( (char*)&nextTime, 8 );
+        TastaturEreignis te;
+        te.verarbeitet = 0;
+        te.taste = taste;
+        te.id = TE_Press;
+        map->doTastaturEreignis( te );
+    }
+    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;
+    screen = zScreen->getThis();
 	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 }, { "Höhe", 70, 0, 0 }, { "+Tempo", 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 }, { "Höhe", 70, 0, 0 }, { "+Tempo", 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 },{ "Höhe", 70, 0, 0 },{ "+Tempo", 60, 0, 0 },{ "Tempo", 65, 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 }, { "Höhe", 70, 0, 0 }, { "+Tempo", 60, 0, 0 }, { "Tempo", 65, 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 }, { "Höhe", 70, 0, 0 }, { "+Tempo", 60, 0, 0 }, { "Tempo", 65, 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();
@@ -214,6 +383,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,11 +410,17 @@ Men
 	removen->release();
 	zurück->release();
 	schrift->release();
+    klient->release();
+    if( wiederH )
+        wiederH->release();
+    screen->release();
 }
 
 // nicht constant
 void MenüStatistik::reset()
 {
+    if( wiederH )
+        wiederH = wiederH->release();
 	int anz = gesammtT->getZeilenAnzahl();
 	for( int i = 1; i < anz; i++ )
 	{
@@ -239,6 +431,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( "Tetris", &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 *nTempo = optionen.getTeilText( optionen.positionVon( '=', 2 ) + 1, optionen.positionVon( ',', 2 ) );
+            Text *tempo = 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 *nTempoT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, nTempo->getText() );
+            nTempo->release();
+            TextFeld *tempoT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, tempo->getText() );
+            tempo->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( "Tetris", 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, nTempoT );
+            tmpWBT->setZeichnungZ( 6, i + 1, tempoT );
+        }
+        tmpKlient->release();
+        tmpWBT->release();
+        tmpSchrift->release();
+    }, &asyncFinished );
 	InitDatei *opd = new InitDatei( "data/Minigames/Tetris/data/optionen.ini" );
 	opd->laden();
 	if( !opd->wertExistiert( "Breite" ) )
@@ -366,8 +629,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 +678,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 +693,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 +739,12 @@ bool Men
 	return beendet;
 }
 
+bool MenüStatistik::istWiederhohlung() const
+{
+    return wiederH != 0;
+}
+
+
 // Reference Counting
 MenüStatistik *MenüStatistik::getThis()
 {
@@ -656,14 +954,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 +1090,7 @@ bool Men
 
 void Menü::render( Bild &zRObj )
 {
-	if( status != 3 && hintergrund )
+	if( status != 3 && hintergrund && ( status != 2 || !statistikF->istWiederhohlung() ) )
 		zRObj.drawBild( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), *hintergrund );
 	switch( status )
 	{
@@ -814,7 +1112,7 @@ void Men
 		optionenF->render( zRObj );
 		break;
 	case 2:
-		if( hintergrund )
+		if( hintergrund && !statistikF->istWiederhohlung() )
 		   zRObj.alphaRegion( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), 0xD0000000 );
 		statistikF->render( zRObj );
 		break;

+ 40 - 3
Tetris/Menü.h

@@ -39,12 +39,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 +61,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 +99,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 +124,7 @@ public:
 	void render( Bild &zRObj );
 	// constant
 	bool istBeendet() const;
+    bool istWiederhohlung() const;
 	// Reference Counting
 	MenüStatistik *getThis();
 	MenüStatistik *release();
@@ -146,7 +183,7 @@ private:
 
 public:
 	// Konstruktor
-	Menü( Schrift *zSchrift, Bildschirm *zScreen );
+	Menü( Schrift *zSchrift, Bildschirm *zScreen, MinigameKlientV *klient );
 	// Destruktor
 	~Menü();
 	// nicht constant#