Autore Topic: OutOfMemory con GameLoop e uso delle Sprite  (Letto 499 volte)

Offline gorgo

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy s2
  • Sistema operativo:
    Win7 / Linux Mint 14
OutOfMemory con GameLoop e uso delle Sprite
« il: 26 Marzo 2013, 22:11:07 CET »
0
Ciao a tutti :)
Ho da poco cominciato a smanettare con Android e come progetto per l'uni, ho deciso di realizzare un piccolo gioco.
Per chi lo conosce è "I duelli a insulti" di Monkey Island 1.

Innanzitutto ho alcuni dubbi sulla logica del GameLoop in sè.
Ho letto parecchie guide a riguardo (tipo questo: http://www.koonsolo.com/news/dewitters-gameloop/), ma una cosa forse basilare mi sfugge:

Codice (Java): [Seleziona]
public class MainThread extends Thread {

private static final String TAG = MainThread.class.getSimpleName();

// desired fps
private final static int    MAX_FPS = 50;  
// maximum number of frames to be skipped
private final static int    MAX_FRAME_SKIPS = 5;    
// the frame period
private final static int    FRAME_PERIOD = 1000 / MAX_FPS;  


// Surface holder that can access the physical surface
private SurfaceHolder surfaceHolder;
// The actual view that handles inputs
// and draws to the surface
private MainGamePanel gamePanel;    

// flag to hold game state
private boolean running;
public void setRunning(boolean running) {
    this.running = running;
}

public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
    super();
    this.surfaceHolder = surfaceHolder;
    this.gamePanel = gamePanel;
}

@Override
public void run() {
    Canvas canvas;
    Log.d(TAG, "Starting game loop");
    // initialise timing elements for stat gathering
    initTimingElements();

    long beginTime;     // the time when the cycle begun
    long timeDiff;      // the time it took for the cycle to execute
    int sleepTime;      // ms to sleep (<0 if we're behind)
    int framesSkipped;  // number of frames being skipped

    sleepTime = 0;

    while (running) {
        canvas = null;

        // try locking the canvas for exclusive pixel editing
        // in the surface
        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder) {
                beginTime = System.currentTimeMillis();
                framesSkipped = 0;  // resetting the frames skipped
                // update game state
                this.gamePanel.update();
                // render state to the screen
                // draws the canvas on the panel
                this.gamePanel.render(canvas);              
                // calculate how long did the cycle take
                timeDiff = System.currentTimeMillis() - beginTime;
                // calculate sleep time
                sleepTime = (int)(FRAME_PERIOD - timeDiff);

                if (sleepTime > 0) {
                    // if sleepTime > 0 we're OK
                    try {
                        // send the thread to sleep for a short period
                        // very useful for battery saving
                        Thread.sleep(sleepTime);    
                    } catch (InterruptedException e) {}
                }

                while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                    // we need to catch up
                    this.gamePanel.update(); // update without rendering
                    sleepTime += FRAME_PERIOD;  // add frame period to check if in next frame
                    framesSkipped++;
                }

            }
        } finally {
            // in case of an exception the surface is not left in
            // an inconsistent state
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }   // end finally
    }
}

Nel mio loop, se ho immagini che stanno ferme (lo sfondo, piuttosto che un'animazione che rimane in attesa di input), il loop continua a utilizzare cpu/memoria? Più in dettaglio, continuerò a chiamare render() anche se update() non ha cambiato nulla?

Inoltre, nella mia funzione render() sono legittimato a chiamare funzioni tipo:
Codice (Java): [Seleziona]
canvas.drawBitmap(background, null,new Rect(0, 0,canvas.getWidth(),canvas.getHeight()), paint);o
Codice (Java): [Seleziona]
Rect dest = new Rect(this.getXpos(), getYpos(), getXpos() + (rclip.right - rclip.left),
            getYpos() + (rclip.bottom - rclip.top));
canvas.drawBitmap(tileSheet, rclip, dest, null);

che contengono delle new? Parlo dell'uso di memoria..
Ci pensa il Garbage Collector ha pulire il tutto o è spreco di memoria?

Con la mia app sono al momento bloccato su un outOfMemory error, probabilmente dovuto a un cattivo uso del GameLoop o della codifica Bitmap.
Sto usando una logica MVC e nel costruttore del renderer carico le mie spritesheet per gestire Guybrush e il pirata.

Codice (Java): [Seleziona]
currentGuy = new SpriteTile(R.drawable.guybrush1, R.xml.guybrush,
                                context);
currentEnemy = new SpriteTile(R.drawable.pirata0, R.xml.pirate1,
                                context);

Il costruttore di SpriteTile si preoccupa di caricare la mia spritesheet ( 1792x1872 363KB guybrush, 2464x2688 89KB pirata), di parsare l'xml contenente le coordinate di ogni frame.
Poi ci pensa una chiamata currentGuy.draw() ha disegnare nella canvas l'animazione voluta.

Sapete già consigliarmi su dove possa essere il problema? Vi devo postare altro codice?
Spero di aver azzeccato la categoria giusta del vostro forum :)

