Monday, August 8, 2011

Baddies 2.3–Node Updating

When dealing with a node – tree architecture, there are several functions that need to be called recursively down the tree (mainly draw and update, but there are others, such as cull, exit, etc…) AND they need to be overridden in base classes, normally by the user.


Implementing either one of these things is trivial, but doing them together and while keeping the system secure from any slips by the user is not. One possible solution is to remind the user in the documentation that when he overrides update, he must always call update on all the children of the node. But this is playing with fire, eventually someone is going to forget, and put a sneaky bug in the system.


The easiest solution I’ve come up with is putting 2 functions of each: Update and NodeUpdate, Draw and NodeDraw… where the single word function is an abstract function for the user to override, and the double word function is the one actually called in the tree update, which calls to the simple function, does some extra necessary stuff and updates the children.


This method is transparent to the user, who just needs to override the function as expected, and doesn’t let him fuck up anything important. Similar solutions might be made with delegates or callbacks.

XNA Notes–Day 2

Random notes

Program.cs is a stub that launches the game, it's not even used in WP7

GraphicsDeviceManager implements IGraphicsDeviceService and IGraphicsDeviceManager, and adds itself to the "Services" property of the game object.

You can create your own services and get them directly from the game object. For example a spritebatch for public access with: Services.AddService(typeof(SpriteBatch), spriteBatch); and you can access it from anywhere you can access the game with SpriteBatch spriteBatch = Game.Services.GetService( typeof(SpriteBatch)) as SpriteBatch;

GraphicsDeviceManager (GDM)

Instantiating a GraphicsDeviceManager makes it create a GraphicsDevice as a property of game and of GDM. It also creates the GraphicsProfile property and the IsFullScreen property (that behaves differently depending on the platform).

The GDM also has preferences. The runtime attempts to use them and if it cant it falls back on the closest it can.

  • PreferedMultisampling (to blend pixels together and remove jagged edges, defaults to fault because of the overhead)
  • PreferedBackbufferHeight /Width (size of the window on non-fullscreen, resolution on fullscreen and ignored in XBox and WP7)
  • PreferBackBufferFormat / ScencilFormat (how many bits used for the deph and stencil buffers)
  • SupportedOrientations (for WP7)
  • SynchronizeWithVerticalRetrace (prevents tearing by pausing until ready to draw).

There are also events you can hook to, most interesting the PreparingDeviceSettings, lets you override any of the settings before the device is created.

Two interesting methods

  • ApplyChanges (flushes the changes)
  • ToggleFullscrenn (changes to and from full screen)

Game class

There are 2 methods to overload BeginDraw and EndDraw which are not visible on default. Overloading EndDraw requires you to call base.EndDraw.

Two other interesting methods to override, BeginRun and EndRun, called just before begins/ after finishes to run.

Events you can hook to:

  • OnActivated (Game is activated at the beginign and any time it regains focus)
  • OnDeactivated (Ditto)
  • OnExiting (Just once when the game is exiting)

