So I stopped developing the game and started to read more stuff online, try out examples and benchmark on my machine. The most useful thing is to read people's past questions on gamedev forums and the like and read the answers they are given by people who know what they are talking about. Even questions which I didn't think of asking provide answers that are useful to know. It saves time having to write a benchmark and test things if someone who knows can give the answer. One trap to bear in mind when doing this is that answers can become obsolete over time as the APIs change. Stuff that used to be inefficient can become efficient and stuff that was important to do for performance can become irrelevant.
Anyway back to the game. I am scaling back massively my overly ambitious plans. I now plan to make a very simple roguelike, no massive map, just a traditional small map for each level of a dungeon. Really I already have this largely in place before I got side-tracked on very big virtualized maps. As a benefit the performance requirements for small maps are even lower. I'll try to get a very simple first game done before trying anything too complicated.
I might as well mention the performance problems I hit in the current game. I have a Tile class and it has a Draw() method. In that method it calls DrawUserPrimitives to render a quad for the tile. The Item and Monster classes also have a Draw() method and do the same thing. This is nice and OO, but rendering a 50x30 tile map results in at least 2500 DrawUserPrimitives calls per frame. Stupidly inefficient for what is largely a static map and could be rendered in a single call.
It's kind of okay, hardware is a bit more advanced these days than 10 years ago. On my machine I can render 100,000 textured triangles at 11 FPS which sounds bad, but now consider I am making 100,000 calls to DrawUserPrimitives each frame, one for each triangle. If I instead render in batches of 10,000 triangles (so 10 DrawUserPrimitives calls), I get about 220 FPS.
- What matters? Doing it "right" or getting it to work? So what if the rendering is stupidly inefficient, if it renders at 60FPS on any modern PC or laptop who cares?
- I am making a turn-based roguelike with exceedingly low graphical requirements, not some cutting edge FPS. I can sacrifice a lot of efficience.
- Does improved performance really require breaking OO purity or can I do OO differently?
For the last question I thought it should be possible to insert my own caching/batching layer between the game and DrawUserPrimitives. Still working on it but so far it doesn't perform as well as I hoped.
As a side note I am going to the International Roguelike Development Conference in London at the weekend as a noob looking to learn from people who know what they are doing.
*Anyone who is confused why I am not just using spritebatches in a 2D game, I wanted to learn 3D rendering even though I am making a 2D game.