|
Written by Markus Ewald
|
|
Tuesday, January 19 2010 20:24 |
|
Welcome to day 2 of the XNA Game Architecture series!
I have thought hard about whether I should just assume a certain level of object
oriented programming knowledge in this series. People picking up these articles likely
already have some knowledge about objects and design, so I settled on a quick
run-over of the principles that hopefully won't bore the seasoned developers and
provide a good reference for people just starting out!
If you already know all this, feel free to skip ahead until it becomes interesting
again or to the next chapter !
|
|
Written by Markus Ewald
|
|
Friday, December 25 2009 19:45 |
|
Welcome to day 1 of the XNA Game Architecture series! We're about to
create a small 3D Shoot 'em Up using the principles
of modern software architecture.
If you missed the
introduction, this series is about the architecture of games. Instead of
focusing on a single concept, we'll be focusing at how it all comes together and
how you can keep your game's code manageable and clean. You'll be looking over
my shoulder as I write a small game and explain why I do things one way and
not the other
.
Today, I will start the project by creating a development tree that
contains the actual XNA project and some third-party libraries I'm going to use
within the game. Normally, I would add those libraries as I go, but I've got a
pretty clear idea for this project and it will be easier for you because I can just
package them all in a handy zip archive which you'll find at the end of this article.
|
|
Written by Markus Ewald
|
|
Thursday, December 03 2009 23:27 |
|
When I release components, example code or even just helper classes, I often
tout 100% test coverage as a feature. Which (as I probably also state often
enough :P), means that my unit tests execute 100% of all lines in the source code.
But what advantage does this actually bring to a developer, and, just as
interesting, what does having complete test coverage not mean?
For people practicing true TDD (test first -> red, green, refactor),
100% coverage is nothing unusual, though even they may decide to not write tests
for all invalid inputs possible: if a piece of code satisfies all the tests and
the tests cover everything the code should do, it's enough. If you're
building a library on the other side, the use case of a customer providing invalid
inputs will be a valid concern worthy of a test.
I, however, am currently adding unit tests to an existing code base and I decided
to go for 100% test coverage. In this short article, I will explain why I see
complete test coverage as a worthwhile goal, what effect going for that level of
test coverage has on a project and what it says about the code.
|
|
Written by Markus Ewald
|
|
Monday, July 27 2009 20:59 |
|
Sometimes, games have to render highly dynamic geometry such as sparks, bullet trails,
muzzle flashes and lightning arcs. Sometimes it's possible to off-load the work of
simulating these things to the GPU, but there are effects than can't be done by
the GPU alone.
These cases usually occur when effects require heavy interaction with level geometry
or when they require lots of conditionals to mutate a persistent effect state.
And sometimes, the effort of simulating an effect on the GPU is just not worth the results.
If you have maybe a hundred instances of a bullet trail at once, letting the GPU orient
the constrained billboards for the trails instead of generating the vertices on the CPU
might just not yield any tangible benefits.
However, there are still a lot of traps you can run into. A typical mistake of the
unknowing developer is to render the primitives one-by-one either using one
Draw[Indexed]UserPrimitives() call per spark/trail/arc.
This is not a good idea because modern GPUs are optimized for rendering large numbers
of polygons at once. When you call Draw[Indexed]UserPrimitives(), XNA will
call into Direct3D, which will cause a call into driver (which means a call from code
running in user mode to code running in kernel mode, which is especially slow). Then
the vertices are added to the GPU's processing queue.
By sending single primitives to the GPU, this per-call overhead is multiplied and can
become a real bottleneck. To demonstrate the effects of making lots of small drawing
calls, I wrote a small benchmark and measured the results on my GeForce 8800 GTS 512
and on whatever the XBox 360 uses as its GPU.
|
|
Written by Markus Ewald
|
|
Monday, March 09 2009 18:25 |
|
Today, I've got some new screen shots! Read on :-)
Over the weekend, I implemented proper camera and terrain selection controls.
Getting keyboard, mouse and gamepad working at the same time proved a bit of
a nightmare. PC RTS players will expect the arrow keys to move around their view
and the mouse to be usable as a selection tool. XBox 360 RTS players need some way
of telling the game where to place buildings, but the gamepad isn't suited for this task
as well as the mouse is.
So I decided to split my terrain into a regular grid in which a terrain cursor can be
moved. The grid is in units of 3x3 terrain quads, which allows me to add some detail
to the terrain on the sub-grid-cell level. Otherwise, it would look fairly obvious to the
player that the terrain is based on a heightmap with regular X/Y samples.
|
|
Written by Markus Ewald
|
|
Friday, March 06 2009 19:15 |
|
During the past week, I got missiles working to a point where they will launch,
gain altitude, head towards their target and dive for the attack. They will damage
the island (which means scraping off texture layers and possibly alter the terrain,
not sure whether I want this, however). Buildings in the vicinity are then destroyed.
For the missile trajectory, I went for the simplest thing that could possibly work:
-
Until the missile has reached its cruise altitude, it will ascend at a 45 degree
angle. If during this phase, missile closes in to the target so much that it needs
to start diving, the diving phase will be entered.
-
Once at its cruise altitude, the missile will simply fly in a horizontal line
towards its target. If the missile gets closes enough to its target, it will
enter the diving phase.
-
In the diving phase, the missile accelerates to maximum speed and descends
towards its target at a 45 degree angle. Once it hits the ground, it explodes.
|
|
Written by Markus Ewald
|
|
Wednesday, March 04 2009 21:37 |
|
Today, I watched an interesting discussion on
gamedev.net where someone asked why everyone
is recommending beginners to start off with XNA and C# whereas the entire
gaming industry is based on C/C++.
I would have expected to read something along the lines of
"We recommend XNA because it's very easy to learn and you will hit the ground running fast. It
teaches beginners the kind of thinking required to lay out the logic of a program
and doesn't discourage them by forcing them to write boring console applications
for months until they know the semantics of the language well enough to use
a graphics library such as SDL, DirectX or OpenGL. Some people may not even want
to enter the industry, so C# and XNA is a fine choice for them. Those that do can
switch over to C/C++ after they're fluent in C# and it will be a mostly easy going,
incremental learning process."
Instead, an ugly mess resulted with people firmly stating that .NET/Mono is the way
to go for games, that the gaming industry is using it for prototyping, scripting and
development tools and that the only reasons for not adopting C# yet are
legacy code bases and unwillingness by developers to learn new stuff or to change
proven ways. People began dissecting each other's posts one by one and, well, if you've
been on the internet some time, you can probably imagine how it turns out.
|
|
Written by Markus Ewald
|
|
Wednesday, February 04 2009 22:04 |
|
Last time, I wrote about how I set sail for the Island War project and
how my motivation faltered slowly over time. And I promised to write
a follow-up post that explains how I believe to get back on track and
finish development of my Island War project. Well, here it is, folks!
I see the primary reason for my loss of motivation in my tendency to
write and fully implement systems instead of just the piece of code I need.
While I knew that I had to "write a game, not an engine", I still fell for
the same old trap: I didn't technically write an engine, but I started to
design entire systems and fully implement them when all I needed was
a small routine to get the job done.
|
|
Written by Markus Ewald
|
|
Thursday, January 22 2009 19:36 |
|
It's baack!
Slowly, the Island War project begins to grind its wheels again. Time for a review of
what's happened so far. When I started this project, I was still intoxicated from
the successful completion of my just-for-fun project "Ball Race". I was eager to build
a real, full-blown game taking no shortcuts and doing everything in the best
way imaginable.
This turned out to be a real time waster and motivation sapper.
|
|
Written by Markus Ewald
|
|
Saturday, January 10 2009 18:59 |
|
For the past two years, I couldn't test all the XNA stuff I made on a real XBox 360. Whenever
something went wrong, I had to guess and diagnose from the feedback I was getting from users.
I've become quite good at remote-diagnosing problems. It didn't ever take me more than 3 emails
or postings in my forum exchanged with the people who discovered a bug until I had gathered
enough feedback to locate a bug and fix it in my code. But that certainly isn't how I want to
get in contact with my customers when I start to sell games on XBox Live :)
That's why, as of now, I've ordered an XBox 360 Elite, which finally has the right color: black.
I just love black, I've got a black keyboard, black mouse, black mouse mat, my PC sits in
a Lian Li PC-71 Black and my monitors are also black -- erm well, at least their frames are,
otherwise I'd be having a really hard time posting this blog entry, I think :D
|
|