Cocos2dx – Spinning Globe by Masking technique

In this post, lets see how we can implement a spinning world in cocos2d-x using masking technique. See the video below for sample output:


Low FPS is because of my Mac Mini; In device, it runs at 60 FPS

Downloads

1. Full Project

1. Create a Cocos2d-x Project

I am not going to discuss about how to setup a cocos2d-x project for iOS 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. Masking Functionality

The hardest part in achieving our goal would be ‘Masking’ and we resort to Pavel Hancak’s tutorial on cocos2d-x masking. Please check the tutorial on how to mask a sprite. Based on that code, I rewrote the function as below:

CCSprite* HelloWorld::maskedSpriteWithSprite(CCSprite* pTextureSprite, CCSprite* pMaskSprite, float xoffset, float yoffset)
{
    // store the original positions of both sprites
    CCPoint textureSpriteOrigPosition(pTextureSprite->getPosition().x, pTextureSprite->getPosition().y);
    CCPoint maskSpriteOrigPosition(pMaskSprite->getPosition().x, pMaskSprite->getPosition().y);

    // convert the texture sprite position into mask sprite coordinate system
    pTextureSprite->setPosition(ccp(pTextureSprite->getContentSize().width/2 - pMaskSprite->getPosition().x + pMaskSprite->getContentSize().width/2 - xoffset, pTextureSprite->getContentSize().height/2 - pMaskSprite->getPosition().y + pMaskSprite->getContentSize().height/2 + yoffset));

    // position the mask sprite so that the bottom left corner lies on the (o,o) coordinates
    pMaskSprite->setPosition(ccp(pMaskSprite->getContentSize().width/2, pMaskSprite->getContentSize().height/2));

    CCRenderTexture* rt = CCRenderTexture::renderTextureWithWidthAndHeight((int)pMaskSprite->getContentSize().width, (int)pMaskSprite->getContentSize().height);

    ccBlendFunc bfMask = ccBlendFunc();
    bfMask.src = GL_ONE;
    bfMask.dst = GL_ZERO;
    pMaskSprite->setBlendFunc(bfMask);

    // turn off anti-aliasing around the mask sprite
    pMaskSprite->getTexture()->setAliasTexParameters();

    ccBlendFunc bfTexture = ccBlendFunc();
    bfTexture.src = GL_DST_ALPHA;
    bfTexture.dst = GL_ZERO;
    pTextureSprite->setBlendFunc(bfTexture);

    rt->begin();
    pMaskSprite->visit();
    pTextureSprite->visit();
    rt->end();

    // generate the resulting sprite
    CCSprite* pOutcome = CCSprite::spriteWithTexture(rt->getSprite()->getTexture());
    pOutcome->setFlipY(true);

    // restore the original sprite positions
    pTextureSprite->setPosition(textureSpriteOrigPosition);
    pMaskSprite->setPosition(maskSpriteOrigPosition);
    pOutcome->setPosition(maskSpriteOrigPosition);

    return pOutcome;
}

I added two parameters `xoffset` and `yoffset` to the original code. These parameters are to offset the position of underlying map. By varying this offset parameter in gameloop, we move the map linearly over a period of time.

3. Setup Sprites

Add two sprites `map` and `mask`, where

2d world map

`map` contains the full map. Only a part of will be seen at any time

When one edge of the scrolls into the keyhole (mask), we dont want the background to be visible, but the other edge to wrap and fit the gap. For this purpose, we duplicated the map horizontally, and when one edge is within keyhole, the duplicated part will fit in and when the edge crosses the keyhole completely, we reset the map to initial position. (Will see implementation details in subsequent sections).

mask for world map

`mask` picture is like a circular keyhole through which we sees part of a map.

Code to add these two sprites is as follows. Dont add the sprite as child of layer yet.

    
    // in init() function
    map = CCSprite::create("worldmap2d.jpg");
    map->setPosition( ccp(512, 768/2) );
    map->retain();

    mask = CCSprite::create("worldmapmask.png");
    mask->setPosition( ccp(512, 768/2) );
    mask->retain();

Apart from the `map` and `mask`, a star background is added behind.

4. Masking

With Pavel Hancak’s tutorial, masking is now very simple as following:

    // in init() function
    masked = maskedSpriteWithSprite(map, mask, 0, 100);
    addChild(masked);

Only the masked sprite should be added to the `layer`. I found the offsets on trial and error basis 😛 At this point, you should see circular part of the map and not the whole. We masked the map, but still it looks like a flattened map without any depth. To add some depth, add a `shade` picture, above all the sprites as follows

    // in init() function
    shade = CCSprite::create("worldmapshade.png");
    shade->setPosition( ccp(512, 768/2) );
    addChild(shade);
