Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Adjusting The Player Size In a 2D RPG Built with XNA on Windows Phone

DZone's Guide to

Adjusting The Player Size In a 2D RPG Built with XNA on Windows Phone

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

Game development is an interesting area mainly because you get to learn a lot of stuff as you go. There is no universal recipe for every game and every possible scenario that might be encountered. Last night I was working on my Dream.Build.Play entry - it is a 2D PRG for Windows Phone that is built to work in an isometric space.

There is a main character, that moves around the screen on pre-defined paths (directions). 

The character itself is drawn from a spritesheet defined by 12 96x96 squares. It is rendered with a slight manual delay in the game loop, and no matter what direction the character moves in - the sprite sheet size and format remain the same (obviously the sprite sheet content is not). In some scenarios, the above-mentioned character will engage in activities that require secondary motions, like attacking an enemy.

When that happens, I am loading a sprite sheet that has the same sequence format (2 rows, 6 squares) but is defined by a different square size - 128x128. If I simply replace the existing sprite sheet with the new one, an unwanted character displacement will take place:

This displacement takes place due to the fact that although the character is centered in the spritesheet, by default XNA does not take the center as the drawing origin, but rather the leftmost corner (unless specified otherwise). that being said, take a look at how a 128px sprite is being overlapped on a 96px one:

You can clearly see in the image above that when the character proceeds to attack another unit, it will be moved to the right, given that the origin is preserved.

Here is how to avoid the issue mentioned above:

  1. Calculate the difference in size between the two sprites. 128 - 96 = 32 . That is the number of pixels you have to worry about. 
  2. You need to displace the larger image by half of the value you got above. Because you need to keep the character centered, imagine that you need to overlay the smaller square over the larger one, and you need to keep it dead in the middle.

For my specific case, the code looks like this:

private void ResetAttackState(bool isAttacking)
{
    if (isAttacking)
    {
        if (!flagged)
        {
            CharacterFrameSize = new Point(128, 128);
            Location = new Vector2(Location.X - 16.0f, Location.Y - 16.0f);
            flagged = true;
        }
    }
    else
    {
        if (flagged)
        {
            CharacterFrameSize = new Point(96, 96);
            Location = new Vector2(Location.X + 16.0f, Location.Y + 16.0f);
            flagged = false;
        }

    }
}

The size of the sprite square is determined whenever the character is engaged in a specific action. In case it is an attacking one, I am using 128px as the size. Otherwise - 96px. The location vector is adjusted based on half-sizes of the sheet square difference, just like I mentioned above. This generally ensures that the transition between sprites is pretty smooth, since the character is in one place and the player does not notice the fact that something happened to the character model.

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}