CocosSharp – The Foundation

This post is part of my Mobile Game Development series. Start at the beginning to catch up. This series was inspired by the things I learned developing a new game for Android and iOS called Mirror Maze.

Getting started with anything new can be daunting and CocosSharp is no exception. I certainly felt a little overwhelmed as I started to play around with test applications. Once I started to get an understanding of how CocosSharp works, I found it easier to focus on what I needed to learn one part at a time. My hope with this post is to help you gain enough understanding of the basics to be able to do the same.

As I said earlier in this series, CocosSharp is an implementation of the Cocos2D game engine. That’s important to remember because documentation on CocosSharp can sometimes be lacking. However, it opens up the door if you can find examples of what you are looking for with Cocos2D, then translate it to CocosSharp. That being said, Xamarin does have some CocosSharp documentation available to check out.

A quick note before I go any further. For the purposes of this series, I’ll be talking about CocosSharp in the context of Android and iOS. However, CocosSharp will run on many more platforms than just those two. Most of the topics I plan to discuss should apply to all the platforms CocosSharp is available on, though.

CocosSharp has a Game View (CCGameView) that will be placed either in your MainActivity for Android or your main ViewController for iOS. That Game View will contain your entire game. That means your app lives entirely in a single Activity or view. All navigation between “pages” within the game is only logical navigation. As far as your device is concerned, your app doesn’t navigate anywhere.

That Game View will need to be initialized in order to know how big your design resolution is and where to look for things. In some examples you’ll see that initialization code copied into each platform’s project, but I found it was the same code and moved it into my common project.

Below is my initialization code for Mirror Maze, followed by how it gets wired up in an Android Activity and an iOS ViewController.

What is Design Resolution?

The design resolution topic is rather interesting. You specify the resolution of the Game View by giving it a width and a height. That is the logical size, not the pixel size. CocosSharp will take that resolution and scale it to fit whatever size device your app is running on. That means that all the sizing and positioning you do in your application doesn’t necessarily directly relate to the actual pixels on the device. This fact is actually really cool. It takes away the need to handle different sized devices in your code. There are some drawbacks, however. The first is that you can’t make your game look different on tablets vs phones, at least not without a lot of extra work. Second, if your defined resolution doesn’t fit perfectly on the device that your app is running on, you will get what is known as “letterboxing”.

Letterboxing is where there are bars either above and below or to the left and to the right of your Game View. That is because your Game View will size your game to fit the device’s physical aspect ratio, position it in the center of the screen, then fill in any remaining space with a default color (black on Android and white on iOS). I found that to be rather annoying when I was getting serious about my game’s look-and-feel, but I did find a way to change the color of the bars to blend into my app. Don’t worry, I’ll share that in a later post.

The design resolution doesn’t need to match your physical device’s actual resolution. I learned this the hard way. I thought it needed to match the width and height to the pixel, so I added code that made the design resolution dynamically match the device when the app started up. All that did was make my aspect ratio goofed up on any device other than the one I targeted first, causing things to be sized and positioned wrong within my game. Take my word for it: don’t do that. Instead, pick an aspect ratio that you want to work with, then find a comfortable size with that aspect ratio to set your Game View. A smaller design resolution will make a 10×10 sized object look bigger and a bigger design resolution will make that same object look smaller. What resolution you choose will depend on your app’s UI needs.

Asset Location

The other thing your Game View setup code will need to do is tell the Game View where to look for assets, such as image files for sprites, audio files, and fonts. Most of the examples you see will show the Images folder containing two sub-folders: Hd and Ld. Hd is for High density devices and Ld is for Low density devices. You can also write your app to have more options than that, if you like. I found that the image files I needed for Hd were twice the pixel size as those I needed for Ld. Which brings me to another interesting point: use vector-based graphics for your source. I used Inkscape to create my graphics. That allowed me to resize easily, without losing image quality.

Another lesson I learned regarding the Hd vs Ld concept was that fonts also need to be different sizes for your labels to be scaled correctly on different sized devices. The way I handled this is to add a static property called FontSizeMultiplier, which I set along with the Game View initialization stuff. For Hd devices, the multiplier is 2.0. For Ld devices, the multiplier is 1.0. Then, every label would have whatever font size I wanted to use * that multiplier. Now all my labels are sized as I expect them to be. I didn’t even notice this was an issue until I tried testing my app on a tablet, instead of the usual phone, and saw that all the labels were way too small.

One thing that isn’t immediately clear until you look at a sample project is that the Images folder (containing Hd and Ld), as well as the Fonts and Sounds folders all reside within a Content folder. That Content folder is NOT part of the common project where most of your code will go. This is because the files contained within the Content folder need to be included in the output generated by each platform’s project. Android references those files differently than iOS does. As a result, both the Android project and the iOS project have a Content folder containing your sounds, images, and fonts. On Android, the Content folder resides within the Assets folder. On iOS, the Content folder resides in the root.

Since you will likely be using the same files on both Android and iOS, it makes sense to only create those files once, then reference them in both places. I did this by adding all the files to my Android project, then adding them as Links in my iOS project. Believe me, you’ll want to do something similar so save yourself the headache of double maintenance.

In the next post we’ll start taking a look at the classes you’ll be working with to build CocosSharp games.

Leave a Reply

Your email address will not be published. Required fields are marked *