Category

Technical

Dev Diary – Oculus Rift F1 Demo

By | Developer Diary, Game Development, Oculus, Technical, Unity | No Comments

From the time we received the Oculus Rift development kit, in July 2013, we were very keen on working on something related to Oculus, since there weren’t any good games or demos to showcase its true potential. Although Oculus is still in development and it will take time for it to reach its true potential, we felt the need to create something for the new realm of gaming it opens up. We already had Leap Motion and the Xbox Racing Controller on hand so we decided to make a racing game owing to our prior experience in racing games.

Oculus

Eventually we decided that a Formula 1 racing game would do wonders if we gave the gamers a real-time experience of driving a real Formula 1 car.

I did some research on the circuits of Formula 1 racing and found the Monaco Street Circuit quite fitting to our requirement as it provides a rich architectural view being close to the sea as well as some nice looking building along the track.

But as I started to gather more information on the circuit it became obvious that Monte Carlo circuit was not the right choice. The race circuit has many elevation shifts, tight corners, and narrow track. These features make it perhaps the most demanding track in Formula 1 racing. Due to the tight and twisty nature of the circuit, it favors the skill of the drivers over the power of the cars. Although we had Formula 1 fanatics in mind when we started off, putting a lot of effort into the physics of the car was impossible keeping in mind that we only had 3 weeks to finish the demo.

Motor Racing - Formula One World Championship - Monaco Grand Prix - Saturday - Monte Carlo, Monaco

On further research of racing tracks, I came across the Valencia Street Circuit which had the same geographical characteristics of Monaco and it provided ample beauty and rich architecture. Another fact that helped in locking down Valencia was that the last grand prix at the Valencia Street Circuit was held in July 2012, and since then the circuit is no longer host to the European Grand Prix. So in a way we are giving tribute to Valencia Street Circuit by making it our choice of track in the Oculus Rift F1 Demo.

Valencia

In the research phase of Valencia Circuit, Google Maps and Bing Maps were really helpful in categorizing and identifying the monumental buildings and structures that stood out. Keeping in mind, that not all buildings need to be modeled in detail because we basically wanted to show them primarily from the driver’s point of view. Some buildings which had unique architecture were to be modeled in detail.

Bing

Then came the documentation phase, in projects like these documentation is key in order to complete it in a timely and organized manner. Also, it is important to note that although we were a team of 2 guys working on the assets, its best to have the documentation laid out in a manner that projects can be scalable. So we could easily be working in a team of say 15 people and be organized. We used Trello for documentation, listing buildings with their names and assigning level of detail for each building.

We marked around 40 Buildings throughout the 5.419 km track, and through Google Street View referenced each of those buildings in order to have ample data to model them.

For Texturing, we marked similar tile-able textures from our database, as we maintain a library of textures we have made previously on other projects which are always useful.

So, after completing model and texturing work for building we brought them into unity individually to have their LODs set up and ready for the demo.

A demo for oculus

By | Game Development, Oculus, Technical, Unity | No Comments

So these days we have taken upon a very cool project of creating a demo for the Oculus Rift. Now i wont share the details just yet as the details deserve a few photos but i solemnly swear we are up to no good.

So the core needs for the projects are that it should look good, like really good. So with this core goal in mind I ventured into a research of existing solutions and latest tech which i had been missing reading up on as for the past few months i had been very busy with Death Mile. Of course as Death Mile was created in Unity 3D and i had been working for and loving Unity for the past year I started my experimentation in it.

Being a graphics programmer at the core of my heart as i experimented with DirectX 11 tech which I only had been reading up for a long time but never got to work with, I went crazy. The endless possibilities with the now near complete exposure of all DirectX 11 properties in Unity made my mind go wild but as I ventured deeper I realized that I needed to back up a little and make a realistic goal that I can finish in the 3 weeks planned for the demo.

During this experimentation I kept working on a test scene with the amazing Marmoset Sky Shop for Unity as the core lighting solution but wasn’t testing the scene with the Oculus itself as it was supposed to be just a test scene for testing techniques and as I was waiting for my new GPU to arrive. Yesterday I finally tested the scene and ill have to say it changed my view about the project quite a bit. I had played around a bit with the Oculus before this and so I knew the resolution is quite low but I still expected it to show some details. But with the Oculus a scene with moderate realism (IBL for ambient term, simple ambient occlusion baked + SSAO, soft but stable shadows to reduce aliasing and a few tricks here and there but nothing mind blowing) could produce a very good looking image as the blurring removes most of the detail. The new problem set that I am focusing on at the moment is to improve image quality while using Oculus, an interesting paper on that, and to find alternates to problems with aliasing in Unity that need fixing too.

