Friday, September 27, 2013

Games taking too long to make?

When I am designing and creating and programming a game. I tend to find that it takes a really long time. Yes, I am only doing this in my spare time, and yes when I am drained after a day at work I am unable to code. Still I really want to try and get 4 games out a year. That doesn't seem too much to ask does it?

So instead of keep fighting this losing battle I have with games taking more time than I want (no, I won't rush them or release them when they are not ready!). I have decided to adjust my course a little. It is a sensible decision really. I still want to do 4 games, but what if I make every other game an App or simple game. A game that has very low graphic intensity (I find anything with graphics makes it take twice as long to develop).

So from now on I am going to try this new theory out. Which will give me approximately 6 months per real game and overlay those with two small games/apps.

Brilliant eh!

Laters
Da Voodoochief

Wednesday, September 25, 2013

Don't Hide ya IAP

I read this article the other day on Gamasutra called 'Make Purchasing Present' by Ethan Levy. I found it to be obvious and also revealing. It was obvious that all the shops you ever go in try to show you their wares, as that is how they exist. Selling you stuff allows them to continue in business. They are not shy about selling you stuff, and they should be. The same goes for IAP in my humble opinion.

What was revealing was the way I felt about the IAP. In some ways putting it on the back shelf. Not exactly hidden, but no fanfare or billboards were around it either. I really think I felt a little embarrassed by the fact I had IAP in my game. Well no more, this game has been designed with the idea of IAP for cosmetic changes to the game and a quicker way to purchase all the in game ship upgrades. I am not going to be embarrassed that people are so used to free that they don't even want to spend a measly 1 freakin dollar to purchase my game. So if this is the way it is, then so be it. I will offer what I believe to be great value per item and then let the public decided on it's value or not, with their wallets, like in a  real shop.

So after reading this article my mind is changed and I think in a good way. All you blanket nay sayers on IAP can just keep on bleating, but in the end you are going to have to deal with the way the world in selling games is changing, well has been changing for several years now. So for me, I am stepping forward the best way I feel I can, and will try to do my best for making enough money to cover this games costs, or maybe the next one, meanwhile giving good value to my customers.

I will also add banners, not intrusive per say, but at the end of a level I will display the odd quick buy banner for the player to see that this stuff exists and YES, you can buy it if you want. I feel it is a little like the displays at the counters of the local Vons. Hopefully I can sell some of my Candy :)

Laters
Da Voodoochief

Monday, September 23, 2013

GameCenter Marmalade Code in a Class

Here is my gamecenter code that works from within the Marmalade SDK. I hope you programmers can find aspects of this useful.  I basically took the example that Marmalade supplies and then converted the aspects I wanted into a class.

Good luck,
Da Voodoochief

GameCenter.h
#if !defined(_CGAMECENTER_H_)
#define _CGAMECENTER_H_
#include "s3eIOSGameCenter.h"
#include "s3eIOSIAd.h"
extern bool gAuthenticated;
extern char gUserName[S3E_IOSGAMECENTER_STRING_MAX];
extern int gGameCenterState; // useful for debugging
class cGameCenter
{
public:
 int g_NumFriendsFound;
 char** g_FriendIDs;
 s3eIOSGameCenterVoiceChat* g_VoiceChat;
    //-------------------------------------------------------
    cGameCenter()   {
  gAuthenticated = false;
  strcpy (&gUserName[S3E_IOSGAMECENTER_STRING_MAX], "Unknown");
  g_NumFriendsFound = 0;
  g_FriendIDs = NULL;
  g_VoiceChat = NULL;
  gGameCenterState = 0;
 };
 static void LoadAchievementsCallback(s3eIOSGameCenterAchievementList* list);
 static void ReportAchievementCallback(s3eIOSGameCenterError* error);
 static void LoadAchievementInfoCallback(s3eIOSGameCenterAchievementInfoList* list);
 void GetMyAchievementsHandler();
 void GetAchievementsHandler();
 void ReportAchievementHandler();
 void GameCenter_DisplayAchievements();
// static void GetPlayersCallback(s3eIOSGameCenterPlayerInfo* playersInfo);
 static void AuthenticationCallback(s3eIOSGameCenterError* error, void* userData);
 void AuthenticateLocalHandler();
 void GameCenterRegister();
 static void GameCenter_ReportScoreCallback(s3eIOSGameCenterError* error);
 void GameCenter_ReportScore(int _score, int _level);
 void GameCenter_DisplayLeaderboard();
};

#endif

