MTG Tracker 5.7

Another core set is here: Magic 2014 Core Set, and another update of MTG Tracker is here as well.

Apart from the new set, there are a few other improvements:

  • Added Magic 2015 Core Set
  • Improved format validation (deck size & number of cards)
  • Fixes in Tournament mode
  • Minur UI and navigations tweaks
  • Added setting to disable animations on the life counter
  • Stability improvements

In particular, I want to talk about the improvements on format validation.

Improved format validation

Until now the format validation checked if the cards were valid or not. Just that.

With this update it will validate that you don’t have more than 4 copies of any card (except basic lands and *cough* Relentless Rats)

It will also validate that any constructed deck has at least 60 cards, for unknown formats the lower limit is 40 cards.

Finally, for EDH, it will specifically check that you have exactly 100 cards (general included) and that you have one copy of each card (except, again, basic lands and Relentless Rats)

In future updates the restricted list will be added to vintage with proper validation.

MTG Tracker on Google Play

MTG Tracker 5.6

WotC has just released a new set designed for draft: Conspiracy. As any new set, it has new cards, and so, a new version of MTG Tracker is released.

MTG Tracker on Google Play

Changelog:

  • Added Conspiracy
  • Added Modern Event Deck
  • Added option “Import into List” on Card Lists.
  • Minor UI tweaks
  • Improved stability

A bit more in detail

So, in addition to including Conspiracy and Modern Event Deck, other improvements have been done.

MTG Tracker has migrated away from ActionBarSherlock and now uses the official ActionBarCompat and DrawerMenu. This visually only means that the icon on the top left shows three lines when it opens a menu and an arrow when it goes back. Subtle, yet important.

The drawer menu seems to be hard to discover, so now the dashboard adds two new items, one of them called “More…” which opens the side menu. You can compare the old and new dashboards and also see the difference in the action bar icon (arrow Vs. three lines).

dashboard_comparison

Some animations have been added to the card display and the life counter, they are meant to make the user experience more enjoyable with a more playful design.

When we added multiple lists, the functionality to import cards from a text file inside an existing list was missed. It has been added again, now named “Import Into List”

And a few bug fixes, specially crashes when browsing many cards.

cardshark_header

Leonids Particle System Lib

Leonids is a particle system library that works with the standard Android UI. It is Free Software and is available on GitHub.

You can download Leonids Demo from Google Play to check out what can be done with it.

The library is extremely lightweight, it is just a jar file of 18Kb you can add to your project. You can download LeonidsLib.jar from the project page on GitHub.

Why this library?

Particle systems are often used in games for a wide range of purposes: Explosions, fire, smoke, etc. This effects can also be used on normal apps to add an element of “juiciness” or Playful Design.

Precisely because its main use is games, all engines have support for particle systems, but there is no such thing for standard Android UI.

This means that if you are building an Android app and you want a particle system, you have to include a graphics engine and use OpenGL -which is quite an overkill- or you have to implement it yourself.

Leonids is made to fill this gap, bringing particle sytems to developers that use the standard Android UI.

Code examples and features

You can get the code for all the examples on GitHub, but let’s get to the basics.

Simple one shot

Creating and firing a one-shot particle system is very easy, just 3 lines of code.

new ParticleSystem(this, numParticles, drawableResId, timeToLive)
.setSpeedRange(0.2f, 0.5f)
.oneShot(anchorView, numParticles);

When you create the particle system, you tell how many particles will it use as a maximum, the resourceId of the drawable you want to use for the particles and for how long the particles will live.

Then you configure the particle system. In this case we specify that the particles will have a speed between 0.2 and 0.5 pixels per milisecond (support for dips will be included in the future). Since we did not provide an angle range, it will be considered as “any angle”.

Finally, we call oneShot, passing the view from which the particles will be launched and saying how many particles we want to be shot.

This produces a fireworks-like effect as you can see here:

Leonids_one_shot

One Shot – Dust simulation

As an example of something used in production, this dust simulation is almost identical to the one implemented on the game Rabbit and Eggs, but made with Leonids instead of AndEngine.