Google Play Game Services for Unity

By | Game Development, iPhone, Technical, Unity | 105 Comments

Google announced Google Game Play Services (GPG) for iOS and Android about 2 days ago at Google I/O. The most important part for us is the ability to save game progress in Google Cloud and realtime Multiplayer game support. This brings Google upto mark with iOS GameCenter.

We just created a plugin for Unity for iOS and Android for GPG with following features

  • Google Cloud Save
  • Leaderboards
  • Achievements
  • Signin/SilentSignin

Google Play Game Services Unity Plugin Demo

In coming weeks we shall add support for Android as well.

Multiplayer matchmaking will be a bit of work since state synch will have to be done from scratch just like it needs to be done for GameCenter. The Unity.Network would not be helpful in multiplayer without a Unity Raknet MasterServer.

The code is available as opensource at https://github.com/faizann/UnityGPGPlugin

Update June 16, 2013

The code now supports Android plugin as well.

Using Dropbox as GIT Backup/Repo

By | Developer Diary, Technical | No Comments

We wanted the ability to checkout our recent code from different locations as we are sometimes not in same geographical location. We simply needed a versioning system with repository on internet. This would have meant using one of bitbucket or github like services or setting up our own server. None of that is technically a challenge but we had been using Dropbox for sharing documents and thought to use it for GIT. This meant that we could use Dropbox for everything from code to documents to web backups.

We also wanted to take backup on NAS.  This way we get backup on 2 different locations.
We realised that best way to use Dropbox is by creating bundle of the code + assets and putting it in Dropbox folder.

We created a batch script to automate the whole system of adding new files (using gitignore of course), committing them and then creating bundle out of it to put it on Dropbox and local NAS drive. The script prompts to input commit message before committing the code.
Here is code for batch file where p drive is our NAS drive mounted on Windows.


echo "Commiting Nerdiacs Project Repo"
set INPUT=
set /P INPUT=Type input: %=%
cd e:GamesRepo
e:
call git add . -A
call git commit -m "%INPUT%"
call git bundle create E:DropboxTeamSharedCodeRepoGamesRepo.bdl master
cd p:GamesRepo
p:
call git pull origin
pause

I hope this helps others in automating bundle creation and backup on Dropbox.

Artificial Intelligence in BLAZ3D

By | Developer Diary, Game Development, Technical | No Comments

As we have already released BLAZ3D on iOS and Playbook, I would like to share a bit about the development process of the game. Specifically the Artificial Intelligence (AI) part.

BLAZ3D was initially planned to run on devices such as the Nokia N95, Nokia N82 and later on iPhone 2g. So, considering the specs of the phone we were quite restricted with the hardware. Now we needed to find a sturdy solution that could give us intelligent AI that acted smart, and yet won’t eat a lot of processing. Actually considering the amount of load that bullet physics was sucking on the device, we had allocated near zero space for AI.

Now the AI was supposed to be able to pickup powerups, use shortcut ramps, and avoid obstacles. With these goals in mind we started designing the AI, but we quickly realized that we needed to keep AI constantly competitive too, as the levels had a large variety in their difficulty so the AI would quickly become too easy to defeat or at times too hard.

So the solution we came for the near zero CPU intensive AI was to use simple splines. But not using only the traditional best path splines, but instead we distributed splines. Through each level we manually placed small regions of splines, connecting options for the AI.

For example a straight line to go through a straight piece of tunnel would keep going straight until we reached powerups. After which 3 splines would cut out of the main spline, and go through the powerups, and finally merging into one. We had some complex scenarios as well when we extended splines, to give the AI logic to turn sharp through the next turn and catch the near powerup, or to turn loose and catch the powerup near the far wall of the tunnel.

Each line had an identifier in its name and a list of children in the name to tell the AI options it had to choose the next spline. But this still meant the AI was pretty dumb, so to give it a bit more intelligence we simply added one more variable to each line, for the probability of using that line. Then we assigned each AI its own probability on load. So if there were 3 AI in a race, there would be one AI how would always be tough to defeat (much like the red enemy in pacman <sad to see that wordpress spellcheck tries to correct pacman>).

So by this simple variable of probability in each spline, we managed to suddenly bring life in each character with this equation:

[highlight type=”one”]finalProbability = nextLinesProbability + enemyProbability + Random value between 0 – 0.25[/highlight]

We looped through all the lines in the child list with this equation and if one of the finalProbability goes over 1, we go ahead with that spline. This simple system allowed us to give each AI a dynamic feel with just a few additional operations.

 

Our experience with Apple’s approval process for submission of BLAZ3D