GameCenter.cpp
#include "Game1.h"
//-------------------------------------------------------
int gGameCenterState = 0; // useful for debugging
bool gAuthenticated = false;
char gUserName[S3E_IOSGAMECENTER_STRING_MAX];
//-------------------------------------------------------
// Callback functions to report authentication, matchmaking, data events, etc...
/*void cGameCenter::GetPlayersCallback(s3eIOSGameCenterPlayerInfo* playersInfo)
{
    if (playersInfo->m_Error != S3E_IOSGAMECENTER_ERR_NONE)
    {
//        AppendMessageColour(RED, "Get players info error: %s", ErrorAsString(playersInfo->m_Error));
        return;
    }
    if (!playersInfo->m_PlayerCount)
    {
//        AppendMessage("`x996666Error? ReceivedPlayers callback indicates no players!");
        return;
    }
    for (int i = 0; i < playersInfo->m_PlayerCount; i++)
    {
        s3eIOSGameCenterPlayer* player = playersInfo->m_Players[i];
        // NB: GetString only guarantees the string will stay valid until the next call to GetString
        // so we have to copy it if calling more than once and expecting it to persist
        char alias[S3E_IOSGAMECENTER_STRING_MAX];
        strcpy(alias, s3eIOSGameCenterPlayerGetString(player, S3E_IOSGAMECENTER_PLAYER_ALIAS));
//        printPlayerInfo(alias,
//                        s3eIOSGameCenterPlayerGetString(player, S3E_IOSGAMECENTER_PLAYER_ID),
//                        false, 0,
//                        s3eIOSGameCenterPlayerGetInt(player, S3E_IOSGAMECENTER_PLAYER_IS_FRIEND) == 1);
    }
    s3eIOSGameCenterReleasePlayers(playersInfo->m_Players, playersInfo->m_PlayerCount);
}
*/