new ParticleSystem(this, 4, R.drawable.dust, 3000)
.setSpeedByComponentsRange(-0.07f, 0.07f, -0.18f, -0.24f)
.setAcceleration(0.00003f, 30)
.setInitialRotationRange(0, 360)
.addModifier(new AlphaModifier(255, 0, 1000, 3000))
.addModifier(new ScaleModifier(0.5f, 2f, 0, 1000))
.oneShot(findViewById(R.id.emiter_bottom), 4);

It sets an initial rotation range and then 2 modifiers for Alpha and Scale. Using modifiers is the advanced way of managing a particle system. It allows more flexibility about the starting and end times.

The parameters for the modifiers are: initialValue, endValue, startTime and endTime. In this case, we do a scale from 0.5 to 2 in the first 1.5 seconds and a fade out from second 1 to 3.

We also set an external acceleration simulating wind.

And it looks almost exactly like the one in the game, but on a standard Android UI:

leonids_dust

Using emitters – Confeti

Another example we used on Rabbit and Eggs was confeti. This is done using two emitters one on each side of the top of the screen

new ParticleSystem(this, 80, R.drawable.confeti2, 10000)
.setSpeedModuleAndAngleRange(0f, 0.3f, 180, 180)
.setRotationSpeed(144)
.setAcceleration(0.00005f, 90)
.emit(findViewById(R.id.emiter_top_right), 8);

new ParticleSystem(this, 80, R.drawable.confeti3, 10000)
.setSpeedModuleAndAngleRange(0f, 0.3f, 0, 0)
.setRotationSpeed(144)
.setAcceleration(0.00005f, 90)
.emit(findViewById(R.id.emiter_top_left), 8);

Which looks like this:

leonids_confeti

Other details

Leonids requires minSDK 11 because it uses ValueAnimators. It should be very easy, however to use the compatibility library and make it work on Gingerbread.

The library is Free Software, you can use it, extended with no requirement to open source your changes. You can also make paid apps using it.

MTG Tracker 5.5

There is a new set coming out -Journey into Nyx- and as usual there is a new version of MTG Tracker, but it does not only add the cards from Journey Into Nyx and Duel Decks: Jace vs. Vraska, it also has some new features.

MTG Tracker on Google Play

Multiple Card Lists

Many people was using collection and / or wishlist for keeping multiple lists by saving them and importing them again. That is quite inefficient, so now you can have as many card lists as you want.

Want a list for the top priority cards you want? What you have borrowed to someone? The cards in your Drafting Cube? Which ones you are willing to trade? The missing cards for a deck?

Now it is up to you, create a list, name it, and you can use it for whatever you want.

multiple_card_list

Playtest Improvements

Playtest is nice, but there was no way to keep track of what was tapped and what was untapped. For quick tests, you can track it in your head, but that is far from ideal.

From this version you can tap / untap the cards on the battlefield. And yes, they do untap when you click next turn.

playtest_tap

Also, some people complained that they exited playtest by clicking back accidentally. For those cases there is a new setting to display a confirmation dialog before exiting. I know some people will love it.

Notes for Decks

Another feature requested many times is to add notes to decks. There is now a 3rd tab on each deck where you can keep your notes.

More options for prices

Card prices is one of the features people like. To save network traffic the prices are cached for 3 days, but when some cards get banned or unbanned prices may change quickly.

Since this version, you have new settings for how long you want to have the price cached (and to clean all prices manually) and the option to show Normal / Foil or Low / Avg / High (if the price provider has that).

MTG Tracker on Google Play

SpaceCat HD and OUYA

A few weeks ago I released SpaceCat HD for OUYA.

SpaceCat is the only game I have that makes sense to be played with a gamepad, and because of that it supports most of the gamepads already, including Gametel, MOGA, NVidia Shield and some others. It was also ported to GameStick, but that is another story.

A different SpaceCat

There is SpaceCat (3D), which is a Free2Play game with really low conversion. The first 24 levels are free and the remaining 24 levels can be purchased with In-App Currency.

Then there is SpaceCat HD, which is a premium game. All the levels are unlocked and it has no ads.

OUYA has a Free to Try mode, so I needed to find some middle ground.

SpaceCat HD for OUYA has the first 9 levels for free, then the game can be unlocked with a single payment.

