Cocos2d-x Cross Platform Video Player – Part 2 Android

In the last post, we saw how to create a skeleton to handle multiple platforms with the `WrapperClass` and how to implement video player in iOS. Please go through the first post, to get a good understanding of this post.

Download

Download project @ https://github.com/saiy2k/cocos2dx-videoplayer-android/archive/master.zip

Complete Project can be found in GITHUB.

1. Project Creation

For setting up the project, refer this page. Create a project named `VideoPlayer` and come back here once you got the `Hello World` running in Android.

2. Copy Wrapper Classes from previous Tutorial

Copy the WrapperClass(.h, .cpp), AudioManager(.h, .cpp), Config(.h, .cpp), AppDelegate(.h, .cpp) and HelloWorldScene(.h, .cpp) files to the newly created Android project. If all configurations are done right and the old CPP files are copied in right way, running the project should show `Click to play Video` in the center of the screen. But one catch, it will show a Compilation error, since the `CCApplication` class wont be having `playVideo()` function, which is called from the `WrapperClass`. This line can be commented out temporarily to check if everything is configured right and if the label `Click to play Video` is being rendered.
Cocos2dx Cross Platform Video Player Screenshot

3. Passing control from C++ to Java

We already have the touch handler in HelloWorldScene, which calls on `WrapperClass->playVideo()), when a touch is made.

Branching to Android specific code lies in `WrapperClass`, which calls `playVideo()` function of `CCApplication`. So lets add that function in `CCApplication`(.h, .cpp). The corresponding file will be located @ $COCOS2DX_HOME/cocos2dx/platform/android/CCApplication.h/cpp, where $COCOS2DX_HOME is the path where you installed coos2d-x files.

Add the following code to that class:

void CCApplication::playVideo(){
    JniMethodInfo minfo;
    if(JniHelper::getStaticMethodInfo(minfo,
                                      "in/gethugames/VideoPlayer",
                                      "playVideo",
                                      "(Ljava/lang/String;)V")) {
        jstring StringArg1 = minfo.env->NewStringUTF("sample.mov");
        minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, StringArg1);
        minfo.env->DeleteLocalRef(StringArg1);
        minfo.env->DeleteLocalRef(minfo.classID);
    }
}

The `getStaticMethodInfo` function of `JniHelper` defines the static JAVA function, which needs to be invoked. 2nd parameters defines a static Java function named playVideo, with first parameter stating the class path in.gethugames.VideoPlayer. And the static JAVA function is expected to take a string parameter, which is defined by the cryptic third parameter. The function `CallStaticVoidMethod` makes the actual function call to JAVA function.

For now, just add an empty function in the JAVA activity class `VideoPlayer` (.java)

public static void playVideo(final String msg) {
    System.out.println("Play Video in JAVA class in invoked");
}

Build and tun the project now and if everything is done right, when the `MenuItemLabel` is touched, the above line should get logged in LogCat. Wow, we passed the control from CPP to JAVA after much effort. Now is the time to play the video.

4. Invoking a separate Video Activity

I am not an android guy and there may be better solutions to play video than what I write here. Please comment, if any other easy / better methods are there.

Add the following code to the VideoPlayer class:

// in VideoPlayer class
public static VideoPlayer selfActivity = null;

// inside onCreate()
selfActivity = this;

// in playVideo() function
Intent i = new Intent();
i.setClass(selfActivity, Cocos2dxVideo.class);
selfActivity.startActivity(i);

`selfActivity is a object reference to the the VideoPlayer object. It is assigned in onCreate() and in `playVideo()`, an Intent is created to switch to another activity, named `Cocos2dxVideo`. This new activity will play a video and when touched in middle, will close itself and also notifies our CPP part of the project.

5. Cocos2dxVideo

Create a layout file `activity_cocos2dx_video.xml` in the res/layout folder with the following contents:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/relative"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="2dp"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:paddingTop="2dp"
tools:context=".Cocos2dxVideo" >

    <VideoView
    android:id="@+id/videoPlayer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true" />