//---------------------
void cGameCenter::AuthenticationCallback(s3eIOSGameCenterError* error, void* userData)
{
    gGameCenterState++;

 if (*error != S3E_IOSGAMECENTER_ERR_NONE)
    {
//        AppendMessageColour(RED, "Authentication Error: %s", ErrorAsString(*error));
//  debugBGColor = 0x0000ff00; // red
//        updateBGColor();
  gAuthenticated = false;
        return;
    }
    gAuthenticated = true;
    const char* alias = s3eIOSGameCenterGetString(S3E_IOSGAMECENTER_LOCAL_PLAYER_ALIAS);
// debugBGColor = 0x00ff0000; // green
// updateBGColor();
    if (strlen(alias) > 0)
        strcpy(gUserName, alias);
    else
        strcpy(gUserName, "!user alias error!");
//    AppendMessageColour(BLUE, "---------------------------------------------------");
//    printPlayerInfo(g_UserName,
//                    s3eIOSGameCenterGetString(S3E_IOSGAMECENTER_LOCAL_PLAYER_ID),
//                    true, s3eIOSGameCenterGetInt(S3E_IOSGAMECENTER_LOCAL_PLAYER_IS_UNDERAGE));
//    AppendMessageColour(GREEN, "Local player authenticated:");
//    AppendMessageColour(BLUE, "---------------------------------------------------");
//    s3eIOSGameCenterSetInviteHandler(InviteCallback);
}
// Authenticate local player - prerequisite for other funcs to be used
void cGameCenter::AuthenticateLocalHandler()
{
    // Start new attempt
//  AppendMessageColour(BLUE, "%suthenticating local player...", g_Authenticated ? "Re-a" : "A");
// debugBGColor = 0xff000000; // green
// updateBGColor();
 gGameCenterState++;
 if (!gAuthenticated)
        gAuthenticated = s3eIOSGameCenterGetInt(S3E_IOSGAMECENTER_LOCAL_PLAYER_IS_AUTHENTICATED) ? true : false;
    if (gAuthenticated)
    {
//        AppendMessageColour(GREEN, "Authenticated! (player already logged-in)");
//  debugBGColor = 0x00ff0000; // green
//  updateBGColor();
  return;
    }
    s3eIOSGameCenterAuthenticate(AuthenticationCallback, NULL);
}
void cGameCenter::GameCenterRegister()
{
 gGameCenterState = 0;
 if (!s3eIOSGameCenterAvailable())
    {
  debugBGColor = 0x0000ff00; // red
  updateBGColor();
        s3eDebugErrorShow(S3E_MESSAGE_CONTINUE, "GameCenter extension not found");
        s3eDeviceExit(1);
    }
 AuthenticateLocalHandler();
}
//---------------------
// Achievements
void cGameCenter::ReportAchievementCallback(s3eIOSGameCenterError* error)
{
//    if (*error != S3E_IOSGAMECENTER_ERR_NONE)
//        AppendMessageColour(RED, "Achievement Report Failed: %s", ErrorAsString(*error));
//    else
//        AppendMessageColour(GREEN, "Achievement Reported Successfully");
}
void cGameCenter::LoadAchievementsCallback(s3eIOSGameCenterAchievementList* list)
{
    for (int i = 0; i < list->m_AchievementCount; i++)
    {
        s3eIOSGameCenterAchievement* info = &list->m_Achievements[i];
//        AppendMessage(" %s : %d", info->m_Identifier, info->m_PercentComplete);
    }
//    AppendMessage("Got %d achievements", list->m_AchievementCount);
//    AppendMessageColour(BLUE, "---------------------------------------------------");
}
void cGameCenter::LoadAchievementInfoCallback(s3eIOSGameCenterAchievementInfoList* list)
{
    for (int i = 0; i < list->m_AchievementCount; i++)
    {
        s3eIOSGameCenterAchievementInfo* info = &list->m_Achievements[i];
//        AppendMessage("  desc2: %s", info->m_UnachievedDescription);
//        AppendMessage("   desc: %s", info->m_AchievedDescription);
//        AppendMessage(" %s : %d : %s", info->m_Identifier, info->m_MaxPoints,info->m_Title);
    }
//    AppendMessage("Got %d possible achievements", list->m_AchievementCount);
//    AppendMessageColour(BLUE, "---------------------------------------------------");
}
void cGameCenter::GetMyAchievementsHandler()
{
    s3eIOSGameCenterLoadAchievements(LoadAchievementsCallback);
}
void cGameCenter::GetAchievementsHandler()
{
    s3eIOSGameCenterLoadAchievementInfo(LoadAchievementInfoCallback);
}
void cGameCenter::ReportAchievementHandler()
{
    char name[255];
    const char* tmp = s3eOSReadStringUTF8("Enter achievement name:");
    strcpy(name, tmp);
    const char* valueStr = s3eOSReadStringUTF8("Percent Complete:", S3E_OSREADSTRING_FLAG_NUMBER);
    int value = atoi(valueStr);
    s3eIOSGameCenterReportAchievement(name, value, ReportAchievementCallback);
}
void cGameCenter::GameCenter_DisplayAchievements()
{
 if (s3eIOSGameCenterAchievementsShowGUI() == S3E_RESULT_ERROR)
  return; // error'd out
}
//------------------
// Leaderboards
void cGameCenter::GameCenter_ReportScoreCallback(s3eIOSGameCenterError* error)
{
    if (*error != S3E_IOSGAMECENTER_ERR_NONE) {
  // all bad
  if (*error == S3E_IOSGAMECENTER_ERR_COMMUNICATIONS_FAILURE)
   return;
 } else {
  // all good
 }
}
void cGameCenter::GameCenter_ReportScore(int _score, int _level)
{
// const char* scoreStr = s3eOSReadStringUTF8("What Score?", S3E_OSREADSTRING_FLAG_NUMBER);
// int score = atoi(scoreStr);
 char category[20]; //s3eOSReadStringUTF8("Category (SI_LB01)");
 sprintf(category, "SI_LB%02d", _level);
 s3eIOSGameCenterReportScore(_score, category, GameCenter_ReportScoreCallback);
}
void cGameCenter::GameCenter_DisplayLeaderboard()
{
 const char* category = "SI_LB00"; //s3eOSReadStringUTF8("Category (SI_LB01)"); // enter a name of the LB
 if (s3eIOSGameCenterLeaderboardShowGUI(category, S3E_IOSGAMECENTER_PLAYER_SCOPE_ALL_TIME) == S3E_RESULT_ERROR)
  return;
}

Thursday, September 19, 2013

iOS IAP Obtaining Multiple Products Info

I have been doing some coding and researching the iOS In App Purchasing. I set up my code to loop through all the product IDs I had set up in the Manage app section of iTunes Connect. I wasn't certain however if this was the way to make it work. Seemed a little silly to ask for product information multiple times, yet I was ok with it. that was ok, until I noticed that the call to get the product information had a number on the end asking for number of product Ids sent in the first parameter which was a char **.

So then I recoded my game to send in all the product IDs as a batch. The only thing was the callback that receives the information seemed only to handle the information coming back as a singular entity. Nowhere could I find a reference as to how this is supposed to work. So I used logic to decide that the information must come back a single product at a time, even when asked for as a bundle.