ouya_icon

Some other changes were required for OUYA, mainly updating some assets and strings to display the special names of the buttons. Also reimplement In-App purchases to use the OUYA library. All in all, It was actually quite straight forward.

A better App Store

One of the best things of OUYA is that it is a much better App Store than Google Play.

New releases get visibility, so does the top 30 games and so does the hand-picked features.

There are about 20 new games released each week, so you can expect to be in the home screen for about a week. Be aware that the screen has space for 4.5 tiles and to see the rest users have to scroll. Your first day is probably going to be the best.

Show me the numbers

This is the chart of the downloads of SpaceCat during the first weeks on OUYA.

spacecat_ouya_downloads

We have a solid start on the first 2 days when there were ~75 downloads. This is when SpaceCat HD was on the top of “New Releases”. As you can see, the longer the users have to scroll to find you, the less downloads you get.

Then SpaceCat was featured. That put it on the front. It was the first thing you saw when you start your OUYA, literally the best spot, and it really made a difference: Over 125 downloads per day.

spacecat_featured_ouya

After a few days, the feature games rotate, and you can see how the downloads per day get down to just 50.

But here comes the last factor. Given the amount of people that downloaded (and played) the game, it also made it into the top 8 of the trending games, which helped it getting a decent amount of downloads. I’m proud to say that it even topped Final Fantasy III.

ouya_top8But after the featuring, and given that SpaceCat is a game you usually play for a week and you either finish it or get bored, it slowly disappeared from the top 30 and not it only gets a few installs per day.

How does it compare to Google Play?

The amount of downloads is in a complete different league. When SpaceCat was featured on Google Play (on 2012) it was getting over 50,000 downloads per day, 400 times more than on OUYA, Even today, SpaceCat (3D) get about 100 downloads per day.

But, partly because the monetization is different and partly because of the public is different, the percentage of users that purchased the game is way higher on OUYA than on Google Play.

The conversion of SpaceCat HD on OUYA is over 5%. Which is very impressive.

Also, there is the human aspect. The people from OUYA were a pleasure to work with: Diligent, responsive and professional. Google Play has improved that, but they still have a long road to go.

TL;DR;

There is a chicken-and-egg problem with OUYA: There are not many players, so it is not worth developing for it alone. Since there are not many games for OUYA (750 is still an impressive amount), it is not very attractive for players.

OUYA has the Free the games initiative to break the vicious circle. I like it, and I really hope they succeed.

If you have a game that already supports gamepads, you should totally port it to OUYA, it is not much work and it is a very rewarding platform. If you have a good game, the chances of being featured are very high, and that is always nice.

I wish there were more OUYAS out there so I could develop a game exclusively for them, but right now it is just not viable. Time will tell.

Android: Front Cameras are not Cameras

Let’s say you want to make an app that includes the occasional taking of a photo (i.e. for the profile pic) but you want to have it in-app and not launch the default intent.

Of course you follow the instructions for “Building a camera App” from the official website.

But there are a few points where the API is not obvious and can drive you mad. Specially if you are using a 2012 Nexus 7 as a test device (or any device that has front facing camera only).

Checking the hardware

Here is where the fun begins. Because this is not a killer feature, we won’t request the feature in the manifest, but check it in the code (as the documentation suggests)

getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)

Returns false. So it seems there is no camera. Let’s try something else.

Camera.getNumberOfCameras();

This returns 1. It seems there is a camera. Hmmm.

The documentation takes us out of our error. FEATURE_CAMERA means:

The device has a camera facing away from the screen.

There is FEATURE_CAMERA_ANY, but that is API level 17, and we are “only” minSDK=14, so we can not use it. We also have FEATURE_CAMERA_FRONT, we are saved.

The way to check if a device has any camera is:

PackageManager pm = getPackageManager();
boolean backCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
boolean frontCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
return backCamera || frontCamera;

Or just use Camera.getNumberOfCameras().

Be aware that if the camera feature is requested in you manifest, your app will not be available on devices with only a front facing camera. Maybe you want that, maybe not.

Opening the Camera

The fun continues when we try to open the camera. If we have more than 1 camera, we can select the one we want, but if there is only 1 camera we can go ahead and open it