shade over world map

shade to be applied over the world map to create an illusion of depth

5. Spinning Animation

We dont have any real `3D` object here and so we achieve spinning animation by moving the map horizontally behind the keyhole (mask) infinitely. Add this final piece of code and we are done:

    // in init() function
    this->scheduleUpdate();

    void HelloWorld::update(float dt) {
        CCSprite *m;
        xoff += dt * 100;
        if (xoff > 1024) {
            xoff = 0;
        }
        m = maskedSpriteWithSprite(map, mask, xoff, 120);
        masked->setTexture(m->getTexture());
    }

In above code, `xoff` determines the amount of distance that the map should be moved. `Update` is the gamploop, where we increment `xoff` by small amounts in each frame, thus moving the map. When the `xoff` reaches its limit, we reset it. Changing `xoff` doen’t do anything magically. We create a new sprite based on offset position and apply the texture to our `masked` sprite.

Run the project and see the world spinning. Thats the end of the tutorial. Hope it helped :-)

Source can be browsed @ https://github.com/saiy2k/cocos2dx-masking 

C Program for 21 Sticks game

Here is a good brain refreshing puzzle that I solved recently. Thanks to my friend Raghul for sharing this good piece of puzzle with me. Its a turn based 2 player game (player and computer in our case). c

Now, I am to write a program for this game in such a way that however the player plays, he always picks the last one and thus the computer wins. Looked very simple at first and I came with the following program in 15 minutes and thought to myself (very proudly) that I solved it.

    
    int lineCount;
    int userPick;
    int aiPick;

    lineCount = 21;
    while (lineCount > 1) {
        printf("\n\n%d lines remaining. Pick 1 or 2 or 3 or 4: ", lineCount);
        scanf("%d", &userPick);
        lineCount -= userPick;

        if (lineCount == 1) {
            printf("\nyou win and AI lose\n");
            return;
        }
        if (lineCount <= 5) {
            aiPick = lineCount - 1;
        } else {
            aiPick = rand() % 4 + 1;
        }

        printf("you took %d lines", userPick);
        printf("\nAI took %d lines", aiPick);
        lineCount -= aiPick;
    }
    if (lineCount == 1) {
        printf("\nyou win and AI lose\n");
        return;
    } else {
        printf("\n1 line remains and u lose\n\n");
    }

The AI seems to be working good, but its not perfect. It fails occasionally, especially when the player gets a turn with the remaining number of sticks in the range 2 to 5. So I tried to fix this by playing in such a way that AI always gets its turn when the remaining number of sticks is in the range 2 to 5. But I couldn’t figure out how to do this inside my little mind. So I took a pen and paper and started writing the remaining number of lines, all possibilities of AI’s move and corresponding result, which resulted in a table such as this:

Possible States with results
Remaining Sticks AI Move Worst Case
2 1 Win
3 2 Win
4 3 Win
5 4 Win
6 1 Lose
2 Lose
3 Lose
4 Lose
7 1 Win
2 Lose
3 Lose
4 Lose
8 1 Lose
2 Win
3 Lose
4 Lose
9 1 Lose
2 Lose
3 Win
4 Lose
20 1 Lose
2 Lose
3 Lose
4 Win
21 1 Lose
2 Lose
3 Lose
4 Lose

Only after completely writing out the above table, I found that when there are some certain magic remaining sticks at your turn, regardless of your move, if ur opponent plays his best move, he can win. The magic numbers are found to be 21, 16, 11, 6 and of course 1.

Since the player begins the game with 21 remaining sticks (one of the magic number), as long as my AI plays its best move, it can win. The AI’s best move nothing but the move which makes the remaining number of lines to the next lowest magic number and as we continue when the player plays his move, he will have the remaining sticks as 16, 11, 6 and finally 1 and he loses. Here is the final working program with perfect AI:

#include <stdio.h>

int lineCount;

void main() {

    int userPick;
    int aiPick;

    lineCount = 21;
    while (lineCount > 1) {
        printf("\n\n%d lines remaining. Pick 1 or 2 or 3 or 4: ", lineCount);
        scanf("%d", &userPick);

        lineCount -= userPick;

        if (lineCount >= 17 && lineCount <= 20) {
            aiPick = lineCount - 16;
        } else if (lineCount >= 12 && lineCount <= 15) {
            aiPick = lineCount - 11;
        } else if (lineCount >= 7 && lineCount <= 10) {
            aiPick = lineCount - 6;
        } else {
            aiPick = lineCount - 1;
        }

        printf("you took %d lines", userPick);
        printf("\nAI took %d lines", aiPick);
        lineCount -= aiPick;
    }

    printf("\n1 line remains and u lose\n\n");
}

