A couple questions relevant to games

  • Hi. I'm planning to make a game, and I have a couple of questions
    since I'm new to cocoa.

    1) Is there some functionality to stack views, such that only one is
    visible at a time in the outer window?  If you look at most games,
    they're usually presented as a set of screens, such as the tile screen
    or the map screen, all within a single window.  Certain actions within
    these screens makes the application switch to a new screen.  Does
    cocoa/Interface Builder have something like that built in?

    2) I intend to have a view that shows a grid of tiles.  Its actual
    dimensions should depend on the dimensions of the grid and the
    dimensions of the images drawn on it (I assume the tile images are of
    equal size).  I may allow dynamic resizing of the view, but it should
    be constrained so that the images retain their proportions and there
    are no extra gaps or "partial tiles."  So, if the images are square
    and the grid is square, the view should always be square.  I'm asking
    because in Interface Builder it seems you define the dimensions of a
    view directly instead of letting it be defined by user parameters at
    runtime (in this case, the grid and tile dimensions).  Is there a way
    around this?

    Thank you,

    Aaron J. M.
  • On Feb 17, 2008, at 7:44 AM, Aaron MacDonald wrote:

    > 1) Is there some functionality to stack views, such that only one is
    > visible at a time in the outer window?  If you look at most games,
    > they're usually presented as a set of screens, such as the tile
    > screen or the map screen, all within a single window.  Certain
    > actions within these screens makes the application switch to a new
    > screen.  Does cocoa/Interface Builder have something like that built
    > in?

    In Cocoa you would typically use a NSTabView (with the actual tabs
    hidden) for this purpose. Or, alternatively, you would just insert /
    remove subviews manually from your root view.

    > 2) I intend to have a view that shows a grid of tiles.  Its actual
    > dimensions should depend on the dimensions of the grid and the
    > dimensions of the images drawn on it (I assume the tile images are
    > of equal size).  I may allow dynamic resizing of the view, but it
    > should be constrained so that the images retain their proportions
    > and there are no extra gaps or "partial tiles."  So, if the images
    > are square and the grid is square, the view should always be
    > square.  I'm asking because in Interface Builder it seems you define
    > the dimensions of a view directly instead of letting it be defined
    > by user parameters at runtime (in this case, the grid and tile
    > dimensions).  Is there a way around this?

    In IB you set the default size & position for your views, but you can
    always change them at runtime.

    With regards to your concerns about keeping square proportions, take a
    look at "-[NSWindow setResizeIncrements:]", or alternatively "-
    [NSWindow(Delegate) windowWillResize:toSize:]".

    j o a r
  • On 17 Feb '08, at 7:44 AM, Aaron MacDonald wrote:

    > Hi. I'm planning to make a game, and I have a couple of questions
    > since I'm new to cocoa.

    I'd highly recommend looking at CoreAnimation if you're going to
    design a game. Its drawing model is very well suited to 2D sprite
    animation. There's an Apple sample app called GeekGameBoard that
    demonstrates using CA for games like checkers and solitaire:
    http://developer.apple.com/samplecode/GeekGameBoard/index.html
    It includes a small framework for generic board/card games, that you
    can reuse and extend.

    (Disclaimer: I wrote this sample. I'd be chuffed if someone wants to
    use it, and I'll be glad to answer questions about it...)

    I also have an unpublished/incomplete project that glues together
    CoreAnimation and the open-source "Box2D" physics engine, letting you
    add realistic 2D physics to your CA animations.

    —Jens
  • On 17-Feb-08, at 1:21 PM, j o a r wrote:
    > In Cocoa you would typically use a NSTabView (with the actual tabs
    > hidden) for this purpose. Or, alternatively, you would just insert /
    > remove subviews manually from your root view.

    Thanks. The tabless option for NSTabView is exactly what I needed.

    > In IB you set the default size & position for your views, but you
    > can always change them at runtime.
    >
    > With regards to your concerns about keeping square proportions, take
    > a look at "-[NSWindow setResizeIncrements:]", or alternatively "-
    > [NSWindow(Delegate) windowWillResize:toSize:]".

    Are you sure? I only want to control the resizing of the tile view
    (that's what I'll call it) itself.

    This is what I've tried so far. I have a function bestRect() that
    takes an NSRect and the desired grid dimensions and returns a trimmed
    NSRect. I use this in initWithFrame, and have also tried this in
    setFrame to handle resizing.

    ----------

    - (id) initWithFrame: (NSRect) frame
    {
        self = [super initWithFrame: bestRect(frame, 15, 10) ];

        if (self)
        {
            gridWidth = 15;
            gridHeight = 10;
        }

        return self;
    }

    - (void) setFrame: (NSRect) frameRect
    {
        [super setFrame: bestRect(frameRect, gridWidth, gridHeight) ];
    }

    ----------

    This works when the window is first shown, but it doesn't handle
    resizing well. When I have it set to not expand and I shrink the
    window to smaller than the tile view's initial size, its tiles get
    squished out of proportion (so far I'm trying to get square tiles).

    There's also the issue of the grid dimensions been magic numbers. I
    want an initialization method where I provide the grid width, grid
    height, and tile size. It's just that I can't see where I'd be able to
    call that since it appears I can only access my tile view through
    Interface Builder. This is especially troublesome if I want to have
    more than one tile view, such where I have a main view screen and a
    mini-map.

    Thank you,

    Aaron J. M.
  • On Feb 17, 2008, at 7:20 PM, Aaron MacDonald wrote:

    >> With regards to your concerns about keeping square proportions,
    >> take a look at "-[NSWindow setResizeIncrements:]", or alternatively
    >> "-[NSWindow(Delegate) windowWillResize:toSize:]".
    >
    > Are you sure? I only want to control the resizing of the tile view
    > (that's what I'll call it) itself.

    Most of the time, changes to the width/height ratio of the view would
    correspond directly with changes to the width/height ratio of the
    window. Are you sure that's not the case in your app? That said, if
    this option doesn't work out for you, you can always just
    programmatically keep the view at the right size in response to
    whatever other event that suits you.

    > This works when the window is first shown, but it doesn't handle
    > resizing well. When I have it set to not expand and I shrink the
    > window to smaller than the tile view's initial size, its tiles get
    > squished out of proportion (so far I'm trying to get square tiles).

    It sounds like you have some sort of bug in your resizing code. Add
    logging statements to see how the size of your view correlates to the
    size of your window as it is resized.

    > There's also the issue of the grid dimensions been magic numbers. I
    > want an initialization method where I provide the grid width, grid
    > height, and tile size. It's just that I can't see where I'd be able
    > to call that since it appears I can only access my tile view through
    > Interface Builder. This is especially troublesome if I want to have
    > more than one tile view, such where I have a main view screen and a
    > mini-map.

    Make sure that the view is assigned to an "outlet" (instance variable)
    of your window controller. This will give you a reference to the view
    to be used at runtime.

    j o a r
  • On 17 Feb '08, at 7:20 PM, Aaron MacDonald wrote:

    > This works when the window is first shown, but it doesn't handle
    > resizing well. When I have it set to not expand and I shrink the
    > window to smaller than the tile view's initial size, its tiles get
    > squished out of proportion (so far I'm trying to get square tiles).

    Here's some old code of mine that ensures its window's main view
    remains square, by always preserving the difference between the
    window's height and width. This goes in the window's delegate object:

    - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize
    {
        // This will get called _before_ awakeFromNib if frame default
    has been set!
        if( _extraHeight == 0.0 ) {
            NSRect frame = [_window frame];
            _extraHeight = frame.size.height - frame.size.width;
        } else {
            frameSize.height = frameSize.width + _extraHeight;
        }
        return frameSize;
    }

    > There's also the issue of the grid dimensions been magic numbers. I
    > want an initialization method where I provide the grid width, grid
    > height, and tile size. It's just that I can't see where I'd be able
    > to call that since it appears I can only access my tile view through
    > Interface Builder. This is especially troublesome if I want to have
    > more than one tile view, such where I have a main view screen and a
    > mini-map.

    Yeah, you can't use initialization methods with objects in nibs. You
    can implement -awakeFromNib on the view subclass, or on an app/window
    controller that will then tell the view to set itself up.

    —Jens
  • On Feb 17, 2008, at 10:48 PM, Jens Alfke wrote:

    >
    > On 17 Feb '08, at 7:20 PM, Aaron MacDonald wrote:
    >
    >> This works when the window is first shown, but it doesn't handle
    >> resizing well. When I have it set to not expand and I shrink the
    >> window to smaller than the tile view's initial size, its tiles get
    >> squished out of proportion (so far I'm trying to get square tiles).
    >
    > Here's some old code of mine that ensures its window's main view
    > remains square, by always preserving the difference between the
    > window's height and width. This goes in the window's delegate object:

    The significantly easier way is to use:

    [window setContentAspectRatio: 1.0];

    (Available from 10.3 on)

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium | prime : build, mutate, evolve, animate : the next
    generation of fractal art
  • On Feb 18, 2008, at 10:23 AM, glenn andreas wrote:

    > The significantly easier way is to use:
    >
    > [window setContentAspectRatio: 1.0];
    >
    > (Available from 10.3 on)

    I think the aspect ratio setting is not enforced precisely enough or
    in enough cases. I've had trouble with it not always working. If I
    remember correctly it has shortcomings when it comes to zooming a
    window, and perhaps is ignored when setting the frame programatically.

    I can't remember all the reasons, but in my crossword solving
    application it's important to keep the window a size that allows the
    puzzle grid to be an even pixel multiple. I ended up enforcing it in
    windowWillResize and windowWillUseStandardFrame.

    Daniel
  • On Feb 18, 2008, at 11:22 AM, Daniel Jalkut wrote:

    > On Feb 18, 2008, at 10:23 AM, glenn andreas wrote:
    >
    >> The significantly easier way is to use:
    >>
    >> [window setContentAspectRatio: 1.0];
    >>
    >> (Available from 10.3 on)
    >
    > I think the aspect ratio setting is not enforced precisely enough or
    > in enough cases. I've had trouble with it not always working. If I
    > remember correctly it has shortcomings when it comes to zooming a
    > window, and perhaps is ignored when setting the frame programatically.
    >

    I've not seen that personally, though setAspectRatio suffers from such
    a fate (since it includes the title bar in the aspect ratio, making it
    basically useless).

    >
    > I can't remember all the reasons, but in my crossword solving
    > application it's important to keep the window a size that allows the
    > puzzle grid to be an even pixel multiple. I ended up enforcing it in
    > windowWillResize and windowWillUseStandardFrame.
    >
    > Daniel

    Since you needed pixel multiples, you'd also need to use
    setContentResizeIncrements:

    There may be a bug that the zooming doesn't use
    setContentResizeIncrements (I've never needed that functionality) but
    from what I remember, setAspectRatio worked fine with zooming.

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium | flame : flame fractals & strange attractors : build,
    mutate, evolve, animate
  • On Feb 18, 2008, at 9:22 AM, Daniel Jalkut wrote:

    > I think the aspect ratio setting is not enforced precisely enough or
    > in enough cases. I've had trouble with it not always working. If I
    > remember correctly it has shortcomings when it comes to zooming a
    > window, and perhaps is ignored when setting the frame programatically.

    This is true for most of Cocoa: All the different API:s for
    restricting things (max/min size of windows, control of the selection
    in table views, etc.) only applies for user actions. The restrictions
    doesn't apply for programmatic control of these properties.

    j o a r