iphoneobjective-ccocos2d-iphoneccnode

Moving a Stick figure, anchorpoints, animation, or something else...?


Ok so I am making a game with stick figures with cocos2d in objective c... Different things need to be animated so please, give me a suggestion of what would be the best way to go about accomplishing the movement for these things:

  1. The main character- he is an archer in the bottom left corner who does not move around, except he will move his upper body because you need to change the angle of where you are shooting the angle...

  2. The enemies- hordes of stick figures coming at you that have collision detection and die when shot by an arrow sprite.

How should I make 1 and 2 move? should I master anchor points and use those? (I really hate stupid anchorpoints they are so hard to get to work... but I'll use these if they are better) or make tons of animations, or is there another simpler way to combine many sprites into a single movement?


Solution

  • My general advice: never, ever modify the default anchorPoint (0.5f, 0.5f) unless you have a really good understanding of what it does and how it helps you accomplish things. In all other cases, modify the position property.

    Especially if you do bounding box or radius based collision detection, modifying the anchor point is counter-productive.

    Let's assume your rectangular sprite image uses a default anchor point, which is in the center of the texture:

    ._______.
    |       |
    |       |
    |   *   |
    |       |
    |       |
    °-------°
    

    The * marks the anchorPoint of the texture. If you place this sprite at position (250, 100) then the sprite's anchorPoint will be at the coordinates (250, 100).

    Let's say you move the anchorPoint to (0.1f, 0.1f):

      ._______.
      |       |
    . |     . |
      |       |
      |       |
      | *     |
      °-------°
    
    °       ° 
    

    The position of the sprite remains unchanged at (250, 100). The anchorPoint position also doesn't change. What changes is how the texture is centered around that point. You can see the previous image position before modifying the anchor point by looking at the floating dots. In effect, all you do by modifying the anchorPoint is to move (offset) where the node's texture is drawn relative to the node's position.

    In the above case the texture is now centered with its lower-left corner over the node's position. You can no longer rely on the position of the sprite marking the center of the sprite image. If you modify the anchorPoint arbitrarily for every node in the game, you no longer have any correlation between the visual representation of a node and its position. Thus it is bad design to modify the anchorPoint for gameplay objects.

    Furthermore, rotation or scaling will always be centered on the anchorPoint. Modifying the anchorPoint can result in undesirable behavior when rotating or scaling nodes.

    Let's assume an odd, worst case, but entirely possible scenario where the anchorPoint is no longer inside the texture:

                         ._______.
                         |       |
                         |       |
                         |       |
      *                  |       |
                         |       |
                         °-------°
    

    That means the position of that sprite is offset far to the left of where the actual image is being displayed. This can lead to collision check discrepancies, in particular the above situation would entirely void radius-based collision checks. This is also a confusing situation to be in during development.

    Your game will be far easier to develop if you can be sure that a sprite's position is always in the center of its texture, rather than some arbitrary point that you can't even see without the help of some debug drawing.

    The question remains:

    When would you want to modify the anchor point?

    I've done so only in the following situations, and avoid it in all other scenarios:

    1. to align non-animated textures with the screen/window borders or similar
    2. to right/left/top/bottom align a label, button or image
    3. to align a modified image (ie artist update) without modifying the node position.

    1) Is easy to explain. Assume you have a full-screen background image. To make it cover the entire screen, you can do one of two things:

    You can imagine the latter is easier to do. If you'll never move the background, it's fine doing that. However for a scrolling background I wouldn't change the anchorPoint.

    2) Assume your menu system calls for various buttons and images to be right-aligned exactly with the right border of the screen. All buttons and images differ in width: ie Play Game, Credits, Settings, More Cool Games!

    Instead of figuring out the individual positions for each image/button, it is easier to simply right-align them by modifying the anchorPoint to (1.0f, 0.5f) and then position the images/buttons at exactly the screen width (and variable screen height): position = (screen width, 100).

    Let's assume the following image's position is at (screen width, screen height / 2) with a default anchorPoint (0.5f, 0.5f). You can see the right half of the image is outside the screen area:

    __________.
              |
          .___|___.
          |   |   |
          |   |   |
          |   *   |
          |   |   |
          |   |   |
          °---|---°
              |
    ----------°
    

    With a modified anchorPoint of (1.0f, 0.5f) the image can be neatly right-aligned with the right screen/window border, regardless of the width of its texture. The position remains the same: (screen width, screen height / 2).

    __________.
              |
      ._______.
      |       |
      |       |
      |       *
      |       |
      |       |
      °-------°
              |
    ----------°
    

    Just for comparison, if you wanted to right-align this image, menu button, or label without modifying the anchorPoint, you would have to set its position according to this formula:

    (screen width - contentSize.width * anchorPoint.x, screen height / 2)
    

    The formula is still pretty simple, it becomes a chore however if the contentSize of the node changes, which is often the case for labels, for example the score starts with 1 digit but increases to 2, 3 and 4 digits over time. In such cases right-aligning a node by modifying the anchorPoint is justified because it avoids having to recalculate the position every time the contentSize of the node changes.

    3) There are rare cases where an artist provided me with an updated image of a game object. The image size has changed, so it no longer fits naturally into the game's graphics. On the other hand, the object's position has already been well established through gameplay testing and should not be changed to avoid re-testing the game.

    In such a case tweaking the anchorPoint so that the new image aligns well with the other graphics, without affecting the gameplay, is warranted. This is a safe, last-minute modification. Don't start doing this during the production phase or you'll end up in anchorPoint-tweaking-hell throughout the lifetime of your project. Don't go there!

    In summary:

    Modify anchorPoint only if that makes it easier to align nodes with other nodes or a screen/window border, or to fine-tune final art without affecting gameplay.

    In all other cases, use position exclusively to move nodes.