2012-04-22 50 views
4

發現,開始一個新的意圖可能不通知GAMEOVER的用戶以正確的方式後,我現在runOnUiThread,Runnable接口和對話框struggeling ..顯示對話框中的遊戲用帆布

問:如何以及在哪裏我會實現一個Dialog.show()來通知用戶遊戲已結束?在我的日誌中,它一切正常(所以我設法讓消息遊戲結束,當它應該)。在某個時候,布爾GameManger.LevelEnded切換爲true。當發生這種情況時,我想顯示對話框。

我嘗試過使用runOnUiThread,Runnable和Async線程。無法弄清楚。

我有一個遊戲。活動AppelzActivity:

public class AppelzActivity extends Activity { 
    /** Called when the activity is first created. */ 

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

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(null); 

     // requesting to turn the title OFF 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     // making it full screen 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     // set our MainGamePanel as the View 
     setContentView(new MainGamePanel(this)); 
     Log.d(TAG, "View added"); 
    } 
} 

我MainGamePanel類:

public class MainGamePanel extends SurfaceView implements 
SurfaceHolder.Callback { 

// DECLARING VARS (REMOVED FOR READABILITY) 

    public MainGamePanel(Context context) { 
     super(context); 
     getHolder().addCallback(this); 
     Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) 
     .getDefaultDisplay(); 
     GameManager.panel = this; 

     width = display.getWidth(); 
     height = display.getHeight(); 
     RectScreen.set(0,0,width,height); 

     // CREATING CONTROLS, MISSION AND VISIBLE OBJECTS (REMOVED FOR READABILITY) 

     thread = new MainThread(getHolder(), this); 
     setFocusable(true); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     thread.setRunning(true); 
    } 

     // HANDELING ON TOUCH EVENTS AND SUCH (REMOVED FOR READABILITY) 


    @Override 
    protected void onDraw(Canvas canvas) { 
     // fills the canvas with black 
     canvas.drawColor(Color.BLACK); 
     backGnd.draw(canvas); 

     basket.draw(canvas); 
     for (int i = 0; i < AppleList.size();i++){ 
      AppleList.get(i).draw(canvas); 
     } 
     btnMoreFruit.draw(canvas); 
     btnLessFruit.draw(canvas); 

     if (GameManager.count){ 

      glyphsCount.drawString(MainThread.canvas, Integer.toString(GameManager.i), (width/2-120), (height/2-120)); 

     } 

    } 
} 

最後,MainThread類:

public class MainThread extends Thread { 

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

    private SurfaceHolder surfaceHolder; 
    private MainGamePanel gamePanel; 
    private DialogManager dialogManager; 
    public static boolean running; 
    public static Canvas canvas; 

    public void setRunning(boolean running) { 
     MainThread.running = running; 
    } 

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