I am sure this is not the best way to solve this problem, I should have done some research on maths and find some elegant solution, but I guess this is fine for the first step and to achieve the goal. I will look into other possible elegant solutions and if I find any, I will post about it later.

Happy Programming !!!

Extended EPGLTransitionView

Get the project @ https://github.com/saiy2k/EPGLTransitionView

I was searching for some techniques to do flip screen transitions as in Flipboard iphone app and I found this awesome project, EPGLTransitionView.

EPGLTransitionView is an excellent project to do some cool UIViewController transitions. It basically works by taking screenshots of the two views you would like to switch and manipulating the screenshots with OpenGL commands for cool transition effects. Official URL for the project is http://www.memention.com/blog/2010/02/28/Bells-and-Whistles.html

The project comes with 3 basic transitions:

fall turn flip

Reverse Animation:

The class Demo2Transition in the ‘Demo Project’ provided is exactly what I wanted. But it lacked certain features like turning in reversed direction and turning from bottom up.

So I downloaded the project from github, tinkered with the Demo2Transition class and in a while found a way to reverse the animation. Actually reversing was not a big deal, the animation is controlled by a control variable f, which determines the turned position of view at any given time. I just reversed the initial and final values and it worked flawlessly.

Up Down Transition:

I am not much into OpenGL before, so pulling this’up down turn transition’ took me some time with lots of trial and errors. I did this by changing the order of vertices and texture co-ordinates in which the image is read.

Now both of reversal and up down transition and working great except for 1 frame flicker in ‘reverse animation’. Working on fixing it.

My fork:

I forked the project and committed my changes to the forked repo @ https://github.com/saiy2k/EPGLTransitionView

I also sent a pull request to the original repo, lets see if its accepted. I done a few open source projects before, but this is the first time that I contribute to some one else’s project.

Usage:

I changed the ‘init’ method in the original project into the following:

– (id)initWithView1:(UIView*)view1 andView2:(UIView*)view2 delegate:(id)_delegate fwdDirection:(BOOL)fwd

where `view1` is the UIView which is currently being active and `view2` is the UIView which need to be shown, `delegate` is the transition class that conforms to `EPGLTransitionViewDelegate` protocol, and `fwd` is a flag that determines the direction of transition.

The EPGL TransitionView can reverse the transition only if the Transition class supports it by implementing the `isVertical` property. If it isn’t then, the value of `fwd` doesn’t have any effect.

A sample use case is given below:

UIViewController *controller = [[[UIViewController alloc] init] autorelease];
controller.delegate = self;
controller.view.frame = CGRectMake(0, 20, 320, 460);
NSObject<EPGLTransitionViewDelegate> *transition;
EPGLTransitionView *glview;

transition = [[[Demo2Transition alloc] init] autorelease];
[transition setIsVertical:YES];
glview = [[EPGLTransitionView alloc]
initWithView1:self.view
andView2:controller.view
delegate:transition
fwdDirection:NO];

[glview startTransition];
[self presentModalViewController:controller animated:NO];

Happy flipping.

Tic Tac Toe Extended

I started this project nearly 9 months ago planned to finish in a month, but because of my laziness dragged till now and finally I completed the development now. Very big thanks to my friend Sridhar for his awesome idea of extended Tic Tac Toe game. At first I never thought it would be much fun, but I started doing it because it seemed simple from development point of view. But when I play the game now with any of my friend, I feel the game addictive.

Game is hosted at http://www.gethugames.in/tictactoe/

 

Source code available at https://github.com/saiy2k/Tic-Tac-Toe-Extended-HTML5-Game

 

Game Description:

This is an extended version of Tic Tac Toe game with a board size of 9×9. The player scores a point on placing his sign in 4 consecutive tiles. The game can be played with another human player or with AI. At the end of the game based on player’s score and timing a Badge is awarded which can be shared to Facebook / Twitter. This game also supports HTML5 offline mode, thus requiring no internet connection to play after first run.

Tic Tac Toe Extended – Screenshot

HTML5 Features:

* Uses Canvas Tag to draw the game board and player marks.
* supports Offline mode
* uses CSS media queries to scale to different screen sizes.
* Playable on all devices from Desktop, Tablet to mobile devices (with minimum resolution of 320×480)

Class Design:
* GameManager: Handles high level game flow and handles UI controls and their events(using jQuery).
* InputManager: manages game specific input.
* GameState: holds the state of the game from game tile array, scores, clicked tile, elapsed time, player names, etc.,
* GameLogic: core game logics like score calculation, checking for win/lose condition, AI.
* GameBoard: updates and draws the gameboard using an array of BoardTile objects.
* BoardTile: handles a single tile in the board, updates and draws them.
* FBWrapper: connects to facebook and shares the game status.
* TwitterWrapper: connects to twitter and shares the game status.

