0

最近我一直在努力做一個西蒙說android的遊戲,並越來越難以預料。西蒙說android的遊戲

現在遊戲快完成了,引擎工作正常,遊戲邏輯運行良好,等等......問題出現在序列必須顯示在顯示器上,以便玩家可以複製它。

聲音工作正常,但是當序列必須完成時纔會繪製直到方法結束。

它說,每個動作之間的暫停必須做,這個緣故,我已經嘗試了很多的東西同樣的結果在他們每個人是很重要的:

  • 了Thread.sleep(.. );
  • SystemClock.sleep(...);
  • AsyncTask只是做一些睡眠,然後上升一個標誌...
  • View.invalidate();
  • View.postInvalidate();

等等......

最好的結果與SystemClock.sleep(...)的屏幕變得不顯示任何東西,但一切工作得很好。

同樣重要的是要解釋我沒有使用drawables或xml文件來繪製按鈕,而不是我在畫布上繪製具有路徑和繪圖的形狀,而所有這些都在SurfaceView內部。

我在這裏把我認爲不能正常工作的方法,在項目中有更多的代碼,但它似乎是工作,而不是搞亂任何東西。

這是surfaceView類爲我們所做的事情中最重要的方法:

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { 

//Elementos del thread 
public MySurfaceThread thread; 
public boolean touched; 
public boolean reproduciendo; 
public boolean juega; 
public boolean despierta; 
public boolean llamaPausa; 


//Colores 
public int mediumOrchid = 0xBA55D3; 
public int crimson = 0xDC143C; 
public int gold = 0xFFD700; 
public int cornFlowerBlue = 0x6495ED; 
public int limeGreen = 0x32CD32; 

public int darkOrchid = 0x9932CC; 
public int fireBrick = 0xB22222; 
public int goldenRod = 0xDAA520; 
public int midNightBlue = 0x191970; 
public int mediumSeaGreen = 0x3CB371; 

public int[]colores = {mediumOrchid, crimson, gold, cornFlowerBlue, limeGreen}; 
public int[]tocados = {darkOrchid, fireBrick, goldenRod, midNightBlue, mediumSeaGreen}; 


//Coordenadas de pulsación 
PointF click; 

public int indice = 0; 
public int repId; 


private int correctas; 
private Vector<Integer> secuencia = new Vector<Integer>(); 
private Random aleatorio; 


//Sonido 
SoundPool mp; 
int idBell1; 
int idBell2; 
int idBell3; 
int idBell4; 


Activity padre; 


public MySurfaceView(Context context, SoundPool mpObj, Random rnd) { 
    super(context); 
    getHolder().addCallback(this); 
    aleatorio = rnd; 

    //Soundloop 
    mp = mpObj; 
    idBell1 = mp.load(context, R.raw.sy01, 1); 
    idBell2 = mp.load(context, R.raw.sy02, 1); 
    idBell3 = mp.load(context, R.raw.sy04, 1); 
    idBell4 = mp.load(context, R.raw.sy06, 1); 


} 



@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    thread = new MySurfaceThread(getHolder(), this); 
    thread.setRun(true); 
    thread.start(); 
    Log.e("surfaceCreated", "Creado"); 






} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 

    boolean retry = true; 
    //Detenemos el hilo 
    thread.setRun(false); 
    while (retry){ 
     try{ 
      thread.join(); 
      retry = false; 
     } 
     catch (InterruptedException e){} 
    } 

} 


@Override 
public void onDraw(Canvas canvas){ 
    if(reproduciendo){Log.e("onDraw", "Entro a onDraw desde repsec");} 
    //Fondo negro 
    canvas.drawColor(Color.BLACK); 

    //Creamos el pinceles 
    Paint pincel = new Paint(); 
    pincel.setAntiAlias(true); 
    pincel.setStyle(Paint.Style.FILL); 

    if (touched){//Activates when user is touching the screen 
     int id = quePieza(click, canvas); 
     //Log.e("onDraw", touched + " " + id); 
     if(id != -1) colores[id] = tocados[id]; 
    } 

    if(reproduciendo){//Activates when sequence must be shown, just changes colours in the color array conveniently 
     Log.e("onDraw", "repId = " + repId); 
     if(repId != -1){colores[repId] = tocados[repId];} 
     repId = -1; 
     correctas++; 
     Log.e("onDraw", "Correctas = " + correctas); 
    } 
    //Pintamos las piezas 
    for(int i = 0; i < colores.length; i++){ 
     pincel.setColor(Color.rgb(Color.red(colores[i]), Color.green(colores[i]), Color.blue(colores[i]))); 
     pintarPiezas(i, canvas, pincel);//Paint each button according to an int code (0 to 4) 
    } 

    //Pintamos el texto 
    pincel.setColor(Color.WHITE); 
    dibujarTexto(canvas, pincel); 

    //Reestablecemos colores originales 
    resetColor(); 
    //Log.e("onDraw", "He terminado de pintar"); 



} 