    @Override 
    public void run() { 
     // Canvas canvas; 
     Log.d(TAG, "Starting game loop"); 
     while (running) { 
      MainThread.canvas = null; 
      // try locking the canvas for exclusive pixel editing on the surface 

      try { 
       MainThread.canvas = this.surfaceHolder.lockCanvas(); 
       synchronized (surfaceHolder) { 
        // update game state 
        this.gamePanel.update(); 

        // render state to the screen 
        // draws the canvas on the panel 
        this.gamePanel.onDraw(MainThread.canvas); 

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

Basket.java - 這是在遊戲中的對象。正如你所看到的,如果它是在一定的位置上,我開始倒計時:

public class basket { 

private Bitmap bitmap; // the actual bitmap 
private int x; // the X coordinate 
private int y; // the Y coordinate' 
public static int width; 
public static int height; 
public float X = 100; 
public float Y = 100; 

private boolean touched; // if droid is touched/picked up 

public basket(Bitmap bitmap, int x, int y) { 
    this.bitmap = bitmap; 

    width = bitmap.getWidth(); 
    height = bitmap.getHeight(); 
} 

public Bitmap getBitmap() { 
    return bitmap; 
} 
public void setBitmap(Bitmap bitmap) { 
    this.bitmap = bitmap; 
} 

public int getWidth(){ 
     return bitmap.getWidth(); 
    } 

    public int getHeight(){ 
     return bitmap.getHeight(); 
    } 

public int getX() { 
    return x; 
} 



public void setX(float x) { 

    // if basket is further than slotmargin 
    if (x + width/2 > SlotManager.SlotmarginX) { 
     // if basket is NOT in CheckOut area  
     if (this.Y < MainGamePanel.height - 80 - height/2){ 
      x = SlotManager.SlotmarginX - width/2; 

     } else { 
      // if basket IS in CheckOut area 
      x = MainGamePanel.width - width/2; 

      // Start the countdown timer if not already running 
      if (!GameManager.count){ 
       GameManager.count=true; 
// --- HERE I START COUNTDOWN 
       GameManager.handler.postDelayed(GameManager.runnable, 0);        
      } 

     } 
    } else { 

     // Basket is NOT in CheckOut area; stop countdown timer 
     GameManager.count=false; 
    } 

    this.X = x; 
} 


public int getY() { 
    return y; 
} 
public void setY(int y) { 
     if (y + height/2 > MainGamePanel.height - 80){ 
      y = MainGamePanel.height - 80 - height/2; 
     } 


    this.Y = y; 
} 


public boolean isTouched() { 
    return touched; 
} 

public void setTouched(boolean touched) { 
    this.touched = touched; 
} 

public void draw(Canvas canvas) { 
     canvas.drawBitmap(bitmap, X - width/2, Y - height/2, null); 
} 

public void handleActionDown(int eventX, int eventY) { 
    if (eventX >= (X - width/ 2) && (eventX <= (X + width/2))) { 
    if (eventY >= (Y - height/ 2) && (eventY <= (Y + height/ 2))) { 
    // basket touched 
    setTouched(true); 
    } else { 
    setTouched(false); 
    } 
    } else { 
    setTouched(false); 
    } 

} 
} 

在遊戲管理倒計時:

 @Override 
     public void run() 
     { 
      if (SlotManager.alSlottedFruitList.size() > 0){ 
      //TODO Create Full screen countdown timer 
       Log.d("", "Countdown Timer in GameManager " + i); 

       i--; 
       if (count && i > -1) // stop timer when count is false 
       { 
        handler.postDelayed(runnable, 1000); 
       } else { 
        if (i == -1){ 
         Log.d("", "RoundUp the Level"); 

// --- HERE I WANT TO DO A LEVEL END AND SHOW THE DIALOG       

        } 
        // reset Countdown (if basket outside checkout) 
        i = 6; 
       } 
      } else { 
       // reset Countdown (if slot has no fruits) 
       i = 6; 
      } 
     } 
    }; 

    public static void startCountDown() { 
     handler.postDelayed(GameManager.runnable, 0); 
    } 

    public static void finishRound() { 
     listener.onRoundFinished(); 
    } 



    public static List<Integer> missionlist; 

    public static void CreateMission(){ 
     int maxtotalitems = 6; 
     missionlist = new ArrayList<Integer>(); 
     Random Rnd = new Random(); 

     for (int FruitType = 0; FruitType < FruitManager.fruitResources.size();FruitType++){ 
      for (int x = 0; x < Rnd.nextInt(maxtotalitems); x++){ 
       missionlist.add(FruitType); 
      }} 

// --- HERE I WANT TO SHOW A DIALOG CONTAINING THE MISSION 


     for (int x = 0; x < FruitManager.fruitResources.size();x++){ 
      Log.d("MISSION", "Mission for " + x + " : " + Collections.frequency(missionlist, x)); 
     } 

// Let's show the Dialog containing the mission 

    } 

    public void LevelEnd(){ 
     // First, count the Fruits in the slot 
     SlotManager.countSlotInv(); 
     List<Integer> list = new ArrayList<Integer>();  
     // Fill itemIds with the types of fruits 
     for (apple a : SlotManager.alSlottedFruitList){ 
      Integer itemId = Integer.valueOf(a.FruitType); 
      list.add(itemId); 
     } 


      for (int key = 0; key < 3 ; key++) { 
       boolean succeed = CheckMissionComplete(key, Collections.frequency(list, key)); 

       System.out.println(key + " : " + Collections.frequency(list, key)); 
        Log.d("MISSION", "Number : " + key + " : succeed = " + succeed);     
      } 
      listener.onRoundFinished(); 
    } 

    public boolean CheckMissionComplete(int key, int amount) { 

     //CheckMission 
     if (amount == Collections.frequency(missionlist, key)){ 
      return true;    
     } else { 
     return false; 
     } 
    } 

    public GameManager(GameListener listener) { 
     this.listener = listener; 
    } 





} 
+0

你可以請註明您要對話框正是 – Sameer 2012-04-27 05:29:06

+0

薩米爾一條線,我已經添加了類籃。這是遊戲中的一個對象。如果你把籃子放在特定的位置,倒計時開始。如果倒計時完成(5秒),我開始一個例程來檢查用戶對特定任務的輸入。然後,我想顯示對話框。提前致謝! – 2012-04-27 06:44:03

+0

我想你是從Thread調用帖子無效,所以你不能顯示對話框。爲了顯示對話框,基本需求是活動上下文。第二,它可以直接在線程內部顯示,以便當條件滿足時從表面視圖類中選擇活動的上下文,然後取出一個處理程序,然後顯示對話框。 – Sameer 2012-04-27 07:35:53

回答

1

只是儘量保持簡單。請在您的GameManager課中提及上下文。用它來顯示你的對話框。

public class MainGamePanel extends SurfaceView implements 
            SurfaceHolder.Callback { 

public MainGamePanel(Context context) { 
    super(context); 
    ....... 
    GameManager.panel = this; 
    GameManager.context = context; // add a reference to the context in GameManager.. 
    ........ 
    ........ 

    thread = new MainThread(getHolder(), this); 
    setFocusable(true); 
} 

在你GameManager用它打電話runOnUIThread()

Activity context; // Context of the main activity.. 
........ 
@Override 
    public void run() 
    { 
     if (SlotManager.alSlottedFruitList.size() > 0){ 
     //TODO Create Full screen countdown timer 
      Log.d("", "Countdown Timer in GameManager " + i); 

      i--; 
      if (count && i > -1) // stop timer when count is false 
      { 
       handler.postDelayed(runnable, 1000); 
      } else { 
       if (i == -1){ 
        Log.d("", "RoundUp the Level"); 

// --- HERE I WANT TO DO A LEVEL END AND SHOW THE DIALOG  

        context.runOnUIThread(new Runnable() { // Use the context here 
         @override 
         public void run() { 
          showLevelEndDialog(); 
         } 
        } 
       } 
       // reset Countdown (if basket outside checkout) 
       i = 6; 
      } 
     } else { 
      // reset Countdown (if slot has no fruits) 
      i = 6; 
     } 
    } 
}; 
+0

我得到一個錯誤:「方法runOnUIThread(新的Runnable(){})是未定義的類型上下文」 – 2012-05-04 21:36:21

+0

只需將'GameManager.context'的引用類型更改爲'Activity'而不是'Context' ... – Ronnie 2012-05-05 10:42:09

+0

「類型不匹配:無法從上下文轉換爲活動」 - 嗯..我也在想;在遊戲的不同部分,我希望控件的行爲不同。所以,不僅僅是顯示項目,還有OnTouchEvents。我可能想完全實現一個不同的解決方案? – 2012-05-05 11:27:58

6

我認爲,最簡單的方法是引入回撥機制通過聽衆。爲此,添加一個監聽器接口(例如,GameListener.java),持有對該接口實例的引用,並在類中調用其方法,在該類中出現所有遊戲邏輯(比如說Game.java)。然後,讓你的AppelzActivity實現在適當的時候調用回調這個接口,並顯示對話框:

GameListener.java

public interface GameListener { 
    /** 
    * ... 
    * NOTE: may be called on any thread 
    */ 
    public void onRoundFinished(); 
    ... 
} 

Game.java

public class Game { 
    private GameListener listener; 

    public Game(GameListener listener) { 
     this.listener = listener; 
    } 

    ... 

    //Let's say, round finishes here 
    public void finishRound() { 
     ... 

     listener.onRoundFinished(); 
    } 
} 

AppelzActivity.java

public class AppelzActivity extends Activity implements GameListener { 

    private static final int DLG_ROUND_FINISHED = 1; 

    ... 

    @Override 
    public void onRoundFinished() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       showDialog(DLG_ROUND_FINISHED); 
      } 
     }); 
    } 

