Monday, June 25, 2007

Design: Mouse Click

Without this next design concept I would have never been able to get MTG Forge off the ground. Processing user input, usually though the mouse, is critical but complicated. A mouse click can mean that I want to attack, block, play a card, use an ability, select targets for a card, or choose which land to tap. We all innately understand that a mouse click means different things at different times, but how do you program that?

I used the software pattern called State, it is mentioned in the original pattern book “Design Patterns” by Erich Gamma. I’m going to show you some pseudocode that looks similar to Java and then explain it afterwards.

interface Mouse
public void click(Card c);

class MouseState implements Mouse
private Mouse mouse;
public void setMouse(Mouse m) {mouse = m;}
public void click(Card c) {mouse.click(c);}

class MainMouse implements Mouse
public void click(Card c)
{
//If card in hand, try to pay for card
//If card in play, try to play ability
}

class AttackMouse implements Mouse
public void click(Card c) {//add creature to attackers}

class BlockMouse implements Mouse
public void click(Card c) {//add creature to blockers}

OK, we have an interface (or abstract class) that has one method, click(). MouseState just acts like a shell for the 3 other classes.

After this statement MouseState.setMouse(new MainMouse()), MouseState will act like it is a MainMouse object. If MouseState is passed an AttackMouse object, it will act like that object. Basically MouseState morphs into another object. So externally MouseState can act like multiple classes. The beauty of the State pattern is that MouseState doesn’t require a ton of IF statements. I can change the behavior of MouseState without changing the source code of MouseState, can you see the flexibility? The user interface only holds a reference to MouseState, and other classes change the behavior of MouseState as needed. MTG Forge uses Input instead of Mouse and InputControl instead of MouseState.

1 comment:

Anonymous said...

great pattern!!!
First I used to write my app without it, but when I saw how you use it, I was impressed. It really makes your programming life easier ;)
must have!