N.b. L'errore lo sto sperimentando eseguendo direttamente l'app sul mio GalaxyS2. Tra l'altro dopo aver eseguito il tutto il cellulare mi dà problemi di memoria: se apro la galleria mi dice "Spazio insufficiente". Eliminare elementi non necessari ecc.
Ma di memoria ne ho...ho il dubbio che sia l'app di MonkeyIsland a riempire la cache..


Vi allego il LogCat

Codice: [Seleziona]
03-26 22:08:27.120: D/dalvikvm(1890): GC_FOR_ALLOC freed 59K, 14% free 9378K/10819K, paused 19ms, total 19ms
03-26 22:08:27.125: I/dalvikvm-heap(1890): Grow heap (frag case) to 13.170MB for 2949136-byte allocation
03-26 22:08:27.150: D/dalvikvm(1890): GC_CONCURRENT freed <1K, 11% free 12257K/13767K, paused 6ms+2ms, total 25ms
03-26 22:08:27.185: D/GuybrushRenderer(1890): Sfondo CARICATO
03-26 22:08:27.220: D/dalvikvm(1890): GC_FOR_ALLOC freed 1K, 11% free 12258K/13767K, paused 23ms, total 28ms
03-26 22:08:27.240: I/dalvikvm-heap(1890): Grow heap (frag case) to 25.967MB for 13418512-byte allocation
03-26 22:08:27.280: D/dalvikvm(1890): GC_CONCURRENT freed <1K, 6% free 25362K/26887K, paused 12ms+1ms, total 41ms
03-26 22:08:27.720: I/System.out(1890): Start document
03-26 22:08:27.720: I/System.out(1890): Start document
03-26 22:08:27.720: I/System.out(1890): Start tag animations
03-26 22:08:27.720: I/System.out(1890): Start tag animation
03-26 22:08:27.720: I/System.out(1890): Start tag framerect
03-26 22:08:27.720: I/System.out(1890): Start tag framerect
03-26 22:08:27.720: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.725: I/System.out(1890): Start tag animation
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.725: I/System.out(1890): Start tag animation
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.725: I/System.out(1890): Start tag animation
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.725: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.730: I/System.out(1890): Start tag animation
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.730: I/System.out(1890): Start tag animation
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.730: I/System.out(1890): Start tag animation
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.730: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.735: I/System.out(1890): Start tag animation
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.735: I/System.out(1890): Start tag animation
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.735: I/System.out(1890): Start tag animation
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag framerect
03-26 22:08:27.735: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.735: I/System.out(1890): Start tag animation
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.740: I/System.out(1890): Start tag animation
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.740: I/System.out(1890): Start tag animation
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag framerect
03-26 22:08:27.740: I/System.out(1890): Start tag collisionrect
03-26 22:08:27.740: I/System.out(1890): Sprite Loaded
03-26 22:08:27.755: D/dalvikvm(1890): GC_FOR_ALLOC freed 20K, 6% free 25373K/26887K, paused 12ms, total 12ms
03-26 22:08:27.755: I/dalvikvm-heap(1890): Forcing collection of SoftReferences for 26492944-byte allocation
03-26 22:08:27.770: D/dalvikvm(1890): GC_BEFORE_OOM freed 9K, 6% free 25363K/26887K, paused 17ms, total 18ms
03-26 22:08:27.770: E/dalvikvm-heap(1890): Out of memory on a 26492944-byte allocation.
03-26 22:08:27.770: I/dalvikvm(1890): "main" prio=5 tid=1 RUNNABLE
03-26 22:08:27.770: I/dalvikvm(1890):   | group="main" sCount=0 dsCount=0 obj=0x40fc4508 self=0x40ee0a78
03-26 22:08:27.770: I/dalvikvm(1890):   | sysTid=1890 nice=0 sched=0/0 cgrp=apps handle=1074331440
03-26 22:08:27.770: I/dalvikvm(1890):   | schedstat=( 550930779 206532425 613 ) utm=47 stm=7 core=1
03-26 22:08:27.775: I/dalvikvm(1890):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
03-26 22:08:27.775: I/dalvikvm(1890):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:625)
03-26 22:08:27.775: I/dalvikvm(1890):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:478)
03-26 22:08:27.775: I/dalvikvm(1890):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:501)
03-26 22:08:27.775: I/dalvikvm(1890):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:531)
03-26 22:08:27.780: I/dalvikvm(1890):   at com.gorgo.pirates.view.SpriteTile.loadSprite(SpriteTile.java:65)
03-26 22:08:27.780: I/dalvikvm(1890):   at com.gorgo.pirates.view.SpriteTile.<init>(SpriteTile.java:60)
03-26 22:08:27.780: I/dalvikvm(1890):   at com.gorgo.pirates.view.GuybrushRenderer.<init>(GuybrushRenderer.java:42)
03-26 22:08:27.780: I/dalvikvm(1890):   at com.gorgo.pirates.MainGamePanel.<init>(MainGamePanel.java:56)
03-26 22:08:27.780: I/dalvikvm(1890):   at com.gorgo.pirates.Pirates.onCreate(Pirates.java:21)
03-26 22:08:27.785: I/dalvikvm(1890):   at android.app.Activity.performCreate(Activity.java:5206)
03-26 22:08:27.790: I/dalvikvm(1890):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
03-26 22:08:27.790: I/dalvikvm(1890):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
03-26 22:08:27.790: I/dalvikvm(1890):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
03-26 22:08:27.790: I/dalvikvm(1890):   at android.app.ActivityThread.access$700(ActivityThread.java:140)
03-26 22:08:27.790: I/dalvikvm(1890):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
03-26 22:08:27.790: I/dalvikvm(1890):   at android.os.Handler.dispatchMessage(Handler.java:99)
03-26 22:08:27.795: I/dalvikvm(1890):   at android.os.Looper.loop(Looper.java:137)
03-26 22:08:27.795: I/dalvikvm(1890):   at android.app.ActivityThread.main(ActivityThread.java:4921)
03-26 22:08:27.795: I/dalvikvm(1890):   at java.lang.reflect.Method.invokeNative(Native Method)
03-26 22:08:27.805: I/dalvikvm(1890):   at java.lang.reflect.Method.invoke(Method.java:511)
03-26 22:08:27.810: I/dalvikvm(1890):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
03-26 22:08:27.810: I/dalvikvm(1890):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
03-26 22:08:27.810: I/dalvikvm(1890):   at dalvik.system.NativeStart.main(Native Method)
03-26 22:08:27.810: D/skia(1890): --- decoder->decode returned false
03-26 22:08:27.810: D/AndroidRuntime(1890): Shutting down VM
03-26 22:08:27.810: W/dalvikvm(1890): threadid=1: thread exiting with uncaught exception (group=0x40fc32a0)
03-26 22:08:27.810: E/AndroidRuntime(1890): FATAL EXCEPTION: main
03-26 22:08:27.810: E/AndroidRuntime(1890): java.lang.OutOfMemoryError
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:625)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:478)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:501)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:531)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.gorgo.pirates.view.SpriteTile.loadSprite(SpriteTile.java:65)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.gorgo.pirates.view.SpriteTile.<init>(SpriteTile.java:60)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.gorgo.pirates.view.GuybrushRenderer.<init>(GuybrushRenderer.java:42)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.gorgo.pirates.MainGamePanel.<init>(MainGamePanel.java:56)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.gorgo.pirates.Pirates.onCreate(Pirates.java:21)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.Activity.performCreate(Activity.java:5206)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.ActivityThread.access$700(ActivityThread.java:140)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.os.Handler.dispatchMessage(Handler.java:99)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.os.Looper.loop(Looper.java:137)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at android.app.ActivityThread.main(ActivityThread.java:4921)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at java.lang.reflect.Method.invokeNative(Native Method)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at java.lang.reflect.Method.invoke(Method.java:511)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
03-26 22:08:27.810: E/AndroidRuntime(1890):         at dalvik.system.NativeStart.main(Native Method)


L'app deve fare uso delle API 10 di Android.
« Ultima modifica: 26 Marzo 2013, 22:21:43 CET da gorgo »

Offline gorgo

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy s2
  • Sistema operativo:
    Win7 / Linux Mint 14
Re:OutOfMemory con GameLoop e uso delle Sprite
« Risposta #1 il: 03 Aprile 2013, 19:24:32 CEST »
0
Mi "risolvo" da solo.

Il problema sta nella decompressione del png della spritesheet.
Utilizzare sprite più grandi di 1024x1024 (circa), come le mie ( 1792x1872 363KB guybrush, 2464x2688 89KB pirata), portano al facile esaurimento dei 16MB di Heap (circa) a disposizione.
Quindi il consiglio è di ridurre la dimensione o di dividere la sprite in più sotto-sprite, magari caricandole solo nel livello necessario (se stiamo svolgendo un gioco a livelli).