So the last few days I have been playing with this idea and last night I was in fact able to prove that it does indeed work in that way. So now I ask in a bundle and process my results within the callback, and then I copy the relevant information to my shop packages array for displaying to the player.

It is all working really well, and apart from some reformatting of the shop screen I am very close to actually attempting a purchase of one of my products. Very exciting indeed.

Laters
Da Voodoochief

Wednesday, September 18, 2013

The Toll of Expense or Doom

I cannot believe it, but somehow a whole year has nearly passed by since I purchased my 500 dollar license with Marmalade. Of course I had a paying gig that allowed me to buy that one without dipping into my own pocket. This time round I am not in such a position, so what should I do?

Each day I sign in and build my latest creation I get a warning saying how many days left are on my License. I know it ends at the end of September and I have to admit to feeling sad about the fact it is expiring. I will most likely go with the 150 dollar license next. After all I was not able to put out nearly as many games as I had hoped I would. In fact with that License I only put out two childrens apps(A Day at the Zoo and 5 Golden Coins) and though I have Hoopfighter done, it is not yet released. Which might be an issue if I don't have a license when they finally want to release it.

I know other Indie developers go through this same thought process each year. Which license should I buy and what level of license. I really like the Marmalade code base, even if some is broken (which SDK isn't without its problems eh). Still I will be sad when it goes.

Laters
Da Voodoochief

Monday, September 16, 2013

Scoreloop is still Rockin

A year and a half ago I put into one of my games 'Hot Chicks the Card Game' the Scoreloop backend. I really wanted high scores and maybe more later. So I looked around and asked in twitter what people thought I should use as a solution. I got recommended a few different systems, and yet Scoreloop seemed so easy, AND was already available as an extension to Marmalade (the extension is actually by Scoreloop I believe). So I figured how hard could it be, well it was pretty easy to get in and working, and it is STILL working today, a year and a half of no modifications by me. It is still working hard recording scores from new and also experienced players alike.

So I visited the Scoreloop - Hot Chicks high score table to take a look at it. Below is what I see.
As you can see there are now 7403 registered scores.. Woohoo, and still coming in at about 13 new ones a day. I only wish I had got scoreloop in the game when it was first released. I know this number would have been more than 10K by now (I believe there were nearly 5K downloads of version 1).

The other thing that astounds me is just how high a set of scores can be obtained in this game. 8K, are ya kiddin me? I cannot make it past 4.5k myself.

Still, it is gratifying beyond words to see some dedication like this in one of my games. Makes me want to write more, and ALL of them will have High Scores in them.

Laters
Da Voodoochief

Wednesday, September 11, 2013

It's 9/11 and ya know what that means

It's my birthday!

I know today has other less celebratory awareness in peoples consciences. However I was born on this day 48 years ago.. so in my mind I have precedence.

48 years ago.. wow. Time has flown by. I was 15 when I was making and publishing my first games. Text adventures for the zx80/1 and then onto the Commodore Vic20. So long ago in numbers, seems like yesterday in my brain.

 This means I have now been publishing a wide variety of games for 33 years. 33 years is also an astounding number of course. The most amazing thing is that I still have such passion and drive to create and develop more games. I wonder where it all comes from? It is still good to be passionate about games, even though when I was in my early twenties we never thought this game creation lark would last beyond me getting to maybe 30 years old.

How wrong I was (gladly).

I have a busy day ahead of me, at work, running the kids around for boy scouts and my daughters in a new YAE play in T.O. So gotta go there also tonight. I am hopeful that sometime late this evening I can simply sit and marvel at my age with a nice calming drink in hand.

Take care out there!
Da Voodoochief

Monday, September 9, 2013

Brain dead, but I can do useful stuff

My day job is removing all my ability to code each day. I am working very hard on some tough coding puzzles both with the theory and the implementation. I am debugging many many thousands of lines of code to try and work a new system inside the old one, to eventually replace the old and not as efficient one. This means I am debugging code and theorizing what is going wrong for 9 or 10 hours a day. I have found that this saps all my programming strength and drive. Which is a pity as I really want to finish my IAP code for the iOS side and move back into the game coding side of Space Invaliens.

Still as the title points out, I am not idling sitting by. I am in fact relaxing as best I can my spent brain. I am reading quite a bit, but more importantly for Space Invaliens and my future products, I am investigating and analyzing the competition.

OK, so competition isn't quite the right word, and neither is investigating if truth be told. What I am doing is playing games, lots of them. I have picked up a new Xbox 360 compilation of the old Midway arcade games, and I am very excited to say that Sinistar is one of them, which is one of the inspirations for aspects of Space Invaliens. Now I cannot say I am playing them well, but who cares, so long as I am having fun. I even got to spend some quality time playing Gauntlet while laughing and playing with my son. We both suck bad, and the lack of good diagonals on the controls or the Xbox360 dpad makes it quite excruciating at times.

Playing things games really inspires me and reminds me where I come from. The only down side is that it makes me want to design some new flavor of game, and I simply don't have the time, lol.

Take it easy out there,
Da Voodoochief

ps. Here is a Picture of me at work with my new T-Shirt I love!   I am a Coder+Dr Who fan.

Friday, September 6, 2013

Time invested in the best place?

One of the things I am really struggling with at the moment is where to put most of my time and effort.

I could just keep trucking along on what I am working on, but circumstances change, as well as skilled manpower available to me. This means that I am constantly watching for an opportunity to do something bigger, grander purposeful and hopefully more successful and worthy of more notoriety.

So here I am trying hard to figure out what is the best thing to do. How much time to invest of everyones time and to what extent should we create the next prototype or IP to have an agent show men in suits.

It is of course a crap shoot. I could take several approaches next and still end up with nothing more than I have now, only I should say, slightly more. Till I decide I will keep on trucking with what I have and hope maybe that will allow me to find the last part that could unlock a successful future.

G'night all,
Da Voodoochief

Tuesday, September 3, 2013

Selling your App/Game, is it possible?

It seems that I always thought about selling my game to the players. You know, individuals who will most likely play the game. However there is another form of selling a game or App.

I was contacted via email a few days ago by a website that sells apps and games, the rights, the IP the assets the code, the whole shebang. I presume this is where someone comes in who has some weight and desire to further develop the game/App they want to buy. I can believe that some companies would see potential in various games and apps and want to buy up all of its rights so they can move forward with a redevelopment or maybe even just adding a marketing budget and plan to really move the title forwards.

I find the whole thing a bit surreal and am not sure how well I think this kind of thing can work. I see they have sold quite a number of apps and games, but in reality I think I would like to know why those were bought and what happened to them afterwards. Ok, so maybe it is my curiosity more than anything. But oddly, it would be easier to part with my baby if I thought they wanted to simply promote it, then again, if they simply bought it for my outstanding design.. maybe that would be great as well. In fact maybe there is no down side to this.

I will continue to think on this. I do have some older games that I could unload, but am not sure I want to at this stage. The other thing is the data on the site, saying that some of these games are making 1500 bucks a month from advertising revenue, What a crock. I wish I was making a tenth of that each month for 10K downloads, but I am not that's for sure. So some of their numbers are interesting for sure.

Still I will have another look over this site with a friend of mine, see what he thinks.

What do you think?

AppTopia

Laters
Da Voodoochief

Monday, September 2, 2013

My In Game Shop

This  my in game shop, programmer style of course, as I am the one who created and laid it all out. I thought it was about time I posted a picture (yeah, been a while). As I am now working on the In App Purchasing I thought it would be good to show where I am.

Yesterday I spent some time reorganizing my shop screen in the game. Also I prepared the code for when I ask the IAP servers for some item information (yes, the item description and cost etc all come from the setup on iTunes Connect). Now it is ready.. oh wait that picture I mentioned...


As you can see it is titled (as are all my menu screens). It also has a new improved listing barrel of the items you can buy (now shows 7 and not just 5). The real new stuff though is at the bottom, and all those Quick Buttons. By pressing them it will immediately adjust the selector barrel to highlight the first of the kind named on the button. I feel this is essential as I have a LOT of items for sale. Oh, and yes there are many ways to show a shop, and use drill down pages etc, but I really wanted to use a barrel design. Next up will be to have an icon or image associated with each purchasable item (or package as I call them), then place that on the screen as well.

You will notice the new 'Special Premium Powerups' button. Of course if this was not my graphics, then I would expect this button to really stand out, I can also make it a lot larger of course, which could be nice to have people to go check out the premium IAP items I have for sale in this game. After All, I believe these things should be obvious and easy to find.

If a player clicks that button, the selector barrel sets itself on the premium items for sale.  I will disable this button if a player is not connected to the internet, after all, I would not have been able to retrieve the items for sale list anyway.

Now to actually start on the code to find the items for sale and their cost and descriptions, with that information I will fill out my arrays and allow myself to purchase them.. Hopefully by the end of this week it will all be done.

Laters
Da Voodoochief