Using an NSMatrix subclass for a board game view

  • Hi all,

    I'm writing a simple Reversi game, and I'm currently struggling a bit
    trying to create a simple animation of the pieces being flipped when
    a player (or the AI) makes a move. I'm using a subclass of NSMatrix
    for my main view, and trying to make it call its own display routine
    again.

    Questions:

    1. How would I best make the NSMatrix display itself again after a
    small delay (say 10 ms)?

    2. Am I going about this in the wrong way? Should I perhaps not
    subclass NSMatrix at all, but just delegate to the controller for
    this logic?

    The code of the project is available here: http://svn.brautaset.org/
    Desdemona/trunk/
    The NSMatrix subclass in particular is here: http://svn.brautaset.org/
    Desdemona/trunk/BoardView.m

    Stig
  • On 12 Oct 2007, at 11:31 AM, Brautaset Stig wrote:

    > I'm writing a simple Reversi game, and I'm currently struggling a
    > bit trying to create a simple animation of the pieces being flipped
    > when a player (or the AI) makes a move. I'm using a subclass of
    > NSMatrix for my main view, and trying to make it call its own
    > display routine again.

    My best guess is that you should define a subclass of NSCell (possibly
    NSImageCell, possibly NSButtonCell), that keeps three states, one
    empty, and one for each player. When it transitions, it should run an
    animation showing it. This could be done:

    In QuickTime with QTKit.

    or

    Using an NSTimer to mark the stages of the animation, and having the
    timer make the cell setImage: for the next frame of the animation.
    Invalidate the timer when the animation is done. The cell should send
    setNeedsDisplay: or setNeedsDisplayInRect to the board view.

    I see no reason why more than one animation can't be done at the same
    time, though it might be less confusing to the user if you didn't
    respond to clicks while animations are in progress.

    The new cell will have to draw itself distinctively when the mouse is
    down over it.

    In the long run, you might want to consider your own board view. You
    are already fighting NSMatrix by providing your own mouseDown: method
    (why can't Desdemona receive an action from the NSMatrix and do the
    transition itself?).

    Also, you're keeping the state of the game in your NSMatrix subclass.
    This is bad. Review the Model-View-Controller (MVC) design pattern at
    developer.apple.com. You'll find it easier if you keep the state of
    the game in its own class. That way, your AI (for instance) can work
    directly on an object that isn't complicated by click-and-draw
    mechanics. You can change the board-view or the game-state-model
    without having to rework the other. Use the class Desdemona as a
    controller object, to translate click actions into state changes, and
    to propagate state changes to the display.

    — F
  • On 12 Oct 2007, at 19:12, Fritz Anderson wrote:
    > On 12 Oct 2007, at 11:31 AM, Brautaset Stig wrote:
    >> I'm writing a simple Reversi game, and I'm currently struggling a
    >> bit trying to create a simple animation of the pieces being
    >> flipped when a player (or the AI) makes a move. I'm using a
    >> subclass of NSMatrix for my main view, and trying to make it call
    >> its own display routine again.

    [snip helpful response]

    > In the long run, you might want to consider your own board view.
    > You are already fighting NSMatrix by providing your own mouseDown:
    > method (why can't Desdemona receive an action from the NSMatrix and
    > do the transition itself?).

    I'd love to do that! I couldn't figure out how though. Using NSMatrix
    seems to be somewhat under-documented.

    Is there a way to configure the NSMatrix to send a 'somebody clicked
    me!' event to its delegate?

    > Also, you're keeping the state of the game in your NSMatrix subclass.

    It's not ideal, but it's only a cache of the state used for display
    purposes. The _actual_ state is somewhere else, in an instance of a
    SBReversiState (hidden away in a framework[0] in vendor/AlphaBeta).

    > having to rework the other. Use the class Desdemona as a controller
    > object, to translate click actions into state changes, and to
    > propagate state changes to the display.

    This is what I'm aiming at, yes. The alphaBeta[1] instance variable
    in Desdemona contains the actual model.

    [0] your book came in real handy learning how to create those ;)

    Stig

    --
    http://code.brautaset.org
    http://blog.brautaset.org
  • On 12 Oct 2007, at 20:27, Stig Brautaset wrote:
    >> In the long run, you might want to consider your own board view.
    >> You are already fighting NSMatrix by providing your own mouseDown:
    >> method (why can't Desdemona receive an action from the NSMatrix
    >> and do the transition itself?).
    >
    > I'd love to do that! I couldn't figure out how though. Using
    > NSMatrix seems to be somewhat under-documented. Is there a way to
    > configure the NSMatrix to send a 'somebody clicked me!' event to
    > its delegate?

    Ok, responding to my self for the benefit of anyone suffering from
    the same problem[0] as me in the future. I've solved my problem. I
    now use a standard NSMatrix view populated with standard NSImageCell
    instances.

    In IB I configured the NSMatrix to be a radio type, so only one cell
    can be selected, then connected the action from the NSMatrix to a
    custom IBAction method on the controller.

    It was as simple as that.

    I'm going back to kicking myself now.

    [0] not seeing the forest for all the trees.

    Stig
    --
    http://code.brautaset.org
    http://blog.brautaset.org
previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today