your turn / my turn logic

Hello everyone,

I am writing a simple abstract game in an attempt to learn java programming, and eventually Android apps. I have been a windows/C++/C# programmer for over 20 years, but I am new to java. I have a solid understanding of the language, threads, GUI, etc.

My question is, how do I implement the state machine logic for a game where there is an initial welcome screen, which switches to the game screen, and allows the user to make a move, then the computer, then the user, etc.

I’m looking for a tutorial that goes beyond “Hello World” or “How to start a background thread”. I just can’t seem to get my head around the state machine logic for a simple game like tic-tac-toe.

I’m hoping someone has a link to a tutorial for a “your turn/my turn” type of game.

Ed

What I did for my game I’m working on is I just have 2 booleans: inGame and inMainmenu, and I flip the values when I switch from menus to game, or vice-versa. In your main game loop, just put the logic for each one there (or use an interface and put the logic for each one in it’s own class)

while (running)
     while (inGame)
          //do game updates
     while (inMainMenu)
          //do menu stuff

I’m new to java too. I feel weird being the one giving advice for once x:

Don’t feel weird, it’s good advice, and appreciated.

I had considered a simple boolean flag to notify the computer player thread to actually make it’s move.
For some reason that seems “amateur” to me, and I thought there might be some other, more elegant
solution that I had never seen before. But, sometimes the simplest solution is the best.

Maybe take a look at this http://www.ludumdare.com/compo/ludum-dare-22/?action=preview&uid=398

I think all the menus are handled in the Game class, but I’m not sure. That’s notch’s “Minicraft”, and he’s one of the best java developers.

You could use a state engine, which I believe is pretty much standard for this. I don’t know how advanced your knowledge of Java is or anything, but it simplifies a lot of things and allow you to add as many different “states” as you want without having to change the main loop. It’s pretty easy, but it relies heavily on object orientation, but as you have experience with C/C++ it should be a piece of cake.

Create a small State interface:

package somewhere.meaningful;

public interface State{
    public void update();
}

Then create a class that implements this interface for each “state” in the game; main menu, playing, pause menu, options menu, ending credits, e.t.c.

package somewhere.meaningful;

public class MainMenu implements State{
    public void update(){
        //Do main menu stuff
    }
}
package somewhere.meaningful;

public class GameRunning implements State{
    public void update(){
        //Do game stuff
    }
}

E.t.c.

Your main class then looks something like this:


private State state; //Remember to set state to something in the constructor of the main class
private boolean running = true;

public void gameloop(){
    while(running){
        state.update();
    }
}

//Use this method to switch between states
public void setState(State state){
     this.state = state;
}

//Use this method to end the game
public void endGame(){
    running = false;
}

You also need to let each State keep a reference to the main class so they can actually access the setState() and endGame() functions.

adding to above post, by using State interface you can share main objects like Graphics or sometimes keyEvent.

I think I finally have my “head around it” now. That is the type of solution I was looking for.
I’ll have to add some thread sync, but I think I’m off and running again.

Thank you everyone for your quick answers.

Ed

Have fun! ;D

Should each state implement its own key listener, or is that a bad idea?

Probably not. They can, but it’s probably not the best idea.

A better idea would be to have a key listener that forwards commands to your state, and allow the state to handle it some how. This doesn’t mean the state itself has just that some member there should perform the logic.

Otherwise, you’ll have to be adding/removing listeners all of the time to make sure that each state only receives the keystrokes when they’re the active one.

My solution to listeners was to have the main class handle the actual “listening” and then sending the event to the current State.
My State interface:

public interface State {
		public void next(Graphics g);	//I'm not allowed to call it Update for some reason  :(
		public void mouseClicked(MouseEvent evt);
		public void mouseEntered(MouseEvent evt);
		public void mouseExited(MouseEvent evt);
		public void mousePressed(MouseEvent evt);
		public void mouseReleased(MouseEvent evt);
		public void mouseDragged(MouseEvent evt);
		public void mouseWheelMoved(MouseWheelEvent evt);
		public void mouseMoved(MouseEvent evt);
		public void keyPressed(KeyEvent evt);
		public void keyReleased(KeyEvent evt);
		public void keyTyped(KeyEvent evt);
		
	}

Then my main class has the listeners and simply forwards the event; my keyPressed event in the main Class:

@Override
	public void keyPressed(KeyEvent evt) {
		state.keyPressed(evt);
	}

You can set state to be any class implementing State. I am passing ‘this’ to my classes when creating them, and they set it to an internal variable of the main class called ‘me’ Then I can change state by doing a me.state = … I do not have my main class implement State, the examples probably do so to make sure you have all the procedures necessary. Or maybe there’s another reason, I dunno.


    public interface State extends KeyListener, MouseListener, MouseMotionListener{
        public void next(Graphics g);   //I'm not allowed to call it Update for some reason  :(
        //Probably because of a collision with the built in function in Swing with the same name
    }

And then just register the current state as a listener and you won’t have to pass events through to the current state in your state handling code. :wink:

Whaaat. I didn’t know interfaces can extend multiple interfaces. Life quality improved!

I was just as surprised as you were when I noticed it but it does make sense though. Name and argument collisions don’t matter because there’s no actual implementation of them, the “blueprints” just happened match up.

EDIT: Also, I’m assuming this, but it makes the most sense to me:

I have a canvas that I’m adding my listeners to. When you say register, then when we change states, we’ll have to remove the current state’s listeners from the canvas, change the state, then add the new state’s listeners to the canvas, right?

My way doesn’t change listeners. The main class handles the listening and forwards the events to the current state. I just thought it was easier this way.

@Gingerious and Gbeebe:
Yeah, the idea is to do something like this:


public void changeState(State newState){
    if(currentState != null){
        canvas.removeKeyListener(currentState);
        canvas.removeMouseListener(currentState);
        canvas.removeMouseMotionListener(currentState);
    }

    currentState = newState;
    canvas.addKeyListener(currentState);
    canvas.addMouseListener(currentState);
    canvas.addMouseMotionListener(currentState);
}

that’s what I do everytime and work fine.

Lot’s of things work fine, but that doesn’t mean they’re optimal or even close to efficient and/or flexible… :wink:

@theagentd
and not mention about reuseable, extendable and readable :wink: Kev said make it run first.