By | Developer Diary, Technical | No Comments

Inspiration for this post

We had a lot of confusion about app submission and approval process of Apple. The best documentation for process is on Apple’s own developer resources but still it doesn’t explain what can go wrong. Something like this you can only learn from experience and hence we decided to share our experience of approval process.
 

29th November 2011 sometime

App ID was setup for BLAZ3D game in iTunesConnect. Put description of app as BLAZ3D RACING and enabled GameCenter. Created all Gamecenter achievements.

13th December 2011 (5 AM SGT)

Created Distribution Mobile Provisioning Profile for AppStore. No Ad-hoc or Developer.
Tried uploading app using App Uploader application. Got error that uploaded content didn’t contain _CodeResource directory etc.
Realised from forums that we have to send appname.app.zip instead of appname.ipa file.
Tried upload again and App Loader rejected without uploading telling us that signature was invalid for Distribution.
Realised it was still going under Developer certificate even though we had used Distribution. Went back to Marmalade and selected Sign for Distribution and gave it distribution profile. Removed other certificates just to be sure that it doesn’t sign with Developer again. Checked if app is signed with App Store Distribution profile using codesign -dvvvvvv appname.

13th December 2011 (6:15 AM SGT)

Finally Uploaded our binary of 55MB. Status was updated to [highlight type=”two”]Upload Received[/highlight]. Shook hands and gave hugs and went to bed next minute. Some of us had been up for over 50 hours to finish game.

13th December 2011 (6:00 PM SGT)

Woke up after almost 12 hours of satisfying/happy sleep to checked emails.
WTF!!! Binary got rejected after a few minutes of our upload because of issue in certificate entitlements. If we had bothered to wait for a few more minutes we would not have wasted 12 hours to see that binary was rejected.
Checked some forums but nothing seemed wrong with our app. Icons and file size and os type etc were all good. Our app supports both iPad and iPhone.
Suddenly we realised that we had been ignoring a warning on Marmalade Deploy Tool about ‘aps-environment‘ not being in provision profile.
Recompiled app and we saw same warning again. We were not using any push notification code so we didn’t think it was necessary to have ‘aps-environment’ in provisioning profile but it appears that marmalade somewhere in its own code uses the API. This we knew from our experience with OpenFeint extension we built for Marmalade that also requires Push Notification.
Went back to AppID and configured SSL certificate for Push Notification for Distribution.
To be sure that provision profile gets updated with this, clicked on Modify in Provisioning portal for our provision profile and then re-saved it without making changes. After that downloaded the profile and used it to sign app.

13th December 8:20 PM SGT (4:20 AM PST)

uploaded app again and went out to dinner leaving the upload running.

13th December 9:01 PM SGT (5:01 AM PST)

received email with status of app as [highlight type=”two”]Waiting for Review[/highlight]. Knew too well not to celebrate pre-maturely.

14th December 12:10 AM SGT (8:10 AM PST)

after almost 24 hours of our planned submission we realised that we were using Marmalade’s old free licence which was about to expire in 10 days. Marmalade used to have free licence that allowed apps to be built for iPhone only and showed now splash screen. We were not sure to take the risk and re-signed our app using Standard Licence.

14th December 1:30 AM SGT (09:00 AM PST)

The status was still [highlight type=”two”]Waiting for Review[/highlight] so we rejected binary in iTunesConnect. App Status email came with [highlight type=”two”]Waiting for Upload[/highlight] status. We re-uploaded the new binary.

14th December 2:00 AM SGT (09:00 AM PST)

App status changed from [highlight type=”two”]Upload Received[/highlight] to [highlight type=”two”]Waiting for Review[/highlight] within a few minutes of upload completion.

16th December 12:11 PM SGT (15th December, 8:11 AM PST)

received email that app status was [highlight type=”two”]In Review[/highlight].

16th December 12:32 PM SGT (15th December, 8:32 AM PST)

Received email with title [highlight type=”two”]App Submission Feedback[/highlight] explaining meta data issue in app. Fortunately Apple allows to change meta data without re-uploading the binary. The App resolution center notified that our app description only had 2 words BLAZ3D RACING which was not descriptive enough. We realised that we didn’t update the description since we set the App on iTunesConnect on 29th November 2011.

16th December 01:00 PM SGT (9 AM PST)

Quickly updated the description with more marketing information and then resubmitted app (without uploading binary).

16th December 5:00 PM SGT (1 PM PST)

Received email that app was [highlight type=”two”]In Review[/highlight]. We knew from experience that it should be approved/rejected in a few minutes. We were wrong here.

17th December 12:08 AM SGT (8 PM PST)