if (Camera.getNumberOfCameras() == 1) {
    return Camera.open();
}
else {
   // Select one camera
   return selectAndOpenCamera();
}

Except that -in our special case- this code returns null. Because, you know, when it says camera it means back facing camera. At least the documentation of Camera.open() is clear.

Creates a new Camera object to access the first back-facing camera on the device. If the device does not have a back-facing camera, this returns null.

You should, instead, try to open the first camera, That works.

Camera.open(0)

In the case of selecting which camera to open (i.e. if you want a front facing camera by default) you have to iterate over the cameras, check the CameraInfo of each of them, and open the one you want using the id.

And remember: For Android, camera means back-facing camera. Front facing cameras are not real cameras.

Codemon 3.1: Dark Codeboxes and more

It has been a while since the Arcanes were released. Today we have an update that includes a brand new item: The Dark Codeboxes.

Dark Codeboxes

Many players were not motivated to open battles. You open them not knowing your opponent and once an player knows the strengths and weaknesses, they can always accept it with a Codemon that has a high chance of winning. And losing most of the battles is demotivating.

But opening battles is key to the game, se we wanted to motivate this players again. The Dark Codeboxes are the first step towards that.

A Dark Codebox hides the Codemon, that simple. This levels the field since you open it blindly, but they are also accepting it blindly. Dark Codeboxes can only be used with Codemons of level 6 or more, which is where efficiency starts to be very relevant.

A Dark Codebox is obtained by applying Dark tinture to a Codebox. You do not get an extra Codebox, but you “Darken” one.

darken_codebox_complete_framed

Darken the first Dark Codebox is free for all the players once they raise a Codemon to level 6.

We will continue to encourage players to open battles in other ways in the future.

Second currency: Codebucks

Dark Codebokes are a premium item, and for that we included a second currency: Codebucks.

You can get Codebucks by linking Codemon on Facebook, as a daily reward and completing free offers. Achievements and (some) Quests will -in the future- give Codebucks.

Of course you can get them as an In-App purchase.

The slots on the market and the extra Codeboxes have changed the price and now cost Codebucks instead of Credits.

When summoning an Arcane you just spend Codebucks or Credits to get an A-Summon or a B-Summon performed on the spot. Prices are the same, just made it simpler.

Event ticker

We do run events every now and then, and when we do so, we send an in-game message to all the players that have been active, and we also publish it on Facebook.

Still, I know that many players miss them. So, from this version on, whenever an Event is running you’ll see a ticker under Quests, where you can see the details of the Event.

event_tick_framed

Improved Codemon filtering for battles

Until now, every time you went to open a battle, the search terms were cleared and all your Codemons were shown. That was a bit unconvenient when you were trying to open a few battles with the same type of Codemon, for example, Epics.

From now on, Codemon will remember your last search for as long as you are opening battles.

Transfer account

Because Codemon associates the account to the phone, we have many requests of people that want to migrate their account to their new phone.

We have added the option under settings, so you can transfer everything to another account.

Final words

This update has taken a lot longer than I expected to be ready, but I hope all of you enjoy it. There are still many ideas on how to extend Codemon, and I hope I’ll have the time to implement them.

Until then, happy scanning and battling!

Get Codemon on Google Play

The importance of a “Rate Us” dialog

Paid apps always had a better ratio of users leaving feedback than free ones, but in the case of MTG Tracker it was too much.

MTG Tracker used to have a very good ratio of users that leave comments. This was reduced when Google Play required G+ sign in to leave a comment, and that was specially bad for the free version, which was released after that change was made.

Things looked like this:

Screen Shot 2014-01-31 at 13.07.04

Both had good average rating, but while almost a 6% of the users leave a rating on the paid version, for the free one that number it is under 0.6%. Yes, 10 times less.

So, I decided to add a “Rate Us” dialog to improve that, knowing that the users of the app use it a lot and just may never thought of rating it.

mtg_rate_us_framed

I did not add it before because for a while I only had the paid app, which has a good amount of reviews. After one week, I went to check the results of the dialog. The stats looked like this:

Please note that the free version has much more installs per day.

