1

I'm trying to create a turn based game using a 1v1 battle for android. My basic game loop checks if the two fighters are dead, if not then checks who is to go next. If its the player's turn then it should wait for an attack button to be clicked. If its the computer's turn, then it will execute a random attack. I'm having trouble getting the program to wait for the user input. I tried setting the button listener here but that's not doing it. [edit] The determination for which character goes is based on a recovery integer. Each attack has a recovery value (50-100) which is added to the character's recovery. The nextMove() method checks to see which is closer to 0 and subtracts the difference from both characters. This allows the game to require more strategy because you don't attack just once a turn.

What can I do to get the game to pause at that point

Here's the code

public void battle(){
    boolean playerGo;
    while(!checkDead()){
        playerGo=nextMove();  //returns true if its the players turn to go
        if(playerGo){
            //The game should wait here for the user input

            moveButton1.setOnClickListener(this);

        }
        else{
            randomMove();  //game automatically goes
        }
    }

}
willmer
  • 233
  • 1
  • 4
  • 12

2 Answers2

3

When your app starts up, there's one thread on which everything runs, including event handlers. After you do your setup and call battle(), that thread is sitting there going around and around the loop. It's so busy going around and around the loop that it doesn't notice that there's a click event waiting to be processed!

There's a few options:

  1. Restructure your code. It looks like the basic structure is that the player moves, then the game moves. You could remove this loop entirely, and instead call randomMove() after each time you handle the player's move. Handle the player's move in the OnClickListener for moveButton1. That way everything just happens on events. This would be simpler overall, and is probably the Right Thing to do.
  2. Make the smallest possible change to your code to get it working. This would probably mean pulling the contents of your while loop into a Runnable, which you schedule by calling Handler.post. The first line calls checkDead and returns if true. The last line reschedules the Runnable. In between is the body of the while loop. The effect of this is that your loop body runs, then the event handler gets a turn, then your loop body runs, then the event handler runs. This is probably a bad idea.
  3. Run battle() in another thread. This is probably a bad idea.

Why are 2. and 3. bad ideas? On a mobile device, battery life is precious, and running a check to see if you need to do something over and over again will keep the CPU busy chewing up battery life. Much better to sit there idle until you need to do something - this is what option 1 achieves.

So if 2. and 3. are bad ideas, why mention them? Welllllll, 2. I mention because it's the closest thing I've got to an answer to the question you actually asked. I mention 3. because there's a sense in which your current code is a fairly clear embodiment of the game logic. You could rework it so it runs in a separate thread, and instead of nextMove() returning true, nextMove() waits until the player makes a move (this would involve semaphores or mutexes or promises). But this would be an explicitly multi-threaded program, and as such would be difficult to write correctly. I recommend you don't attempt it at this stage in your programming career - the most likely outcome is a program that stops and waits forever, or that corrupts its data structures, in a way that is exceedingly difficult to diagnose.

Iain
  • 4,203
  • 23
  • 21
  • Iain, thanks for your informative post. I think I can possibly clarify some things that would make it easier to solve. The battle is not real time, rather I use a recovery stat to figure out who goes next. Each time an attack is made, a value (50-100) is added to a character's recovery stat. The nextMove() function looks to see who is closest to 0 and subtracts that amount from both. It allows me to have a more dynamic battle so that if you use lower recovery attacks, you can attack more often rather than A goes, then B, repeat til dead. Can I accomplish this without using up the battery – willmer Aug 09 '12 at 17:50
  • 1
    What is it that causes the next move to be made? Whenever that occurs, call the thing to decide who goes next. If it's the player's turn, just return. Otherwise, make the next random move. – Iain Aug 11 '12 at 07:40
  • You may want to disable the buttons when it's not the player's move and re-enable them once you're expecting them to pick something. That depends on how long you take and what sort of feedback you give them when the random moves are being made, though. – Iain Aug 11 '12 at 07:42
  • This is exactly what I came up with a few hours before you posted. Thanks a lot for your help. – willmer Aug 13 '12 at 00:23
1

Button.SetOnClickListener() function will be triggered, only when the user clicks on the button. As such it doesn't wait\block till the user input. This is by design in Android, that you cannot have a blocking window waiting for user input. Instead change your design to display hint saying 'now its user's move'.

  1. User does first move by clicking the button.
  2. SetOnclickListener() will be invoked. Have the user action code inside it.
  3. Towards end of SetOnclickListener() have the computer action code.

With this cycle you can have user move and computer move chained.

Rahul Sundar
  • 480
  • 8
  • 26