</RelativeLayout>

Above code defines a standard VideoView control that is used to play video in Android. Then add the following code in `Cocos2dxVideo` (.java) class, which gets a reference to the VideoView defined in the layout above, attach the video in `res/raw` and then plays it. Now register the Activity in `AndroidManifest.xml` as follows:

<activity android:name="in.gethugames.Cocos2dxVideo"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
</activity>

Two points to note here:

1. I didn’t passed the video path from the main activity (VideoPlayer) to here, but instead directly plays the video in `res/raw` folder. (will try and update post, when I get time)

2. The video shouldn’t be in the standard resources folder where sprites and other assets are copied. That folder is for cocos2d-x, but since we play the video from JAVA land, the video should be in `res/raw` folder and its suggested that only lowercase should be used in naming the video file.

        // in Cocos2dxVideo class
        private Cocos2dxVideo me;
        public native int onOver();

        // inside onCreate function of Cocos2dxVideo class
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cocos2dx_video);
        me = this;
        VideoView vv = (VideoView) findViewById(R.id.videoPlayer);
        vv.setMediaController(null);
        vv.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.samplevideo));
        vv.start();
        vv.requestFocus();

If the project is run, clicking on the menu item label should invoke the video. Happy? wait, its not over yet. The activity should be closed either after video playback, or if user touches the screen. Add the following event listeners to do the same:

        // invoked when the video playback is complete
        vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
            	me.onOver();
                me.finish();
            };
        });

        // invoked when the video view is touched
        vv.setOnTouchListener(new View.OnTouchListener()
        {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
            	me.onOver();
            	me.finish();
                return false;
            }
        });

