2012-04-22 26 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