Sunday, December 1, 2013

Porting to Windows Phone 8

Adapting VLAD to WP8 has been harder and more expensive than other mobile platforms. Still, I'm glad I took the bullet, because I ended up with a much more mature game engine, and I have a foot (or two) in the Windows Store.

The Technical Challenges
Where do I begin.. Well, it started in a good place: I'm used to writing cross-platform code and I always liked porting code to new platforms. I find it beautiful to see a game running consistently across completely different systems. It's an important testament to solid engineering, and as an engine programmer, this is where I get most of my satisfaction!

In the case of WP8, porting was probably as challenging as it gets, and this is starting with an already cross-platform engine that runs on PC/iOS/Android.

Graphics: This was by far the most challenging part, I should probably dedicate a blog post to give you more details about it. But in short, coming from OpenGL, writing a DX11 renderer is no cake walk. I don't even remember the year when I last used DirectX, I just know it was DirectX 9 at the time and I was doing simple fixed-pipeline stuff with it. DirectX11 is a whole new world, even more so that it's mandatory to use shaders to get anything on the screen. This will be definitely addressed in a separate post with more details.

It's worth noting that I spent a fair amount of time dealing with the notorious DX COM interface leaks (they show up when using the debug DX runtime). I used to ignore them in the old DX9 days, but this time I wanted to make my engine completely leak free. So I wrote a templated wrapper around DX interfaces, mimicking the COMRef<> C# wrapper, but in C++. Also, I didn't find any quick way of supporting Point Sprites (which I was using everywhere in the GL port) so I had to let go of them and use bill-boarded particles across the board. But generally speaking, DX11 feels future-proof and powerful to use, and that you can rely on it when developing more advanced features. The price being that it's relatively more complex to get something simple rolling specially compared to GL. As an example, here are the DX interfaces needed just to get my GraphicDriver rolling (this is not including textures, vertex buffers, shaders, or other graphic objects):


COMReference<IDXGISwapChain1> m_SwapChain;  
COMReference<ID3D11RenderTargetView> m_RenderTargetView;  
COMReference<ID3D11DepthStencilView> m_DepthStencilView;  
COMReference<ID3D11Buffer> m_MVPBuffer;  
COMReference<ID3D11Buffer> m_TextureTransformBuffer;  
COMReference<ID3D11Buffer> m_MaterialBuffer;  
COMReference<ID3D11SamplerState> m_TextureSamplerLinear;  
COMReference<ID3D11BlendState> m_BlendState[2][D3D11_BLEND_INV_SRC1_ALPHA+1][D3D11_BLEND_INV_SRC1_ALPHA+1]; // blendEnable / srcBlend / destBlend  
COMReference<ID3D11DepthStencilState> m_DepthStencilState[2][2][D3D11_COMPARISON_ALWAYS+1]; // testEnable / writeEnable / depthFunc  
COMReference<ID3D11RasterizerState> m_RasterizerState[2][D3D11_FILL_SOLID+1][D3D11_CULL_BACK+1]; // frontCCW / fillMode / cullMode  
COMReference<ID3D11DeviceContext1> m_ImmediateContext;  
COMReference<ID3D11Device1> m_Device;  
   

File system: For this part, the challenge was to find good information on where to start. Just google "WP8 open file from C++" and get a load of the range of approaches available out there. So I followed multiple leads, before settling for the good old LibC! Yes, fopen works like a charm on WP8, provided you access your files relative to the correct system paths. Here is how I determine the application folder and the writable (for savegame) folder on WP8:


Platform::String^ dataPath = Windows::ApplicationModel::Package::Current->InstalledLocation->Path;  
std::wstring dataPathW(dataPath->Begin());  
std::string dataPathMB(dataPathW.begin(), dataPathW.end());  
shoot::File::SetBasePath(dataPathMB.c_str());  
        
Platform::String^ writablePath = Windows::Storage::ApplicationData::Current->LocalFolder->Path;  
std::wstring writablePathW(writablePath->Begin());  
std::string writablePathMB(writablePathW.begin(), writablePathW.end());  
shoot::File::SetWritablePath(writablePathMB.c_str());  
   

Multi-threading: Same challenge as for the file system, the hard part was finding a simple approach that works well! For this one, C++11 saves the day. Long story short, std::mutex and std::thread work great on WP8, while being incredibly simple to use.

Networking: This was a special case and deserves an article on its own, because I wrote the networking part for all platforms at once, there was no real porting involved. But the bottom line is that I use the good old Winsock2 for network communication on WP8.

The Development Costs
The highest compared to iOS and Android: You basically need a Windows 8 Pro computer. In my case this implied buying a new computer, and buying a Windows 8 Pro license. Also, because I was serious about my game, I had to buy an HTC phone for testing.



Saturday, November 16, 2013

VLAD Heavy Strike is being released as we speak!




After a little more than a year in development, I finally managed to wrap up my space shooter despite a hectic schedule at work and only working on it part time! The result is VLAD: Heavy Strike. As I'm writing this, it is already available on android. The iOS and WP8 versions are on the way and should be out in a week or so.

I'm very excited about the game prospects and is looking forward to improve on it. I learnt a lot about self-producing a game with my own tech and releasing it on mobile. Technically speaking, I couldn't have done it without my game engine and game editor, which I invested about 3 years of work into. Artistically speaking, I was lucky to collaborate with very talented artists, who gave me their best despite working from different countries in 3 different time zones!

I'll be blogging more often about game engine development and the making of VLAD, so stay tuned if interested!

Sunday, April 14, 2013

QuadTree Partitioning

QuadTree-O-clock has arrived folks! After noticing performance drops as a result of Level 1 becoming bigger, I implemented QuadTree Partitioning to make sure that only part of the level is rendered and updated at any given time.

I made a dimension-based QuadTree, meaning I stop sub-dividing nodes that reach a minimum size. Other implementations can be capacity-based, meaning they stop sub-dividing when the number of elements in a node is below a certain threshold, but I chose the former because element density is pretty homogeneous across my level and is generally rather low; Also, I thought it would make level design more solid if I knew in advance the typical dimensions of the QuadTree nodes.

In addition, since I'm making a vertical shooter, I made the QuadTree only sub-divide in one dimension. Thus, this should really be called a BinaryTree! But the implementation is really just the same. I'm pretty happy with the result, below is a screenshot showing the partitioning in Level 1, notice the active nodes (in yellow):

BinaryTree Partitioning

Frustum Culling


Once the QuadTree is built, frustum culling is necessary to determine which nodes ought to be rendered and updated. I implemented a simple frustum/sphere intersection test, and is happy with the result.

I uploaded a video to showcase how this fits within my space shooter game. You can see QuadTree nodes lit-up in yellow as soon as their bounding-sphere intersects with the frustum. There are at most 3 active nodes at any given time, making this feature really worth it performance-wise.