Both the listeners does the some thing, calls the native function `onOver() and end the activity by calling, `finish()`. This resumes the previous activity, which the our `VideoPlayer`. When the video started playing, the in-game music is paused. So, we need to resume it, when the video is done. That’s the reason for calling the onOver().

6. JAVA to CPP – Video Completion notification

The function onOver() is marked with `native` keyword to denote its real implementation is in CPP and control should be transferred. JAVA to CPP is very simple. Just name a function in CPP in the following format to achieve it:

return-type Java_[CLASSPATH]_[FUNCTION_NAME](JNIEnv *env, jobject thiz) { }

So, add the following code anywhere within a extern “C” {} block, I added in jni/hellocpp/main.cpp file.

        void Java_in_gethugames_Cocos2dxVideo_onOver(JNIEnv *env, jobject thiz) {
	CCLog("CPP Function called");
	AudioManager::sharedManager()->playBG();
}

Hence the loop is complete and thus the game sound track gets played after the video is over.

Thats the end of the Tutorial !!!

Download

Download project @ https://github.com/saiy2k/cocos2dx-videoplayer-android/archive/master.zip

Complete Project can be found in GITHUB.

Cocos2d-x Cross Platform Video Player – Part 1 iOS

Cross Platform (iOS and Android) Video playing solution is very much possible in cocos2d-x 2.1.5. But as far as I searched there is not single tutorial / forum discussion that explains it with ease. So here I am summarising how I achieved it. There is no Video Player control in cocos2d-x. So we need to fall back to native video players of iOS and Android platforms. Android Video Playback in 2nd part of this tutorial.

Objective:

To write a single function that plays a video in either iOS / Android, given its file name. Also, the video should be made skippable, by tapping on it. The game’s sound track should be muted when the video gets played, since it might have its own soundtrack and the game’s sound track will be resumed, when the video is stopped.

Download

Download project @ https://github.com/saiy2k/cocos2dx-videoplayer-ios/archive/master.zip Complete Project can be found in GITHUB.

1. Generic Wrapper Class

To handle Features, which require separate implementations on iOS and Android, I implemented wrapper class(WrapperClass.h, WrapperClass.cpp), which will be called from the game code. Then there will be separate Platform dependent wrapper classes, which will get called from WrapperClass. The only functionality of WrapperClass is to forward the flow to platform dependent functions. Here is the code of the Wrapper Class:

//WrapperClass.h
class WrapperClass : public cocos2d::CCObject {
public:
    void                            playVideo(const char *vidPath);
    static WrapperClass             *getShared();
};

//WrapperClass.cpp
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
#include "misc/iOSWrapper.h"
#endif

static WrapperClass *instance   =   NULL;

void WrapperClass::playVideo(const char *vidPath) {
    AudioManager::sharedManager()->stopBG();
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
    iOSWrapper::getShared()->playVideo(vidPath);
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    CCApplication::sharedApplication()->playVideo(vidPath);
#endif
}

WrapperClass *WrapperClass::getShared() {
    if (!instance) {
        instance                =   new WrapperClass();
    }
    return                          instance;
}

The `playVideo` function just calls platform specific function from here. Since playback in Android requires JNI calls to pass the flow to JAVA side, I implemented the required function in CCApplication, which already has few JNI calling functions. Also, this function stops the background music, since the Video will be having its own Audio Track. Game’s sound track will be resumed when the video gets over.

2. Playing Video in iOS

The `iOSWrapper` singleton (iOSWrapper.h, iOSWrapper.mm) called in above code is another wrapper that bridges the CPP side of cocos2d-x and Objective-C part of native `UIView` code. The `playVideo` function of `iOSWrapper` class is as follows:

void iOSWrapper::playVideo(const char *vidPath) {
    NSString                        *string, *stringPath;
    stringPath                  =   [NSString stringWithUTF8String:vidPath];
    string                      =   [[NSBundle mainBundle] pathForResource:stringPath ofType:@"mp4"];
    [[EAGLView sharedEGLView] playTutorialVideo:string];
}

The above code converts the date type of file name from `char *` to `NSString` and then find its path in the Bundle and calls another custom function `playTutorialVideo()` written in `EAGLView`. That function is responsible for actual video play. Add the following in `EAGLView` to complete the iOS part.

 (void) playTutorialVideo:(NSString *)path {

    NSURL                           *url;

    url                         =   [NSURL fileURLWithPath:path];
    player                      =   [[MPMoviePlayerController alloc] initWithContentURL:url];
    player.view.frame           =   CGRectMake(0, 0, self.frame.size.height, self.frame.size.width);
    player.fullscreen           =   YES;
    player.scalingMode          =   MPMovieScalingModeNone;
    player.controlStyle         =   MPMovieControlStyleNone;
    [self                           addSubview:player.view];
    [player                         play];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(removeVideo)
                                                 name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
}

Now we are completely into iPhone Native part, where we use Objective-C and deal with UIView and UIViewControllers, completely away from cocos2d-x land. The above function creates a `MPMoviePlayerController`,  loads the video with given path and plays it. MPMoviePlayerController throws notifications instead of calling delegate callback functions, in case of internal events. So the above code also registers with NSNotificationCenter to capture video pause / stop events.

(void) removeVideo {
    if (player.playbackState == MPMoviePlaybackStatePaused || player.playbackState ==   MPMoviePlaybackStateStopped) {
        [player.view removeFromSuperview];
        [player release];
        player = nil;

        [[NSNotificationCenter defaultCenter] removeObserver:self
        name:MPMoviePlayerPlaybackStateDidChangeNotification
        object:nil];

        AudioManager::sharedManager()->playBG();
    }
}

The above function is registered to handle notifications of MPMoviePlayerController and will get invoked on any change in state. We need to remove the controller, only when the video playback is over and so we check for the Stopped/Paused state and when they happen, we remove the controls, release from memory, resumes the game background music.

Skip on Touch

Not all players will sit through the videos / instructions, but they want to directly get hooked up into the gameplay. So, we will make the video stop and disappear, when user taps on it. To do it, just add the following block of code inside `touchesBegan` function of EAGLView, immediately after `if (isKeyboardShown_)` block:

if (player) {

    [player stop];
    [player.view removeFromSuperview];
    [player release];
    player = nil;

    [[NSNotificationCenter defaultCenter] removeObserver:self
    name:MPMoviePlayerPlaybackStateDidChangeNotification
    object:nil];

    AudioManager::sharedManager()->playBG();

    return;
}

To keep the posts short, I will write about Android part of the Video Player in next post. Once all this is done, setup a Layer (HelloWorldScene.hHelloWorldScene.cpp) with a menu button, whose handler has the following one line of code:

WrapperClass::getShared()->playVideo("sampleVideo");

If everything is done right, you will have a button in screen, which when clicked, stops the game sound track, and plays the video. Once the video is over or skipped, the game sound track resumes.

Download

Download project @ https://github.com/saiy2k/cocos2dx-videoplayer-ios/archive/master.zip Complete Project can be found in GITHUB.

Android

Android Video playback is explained in the second part of this tutorial.

Cocos2dx – Platformer Physics Tutorial

I tried implementing the platforming physics logic in cocos2d-x and it came out pretty well as per my expectations. This tutorial is about how I made it. It might not be the best solution out there, but it is something that works. Before diving in, here is the demo video showcasing the final output:

Downloads

1. Mid Project (with just the platforms render)
2. Full Project (all functionalities)

1. Create a Cocos2d-x Project

I am not going to discuss about how to setup a cocos2d-x project for iOS here. I will directly dwelve into the platforming mechanism here. For info on how to setup cocos2d-x project, refer the official wiki.

All our code will go into `HelloWorld` class that comes with the template.

2. Define the Platforms

Add the following struct in HelloWorld.h to model a Line

typedef struct {
    CCPoint p1, p2;
} Line;

Declare a pointer to Line struct in HelloWorld, which will be an array of all platforms and randomly add a few lines in it:

// in HelloWorld.h
Line *lines;

// in init function of HelloWorld.cpp
lines = (Line *)malloc(sizeof(Line) * COUNT);

lines[0].p1 = ccp(100, 100);
lines[0].p2 = ccp(400, 100);

lines[1].p1 = ccp(500, 600);
lines[1].p2 = ccp(700, 600);

lines[2].p1 = ccp(400, 400);
lines[2].p2 = ccp(600, 500);

lines[3].p1 = ccp(500, 200);
lines[3].p2 = ccp(1000, 200);

The platforms are defined well with their points. Now is the time to render them on screen. Add the `draw` function to the `HelloWorld` scene.

// in header file
virtual void draw();

// in cpp file
void HelloWorld::draw() {
    glLineWidth(4.0);
    for (int i = 0; i < COUNT; i++) {
        ccDrawLine( lines[i].p1, lines[i].p2 );
    }
    CCLayer::draw();
}

The above code sets the line width to 4 pixels, loops through our platform array and draws the lines. Our screen should look like this:

3. Character Sprite and Controls

The platforms are setup right. Now lets add the hero sprite which will run through the platforms and two button controls to make the character move. To add the hero and controls, do this:

// in header file
CCSprite* pSprite;
void menuCloseCallback(CCObject* pSender);

// in init function of HelloWorld.cpp
CCMenuItemImage *pCloseItem = CCMenuItemImage::create("CloseNormal.png",
                                                      "CloseSelected.png",
                                                      this,
                                                      menu_selector(HelloWorld::menuCloseCallback) );
pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 60, 60) );
pCloseItem->setTag(1);
pCloseItem->setScale(2.5f);

CCMenuItemImage *pCloseItem1 = CCMenuItemImage::create("CloseNormal.png",
                                                       "CloseSelected.png",
                                                       this,
                                                       menu_selector(HelloWorld::menuCloseCallback) );
pCloseItem1->setPosition( ccp(60, 60) );
pCloseItem1->setTag(2);
pCloseItem1->setScale(2.5f);

// controls for left and right movement
CCMenu* pMenu = CCMenu::create(pCloseItem, pCloseItem1, NULL);
pMenu->setPosition( CCPointZero );
this->addChild(pMenu, 1);   

// hero sprite
pSprite = CCSprite::create("CloseNormal.png");
pSprite->setPosition( ccp(600, 700) );
pSprite->setTag(-1);
this->addChild(pSprite, 0);

By now our screen should look like this:

4. Basic Movement

The stage is set with all the objects put in place. Now is the time to start moving the objects. Add two variables `speedX` and `speedY` that controls the movement of our hero and schedule the update function of CCLayer to get into the game loop.

// in header file
virtual void update(float dt);
float speedX, speedY;

// in init function of HelloWorld.cpp
speedX = 0;
speedY = 0;
this->scheduleUpdate();

// in HelloWorld.cpp
// moves the hero around the screen as per the speedX and speedY values
void HelloWorld::update(float dt) {
    CCPoint p = pSprite->getPosition();    
    pSprite->setPosition( ccp( p.x + speedX * dt, p.y + speedY * dt ) );
}

// makes the hero to move to left / right based on the touched control
void HelloWorld::menuCloseCallback(CCObject* pSender) {
    if (((CCNode *)pSender)->getTag() == 1) {
        speedX += 100;
    } else {
        speedX -= 100;
    }
}

Now touching the left control button, increases the movement of the hero in left direction and the same with the right control button. As of now, Movement happens only in x-axis and there is no gravity (falling down), friction and collision. The project at this point can be downloaded here for reference.

5. Physics Magic

First replace the `update` function with following code.

void HelloWorld::update(float dt) {
    CCPoint p = pSprite->getPosition();

    speedX *= 0.95; // friction reduces the speed over time

    if (pSprite->getTag() == -1) { // free falling
        CCLog("searching for platform... hero is falling");
        // iterate through all platforms
        for (int i = 0; i < COUNT; i++) {
            // if hero position lies between the x bounds of any platform
            if ( lines[i].p1.x < p.x && lines[i].p2.x > p.x ) {
                // also it is closer than 100 pixels to the platform
                if ( p.y - lines[i].p1.y < 100 && p.y - lines[i].p1.y > 0) {
                    // assign the platform to the hero
                    pSprite->setTag(i);
                    break;
                }
            }
        }
        // gravity pull decreases the y-speed
        speedY -= 10.0;

        // not allowing hero to go down indefinitely, by making him swap to the top
        if ( p.y < 0 ) {
             p.y = 768;
        }
    } else { // resting in or closer to some platform
        int tag = pSprite->getTag();
        CCLog("in platform %d", tag);

        // make sure if hero is still in the x bounds of the platform or moved away
        if ( lines[tag].p1.x < p.x && lines[tag].p2.x > p.x ) {
            float x2, y2;
            x2 = p.x;
            // platform may be a sloppy one, so interpolate the y value based on end points of platform and current hero position 
            y2 = (x2 - lines[tag].p1.x) * (lines[tag].p2.y - lines[tag].p1.y) / (lines[tag].p2.x - lines[tag].p1.x) + lines[tag].p1.y;
            if (p.y - y2 > 0) { // if hero is above platform, make him fall down
                speedY -= 10.0;
            } else {            // nullify the y speed and rest on platform
                speedY = 0;
                p.y = y2;
            }
        } else { // switch to free fall mode, if hero is moved away
            pSprite->setTag(-1);
        }
    }

    pSprite->setPosition( ccp( p.x + speedX * dt, p.y + speedY * dt ) );
}

I believe the above code is self-explanatory with all the comments put in. So I will just add few notes that deserve some explanation here.

Tag

`tag` property of Hero is used to refer to the platform he is in. If he is free falling (i.e., not attached to any platform) then `tag` will be -1.

Friction

 speedX *= 0.95;

Above code decrements the x speed of the hero by 5% on each update, thus simulating the friction effect.

Interpolation

If all the lines are perfectly horizontal, then y values of the end points or any other point in that line would be equal. If the lines are sloppy, things would be different and we need to calculate the y-value of any arbitrary point in the given line for the given x. If its confusing, see the picture below and read on.


For any platform, we have the end points A (x1, y1) and B (x2, y2) and we have the position of the hero represented here as H(hx, hy). But to check if the hero is above or below the line, we need the point that lies in the line which is P(x, y). Of course, x would be same as hx, but how to find y? Not to worry, we can interpolate the y value with the following formula:

y = y1 + (hx - x1) * (y2 - y1) / (x2 - x1)

The above formula is translated to CPP in our code with our variables as follows:

y2 = (x2 - lines[tag].p1.x) * (lines[tag].p2.y - lines[tag].p1.y) / (lines[tag].p2.x - lines[tag].p1.x) + lines[tag].p1.y;

Thats the end of the tutorial and here is the full project. This project can be easily extended to 2d side scrolling platformer games. I will try to write a post on that in future. There might be several places where a beginner can easily get lost. Post the queries in comments and I will try to resolve.

Integrating GoogleTest with Xcode 4

I been thinking and reading about Unit Testing for a long while, but never dared to actually implement it in any of my projects (both in work and hobby projects) for various reasons the most obvious one being ‘laziness’.

But all of a sudden I got enlightened yesterday and been sincerely reading about UnitTest++, googletest and some other testing frameworks and decided to go with googletest for obvious reasons.

I downloaded the framework but found that the official xcode integration guide is out of date now and I couldnt easily find any other guides to integrate it with xcode 4 (mine is 4.2). So here I am writing one….

Building the gtest framework

  • Download the framework.
  • Extract the zip.
  • Open the xcode project @ gtest-1.6.0/xcode/gtest.xcodeproj
  • Select gtest-framework Scheme and build the project.
  • If you get the errorThe run destination My Mac 64-bit is not valid for Running the scheme ‘gtest-framework’. The scheme ‘gtest-framework’ contains no buildables that can be built for the SDKs supported by the run destination My Mac 64-bit. Make sure your targets all specify SDKs that are supported by this version of Xcode“, try setting the following for both `Project` and `gtest-framework` Target:
    • `Base SDK` to any proper available SDK.
    • `Compiler for C/C++/Objective-C` to any proper compiler. LLVM GCC worked for me.
gtest-framework-scheme

scheme selection for gtest-framework

  • On successfull compilation, right click on gtest.framework in Products folder in Navigator and select ‘Show in Finder’
gtest-framework-products

build products for gtest-framework

 

  • Copy the gtest.framework folder to a common location (mine is /Users/saiy2k/projects/gtest-1.6.0/products)

Integrating with Real Project

  • Open the project in which testing capabilities need to be added.
  • Click on the project name in Navigator.
  • Create new target by clicking ‘Add Target’. (pic)
  • select Mac OS X –> Application –> Command Line Tool
  • Enter Product Name and other fields and click finish.
  • Selecting the newly created Target and goto Build Phases tab.
  • Add gtest.framework in our common location to ‘Link Binary with Libraries’
gtest-framework-target-build-phases

adding new target and adding gtest framework to it

Writing Test Case and Testing

In the Project Navigator, you should be having a new folder in the name given to the Target project. Under that project create a header file ‘TestCase1.h’ with the following contents:

TEST(SampleTest, Zero) {
    EXPECT_EQ(0, 0);
}

TEST(SampleTest, Positive) {
    EXPECT_EQ(1, 1);
    EXPECT_EQ(6, 3*2);
    EXPECT_EQ(20, 10*2);
}

TEST(SampleTest, Negative) {
    EXPECT_EQ(-1, -1);
    EXPECT_EQ(-2, -2);
    EXPECT_EQ(-3, -3);
}

Now select the scheme for New Test Target and run it and check the log for output of the test run. For writing actual test cases, refer the googletest wiki.

HTML5 Space Maze

Gethugames’ another product that has been dragged for 6 months of development period is finally released as BETA.

Play the game @ http://www.gethugames.in/html5spacemaze/ Source code @ https://github.com/saiy2k/HTML5-Space-Maze

Dynamic Size

Unlike Tic Tac Toe, which had 2 different sizes for mobile and desktop versions, the goal of this project is to make the gameplay area resize itself to any resolution. A wonderful post @ html5rocks.com made this task much easier.

Leader Board

Another goal is to integrate some sort of leader boards to save user score and make the game little competitive. I integrated Playtomic API for the leader boards and it was very simple and good. But there were some serious server stability issues with Playtomic few months back as more and more people started using it and so I temporarily turned off all Playtomic related code in my game. But now Playtomic seems to be working fine and soon will update the code with leader board functionality.
HTML5 Space Maze Screenshot

No Frameworks

The biggest mistake I been doing since my first project is not using any gaming frameworks / game engines. Hand coding menu systems / buttons / screen flow logics is hectic and meaningless when so much of the work is already being done in many open source game frameworks. This project made me realize my mistake and wont be doing any other project from scratch as this. Been looking into coco2dx for a while and probably will be using it for the next game.

Mobile

The main reason for implementing dynamic game layout is to make the game playable in mobile. But targeting this game for mobile is a bad idea. This gameplay mechanism wont suit for touch devices. The core mechanism is to evade existing lines and asteroids and draw the line through the gaps with high precision. But when you place the thumb in screen in mobile, your view of the drawing tip gets blocked and you lose the precision, thus making the gameplay frustrating.
I tried accelerometer integration and thought drawing as per the device orientation would be cool. It was cool actually, but the problem is browser’s auto-rotation. When you play, the browser auto rotates between portrait and landscape orientations in the mid of the game and there is no API in HTML5 to block browser auto-rotation. Hence mobile gameplay would not all be playable, though it works technically.

Not yet tested in IE. Will do when I get time.

Finally, The Team
Big thanks to Sankar Ganesh, Kevin Skyba for their overall support, ideas and more importantly contributions in programming. Thanks guys :-)

Then big thanks goes to open source / open art community for all the game assets including graphics / sound effects, etc., Here I list out the links to people whose work are used in this game

HTML5 Orientation support (iPhone)

There is a great tutorial on html5rocks.com on how to use device orientation api in javascript. It has neat examples to demonstrate the functionality.

Problems with browser Orientation change:

But one issue that I faced is when the device(iPhone) is tilted, the browser’s orientation gets changed between landscape and portrait, which had a very negative impact on my project. I am currently working on a game named ‘HTML5 Space Maze'(in github), which is supposed to draw a continuous line based on device orientation. But when the device is tilted and the browser’s orientation gets changed, my game’s state gets messed up.Searched with a hope that there should be some API to lock the browser orientation. But there were none, though I got some work arounds(in stackoverflow) to mimic the orientation lock. But I am not satisfied with all this and postponed my R & D.

Phonegap, the savior:

Today morning I was trying out the phonegap framework for first time and my HTML5 Space Maze game integrated well with the phonegap and ran good in iPhone. Then I switched to the long-forgotten ‘orientation’ branch of my project and tried running the code through phonegap, locking the orientation of ‘CDVViewController’ to landscape left.Then tested the code in iPhone and it worked flawlessly. Since the ViewController is restricted to landscape left, no matter how you tilt the phone, the views wont rotate and thus making my game responding well.

I achieved my goal somehow today, but the target platform changed from web to iOS now. Not a big deal for me, I not yet decided or even thought on how and where to deploy the product once its complete.