    @Override 
    protected Dialog onCreateDialog(int id) { 
     Dialog dialog = null; 
     switch (id) { 
     case DLG_ROUND_FINISHED: 
      AlertDialog.Builder builder = new AlertDialog.Builder(this); 

      ... // init your dialog here 

      dialog = builder.create(); 
      break; 
     } 
     return dialog; 
    } 
} 
+0

對不起..我不知道您的意思是「在課程中調用它的方法,您的所有遊戲邏輯都顯示出來(讓我們說Game.java )」。籃子對象觸發倒計時(在GameManager中),當倒計數達到零時,則應該顯示對話框。如果我嘗試從GameManager類中調用Game.finishRound(),我仍然會得到空指針豁免。另外,我不知道如何在該課程中初始化遊戲? ..感覺這是正確的路,但不能執行。你知道關於「遊戲邏輯」的任何教程嗎?日Thnx !!! – 2012-04-27 19:17:10

+0

你認爲這是一種可行的方法嗎? http://www.benareby.com/tutorial/ch36​​ – 2012-04-27 20:36:45

+0

這裏:_basket對象觸發倒計時(在GameManager中),當倒數計數器達到零時,您需要在'GameManager'中調用'listener.onRoundFinished()'(在我的例子中,它是'Game.java')。實際上,這是一般的Java方法,而不是遊戲特定的,所以我會從一些Java教科書開始。 – 2012-04-28 07:54:26