Screen Shot 2014-02-06 at 12.09.30

So, almost 100 new ratings on the paid version and 35 more for the free. The conversion rate grow for both apps. Still the paid version got even more ratings.

I decided to let a few more days pass and checked again.

Screen Shot 2014-02-17 at 14.48.11

Another 80 ratings for the paid version and 40 for the free one. Also, average ratings for the paid app keep getting higher, but the ones for the free seem to oscillate.

As it turns out, the percentage of users leaving a rating on the paid app is almost the same as before the dialog was introduced, but the ratio of reviews for the free version has grown up to 0.7%, may not seem much, but the free app has 30% more ratings than before.

Conclusions

After this experiment, it is very clear to me that you must always add a “Rate Us” dialog, even if your current amount of ratings is good. Most users are lazy and will not rate your app unless you ask them to do it.

Some final notes:

  • Don’t be intrusive, if the user does not want to rate you, so be it. Always have a “No, thanks” option
  • Trigger the pop-up after a satisfying user experience, users will be more likely to give you positive reviews if they are in good mood.

MTG Tracker 5.4 Released

With the new set of Magic The Gathering ™ comes a new version of MTG Tracker. Let’s see what’s new:

Added Born of the Gods

Obviously, as with a new set, the cards need to be added to the app.

Foil prices from TCGPlayer

This has been requested many times. Although it was possible to get foil prices via CardShark, most people uses TCGPlayer as a price reference.

Because of the limited space we have on screen, I have removed the high and low prices, keeping only average and foil. The screen looks like this:

price_comparison

Fixed crashes on card lists on tablets

There were a few crashes and misbehaviour on the card list section when used on a tablet. I was aware of the bug thanks to a user that mailed me with very extensive steps to replicate both problems.

Is because of users like this that I love building the best product I can.

Improve rules search: Allow literals (with quotes) and negatives (with ~)

Another feature suggested by a user. Adding more power to the advanced search by allowing literals and negations. Some examples of why this is useful.

Because it is not the same to search for “target player discard” than for target player discard. The results are down from 232 to “just” 91.

search_quotes

But it gets better, when searching for creature damage, we get almost 2,000 results, but if we want to filter out the cards that do not require to target, we just add ~target to the search, and we are down to “only” 811 cards. Still plenty of creatures that do damage when summoned, but definitely a shorter list.

seearch_negations

Library filtering in playtest

Also a very requested feature, when you use any kind or ramping effect (searching for basic lands) or any type of tutor, searching all the library was inconvenient.

Decks can be sorted by Converted Mana Cost

Cards inside decks have been always been sorted alphabetically, but this may not be the most convenient sorting for some power players. Now the contents of the deck can be sorted by CMC (ascending or descending)

Improved Card lists and Trade with card details

Since the last version, deck screens included the cards casting cost and type. This “extended information” view was very well received and it is now also included on card lists and trade.

Closing the conference season

It is time to close the conference season for this year. It has been a very interesting one, although I’ve spoken only at 4 places, they have been all very interesting.

GOTO Amsterdam: A very important software development conference in the Amsterdam edition, they had a mobile track, I guess I couldn’t miss it.

GDC China: My first time speaking at a GDC, where I presented my “Indie Game Developer Survival Guide”. Great experience, great city and great conference.

DroidCon Amsterdam: For the 3rd year in a row DroidCon celebrated its Dutch edition, and for the 3rd year on a row, I presented a talk there. I think I am holding a record on this one.

GDC Taipei: I was asked to repeat my talk from China at GDC Taipei. I am really humbled that they like it so much that they wanted it there. Also a great experience.

And for next year?

One of the great things of being an international speaker is that you get to travel a lot, given the sort of conferences I like and the expertise I have (Android & Game development) GDCs and DroidCons are where I find myself at home.

So, for 2014 I am sending talk proposals to:

GDC and GDC Europe: The bigger editions of GDC, held in San Francisco (largest) and Cologne, are my next targets to speak at. I want to be able to say that I’ve done the whole set and I’ve been told that the one in San Francisco is amazing.

DroidCon London and DroidCon Berlin: These editions are slightly larger and older than the Amsterdam one, and I’d like to see them first hand.