After a few hours of fixing of meta data. Received email that app was [highlight type=”two”]Being processed for AppStore[/highlight]. This meant that app was approved.

 

All in all the Apple approval process was not that bad. Our own mistakes caused us extra hassle. Forums and blogs complain a lot about Apple approval process but it seems Apple has been improving things all the time. Marmalade documentation also explains steps to follow to prepare your application for submission to Apple which is also a good help.

Openfeint extension for Marmalade

By | Android, Developer Diary, Game Development, iPhone, Technical | 26 Comments

We wanted to integrate Openfeint in our game BLAZ3D but there was no extension in Marmalade, the game engine we used. We decided to create an Openfeint extension for ourselves.
The extension and relevant documentation is available on Marmalade Github Community repo at[highlight type=”two”]https://github.com/marmalade/openfeint[/highlight]

The extension supports following API
[list style=”arrow” color=”blue”]

  • User login/approval
  • Display of Main dashboard
  • Display of dashboard directly to specific page like Challenges, Acheivements, Leaderoards (iOS Only)
  • Sending of challenges (iOS Only)
  • Highscore submission to leaderboards
  • Acheivement unlock
  • iOS Push Notifications for Openfeint (iOS Only)
[/list]  

Some sample code snippets (Not all API is available on Android as OpenFeint doesn’t support them either)

 

Initialising OpenFeint


s3eNOFSettingVal *settings = (s3eNOFSettingVal*)s3eMalloc(sizeof(s3eNOFSettingVal) * 6);
// Fill settings
// UIOrientation value
strncpy(settings[0].m_varName,
"OpenFeintSettingDashboardOrientation",
S3E_NOPENFEINT_SETTINGS_STRING_MAX);
settings[0].m_intVal = s3eNOFUIInterfaceOrientationPortrait;
//
// Shortdisplay name
strncpy(settings[1].m_varName,
"OpenFeintSettingShortDisplayName",
S3E_NOPENFEINT_SETTINGS_STRING_MAX);
strncpy(settings[1].m_stringVal,
"FunkyRacers",
S3E_NOPENFEINT_STRING_MAX);
// Push Notification Setting
strncpy(settings[2].m_varName,
"OpenFeintSettingEnablePushNotifications",
S3E_NOPENFEINT_SETTINGS_STRING_MAX);
settings[2].m_intVal = 1; // TRUE/YES
//
// Sandbox Notification Mode
strncpy(settings[3].m_varName,
"OpenFeintSettingUseSandboxPushNotificationServer",
S3E_NOPENFEINT_SETTINGS_STRING_MAX);
settings[3].m_intVal = 1;
//
// Disable User generated content
strncpy(settings[4].m_varName,
"OpenFeintSettingDisableUserGeneratedContent",
S3E_NOPENFEINT_SETTINGS_STRING_MAX);
settings[4].m_intVal = 0;
//
// Disable ask for approval in debug mode
strncpy(settings[5].m_varName,
"OpenFeintSettingAlwaysAskForApprovalInDebug",
S3E_NOPENFEINT_SETTINGS_STRING_MAX);
settings[5].m_intVal = 0;
//
s3eNOFArray array;
array.m_count = 6;
array.m_items = settings;
s3eNOFinitializeWithProductKey("PRODUCT_KEY_HERE",
"APP_ID_HERE",
"RacingGame",
&array);
s3eFree(settings);

Launch Main Dashboard after login


// Open Main Dashboard
// s3eNOFlaunchDashboard();

Pull Information about all achievements for user


const unsigned int max_achievements = 20; // whatever we think is max we need
void* data = s3eMalloc(sizeof(s3eNOFAchievement) * max_achievements);
if (data == NULL) {
AppendMessageColour(RED, ("Couldn't allocate data"));
return false;
}
//
s3eNOFArray achArray;
achArray.m_items = data;
achArray.m_count = max_achievements;
s3eNOFachievements(&achArray);
// AppendMessage("Size of achievement %d and double %d",
// sizeof(s3eNOFAchievement),
// sizeof(double));
for (uint i=0; i < achArray.m_count && i < max_achievements; i++) {
// s3eNOFAchievement* ach = &((s3eNOFAchievement*)achArray.m_items[i]);
// AppendMessage("Ach at %p", &((s3eNOFAchievement*)achArray.m_items)[i]);
AppendMessage("Acheivement title %s", ((s3eNOFAchievement*)achArray.m_items)[i].title);

Update December 30, 2011

The extension now supports both Android and iOS. Android API is extremely limited by OpenFeint itself and thus most APIs in extension just return -1 and do nothing.