Methods in Game

  • Exit (Causes the game to start shutting down)
  • ResetElapsedTime (Does exactly that)
  • Run (As expected in W and XBox, but throws an exception in WP7 as it's a blocking method)
  • SupressDraw (Stops calling draw until the next time Update is called)
    Tick (Advances one frame, calls Update and Draw)

Propierties in Game

  • InactiveSleepTime (Tells the system how long to sleep when not the active process, default 20 milliseconds)
  • IsActive (Tells you if you're the active process)
  • LaunchParameters (Gests the comand line parameters of in WP7 information oabout the parameters required for launch)

Game time

Game has two parameters to handle time IsFixedTimeStep and TargetElapsedTime, and the update method gets passed a GameTime object with the current time. Interesting detail is the IsRunningSlowly property in the GameTime object, which can be used in FixedTimeStep mode.
For measuring the performance of the game, variable time step should be used.

Components

Encapsulated game objects of 3 types, GameComponent, DrawableGameComponent and GamerServicesComponent.
Focusing on the first 2, they have the same structure more or less than Game.
You can add components in the Game class initialize method, and they get handled by the Game, with no supervision.

Saturday, August 6, 2011

Baddies 2.2–Node Positioning

Each node in the game tree has two possible options when drawing, either relative to the parent node, or with absolute coordinates respect to the screen. This is done as some things like the GUI need to be relative to the screen, regardless of where they are hooked up in the game tree, and for most  of the compound objects (like a player with a sword and a shadow) it makes it a lot easier if you just put the sword and shadow relative to the player and forget about it (when the player moves, the sword and shadow will as well.)


But this apparently simple system raises some questions. First and foremost, do we keep 2 sets of coordinates? We keep the absolute coordinates and (needed for drawing from everyone) and the relative ones? Or we recalculate one of them?
And if we recalculate one of them, do we do it on demand? Or every cycle?
And finally, how do we keep this coordinates “safe” so there are no hidden bugs when the user modifies one set and not the other?


The answer I came with is to keep just the relative coordinates as position, and a variable parentRelativePos, which indicates whether the coordinates are relative to the parent post or not.  No double set of coordinates because data replication is a sure way for innocent bugs to creep invisible into the system, and still attack months later in the development. So by elimination we end up with just one set of data.


As for recalculating them, it will be apparent by now that for the vast majority of nodes, it is only needed to recalculate the absolute position it when drawing (for those relative to the parent position), and not at all for the rest (the not relative to the parent position nodes can just draw with their normal position variable, as it’s absolute coordinates).


So, the problem boils down to recalculating when drawing, or when the position changes. Doing it when the position changes is viable ONLY if we keep the position variable private, and all changes to it go through an accessor method that updates the position and the “drawPosition”, but that is still a possible nest of bugs (maybe we need to open the level of security of position to protected, or have some unacceptable access times in derived classes from node, and this is again giving a user full access to fuck up). So we recalculate the drawPosition every draw cycle, by adding the parent drawPosition to our own position. Just 3 additions per cycle of extra cost, not so bad when the alternative is ninja bugs all over the code.


In conclusion, one variable that is position, the Boolean parentRelativePos indicates whether it is a relative or absolute position, and the drawPosition is updated every draw cycle from our position and our parents drawPosition.

XNA Notes–Day 1

I’ve been programming on and off in XNA for a few years now, but I never really tried to learn XNA, just picked it up on the go, googling whatever was needed at the time. But now I’m working on a more dedicated project, and not knowing my tools in depth can only lead to suboptimal solutions. Therefore, I have decided to pick up the XNA Game Studio 4.0 Programming book, by Tom Miller and Dean Johnson, and start studying it from the beginning.

This series of XNA notes are just that, notes from studying, with curious / useful facts from the book, as I have a horrible memory and writing things down is the only way to remember them. Besides, someone else might find something useful here, who knows?

So, without further ado, today’s notes:

Random notes

Game Studio 4.0 is broken up in two different profiles, Reach which encompasses features for all platforms and HiDef, which includes extra features that exist only in W and Xbox.

The origin of coordinates is the top left.

font.MeassureString(string) tells you the width and height of the string in that font.

SpriteBatch

Tinting in spritebatch.draw multiplies the original color of the image by the color of the tint.

Using a Vector2 instead of a rectangle means we don't do any stretching to the image when we render it on screen, we draw it with the original size.

Different overloads

In the appropriate draw overloads, the source rectangle lets you decide which part of the original image you're going to draw. Useful for frame animations.
In the appropriate draw overloads you can rotate the image using an angle in radians and an origin for the rotation.  You can also scale the image.
You have some crappy SpriteEffect options, which are to flip horizontaly, to flip vertically or none.
There is a Z ordering for the drawing between 1.0 (top) and 0.0 (bottom) that only matter if you play arround with the sorting modes.

Sprite Sorting

Using spritebatch.begin we can specify the draw mode, among others SpriteSortMode…

  • Texture (sort by texture, do all of the same texture at the same time as not to have to change, default),
  • FrontToBack / BackToFront (taking into account the depth specified for each draw call),
  • Deferred (Drawn in the order it is used in the draw calls),
  • Immediate (different from all others bacause hardware render calls are not batched, but instead we have one hardware call per draw call).

Sprite Blending

Using spritebatch.begin we can also specify the blend state, among others BlendState.

  • AlphaBlend (default blending mode, transparency works fine),
  • Opaque (No blending),
  • Aditive (adds the colors together).

Friday, August 5, 2011

Baddies 2.1–Nodes and Tree Architecture

The game engine follows a tree based architecture, that is, all elements are nodes, and any node might be added as a child to someone else. Every node might have at most one parent. Specific cases and conditions can be dealt with from each individual node.
There are three main reasons I’ve opted for this architecture, to the point of redoing several months of work.

Low coupling

Ideally, in any computer science project there is low coupling and high cohesion. This means, in an OOP environment, that the best situation would be one where no class needs to know about any other to function. This is a goal worth pursuing, even though it is not always reasonable to stick to this guideline, as you need to sacrifice other factors (speed, mainly) to achieve it, and that is simply not an option in a game project.
But, low coupling is good, as I’ve found out in countless projects, and most games can be designed as to minimize coupling and be all the better for it. And a tree based architecture is awesome for this because since any node can be added to any other node, you can never assume a node will have a particular parent on whose internal workings it relies, therefore you must always write modular code.
This, of course, takes a toll on efficiency and forces us to use several communication mechanisms we shall see later.

Avoiding repetition

In almost all game projects I’ve done, I find the objects follow a hierarchical structure, and from each parent object I usually have to call the “Enter, Update, Draw, Exit” functions of all of its children, for which I have to create individual variables, and so on. There is a lot of duplicated effort for each object you add to a class.
A tree architecture solves all this by putting all items as nodes, so they can be stored and treated in a generic way. No more remembering to modify half the class when I add a new variable or remove it.
The down side is that accessing elements in a class from the outside is slower as a search of some sort, or even a direct access to the index of the element requires extra work, and therefore time.

Empirical experience

I worked with the Cocos libraries in a couple of projects and found it to be a delightful system, working fine in the limited environment that is a smartphone.

Conclusion

All in all, it’s a good system for games that don’t try to squeeze the processor dry, and like a clean easy to maintain system.

Thursday, August 4, 2011

Baddies 1.3–Project distribution

Reflecting the new architecture explained in the previous article (Baddies 1.2 – Architecture), the whole project was divided in 4 MVS projects, though within a single solution.


Microsoft Visual Studio is a superb tool for this kind of things and as long as you don’t put recursive references of a project within a project, it gets the job done very easily.


The project structure ends up looking like this:

  • Core
  • Game
  • Editor
  • Content


The Content project holds the content files (graphics, audio, and so on) used by any of the other 3 projects, as the amount of non-shared assets in the whole solution is relatively small compared to the total amount of assets.
The references between all the projects are the logical ones, with the game and editor using the core and content.

ProjDep

This setup of projects is interesting to remember as it’s common to a lot of game projects (tough instead of the editor there might be another secondary tool for the game).

Wednesday, August 3, 2011

Baddies 1.2 - Architecture

The initial project was to make a single complete game, and the architecture reflects this. It’s a tree based system where almost every element of the game is a node, and any node can be attached to another. The architecture is inspired on the one implemented very successfully by the Cocos2D libraries.
Here is a class diagram in a simplified UML notation, with each class linked to where it was going to be used later on, instead of normal UML composition, as any node can be linked to any node as need arises.

Architecture 2

After the start of the project, it became apparent however that an editor was needed for the game. The editor shared many of the classes of the original game, thus the need for a library of common classes that both projects (game and editor) needed to access. This evolved into 3 separate architectures, as follows.

Core architecture

The core architecture has all the classes of the core engine and their dependency to the Node class. Classes in green are XNA classes.

Architecture Core

Game architecture

The game architecture has the relationship of the core classes among each other to create the actual game. All the white classes are from the core library, while blue classes are specific to the actual game.

Architecture Game

Editor architecture

The editor architecture is mainly one editor form and one game editor closely coupled via a picture box form. Inside the game editor we build the actual game to be shown, and in the editor form we create the GUI via windows forms.

Architecture Editor