Marmalade SDK Bitesize Tutorial – How to Launch an External File or Web Link

Welcome to another bite size Marmalade SDK tutorial.  This tutorial covers a cross platform way of opening up web links and other types of external file using the Marmalade SDK.

The Marmalade SDK contains a cool function called s3eOSExecExecute() which will launch the file / URL that you provide as a parameter using the underlying OS’s method of handling various file types.

In our example, we want to open up a web page URL. This type of system is great for deep linking your app or game to full and paid versions of free / lite apps or even providing a simple link to your other products or web sites.

The format of s3eOSExecExecute is as follows:

s3eResult s3eOSExecExecute(const char *url, s3eBool exit)

url – The URL you wish to open
exit – Should the app exit when launching the URL

Before you call this function you should however check to make sure that it is supported on the device using:

s3eBool s3eOSExecAvailable()

News from Pocketeers

We finally scrounged a little free time to update our company web site with some of our latest developments over at http://www.pocketeers.co.uk

Pocketgamer.biz featured some of my mental ramblings with regards to the Marmalade SDK over on their site today, so I’m pleased as punch.

I also found myself watching some of RIM’s Devcon 2011 (live web cast), which was very interesting. During the advert break I noticed an ad for the Blackberry Playbook showing a user playing a variety of games on it and low and behold our BattleBallz Chaos was on there! 🙂

Marmalade SDK news – Marmalade 5.1.8 now available for download

Down with the dreaded flu right now so just a few quick blogs for now.

I find it amazing and cool just at how often Marmalade update their SDK. I’m also ultra excited about the impending 5.2 release, lots of cool new stuff due including native UI. I’m hoping to see a flood of Android, iPhone, Bada and even Playbook and iPad application developers when 5.2 hits.

Ok, Marmalade SDK 5.1.8 changes include:

  • Blackberry PlayBook: Fix for touch events in area of video playback.
  • Blackberry PlayBook: Fix for s3eOSReadString.
  • Blackberry PlayBook: Add new icf setting SysSuspendDuringVideo which can be used to pause the application during video playback. Using this setting it is possible to avoid the screen corruption that can occur on PlayBook after video playback.
  • Blackberry PlayBook: Fix several issues relating to fixed and dynamic screen rotation.
  • Multiple platforms: Added s3eWebViewClearCache function to the s3eWebView extension.
  • Blackberry PlayBook: s3eAccelerometer axis are now correct according to the device orientation.
  • Android: Fix for ZeroConf search only returning first service discovered.
  • Android: Fix to allow adding third party .so libraries to Android packages.

Mainly fixes, but a few additions. I am particularly pleased with the Blackberry Playbook fixes

You can grab Marmalade SDK 5.1.8 from Marmalades download section.

Marmalade SDK Tutorial – CIwGameSprite – Creating a Robust Sprite Class

This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index click here

Well, another busy day and as usual I have too much to do and there are only 24 hours in a day (I could do with coding and blogging on a ship travelling faster then the speed of light, so I can finish before I even started!). As usual if you just want the code then grab it from here. if you want the details then please read on

I’m getting quite excited about the tutorial series as we are finally building up to something much more useful than a simple bunch of loosely connected tutorials. That something is a “2D game engine” that will allow you to create cool fast games using the Marmalade SDK that you can deploy to a bucket load of platforms simultaneously and hopefully earn an even bigger bucket load of cash from!

Today we are going to begin our game engine by implementing one of the most basic components of a 2D game engine, The Sprite.

The Sprite

From our game engines point of view, we are going to define a sprite as a visual component that can move and animate on the users screen. I wont go as far as defining a sprite as a bitmap image because our sprites are special, they can be anything we define them to be. They can be anything from a simple point, line or bitmap to something as extravagant as a vector based image. We basically want to leave our options open and offer as much extensibility to our game engine as possible.

One very important point to make at this point. A sprite is only a visual component and should not be made to deal with game logic, collision detection, playing audio etc. It should only be concerned with drawing itself. Some people like this separation of concerns style programming but others (like me), whilst others do not.

Ok, so what do we want our basic sprite to do? Lets make a list:

  • Move around the screen
  • Scale
  • Rotate
  • Change colour / transparency (allows flashing, fades etc..)
  • Draw itself
  • Managed by some controller class (so we don’t have to deal with allocation / deletion)
  • Ability to be pooled to reduce memory fragmentation

In rides CIwGameSprite our new sprite class

CIwGameSprite – The mother of all sprite classes

Erm, put down that Marmalade SDK documentation, don’t let the name fool you, you wont find this class in there. I have named the class as such so that it feels more like its part of the Marmalade SDK.

CIwGameSprite is the name of our basic sprite class that we are going to base our 2D game engine around. CIwGameSprite is not actually a usable class in the sense that you can create one and do something with it. CIwGameSprite acts as a base class for other types of sprite classes and defines some basic sprite information that is going to be common to all types of sprites. Lets take a quick look at CIwGameSprite (defined in the IwGameSprite.h header file) to see what it does.

class CIwGameSprite { /// Properties protected: CIwGameSpriteManager* Parent; // Parent sprite manager CIwSVec2 Position; // Position of the sprite iwangle Angle; // Rotation of sprite (IW_ANGLE_2PI = 360 degrees) iwfixed Scale; // Scale of sprite (IW_GEOM_ONE = 1.0) CIwColour Colour; // Colour of sprite bool Visible; // Sprites visible state bool Pooled; // Tells system if we belong to a sprite pool or not bool InUse; // Used in a memory pooling system to mark this sprite as in use public: void setParent(CIwGameSpriteManager* parent) { Parent = parent; } void setPosAngScale(int x, int y, iwangle angle, iwfixed scale) { Position.x = x; Position.y = y; Angle = angle; Scale = scale; TransformDirty = true; } void setPosition(int x, int y) { Position.x = x; Position.y = y; TransformDirty = true; } CIwSVec2 getPosition() const { return Position; } void setAngle(iwangle angle) { Angle = angle; TransformDirty = true; } iwangle getAngle() const { return Angle; } void setScale(iwfixed scale) { Scale = scale; TransformDirty = true; } iwfixed getScale() const { return Scale; } void setColour(CIwColour colour) { Colour = colour; } CIwColour getColour() const { return Colour; } void setVisible(bool show) { Visible = show; } bool isVisible() const { return Visible; } void forceTransformDirty() { TransformDirty = true; } void setPooled(bool pooled) { Pooled = pooled; } bool isPooled() const { return Pooled; } void setInUse(bool in_use) { InUse = in_use; } bool isUsed() const { return InUse; } /// Properties End protected: CIwMat2D Transform; // Transform bool TransformDirty; // Dirty when transform change void RebuildTransform(); // Rebuilds the display transform public: CIwGameSprite() : Pooled(false) { Init(); } virtual ~CIwGameSprite() {} virtual void Init(); // Called to initialise the sprite, used after construction or to reset the sprite in a pooled sprite system virtual void Draw() = 0; // Pure virtual, need to implement in derived classes };

Ok, we see that we have a bunch of properties for our sprite:

  • Parent – Our sprites are managed by a sprite manager, the parent of our sprites will be the sprite manager that is looking after them (more on the sprite manager later)
  • Position – The 2D position of our sprite in 2D space
  • Angle – The orientation of our sprite in 2D space (Marmalade SDK angles range from 0 to IW_ANGLE_2PI)
  • Scale – The scale of our sprite in 2D space (Marmalade SDK used IW_GEOM_ONE as the value of 1.0f)
  • Colour – The colour and transparency of our sprite
  • Visible – The visible state of our sprite (can the user see it?)
  • Pooled – Should our sprites data be deleted when it is removed from the sprite manager (more on sprite pooling later)
  • InUse – Used to mark a sprite as being used in a pooled sprite system

We also have a few private member variables in there that deal with the transform for our sprite. We covered the Iw2D transform in our Iw2D sprite example code in a previous tutorial. Note that building transforms can be expensive in terms of time when we are rebuilding lots of them every frame, so in our sprite class we only going to rebuild the sprites transform when the sprites position, scale or angle changes (no sense doing all that work if nothings changed).

Note that our Draw() method is a pure virtual method which makes the class abstract. This means that you cannot and are not supposed to create instances of this class. Instead it serves as an interface to defining classed based upon that class. Now thats said lets take a look at a class that we have derived from CIwGameSprite called CIwGameBitmapSprite.

CIwGameBitmapSprite – In Comes the Meat

Here is the class definition for CIwGameBitmapSprite:

class CIwGameBitmapSprite : public CIwGameSprite { // Properties protected: CIw2DImage* Image; // Bitmapped image that represents this sprite int Width, Height; // Destination width and height int SrcX, SrcY; // Top left position in source texture int SrcWidth, SrcHeight; // Width and height of sprite in source texture public: void setImage(CIw2DImage* image) { Image = image; } void setDestSize(int width, int height) { Width = width; Height = height; } void setSrcRect(int x, int y, int width, int height) { SrcX = x; SrcY = y; SrcWidth = width; SrcHeight = height; } // Properties End public: CIwGameBitmapSprite() : CIwGameSprite(), Image(NULL) {} virtual ~CIwGameBitmapSprite() {} void Draw(); };

As you can see we have derived CIwGameBitmapSprite from CIwGameSprite, basically borrowing all of its functionality and then adding on some more. This class now represents a visual component that is represented by a bitmap, or in this case a CIw2DImage.

You can see that we have added a few additional properties:

  • Image – Our Iw2D bitmap image that we have previously loaded somewhere
  • Width – The width that the sprite will appear on screen at a scale of 1.0
  • Height – The height that the sprite will appear on screen at a scale of 1.0
  • SrcX, SrcY, SrcWidth and SrcHeight – These 4 variables are all inter-related. They mark a rectangular area within our source Iw2D image, which allows us to render just a portion of a large image instead of the whole thing, allowing us to use sprite sheets. If you haven’t heard of sprite sheets (or sprite atlases) then you can think of them as a collection of images arranged onto one large image. For example, you may have arranged a whole bunch of animation frames of one of your characters onto one large bitmap. This system will allow us to pick out the smaller images and render them without worrying about the rest.

Ok, we now have a fully functional bitmapped sprite class that will allow us to draw bitmapped sprites to the screen. We can also spin, scale, move, hide and even change the colour or transparency of these sprites

CIwGameSpriteManager – Managing our Little Sprite Children

I like to compare instantiated classes to children. if you allow them, they will misbehave and be difficult to manage. To help prevent your unruly sprites from misbehaving and crashing your awesome game, you need something to manage them, a common place to examine them, draw them and delete them when no longer needed (ok the comparison with children stops at that one!)

So to manage our sprites we create a sprite manager (CIwGameSpriteManager). Lets take a quick look at the CIwGameSpriteManager class:

class CIwGameSpriteManager { public: // Provide public access to iteration of the sprite list typedef CIwList::iterator Iterator; Iterator begin() { return Sprites.begin(); } Iterator end() { return Sprites.end(); } // Properties protected: CIwMat2D Transform; // Transform CIwList Sprites; // Our list of sprites public: void addSprite(CIwGameSprite* sprite); void removeSprite(CIwGameSprite* sprite, bool delete_sprites = true); void setTransform(const CIwMat2D& transform) { Transform = transform; DirtyChildTransforms(); } const CIwMat2D& getTransform() const { return Transform; } // Properties End protected: void DirtyChildTransforms(); public: CIwGameSpriteManager() { // Set up default rotation, scaling and translation Transform.SetIdentity(); Transform.m[0][0] = IW_GEOM_ONE; Transform.m[1][1] = IW_GEOM_ONE; } ~CIwGameSpriteManager() { Release(); } void Draw(); void Release(bool delete_sprites = true); };

Ok, if you aren’t fond on collections / iterators and the likes then you probably won’t like this class very much. I will admit, i am quite obsessed with them. I find them “too” useful.

I chose to use Marmalades CIwList class, which is basically a templated linked list class that lets you define a list of objects / data that is somehow related. In our case we have a list of sprites (A linked list is basically a list of objects where each object points to another and then that object points to another and so on).

Ok, so this class provides some basic functionality:

  • We can add sprites to our manager using addSprite() and not worry about having to delete them when we are done with them. Simply deleting the sprite manager will delete all of the sprites for us
  • We can remove individual sprites from our manager using removeSprite()
  • We can draw all of our sprites in one go
  • We can set a base transform that all of our sprites that are managed by this sprite manager are transformed by. This allows us to rotate, move and scale all of the sprites in one go by the same amount. This can be great for applying effects to all of your sprites and / or simply ensuring that all sprites are scaled and translated to fit on any sized screen.

What’s changed in the example code

If you build and run the Sprite project you will see 100 sprites spinning around their centres with the whole scene of sprites spinning and scaling around the centre of the screen:

Sprite Marmalade SDK Example Screenshot

We have re-used the code from our previous Audio tutorial but ripped a few bits out of the main loop to clarify what’s going on.

Our first change involves creating a sprite manager and then adding some sprites:

// Create a sprite manager and a bunch of sprites CIwGameSpriteManager* sprite_manager = new CIwGameSpriteManager(); for (int t = 0; t < 100; t++) { // Create sprite CIwGameBitmapSprite* sprite = new CIwGameBitmapSprite(); // Set sprite position, angle and scale sprite->setPosAngScale(IwRandMinMax(-max_size, max_size), IwRandMinMax(-max_size, max_size), 0, IW_GEOM_ONE); // Give sprite a random colour CIwColour colour; colour.r = 55 + IwRandMinMax(0, 200); colour.g = 55 + IwRandMinMax(0, 200); colour.b = 55 + IwRandMinMax(0, 200); colour.a = 255; sprite->setColour(colour); // Set sprite image if ((t & 1) == 0) sprite->setImage(image1); else sprite->setImage(image2); // Add sprite to sprite manager sprite_manager->addSprite(sprite); }

Note that the code is a lot simpler than it looks. We are basically create 100 sprites giving each one a random position, random colour and alternative between two different bitmaps.

I want to point out here that using two separate images is bad practice as the underlying Iw2D render will need to switch states continually to switch between both images. To improve performance we would combine both images into a sprite sheet and then change the rectangular area within the image for each sprite.

Next we define a world transform matrix and world angle that we can modify on a per frame basis:

// Dynamic variables CIwMat2D WorldTransform; iwangle WorldAngle = 0;

Next we spin our sprites by walking the sprites list adjusting the angle of each sprite at a different rate (it would be boring if all of our sprites rotated at the same rate)

// Update all sprite rotations int speed = 0; for (CIwGameSpriteManager::Iterator it = sprite_manager->begin(); it != sprite_manager->end(); ++it, speed++) { (*it)->setAngle((*it)->getAngle() + speed); }

Now we do a bit of matrix math jiggery pokery to spin and scale our sprite manager:

// Spin and scale the sprite manager WorldTransform.SetIdentity(); WorldTransform.SetRot(WorldAngle); WorldTransform.ScaleRot((IW_GEOM_ONE / 2) + (IW_GEOM_COS(WorldAngle) / 3)); WorldTransform.SetTrans(CIwSVec2(surface_width / 2, surface_height / 2)); sprite_manager->setTransform(WorldTransform); WorldAngle += 20;

We firstly reset our world transform using SetIdentity(), think of this as setting a variable to its default value. We then set the rotation, scale and translation that all sprites within the sprite manager will transform by. Note that we set the translation position to the middle of the screen because when we created our sprites earlier we defined their positions based around the origin being at 0,0 (top-left hand corner of screen). The world translation will move them back to the middle of the screen.

We now send the world transform to the sprite manager and adjust our world angle, so everything spins.

lastly, we tell our sprite manager to go away and draw its child sprites:

// Draw our sprite manager sprite_manager->Draw();

And finally before we exit the game, we delete the sprite manager which in turn deletes all of our sprites.

// Clean up sprite manager delete sprite_manager;

I Love Concatenating Matrix Transforms

If you are wondering how we manage to spin a sprite individually as well as transform it by the worlds scale and rotation then open up IwGameSprite.cpp and take a look at CIwGameSprite::RebuildTransform()

void CIwGameSprite::RebuildTransform() { // Build the transform // Set the rotation transform Transform.SetRot(Angle); // Scale the transform Transform.ScaleRot(Scale); // Translate the transform Transform.SetTrans(Position); Transform.PostMult(Parent->getTransform()); TransformDirty = false; }

We use a matrix math track called matrix concatenation to multiple two matrices together, effectively combing both transforms into the one single transform. This following line multiplies out two matrices together:

Transform.PostMult(Parent->getTransform());

Object Pooling and Sprites

As your projects get larger and more complex you will find that you are constantly creating and deleting many objects. The constant process of allocating and deleting objects can take its toll on the memory management system, which causes something called fragmentation. Fragmentation is when your available memory pool consists of many small chunks instead of a few large chunks. Depending on the memory management system in use, this can increase the overhead of allocating future objects and risk the chance of running out of memory even though the system is reporting plenty of free memory (this happens because there isn’t a large enough chunk of contiguous memory available to allocate).

To help alleviate this problem we can pre-allocate a large number of objects in one go instead of lots of little ones at random times during the game. This is usually called an object pool.

The problem with C++ is that it doesn’t work very well with object pools because:

  • The objects in the pool usually all need to be of the same type
  • Constructors are usually called to construct and set up your object
  • Destructor’s are usually called to destroy and clean-up your object

We can get around the last two problems quite easily by emptying out our constructors and destructors and putting the code into Init() and Release() methods instead. This will allow us to setup and tear down objects without every having to recreate or delete them. Also, for certain types of objects (those that need to be reset to a default state) I like to add a Reset() method which allows me to set the object back to its original state.

The first problem is a lot more difficult to deal with, but the easiest solution is to simply create object pools for each type of object that you want to pool.

Pooling objects is as easy as allocating a bunch of them during game boot and then using some kind of marking system to mark them as in use or not in use. Instead of creating a new object you would simply search the object pool for a object that is not in use then reset it and use it. The only thing to do is to delete the object pool before you exit your game.

Well that’s it for this tutorial. Our next tutorial will handle adding frame based animations to our bitmapped sprite system which will allow us to truly walk the path of making a cool game.

You can download the code that accompanies this article from here.

Hope you all find this blog useful and until next time, don’t forget, dont read my blog at the wheel!

General Programming Tutorials – Beautiful Classes

Welcome to my first blog on general programming techniques and object oriented software design patterns, part of my general programming series . I’m sharing these programming techniques and software design patterns with you in the hopes that it will enable you to write more readable, functional, re-usable and extensible code, saving you both time and money in software development.

This blog article is going to cover some standard basic class layout techniques that I use to keep classes neat and readable. Please note that class layout and design is a very subjective subject, so this may not be the most efficient or perfect way of laying out classes but I find that it works great for my needs.

All code outlined within my articles will be mainly based around the C++ language. I may include other languages now and again.

Beautiful Classes

When I design classes I tend to think about aesthetics as well as functionality. I like my class to basically look good and appear very readable

Here is the basic layout that I use for most of my classes:

class MyClass { // Section 1 - Public enums, typedefs and static data. //// Public Types public: typedef unsigned int u_int; //// Public Types End // Section 2 – Properties (Provides public access to class properties via getters and setters) //// Properties private: int ClassData1; bool ClassData2; public: void setClassData1(int data) { ClassData1 = data; } int getClassData1() const { return ClassData1; } void setClassData2(bool data) { ClassData1 = data; } int getClassData2() const { return ClassData1; } //// Properties End // Section 3 - Private / protected types, class data and methods (used by the class internally only) //// Class Internals private: bool PrivateClassData; //// Class Internals End // Section 4 - Construction / destruction and initialisation //// Initialisation public: MyClass() : ClassData1(0), ClassData2(false), private_class_data(false) {} ~MyClass() {} bool Init(); void Release(); //// Initialisation End // Section 5 - Public access class functionality //// Public Access public: void DoSomething1(); void DoSomething2(); //// Public Access End };

I usually split my classes into 5 sections:

  • Section 1 – Public enums, typedefs and static data
  • Section 2 – Properties provide public access to class private data via getters and setters. A property can be thought of as a private class variable that you want to allow the outside world to change but in a safe manner.
  • Section 3 – Private / protected types, class data and methods (used by the class internally only)
  • Section 4 – Construction / destruction and initialisation. Note that I usually like to move all class initialisation code out of the constructor and place it into my class Init() method, same goes for  the destructor and the Release() method. This allows me to re-initialise and tear down a class without having to actually new or delete it. This can prove very useful in many situations such as object pooling to reduce memory fragmentation, where the idea is to preserve the class and re-use it.
  • Section 5 – Public access class functionality

I find that this kind of system helps me to determine where to quickly look inside my classes to find what I need.

The Big List of Android App Stores – Where to sell and what to avoid

This list has been replaced by a new and updated list that I now host on my app and game marketing blog at Free Games Bandit

Welcome fellow Android developers! So you wrote the latest smash hit Android game or app but want to know where do you sell it? How do you maximise your app or games exposure to the Android community and increase your potential sales / return on investment (ROI)?

It cannot be denied that Android smart phones and tablets are here to stay. The market share for Android is continually growing, up 5.8% last quarter to a staggering 41.8% of the US market (see my blog on who rules the roost). With the Amazon Kindle Fire tablet on the brink of release at the stupidly low price of $199, I think we are going to see an even bigger shift in Android adoption rates coming towards the end of 2011.

Whilst revenue from paid apps and games aren’t doing so well when compared to the likes of iOS and RIM, Android users will download free and freemium content in droves. This creates a wealth of opportunity for the smart developer.

Selling your Android products is a slightly different ball game when compared to selling them on platforms such as iOS, Bada and Windows Phone 7 etc. because the Android platform is an open system. If you are originally from an iOS / Bada / WP7 dev background then you are in for a bit of a shock (Symbian, Windows Phone and Java developers already know the score).

This wonderful open doors Android system (from the perspective of Android game and app publishers / distributors) however does create a certain amount of fragmentation when it comes to selling / promoting your apps and games to app users and gamers. Some app developers will see this as a bane whilst other app developers will see this as a golden opportunity. I am personally starting to lean on the golden opportunity side of the fence.

The Pros and Cons of a Fragmented Android Market

Whilst a lot can be said about Android’s open doors model for its app distribution system, it does have some clear pros and cons:

Pros

  • Your app or game gets featured in the new / updated sections of each separate app store instead of just the one which gives increased exposure, which in turn increases the chance of getting a hit product
  • You can set the price of your app or game on a per app store basis
  • Some Android app stores will carry content that others will not. For example, the MiKandi market distributes adult content for Android but most other Android app stores do not
  • Some Android app stores inadvertently drive sales on other stores. For example, there is evidence to suggest that releasing a product for free on Slideme can drive sales on the Android Market
  • The main Android app store (Google Android Market) does not allow the developer to switch from free to paid and back again, which completely rules out price-playing marketing tactics. This is however possible on other Android app stores, although changing your price on some app stores (Appia driven app stores for example), there will be a lag between you changing your price and the price changes rolling through to the stores (can sometimes take weeks, if at all)
  • Anyone can sell and distribute Android apps and games  including you the developer. This creates a huge potential opportunity for developers, especially free and freemium app developers

Cons

  • Some Android phones and tablets are locked into certain app stores so if you do not launch your product on those stores then you will be losing out on a significant market
  • Each Android store has its own set of submission guidelines, rules and art asset requirements that you need to adhere to in order to launch your apps and games on that store. This can prove to be a real pain.
  • Updating your products across all Android app stores is very difficult and can be hard to track
  • Many Android app stores have their own licensing check SDK to help prevent piracy (not a problem if you are going for free or freemium app model)
  • Tracking sales across all Android stores takes a while (not a problem if you implement analytics such as Flurry)
  • Promoting  your app or game  on each individual store can be difficult and potentially costly

I’m sure that if I sat here all day, I could probably fill up a few pages with more pros and cons, but alas I want to introduce you to the myriad of Android app stores out there.

The Big List of Android App Stores

Here’s the current list of Android app stores that I’ve built up over the last year or so (some also support other platforms such as iOS, Blackberry, Java and Windows Mobile) where you can sell or upload your wares. Note that some only accept free apps and games whilst others will accept both free and paid apps and games.

And a couple of Android warez sites that can drive big download numbers to free apps:

I have put the app stores in order of importance, so you should submit to those stores in the order provided above. This will allow you to safely ignore the stores lower down the list which do very little in terms of sales and downloads. If you are going free / freemium then you should try hit every single store, especially those listed as supporting only free apps and games.

If you want to see a few download figures across a number of Android stores then check out one of my previous blogs on the subject at
http://www.drmop.com/index.php/2011/08/20/android-apps-the-hard-sell-comparison-of-android-app-stores-included/

The figures are now a bit out of date, but they are definitely a surprising read.

A Few Note-worthy Android App Stores

After submitting a number of apps to the various app stores listed above, its worth mentioning some of our experiences. I have also called out a few other app stores that are quite unique and operate differently to what developers usually think of as an app store.

Google Android Market

The Google Android Market is a good app store in general and many Android phones do have access to it, but not all. Downloads and sales are supposed to update a few times per day, but from what we have observed, they update randomly. We can see no changes for weeks and then all of a sudden we see changes a few times per day. The Android Market also has a 15 minute returns clause, whereby a user can purchase your app and return it within 15 minutes if they do not like it. You will find that a lot of users will purchase your game or app then immediately cancel the purchase. We are not sure why this happens

Appia

Appia are a hidden jewel as far as we are concerned. They supply many app stores across the net including the likes of Handango, Pocketgear and Mobile2day. Our free apps on Appia are beating our Android Market downloads by 600%. Our paid apps sales are however doing less well than the Android Market.

Amazon App Store

Sales on the Amazon Android app store are, how can I put this (abysmal?) and in fact, if Amazon didn’t reduce our price to $0.00 for us then we would probably have no sales. Be warned, if you drop the price of your app or game below the list price you set on Amazons app store then be in for a telling off (we have been bollocked twice already). When you sign up with Amazon you agree to keep your Amazon list price the lowest across all app stores. If you have an app or game that relies heavily on an external service that you have to pay to maintain then be careful about letting any app store reduce your price to free as you could end up with a boat load of free customers to support.

Exent

Exent is actually a subscription service and not a traditional Android app store. Exent allow users to play your games for free, but you are paid a percentage of the subscription that users pay for the service, based upon how often your game has been played.

AppBackr

AppBackr is kind of a unique aopp store in that its targeting users that want to make money from your apps. Instead of selling apps, they ask their users to invest in the apps by committing to purchasing X copies of your app. When the app sells they get the profits.

Mobireach

Mobireach can submit your content to other stores such as AT&T, Nook store, HUHU and MT2, but you must agree to the terms and conditions of the stores. once you are signed up and you have submitted your content, click on Channel Connect->Channel Opt-in and agree to each of the terms and conditions then submit your apps for approval to these stores.

Vodafone (UPDATED)

Best to avoid Vodafone, their new content standards are shown below:

  • Have had a high number of downloads and consistently good reviews in other Android Market places
  • Are updated frequently
  • Are leaders in their category, and fit in with our specific catalogue/portfolio requirements
  • Have good coverage of languages/territories covered by our Market.
  • Have won industry awards and are recognised brands
  • Demonstrate significant innovation

Which translates to “If you app or game is not one of the best selling with great reviews in its category then forget it”. Some how I don’t think that Vodafone’s app shop is going to be very successful with such little choice.

Verizon Wireless

Verizon Wireless is another on operator deck and a little more forgiving than Vodafone when it comes to submissions / certification. The only down side and bonus (double edged sword I’m afraid) is that in order to get your product marketed, you need to provide a lot of high resolution vector art work to what Verizon call “The Machine”. The Machine is basically a marketing machine where you submit your marketing materials for approval. I’m assuming that once submitted and approved that Verizon will somehow use them for marketing your products.

Slideme

Slideme have an updated section on their front page, whenever you make an update to your app it will appear at the top of this section. You can update quite often to increase visibility. I see SlideMe popping up all over the place lately so I did a little more digging. It would appear that SlideMe have many partner stores (much like Appia), particularly with OEM’s such as HTC, Samsung, LG, Motorola, Sony Ericsson, Acer, Asus/Garmin, Olivetti/Telecom Italia, Hewlett Packard, Pandigital, PeopleOfLava (Android TV), HCL that filter the content based on their target markets. Various enterprises even use SlideMe as a private distribution channel!

A Few Tips to Help you Beat the Guidelines

I have listed below a number of technical issues that you should be aware of to ensure that your game or app sails smoothly through the various app stores submission and certification processes:

  • Handle the back and menu buttons – Ensure that the back button takes the user to the previous screen or menu and that the menu button brings up your in-app / game menu
  • Deep linking – If you add links into your app that point to other apps that are available on another app store (and the store you are submitting to), then ensure that the links point to the version on the app store that you are submitting to. For example, of you submit a free / lite version of your game to the Amazon app store then ensure that the buy link points to the paid version on the Amazon app store and not some other app store. Same thing goes for advertising other app stores within you app.
  • Screen shots – Ensure that your screen shots are of the most up to date version that you are submitting. if you app is ad supported then ensure that the screen shot shows the ads (our last build of Funky Cam 3D failed on this one)
  • Make sure that your on-device app icon reasonably matches the icon you use to represent your app on the app store
  • Make sure you get your AndroidManifest file right. If you use the camera for example then ensure that its set the camera uses permission in your manifest file
  • Ensure that you increment your app version every time you submit a new version
  • If your app requires some kind of special testing then let the app store know up front.
  • If you know for certain that your app does not work on certain devices then let the app store know up front

Preparation for Submissions Across Multiple Android App Stores

Submitting your app to a large number of Android app stores requires a little preparation which is best done up-front. Below I have put together a small list of useful pieces of information that will help you prepare all of the information you are going to need up front

  • Write a short 10 word marketing description
  • Write a short 25 word marketing description
  • Write a long marketing description (plain text and HTML)
  • Produce a short list of potential categories that you app or game should fit into
  • Create a list of comma separated keywords that you think users will be using to find apps and games just like yours (20 keywords max), put them in order of importance so you can cull less important ones, as some app stores allow less than 20 keywords
  • Collect together 5 of your best screen shots and re-create them in the following sizes (save them in both JPG and PNG formats):
    • 320 x 240
    • 240 x 320
    • 480 x 320
    • 320 x 480
    • 800 x 480
    • 480 x 800
  • Create versions of your app icon in the following sizes (PNG format):
    • 512 x 512
    • 500 x 500
    • 480 x 480
    • 400 x 400
    • 200 x 200
    • 150 x 150
    • 142 x 142
    • 128 x 128
    • 114 x 114
    • 85 x 85
    • 80 x 80
    • 75 x 75
    • 72 x 72
    • 70 x 70
    • 64 x 64
    • 60 x 60
    • 57 x 57
    • 50 x 75
    • 50 x 50
    • 40 x 40
    • 38 x 38
    • 32 x 32
    • 30 x 30
  • Create some marketing / promotions images::
    • 480 x 120 banner
    • 180 x 120 promo image
    • 1024 x 500 feature image
    • 120 x 180 promo image
  • Produce a short video of your app or game in action (not essential)
  • Produce a short QA FAQ in Doc and PDF format

I will keep updating the big list of Android app stores as I discover more. if you know of a store that you would like to see on this list then please let me know

If you want to monetise your apps by taking them across to other platforms which I highly recommend then I suggest you take a quick peak at my blog on the benefits of porting to other platforms, along with details on the incredible cross platform SDK, the Marmalade SDK

I hope that this little post truly does help increase your sales / downloads
Good luck with your sales and downloads!

Marmalade SDK Tutorial – Dealing with files and the file system

This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index click here

This evening we are going to cover dealing with files and the file system in a cross platform manner using the Marmalade SDK. Note that there is no associated code with this tutorial as it is not required.

To begin with, you will notice that Marmalade’s file functions look and behave very much like those in the standard C library, for example:

s3eFile * s3eFileOpen (const char *filename, const char *mode) FILE * fopen (const char *path, const char *mode)

Paths in Marmalade

Paths with the Marmalade SDK follow the same approach as many other file systems in that they follow the drive, directories and filename pattern (drive:/folder1/folder2/file.extension).

The Marmalade SDK currently supports the following drive names:

‘rom’ for the read-only portion of your apps data area and is read only.
‘ram’ for the writable portion of your apps data area. This drive is the only drive that is guaranteed to exist across platforms
‘rst’ for a removable memory card on the phone or tablet
‘raw’ for paths that will be passed directly to the underlying operating system without modification. (not supported on all platforms)
‘tmp’ for a system temp folder, outside of the s3e data area. (system temporary folder and currently only available on iOS)

Path length is limited to S3E_FILE_MAX_PATH characters (that value is currently 128 bytes, including the NULL string terminator)

Paths can be relative or absolute

Note that when reading a file where no drive has been specified the file system will attempt to find the file on the ram drive. if the file was not found then the system will look to the rom drive.

Marmalade SDK s3e file functions separated into categories

I have separated Marmalade’s s3e file functions into categories to make them easier to find. If you would like to see more details on each of these functions then take a look at the  Marmalade SDK s3E file reference online help doc

Opening and closing files

s3eFile *  s3eFileOpen (const char *filename, const char *mode)
s3eFile *  s3eFileOpenFromMemory (void *buffer, uint32 bufferLen)
s3eResult  s3eFileClose (s3eFile *file)

File query

s3eBool   s3eFileCheckExists (const char *filename)
int32     s3eFileGetSize (s3eFile *file)
int32     s3eFileGetInt (s3eFileProperty property)
int32     s3eFileTell (s3eFile *file)
int64     s3eFileGetFileInt (const char *filename, s3eFileStats stat)
char *    s3eFileGetFileString (const char *filename, s3eFileStats stat, char *str, int len)
uint64    s3eFileGetLastWriteTime (const char *filename)
uint64    s3eFileGetFree (s3eFilePath path)

File reading / writing / seeking

s3eResult s3eFileFlush (s3eFile *file)
int32     s3eFileGetChar (s3eFile *file)
s3eBool   s3eFileEOF (s3eFile *file)
int       s3eFilePrintf (s3eFile *f, const char *fmt,...)
int32     s3eFilePutChar (char c, s3eFile *file)
uint32    s3eFileRead (void *buffer, uint32 elemSize, uint32 noElems, s3eFile *file)
char *    s3eFileReadString (char *string, uint32 maxLen, s3eFile *file)
s3eResult s3eFileSeek (s3eFile *file, int32 offset, s3eFileSeekOrigin origin)
uint32    s3eFileWrite (const void *buffer, uint32 elemSize, uint32 noElems, s3eFile *file)

File and folders deletion / renaming

s3eResult  s3eFileDelete (const char *filename)
s3eResult  s3eFileRename (const char *src, const char *dest)
s3eResult  s3eFileDeleteDirectory (const char *dirName)
s3eResult  s3eFileMakeDirectory (const char *dirName)

Directory Recursion

s3eResult     s3eFileListClose (s3eFileList *handle)
s3eFileList*  s3eFileListDirectory (const char *dirName)
s3eResult     s3eFileListNext (s3eFileList *handle, char *filename, int filenameLen)

File error checking

s3eFileError  s3eFileGetError ()
const char*   s3eFileGetErrorString ()

Reading a file example

s3eFile* file = s3eFileOpen(“myfile.txt”, "rb"); if (file != NULL) { if (s3eFileRead(buffer, len, 1, File) != 1) { s3eFileGetError(); s3eDebugOutputString(s3eFileGetErrorString()); } s3eFileClose(File); } else { s3eFileGetError(); s3eDebugOutputString(s3eFileGetErrorString()); }

Writing a file example

s3eFile* file = s3eFileOpen(“myfile.txt”, "wb"); if (file != NULL) { if (s3eFileWrite(buffer, len, 1, File) != 1) { s3eFileGetError(); s3eDebugOutputString(s3eFileGetErrorString()); } s3eFileClose(File); } else { s3eFileGetError(); s3eDebugOutputString(s3eFileGetErrorString()); }

As you can see the file system is pretty simple to use and doesn’t particularly warrant an example demo to accompany it, so I haven’t written one.

It is worth noting that the file system also supports a call back system that allows you to implement your own file system. I will cover this in a more advanced tutorial.

Reading files within a compressed derbh file

It is possible to attach compressed derbh files to the file system and re-direct all file access to the archive, accessing these archives just like a regular file. To do this you call dzArchiveAttach(“my_archive.dz”);. Note that you can attach multiple archives

To detach the archives afterwards you would call dzArchiveDetachNamed(“my_archive.dz”); or dzArchiveDetach() to detach the last attached archive.

It’s also possible to attach and detach memory based archives using dzArchiveAttachFromMem(void* pMem, uint32 size); and dzArchiveDetachFromMem(void* pMem);

Using this system makes accessing data within compressed archives a doddle.

To use derbh functionality within your app or game you need to include add the ‘derbh’ sub project to the list of subprojects section of your project MKB file.

Creating Derbh (.DZ) Files Manually

Ok, so now you know how to access Marmalade compressed archive, but how do you actually create one? In the folder \Marmalade\5.1\tools\dzip you will find a tool called dzip.exe. You can use this tool to create a derbh compressed archive by supplying it with a .DCL configuration file. This file basically contains a small amount of header information along with the files that you would like to be included into the archive. Here is an example .DCL file:

archive my_archive.dz basedir . file image1.png 0 zlib file image2.png 0 zlib file image3.png 0 zlib file image4.png 0 zlib

basedir – The base director of the source input files

It is possible to specify which compressor to use on a per file based. In this case we use zlib compression, other values include lzma, dz, zero and copy.

Well that’s it from me and that’s it from him for today.

Happy coding and please don’t ever become a door to door sales PERSON! Seriously, those guys / gals do not know the meaning of the word “NO”!

Marmalade SDK Tutorial – Quick and easy audio and music using s3eAudio and IwSound

This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index click here

Today we are going to cover playing sound and music the very quick and very easy way using the Marmalade SDK. As usual if you just want the associated article source code then you can Download it from here. If you want the details on sound and audio with Marmalade then please read on.

I like to separate audio playback into two distinct categories, which are music and sound (or sound effects). The Marmalade SDK has two systems for playing audio:

  • S3E Audio – The S3E audio system uses the devices built-in codec’s to play back compressed audio files such as MP3. QCP and AAC (good for playing background music)
  • S3E Sound – The S3E sound system uses software mixing to play multiple uncompressed sounds simultaneously (good for playing back sound effects, such as button clicks or in-game sound effects)

Now a little more detail

S3E Audio

S3E audio uses the devices built in audio codec’s to play back compressed audio files such as MP3. QCP and AAC, although you do need to query the system to find out if the audio format is supported using
s3eBool s3eAudioIsCodecSupported ( s3eAudioCodec codec )

Valid codecs include:

  • S3E_AUDIO_CODEC_MIDI – MIDI files.
  • S3E_AUDIO_CODEC_MP3 – MP3 files.
  • S3E_AUDIO_CODEC_AAC – Raw AAC files.
  • S3E_AUDIO_CODEC_AACPLUS – AAC plus files.
  • S3E_AUDIO_CODEC_QCP – QCP files.
  • S3E_AUDIO_CODEC_PCM – PCM files.
  • S3E_AUDIO_CODEC_SPF – SPF files.
  • S3E_AUDIO_CODEC_AMR – AMR files.
  • S3E_AUDIO_CODEC_MP4 – MP4 or M4A files with AAC audio.

This s3e audio system can play back audio from either a file or a memory buffer. Note when you play back a file you cannot play a file that is within a compressed derbh file as the device does not know about Marmalades derbh format. If you are using auto derbh to auto compress all of your data on deployment then you should include the audio file as an asset in your MKB’s asset section and not inside a resource group.

Here is a summary of a number of important s3e audio functions:

  • s3eBool s3eAudioIsPlaying ()
  • s3eResult s3eAudioPause ()
  • s3eResult s3eAudioPlay (const char *filename, uint32 repeatCount)
  • s3eResult s3eAudioPlayFromBuffer (void *buffer, uint32 bufferLen, uint32 repeatCount)
  • s3eResult s3eAudioResume ()

Its pretty obvious what these functions are doing so I wont go into any details other than to mention that passing a value of 0 to repeatCount causes the music to repeat playback forever.

S3E Sound

I’m not actually going to cover S3E in much depth as I did promise quick and easy sound, instead I will use the example sound engine that ships with Marmalade (located in $MARMALADE_ROOT/examples/SoundEngine). SoundEngine sits on top of S3E Sound, so if you want to see the internals of the code it’s right there for you to study. If you want to implement your very own audio engine then I suggest you start by checking out Marmalade’s s3e sound docs here

Marmalade’s Sound Engine (IwSound)

Marmalade’s IwSound example sound engine lets you easily organise sounds into resource groups and then playback and control these sound effects very easily in-game. Even though IwSound is an example sound engine it is very capable and covers much of which most developers need. In my opinion it should be included as a standard Marmalade SDK module.

Before we begin looking at the code we will take a quick look at some of the important classes that make up IwSound.

  • CIwSoundData – This class represents the actual data of your sounds (you do not need to deal with this class directly)
  • CIwSoundSpec – This class describes a sound, think of it as a sound material that specifies details about your sound data and how you want it played. You create instances of sounds from their sound specs.
  • CIwSoundInst – This class represents a playing instance of a sound spec, a new CIwSoundInst is returned each time you play a sound from a sound spec (internally these are pooled to reduce memory fragmentation). Its worth noting here that you can only play a finite number of sound effects simultaneously.
  • CIwSoundManager – The sound manager, used to update the sound engine and gives access to such things as master volume, pan and pitch etc.. The sound manager also uses the following app.icf setting to allow you to set the maximum number of simultaneous sound effects that can be played:

[SOUND]
MaxChannels=16

Ok, now we have a basic understanding of the classes we are going to use, lets take a look at how to play something.

// Get a pointer to the sound group CIwResGroup* sound_group = IwGetResManager()->GetCurrentGroup(); // Get the sound spec for our silly_sound sound effect CIwSoundSpec* SoundSpec = (CIwSoundSpec*)sound_group->GetResNamed("silly_sound", IW_SOUND_RESTYPE_SPEC); // Play the sound effect CIwSoundInst* SoundInstance = SoundSpec->Play();

And that’s all you need to load and play sounds from a group

If you would like to change attributes of the played back sound effect, such as its volume, frequency etc.. then you can call the following functions on the sound instance:

  • void SetVol(iwsfixed vol);
  • void SetPan(iwsfixed pan);
  • void SetPitch(iwsfixed pitch);
  • void Stop();
  • void Pause();
  • void Resume();

Note the vol, pan and pitch are fixed point parameters (IW_GEOM_ONE representing the value of 1.0f)

Also note that you should never delete sound instances as they are managed by the IwSoundManager. Sound specs are managed by the resource system so do not delete those either.

Lastly, the IwSound engine manager Update method needs to be called every frame:

IwGetSoundManager()->Update();

Creating and organising sound effects with IwSound

Ok, we have looked at the basics of playing sound using IwSound, now we will look at how to organise our sounds into groups to allow the resource manager to manage them for us. If you do not know what the resource manager is then take a look at one of my previous blogs on the subject here

Firstly we need to add the WAV files that represent our individual sound files to the group like this:

// Sound sample WAV files "./silly_sound.wav" "./explosion.wav"

Next we create a CIwSoundSpec for each sound effect that we want to play:

// Create sound specs (can be thought of as sound materials) CIwSoundSpec { name "explosion" # The name we want to use to refer to this sound effect in our code data "explosion" # The wav file name (without .wav) vol 0.7 # Default volume to be played at loop false # Do we want this sound effect to play forever? } CIwSoundSpec { name "silly_sound" # The name we want to use to refer to this sound effect in our code data "silly_sound" # The wav file name (without .wav) vol 0.7 # Default volume to be played at loop false # Do we want this sound effect to play forever? }

Finally, we create a sound group to contain all of our sound specs:

// Create a sound group to contain all of our sound specs CIwSoundGroup { name "sound_effects" # Name of our sound group addSpec "silly_sound" # Add the silly_sound sound spec to our sound group addSpec "explosion" # Add the explosion sound spec to our sound group }

To save you hours of pulling your hair out and trying out different WAV formats, it’s worth noting that IwSound supports mono PCM (8 and 16 bit) and mono ADPCM (IMA but not Microsoft’s) WAV formats.

And finally finally, you need to add this code somewhere at the start of your main() function so that the resource manager can convert your WAV files into a usable format when you run the resource build mode (Win32 debug build will build resources used by the resource manager)

#ifdef IW_BUILD_RESOURCES IwGetResManager()->AddHandler(new CIwResHandlerWAV); #endif

This line basically adds a WAV resource handler to the resource management system so that when it loads your .WAV files during resource build mode it knows how to convert them.

What’s changed in our example code

We are basing our new Audio example project on the previous Resources example code. Firstly we will deal with what’s changed in our project MKB file, then we will deal with changes to Main.cpp source code and Level1.group resource group file.

If you view the Audio.mkb project file you will notice that we have added a module_path to the options section of our MKB:

options { module_path="$MARMALADE_ROOT/examples" }

This tells Marmalade where to look for modules. In our case we are directing Marmalade to look in the examples folder within the SDK as this is where the IwSound engine is located

Next we have added the SoundEngine module to our sub projects section to enable us to use the IwSound code:

subprojects { iw2d iwresmanager SoundEngine }

And lastly we add our music.mp3 test music file to the assets section of our MKB to make it available when deploying to devices:

assets { (data) music.mp3 (data-ram/data-gles1, data) Level1.group.bin }

Now lets turn to Main.cpp to see what has changed. Firstly we included the header file for IwSound:

#include "IwSound.h"

Then we initialise the IwSound module using:

// Init IwSound IwSoundInit();

We also added some code to ensure that our WAV resources get built during a resource build Win32 debug build run:

#ifdef IW_BUILD_RESOURCES // Tell resource system how to convert WAV files IwGetResManager()->AddHandler(new CIwResHandlerWAV); #endif

In addition, we added code to play our test music.mp3 file (Remember, s3e Audio uses the devices audio player so we firstly have to check that the device supports the MP3 codec):

// Play some MP3 music using s3e Audio (if the codec is supported) if (s3eAudioIsCodecSupported(S3E_AUDIO_CODEC_MP3)) s3eAudioPlay("music.mp3", 1);

Next we tell IwSound to update every frame by placing a call to IwGetSoundManager in our main loop:

// Update Iw Sound Manager IwGetSoundManager()->Update();

This ensures that the sound system and sound instances etc.. get updated regularly. Note that if you find that you play a few sound effects and then no more will play then you have missed out this line!

And now the juicy bit, here we find our explosion sound effect within the Level1 group and play it:

if (!PrevTouched) { CIwSoundSpec* SoundSpec = (CIwSoundSpec*)Level1Group->GetResNamed("explosion", IW_SOUND_RESTYPE_SPEC); CIwSoundInst* SoundInstance = SoundSpec->Play(); }

And finally before we exit the demo we shut down IwSound using:

// Shutdown IwSound IwSoundTerminate();

Ok, so now we’ve been through the changes to Main.cpp lets take a look at the changes to our resource group file Level1.group.

The first thing you will notice is that it contains a lot more stuff, that is mainly down to the fact that we need to define CIwSoundSpec for our sound effect as well as a CIwSoundGroup to include our sound specs in.

You will notice that the first addition is our sound effect wav file:

// Sound sample WAV files "./explosion.wav"

Next we create a sound spec (material) for our sound effect so that it can be played in-game:

// Create sound specs (can be thought of as sound materials) CIwSoundSpec { name "explosion" # The name we want to use to refer to this sound effect in our code data "explosion" # The WAv file name (without .wav) vol 0.7 # Default volume to be played at loop false # Do we want this sound effect to play forever? }

Lastly, we create a group to contain our sound spec:

// Create a sound group to contain all of our sound specs CIwSoundGroup { name "sound_effects" # Name of our sound group maxPolyphony 8 # Maximum sounds that can be played simultaneously killOldest false # Tell system not to stop the oldest sound effects from playing if we run out of channels addSpec "explosion" # Add the explosion sound spec to our sound group }

Ok. that’s it from me for now on audio, hopefully you find enough info in this article and source to be able to add sound and music to your games and apps. You can download the associated Audio project source code from here

I will update this blog article in the near future to act as a full reference for IwSound

Happy coding and don’t play with a grenade that has no pin!

Marmalade SDK the ultimate cross platform SDK for phone, tablets and emerging technologies – the best kept secret?

I spent a few days browsing the web from the point of view of a potential developer looking for a cross platform development software developer kit (SDK)  and I was very surprised and woefully disappointed to find that very few developers are actually aware of the existence of the Marmalade SDK. This tallies with the many developers that I have spoken to over the last year or so and introduced to the Marmalade SDK, who had no idea that it existed.

I searched social media, Google, Bing and other search engines as well as a number of well known developer forums for terms such as “cross platform development”, “cross platform sdk”, “cross platform phone sdk”, “cross platform mobile development” and many others. I came across many top 5, top 10 cross platform SDK’s etc.. but the Marmalade SDK was not listed on any of them. I did leave behind a few posts mentioning the Marmalade SDK to the original posters, so hopefully they will pick up on it and mention it.

We have been using the SDK for over a year now, launching a game across 5 platforms and an augmented reality app across 4 platforms with great ease and very little effort. We also have three additional games in development using the Marmalade SDK, so we have a fair amount of experience with the SDK.

The thing is, the Marmalade SDK is a remarkable piece of software engineering that appears to be  largely going unnoticed by the wider developer community. I mean you can deploy the same native code and in some cases the same art and audio assets to 10 platforms including emerging platforms such as LG TV. I have looked at many of the cross platform SDK’s and cannot find anything  that can directly compete. Some of the HTML / Javascript SDK’s offer wide platform support which is cool but don’t really offer the raw native speed that the Marmalade SDK does.

Here are a few cool things to know about the Marmalade SDK:

  • Marmalade supports 10 platforms to date, including iPhone, iPod Touch,  iPad, Android phone and tablets, Samsung Bada, Blackberry Playbook, Symbian, webOS, Windows, OSX, Mobile Linux and LG TV
  • Producing 2D & 3D games with Marmalade is very simple as all of the components are already written for you using the 3D Studio Max / Maya / Collada exporters and graphics, math and audio modules
  • Marmalade has good UI and font support as well as native access to UI coming October 2011. Coupled with existing Marmalade modules such as http access, video, web view and others, Marmalade allows the user to create apps as good as in in many cases better than using native platform SDK’s
  • Marmalade EDK allows developers to use native platform specific plugins
  • Code developed using the Marmalade SDK is compiled as tight as is possible using modern ARM & MIPS compilers
  • Marmalade SDK deployed apps do not need to carry around bloated VM’s or other unnecessary baggage, ensuring that deployed app sizes are minimal
  • Marmalade SDK allows high and low hardware access
  • Marmalade SDK has some great out of the box modules that support the likes of iOS iAds, game centre, in–app purchasing, market billing and web views.
  • With Marmalade you simply build and deploy your game directly to the phone or tablet on a PC or a Mac, no other hardware required
  • Amazing support, including the apps program and device loan program to aid testing
  • A simulator that lets you test across an unlimited set of screen resolutions and simulated access to Accelerometer, GPS, Camera, Audio, Multi-touch screen, SMS, Compass and more
  • Test actual ARM code without even deploying to an ARM based device
  • Access to a large collection of open API’s such as Box2D, AdMob, Flurry, Chipmunk,SVG, Python, LUA and tonnes of other cool stuff (Full list available at http://github.com/marmalade)

If you are a happy Marmalade developer then help bring the Marmalade SDK to the wider developer community. Mention it in your blogs, tweets, Facebook posts, conversations with clients, fellow developers, PR , so on and so forth.

I have added a new page to my blog that will outline exactly what the Marmalade SDK is and cover all of the cool stuff it supports here

Also, at the end of my Marmalade SDK tutorial blog series the community should have a good basic game engine that new users can use as a base for their own games, with new advanced features added week on week.

You can find out more about the Marmalade SDK at http://www.madewithmarmalade.com/

Marmalade SDK Tutorial – Marmalade’s resource management system

This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index click here

Well, its Saturday evening and instead of being slumped up against a bar talking nonsense and singing songs of old bloody coding battles with my fellow drunks, I’m sat here writing Tutorials to educate the masses on how cool and easy the Marmalade SDK is to use 🙂

In today’s (this evenings?) tutorial we are going to cover the Marmalade SDK’s resource management system. As usual if you just want the associated article source code then you can Download it from here. If you want the details on the resource management system then please do read on.

Marmalade’s resource managements system is a big subject, but I am going to attempt to summarise and pick out the most important bits to help get you up and running with it quickly

Most if not all games and apps should use some kind of resource system to handle the large amount of graphical, audio and other resources that constitute the game or app. Marmalade provides a text based resource group file system that allows you to specify groups of resources that you would like to include in your app.

IwResManager – The Marmalade SDK resource manager

IwResManager is the name given to the Marmalades utility resource management system. To include the module into your build, you will need to edit your project MKB file and add the iwresmanager module to your sub projects:

subprojects { iwresmanager }

You will also need to include the IwResManager.h header file

The resource manager has three functions:

  • Loading of resources file from their original source files. For example inefficient BMP’s , huge model text descriptor files etc..
  • Serialisation of resources to and from their compact binary format. As an example, the serialisation module would save the raw BMP’s, model text descriptors etc.. in a more compact format file called group_name.group.bin
  • Organising resources into groups using group text files. For example, you may want to organise all of the bitmaps for each level into a separate group then load the whole group per level

So as you can see IwResManager has quite a few uses, but its most important use is allowing you to specify your assets in a bulky format and have the resource manager compact them down into a more efficient format for deployment.

Oh, IwResManager will only rebuild the compact binary files from the original sources if you run the x86 Debug build. So if you wondering why your resource group bin files never change, you now know why.

To initialise the resource manager in code you need to call IwResManagerInit() at boot and then IwResManagerTerminate() to close it down at the end of your app.

Resource Manager Groups

All resources exist inside the resource manager in groups. You create groups using a simple text file format (Level1.group for example) that looks something like this:

CIwResGroup { name "Level1" // Level 1 image files "Level1/background.bmp" "Level1/SpriteSheet1.png" "Level1/SpriteSheet1.png" // level 1 audio files “Level1/music.wav” “Level1/sfx1.wav” “Level1/sfx2.wav” “Level1/sfx3.wav” “Level1/sfx4.wav” // Child groups “Characters\buddy_bod.group” “Characters\evil_twiggy.group” }

This group is named Level1 and contains 3 images, 5 sound effects and two other group. Note that the groups included here are known as a child groups. These groups are independent group files, just like this one but containing resources specific to buddy_bod and evil_twiggy.

Resources in the child groups will not be included in the parent resource binary file when serialised as they are groups in their own right, instead a link between them and the parent Level 1 group will be kept so that when you load the parent group, the child groups will also be loaded.

Loading Groups

Firstly, in order for Marmalade to see your group file on the target phone, tablet etc.. the corresponding group_name.group.bin file needs to be added to assets section like this:

assets { (data-ram/data-gles1, data) Level1.group.bin }

But where does this “Level1.group.bin” file come from? Remember I mentioned earlier that a debug build will build the compact binary versions of your resources, well this file is the compact binary version of your Level1 resources group file, which contains your BMP’s and WAV’s.

Next, to load the group in code you would call:

IwGetResManager()->LoadGroup(“Level1.group”);

Note that each time you call LoadGroup() each new group will be added to the resource manager.

Searching Groups

To find a particular named group in the resource manager you would call something like:

CIwResGroup* pLevel1Group = IwGetResManager()->GetGroupNamed(“Level1”);

To find a resource within that group you would call something like:

CIwTexture* pBackgroundTexture = (CIwTexture*)pLevel1Group->GetResNamed(“background”, “CIwTexture”);

A few notes:

  • Searching for a resource within a group will by default also search all child groups for the resource
  • You do not need to supply the type of resource such as “CIwTexture”, but it is recommended for speeding up searches
  • You can add a flag (3rd parameter) to GetResName() to modify the search. For example, if you want to ignore child group resources whilst searching then pass IW_RES_IGNORE_CHILDREN_F. See IwGxResManagerFlags definition for a complete list of flags

Destroying Groups

To destroy a resource group and all its associated resources you would use:

IwGetResManager()->DestroyGroup(“Level1”); or

CIwResGroup* pLevel1Group = IwGetResManager()->GetGroupNamed(“Level1”);
IwGetResManager()->DestroyGroup(pLevel1Group);

Compressing your resources with Derbh

The Marmalade SDK provides a mechanism by which you can compress your data to DZ / dzip files prior to or during deployment and then access the files within the compressed archive within your app or game with very little hassle. The module used for compression / decompression is called Derbh and to use it you need to add the derhb module to your list of sub projects in your project MKB file, like so:

subprojects { derbh }

You can completely automate the process of compressing all of your assets during deployment by adding the following line to the deployments section of your project MKB file:

deployments { auto-derbh }

You do not have to do anything different in your code to access your compressed assets as the decompression is transparent.

Note that you can take finer control over compression and decompression in your app as Marmalade provides derbh access via low and high level API’s that enable you to load archives on demand as well as read individual files.

And that’s about as far as I’m going to go with the resource manager for the moment. If you would like to learn more in-depth details, especially regarding the resource asset conversion process then you should check out the Marmalade SDK docs at here

What’s changed in our example

Ok, now we get to the accompanying example program. Lets take a look to see what has changed (this example is based upon the Keys example from one of our previous tutorials)

Firstly we will take a look at our Resources.mkb project file. You will have noticed that our test1.png and test2.png files are no longer listed as assets. Instead our group binary file is listed as:

(data-ram/data-gles1, data)
Level1.group.bin

Level1.group.bin now contains our PNG files

Also iwresmanager has been added to our list of subprojects

We have also added a new file to the project called Level1.group, which looks like this:

CIwResGroup { name "Level1" // Graphics "./test1.png" "./test2.png" }

This is our resource group definition file, which the Marmalade resource manager will use to build our Level1.group.bin file (when we run the debug version of the app).

Next we will take a look at what’s changed in Main.cpp. Firstly we have included the resource managers header file IwResManager.h. We have also added code to initialise the resource management system and load our Level1 group file:

// Initialise the rsource manager IwResManagerInit(); // Load our Level1 resource group into the resource manager IwGetResManager()->LoadGroup("Level1.group");

Ok, this next code change may seem a bit odd:

// Create two images from PNG resource files IwGetResManager()->SetCurrentGroup(IwGetResManager()->GetGroupNamed("Level1")); // Ensure that Level1 is the current resource group CIw2DImage* image1 = Iw2DCreateImageResource("test1"); CIw2DImage* image2 = Iw2DCreateImageResource("test2");

In the Keys code example, we created CIw2DImage’s from our test PNG files. As our PNG’s now live inside our Level1 group file instead, we need to firstly set the Level1 group as our current group and then create images from the test1 and test2 resources located inside that group.

Lastly, we shut down the resource manager

// Shut down the resource manager IwResManagerTerminate();

Ok, that’s it. You should now have enough info to start using Marmalade’s resource manager and resource groups in your own code, You can download the associated Resource project source code from here

Happy coding and don’t go to work naked!