這一個是負責出顯示器序列的方法:

public void reproducirSecuencia(final Canvas canvas){ 
    reproduciendo = true; 
    //TODO: HACER QUE ESTO FUNCIONE!! 
    Log.e("reproducirSecuencia", "Entro a reproducir"); 

    int i = 0; 

    while(i < secuencia.size()){ 

     Object o = secuencia.elementAt(i); 
     int num = 0; 
     if (o instanceof Integer) {num = (Integer) o;} 


     SystemClock.sleep(1000); 
      i++; 
      reproducirSonido(num); 
      repId = num; 
      onDraw(canvas); 
      i++; 



     //Log.e("reproducirSecuencia", "repId = " + repId); 
     //Log.e("reproducirSecuencia", "Invoco a pintarPiezas"); 





     //SystemClock.sleep(1000); 
     //try {Thread.sleep(1000);} 
     //catch (InterruptedException e) {e.printStackTrace();} 
    } 

    reproduciendo = false; 
} 

而且最後這是在遊戲中玩的主要方法Thread:

public void Play(Canvas canvas){ 


    /*if(juega){ 
     int piezaTocada = quePieza(click, canvas); 
     reproducirSonido(piezaTocada); 
     juega = false; 
    } 
    onDraw(canvas);*/ 

    onDraw(canvas); 

    if (secuencia.isEmpty()){//Creamos el primer movimiento 
     crearMovimiento(); 
     reproducirSecuencia(canvas); 
    } 
    else{//Sigue el juego 
     if(juega){//Esperamos a que haya una jugada 
      int piezaTocada = quePieza(click, canvas);//Method to find which button was pressed 
      //¿Coincide con lo que buscamos? 
      if(piezaTocada != 0){//Que no se cuente el botón central en el modo classic 
       reproducirSonido(piezaTocada); 
       if(esCorrecto(piezaTocada, secuencia.elementAt(indice), canvas)){//Check if user's move was correct or not 
        //Aumentamos el indice 
        indice++; 
        juega = false;//Acabamos con la jugada 
        if(indice > secuencia.size() - 1){//Hemos hecho toda la secuencia, ponemos un nuevo elemento y reiniciamos 
         //SystemClock.sleep(3000); 

         indice = 0; 
         crearMovimiento(); 

         int buc = 0; 
         reproducirSecuencia(canvas); 
        } 

       } 
       else{//No es correcto... 
        gameOver(canvas); 
       } 
      } 
     } 
    } 
} 

I 「M也將在我的Thread類,因爲它似乎在播放序列中被阻塞:

public class MySurfaceThread extends Thread { 

private SurfaceHolder surface; 
private MySurfaceView view; 
private boolean run; 
public boolean pausa; 


//Metodo constructor 
public MySurfaceThread(SurfaceHolder sh, MySurfaceView v){ 
    this.surface = sh; 
    this.view = v; 
} 



public synchronized void pausar() { 
    pausa = true; 
} 

public synchronized void reanudar() { 
    pausa = false; 
    notify(); 
} 

public synchronized void detener() { 
    run = false; 
    if (pausa) reanudar(); 
} 


public void setRun(boolean r){ 
    this.run = r; 
} 



public void run(){ 





    //... 
    //Creamos un canvas 
    Canvas canvas; 
    //Mientras run sea true pintamos 
    while (run){ 


     canvas = null; 
     try { 

      canvas = surface.lockCanvas(null); 
      //Usamos syncro 
      synchronized (surface){ 

       if(canvas != null){//Si el canvas existe pintamos 
        view.Play(canvas); 

       } 
       while (pausa) { 
        try { 
         wait(); 
        } 
        catch (Exception e) { 
        } 
       } 
      } 
     } 
     finally { 
      if (canvas != null){ 
       //Liberamos el canvas y el soundPool 
       surface.unlockCanvasAndPost(canvas); 
      } 
     } 


    } 

} 

}

就是這樣,我會apreciate答案儘可能明確,因爲這是我的第一個應用程序並且我有一年的編碼和幾個月嘗試使用android。

非常感謝!

Luis。

回答

1

否否否。不要睡在你的主線程中,它會阻止你的用戶界面 - 這正是你正在經歷的。你應該播放一個聲音,然後設置一個計時器。一旦定時器到期,播放下一個聲音,設置另一個定時器等。

一個簡單的方法來設置一個計時器是使用Handler.sendMessageAtTime

+0

你能解釋一下更詳細的你怎麼建議設置定時器? – Luis