Game AI:

The challenging part of this project is the AI. At first, I tried implementing some tricky AI which will track all your moves and it either go full defense mode, in which it tries to block tiles making hard for the player to score or go in full attack mode, in which the AI only concentrated on getting score for itself. But implementing those logics proved hard for me.

So I fell back to brute force algorithm which scans the whole board in 8 directions(top to bottom and reverse, left to right and reverse, top left to bottom right and reverse, top right to bottom left and reverse). While scanning cell by cell, it adds up a temporary variable for same consecutive non blank tile it passes. That is if the first nonblank tile is the AI tile itself, and 4 such tile are placed adjancently, then it increases the score of 5th non blank tile by 4.

This same logic is repeated for all rows, columns and diagonals in both directions and a weight-age score is given for each and every cell in the process. In the end, the cell with high weight-age will be marking during the AI’s next move.

Scoring System:

The scoring system is very simple, there is a rank calculated based on which the player is given a badge. Higher rank is given as the difference between player’s score and opponent’s score is high and the rank value is lowered as the player spends more time than the opponent.

Offline Mode and Media Queries:

This is the first time for me to try with this technologies. They were very simple but very useful powerful technologies.

Overall, I learned a hell lot from this project including Audio API and many others mentioned above. From my next project, I well try to implement all the things that I learned. And I am thinking of supporting IE from my next project onwards. Hope IE wont be so stubborn in supporting modern web standards.

Spirocanvas

Oops… I started this blog almost half a year ago and totally forgot to post after that. Nevertheless, I am working on open source projects all these times, which I will write more about, on the following posts.

This post is about the Spirocanvas web application, that I have been developing for the past one month. This application lets user to draw amazing spirographs and allows them to be shared to their friends on social networks. Technically, this project is based on the brand new <canvas> element, that is the part of HTML5 specification and I started this project mainly to learn HTML5.

This project was once hosted on code.google.com @ http://code.google.com/p/spirocanvas/. But just recently I moved the code to github @ https://github.com/saiy2k/spirocanvas.

Spirocavas

What this app is about:

This app let you draw cool spirographs with a single click. Tapping on Random button at the bottom draws cool looking randomly generated spirographs. You can control exactly how the graph should be drawn using the controls at the left side. Each graph is drawn in a separate layer. These layers can be reordered, deleted using the layers panel at the right.

Update – Jan, 2012:

The development is over and the project is not hosted at http://www.gethugames.in/spirocanvas/. The app still needs some polish at many things. It looks much like a prototype than a complete product. But I am not going to spend more time with this now, as I am trying out new things (especially games) now. But will come back and give final touches to spirocanvas soon.

May the Source be with You

I, sometimes used to think about open source software and my idea about open source is its good, noble, but I never believed open source software could ever succeed and replace proprietary systems.

Open Source:

Few weeks back, in my office, I had the opportunity to work in GNUstep, but only for a short period. After that I began showing interest in Open Source and spent some time in reading about open source softwares and their milestones. Then, my idea about open source changed dramatically. Mainly because, I realized that the software I had been using for years, which is killing my processor now in home, which found pulsars, which found the greatest prime numbers, which decoded the Enigma message, which first proved that mass distributed computing is feasible, is nothing but a open source software. I am talking about BOINC.

Open Source in Gaming:

Next, Immediately came to my mind is whats the state of open source in Gaming Industry and found this list and was overwhelmed on seeing whats already had been done. So, I decided to contribute and also make use of the open source community for both my career development and for the sake of community.

VERY FEW open source projects proved something like this is possible, but still it has a very long way to go. So, keep the following quote in mind when you think about opensource:

“Ask not what open source software can do for you, but what YOU can do for open source software.”

This Blog:

I started this blog to support open source. Here, I am going to give out sources of all my works till date, which I have been keeping secretly for many years. I think my friend Jyothiswaroop will get a heart attack, if he read this post. I wont allow him to just glance through my code and he also does the same with me. Though we were very eager to see each others work till school days.

Source:

My works include small programs that I did in my labs to mini application that I developed in school days and college days, to quench my problem solving thirst. I might also give source of the animation works I did, if my friends who worked with me agree. But dont expect me to give out the source of games that I develop in office; I will post only my personal works.
Please use this for educational purposes and dont commercialize it :)<

Download:

I wont put any downloads directly on this blog(actually, blogger wont let me do it). I will be uploading the projects either in code.google.com(for large projects) and Scribd.com(for small programs) and will be publishing the download links here. But, this blog will act as an official page for all the projects hosted outside.

Regards
Saiyasodharan