Showing posts with label abstract. Show all posts
Showing posts with label abstract. Show all posts

Saturday, June 25, 2011

XNA Game Design: Abstract Sprite (part 1)


The problem with displaying a texture2D image is that there are a number of variables associated with how it should be displayed (Vector2 position, Vector2 scale, Color blending color, float rotation... you get the idea). In many cases we wouldn't want to deal with most of variables, but so many are tied together, it actually makes sense to create a object that holds all this information for us. That is why we will begin creating an abstract ASprite class.

Alongside that, it will also allow us to create methods that can be called from SCENE.Update() that would allow us to do more advanced things with our images, such as make them flash a certain color with a certain intensity for X frames (a bonus project I'll put up later. Too tough for a homework assignment -_-). Being able to call Player.Sprite.Flash(...) is very gratifying, and easy on later development.

Our abstract Sprite class will hold nine variables. These are;
  • the Texture2D image
  • a Rectangle source rectangle (for if we only want to display part of an image)
  • a Vector2 position
  • a Vector2 scale
  • a Vector2 origin
  • a SpriteEffects effect (for indicating whether to flip horizontally or vertically)
  • a private Float angle with a public Int Rotation (you'll see)
  • a Float z scale (for determining the draw order of images and how they "stack")
  • a Color blend color

These are a lot of variables that do a bunch of different things, and if you have any questions about them I'll answer them in the comments. We will also need a static ContentManager to load our texture2D, a simple constructor, and a few extra methods. The only necessary value we will require is our Texture2D image, and we retrieve this by asking for a string.

(Note: depending on your game, you might not want to be holding all of these variables. A NES clone would not use a blending color or a rotation, and if you're crafty you might not even want a source rectangle or scale value. Again, all of this depends on the game YOU are making.)

As established, we will begin by making an abstract class to hold all of these variables.

abstract class ASprite
{
    public Texture2D image;
    public Rectangle src_rect;
    public Vector2 pos = Vector2.Zero;
    public Vector2 origin = Vector2.Zero;
    public Vector2 scale = Vector2.One;
    public float z = 0.5f; //default z value
    private float angle = 0.0f; //rotation in radians
    public Color blend_color = Color.White;
    public SpriteEffects effect = SpriteEffects.None;
    private static ContentManager content = 
    new ContentManager(Game1.services, "Content/Graphics");

Now there's one more variable we need: the int rotation. The reason we need another value to represent our angle is because the draw want's the angle of rotation as a float value in radians. If you're so comfortable with radians that you feel you can specify your rotations with exact values, I commend you. But for us humans, we will instead use rotation to specify our angle of rotation in degrees, and use a set accesor to change the angle value into radians. 

The get and set accesors allow the developer to specify extra operations whenever properties are changed. They are very useful for situations like these.

public int Rotation
{
    set
    {
        angle = (MathHelper.Pi * value / 180)
        % (MathHelper.TwoPi);
    }
    get
    {
        return (int)(angle * (180 / mathhelper.Pi);
    }
}

Comic by Bill Amend. It's not that radians are difficult to think in terms of. It's that it's easier to say rotation = 45 as opposed to angle = 0.785398 (pi / 4 as a float).


We will want the constructor to look a little funky, which is why this is being split into two parts. We're almost finished though! No homework because I couldn't think of any just yet -_-  

Thursday, June 23, 2011

XNA Game Design: Thinking Abstractly

The second part of this guide will focus on making two abstract classes to better handle certain aspects of our game. The first will involve creating a class that will better handle image drawing and holding related bitmap data (such as position, rotation, reflection, etc.). The second will use our improved sprites to create a standardized game window that will contain elements such as text, sprites, and selectable choices.

The reason this section is called thinking abstractly is because it will focus intently on elements of polymorphism and inheritance through the use of abstract classes.

To refresh your memory, an abstract class uses the abstract keyword and cannot have instances made of it. Simply put, it acts as a parent class perfect to hold the messier, often untouched variables used by it's child classes.


The Grandpa isn't dead, he's just abstract.
When thinking back to our biggest unsolved problem, we still have the spriteBatch lingering around our SCENE.Draw() method. At the moment, all image drawing must be called from the spritebatch.Draw() method. This makes for horrible looking code because all the methods are directed from the spriteBatch.

  • spriteBatch.Draw(Player.Texture2D, Player.Vector2, Player.Color...)
  • spriteBatch.Draw(Enemy.Texture2D, Enemy.Vector2, Enemy.Color...)
  • spriteBatch.Draw(PowerUp.Texture2D, PowerUp.Vector2, PowerUp.Color...)
  • //This repetitive code is boring!

Every line would be that repetitive. The less code we have to write, the better. So the first part of Abstraction will focus on creating a set of classes to let us instead say;
  • Player.Sprite.Draw(spriteBatch);
  • Enemy.Sprite.Draw(spriteBatch);
  • PowerUp.Sprite.Draw(spriteBatch);
  • //Easy like strawberry daiquiris in Tahiti!

The second part will focus on making a standardized game window, which is just a background with borders and organized elements. While every game does this visual aspect differently, It's inclusion is videogames is so ubiquitous it honestly deserves it's own focus. If you don't believe me, just see for your self. Menus, text boxes and selectable choices are so common in video games, and they're all composed of related objects. As such, it makes perfect sense to tackle them early on. By the end of this chapter, you should have the perfect framework to make and menu system or options screen your game would need (boring, yeah, but it'll make those parts of the game seem like a piece of cake).