@jpsarda's longer tweets

Feb 01

Optimized Fonts Workflow with Unity/Futile, bmGlyph [MacOSX only] and TexturePacker

I’m currently making a game with Unity / Futile, for the #1GAM of february.

And now I’ve arrived to the point where I need to use FLabel and fonts. Fonts scare me a bit, especially since we have to deal with different screen densities, but this time I’ve found a good worflow to create bitmap fonts for Futile, and I’ll share it here. To understand this article you must have already started to experiment with Futile and at least you must have watch the quick-start 10mn video .

The game manage 3 sets of resources with 3 suffixes : “_Scale4”, “_Scale2”, and “_Scale1”.

We need to create 3 sets of resources for our bitmap fonts too (I picked Helvetica). We’re going to create the highest resolution texture “helvetica48.png”, that we’ll add in an atlas with TexturePacker, and then we need 3 fonts definition files “helvetica48_Scale4.txt”, “helvetica48_Scale2.txt” and “helvetica48_Scale1.txt”.

Here are the steps :

Open bmGlyph (available on the mac appstore for 8.99€ at the time I’m writing this) and create your fonts.

image

Then, once you’re ready, click on the “Publish” button image. And here are 4 screenshots showing how to configure your 4 publishing targets. One target called “Main .png” is for publishing the main texture (highest density) in a raw resources folder (not in the Unity resource folder). The 3 other targets are for publishing the 3 fonts definition files directly in the Unity resources folder.

imageimageimageimage

Now you need to open TexturePacker (22.79€ with a free trial at the time I’m writing this, and free for bloggers), and add the main .png texture in the atlas (it can be an atlas dedicated for your fonts, or any other atlas you’ve already created for your game, in this example I’ve used a dedicated atlas called “fonts0.tps”). Before publishing with TexturePacker image, you must set the “Auto SD” options image, has shown in the screenshot below. Note that this is not specific to working with fonts, this is how you want to set the “Auto SD” options of all the atlas you will generate for a Futile project.

Now, you need to load the atlas and the fonts in your Futile project like this :
image

And you’re done.

So next time you want to modify your fonts (and believe me that will happen), the workflow is :

1) Open bmGlyph, modify your fonts
2) Publish with bmGlyph
3) Open TexturePacker and publish the atlas containing your fonts .png

Dec 10

Hey game reviews, link to our twitter!

When I write an article, I usually try to link to the twitter account or a personal website from a person I’m quoting. This is a kind of thank-you and also, more importantly, a valuable information for the reader, who might want to dig more into the work of this person.
Micro Miners was released about a month ago on iOS. It was reviewed on major mobile gaming sites, and so far, I counted 58 reviews or mentions on specialized websites / youtube channels. I was surprised to see so few reviews linking to the official site microminers.com or to my personal twitter @jpsarda.
To get some accurate numbers, I built a short html bot in PHP to analyse the html pages of the reviews ( source code ). And here are the results : only 20% of the reviews (12 of them) linked to one of my personal pages (the 12 reviews : [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]). If you talk about major websites, only 148apps.com linked to one of my pages.

This is a quite low number which makes me think there is actually a policy or some kind of instructions sent to the reviewers, that ask them to avoid linking to official/personal/external pages. I’m not in the business of game reviewing, so I could be completely wrong, but it seems to me that the main reason could be that most of game review sites, rely, in a part, on affiliate links. They will earn a small percentage of the money spent by a visitor who clicks and buy a game from their site. So in theory, linking to external pages, could potentially hurt their revenue (for example, a visitor could click on the “buy” link from a game’s offical website instead of the link in the review).
I’m perfectly fine with sites trying to make a living from their reviews, AND I’m more than thankful for those sites reviewing my game, which is, in the end, all what a game developer wants (hey, I don’t want being blacklisted for my next game).
But if you ask for my opinion, I think that adding a link to the author’s page, will not hurt that much the revenue of a site, it will provide valuable information to the readers, and will give a bit of a help to indie developers. Thank you for reading.

Sep 23

One can build unique personalities with very few graphics elements (26). 1600 *REALLY* unique @microminers .

One can build unique personalities with very few graphics elements (26). 1600 *REALLY* unique @microminers .

Sep 09

Notch can change the privacy settings of your youtube videos

Yesterday, I uploaded a private video of a game I’ve been working on for the past 2 years (MicroMiners). My goal was to recruit beta testers and to show the video to a few selected reviewers.
I wanted also to show the video to Notch (Do I need to tell Markus Person, aka Notch, is the creator of Minecraft?), who wrote a small (4KB!) game called Miners4K a few years before Minecraft. MicroMiners was inspired by Miners4K, and despite the gameplay is now really different, I wanted to check that all is fine with Notch. I sent an email to Notch, and a few hours later he replied. That was unexpected and that was good news. He liked the video Haha, that looks cool! :D. That made my day and I stopped watching the internet…

That was a mistake. Just after sending this email reply, Notch decided to tweet about the video, ignoring it was private. Do I need to tell that @notch has nearly 1M people following him on twitter? I think thousands of people have been trying to watch the video unsuccessfully for 2 hours, until I finally realized the situation (thanks to @mattrix who kindly warned me about it). Despite I was 2 hours late, 1M followers was a great opportunity to promote the game. And that’s why, despite it was not in my plans, I decided to make the video public. I don’t regret it as the video got almost 2500 views and a good ratio of 99% of likes, in the first 24h. More than every small game developer could wish for a gameplay video.

This is how Notch changed the privacy settings of my youtube video.

Here is the gameplay video below, and now that it’s public, I need to accelerate things. I’m about to start a beta test, and I hope the @microminers can be released before the end of the year. It will be universal for iPhone and iPad, and I’ll try to support the longer screen size of the iPhone 5 too.


And here is a short video showing Notch as a super bonus in the game. It was made to thank Notch for the tweet (and a bit of buzz maybe).

Jun 27

Integrate Cocos2d-x (C++) into an Android application (Java)

This is the Android pendant of the Cocos2d-x within UKKit (iOS) tutorial. As you can see, it’s a bit more complex/long with Android as you need to use JNI and configure Eclipse to merge Java and C++ code, whereas Objective C and C++ can be merged with no problem in Xcode for your iOS projects.

Most tutorials about Cocos2d-x and Android will explain you how to compile and run a pure Cocos2d-x application (you will learn a lot on this excellent Cocos2d-x Android tutorial by French developer Jean-Yves Mengant).
Here, you will learn how to launch different Cocos2d-x activities within your classic Java Android application.


I used Cocos2d-x v1 but I guess this shouldn’t be too much different with Cocos2d-x v2.

I’m on MacOSX but there are very few things specific to the OS I think, so that should work fine on any OS.

1. You have an Android (Java) project. For some activities in your app, you want to use the Cocos2d-x engine.

2. Download the sample project SkeletonCocos2dxApp.zip [UPDATED 2012/06/10 fix Activity end]. We’ll copy some files from it in this tutorial. But you can also open it, study it and run it, to quickly see how it works. I’ve not tested, but you might need to setup Eclipse for C++ environment before compiling the sample project (steps 17. 18. 19. 20. 21. 22. and 23.).

3. For this tutorial, you don’t need to download the latest sources of Cocos2d-x, because they are included in the sample project (I used Cocos2d-x v1 / Opengl 1.1). When you complete the tutorial and understand how the integration of Cocos2d-x into your java project works, you can easily update with the latest cocos2d-x source files if needed.
For your informations this is a quick summary of the modifications added to the Cocos2d-x official sources :
- The org.cocos2dx.libs package was modified from the official cocos2d-x HelloWorld example to allow the “BACK” key to be caught in your activity, and to customize the starting CCScene of your activity.
- The AppDelegate.cpp was modified to allow to customize the starting CCScene.

4. Download the latest Android NDK. Cocos2d-x is C++ and the NDK is necessary to mix java and C++ together in your Android app.

5. Unpack the NDK and put it somewhere, at the same level of the Android SDK is not a bad idea.

6. Now we’ll start to modify your Android project. We’ll add the HelloWorld And HelloWorldBis Cocos2d-x activities to your project. Once this is done and once you undersand how it works, you can easily modify these activities to your needs.

7. The resources (images, textures, sounds, files) of your Cocos2d-x CCNodes and game logic must be added in the “assets" directory of your Android project. Copy the content of the "assets" directory from the sample project into your project.

8. Copy from the sample project, the package “org.cocos2dx.lib" on your project (in "src" directory).

9. Copy from the sample project, the package “org.cocos2dx.helloworld" in your project. These are the 2 Cocos2d-x activities, that you can rename and modify later to your needs.

10. Modify your manifest.xml to declare those 2 activities.
        <activity android:name="org.cocos2dx.helloworld.Cocos2dxHelloWorld"
                  android:label="Hello World Cocos2dx"
                  android:screenOrientation="landscape"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:configChanges="orientation">
        </activity>
        
        <activity android:name="org.cocos2dx.helloworld.Cocos2dxHelloWorldBis"
                  android:label="Hello World Bis Cocos2dx"
                  android:screenOrientation="landscape"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:configChanges="orientation">
        </activity>
11. Copy from the sample project, the directory “jni" into your Android project. "cocos2dx" and "CocosDenshion" are the C++ sources copied from official Cocos2d-x package. "Classes" contains the Cocos2d-x CCNodes and game logic specific to your project. And "main/main.cpp" contains the JNI methods called by the Cocos2d-x activities (like Cocos2dxHelloWorld), used to customize which CCScene an activity will start. (.
12. Don’t know JNI? JNI stands for Java Native Interface, it’s a Java feature and not specific to Android. You don’t need to know that much to run this tutorial, but you can learn more on the Wikipedia article about JNI.

13. Create your own Cocos2d-x activity that suits your needs? Don’t do this before you have the HelloWorld examples running in your app, but here is how you would do this :
- Create the Cocos2dxActivity java class (it is a good idea to duplicate the Cocos2dxHelloWorld.java class). Let’s say we’ve created a Cocos2dxJigsawPuzzle.java class in com.mycompany package.
- Don’t forget to declare your new activity in the Manifest.xml.
- Add the following JNI method in the “jni/main/main.cpp" file : void Java_com_mycompany_Cocos2dxJigsawPuzzle_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h) { … }.
- Note that the default parameters are just the width (w) and the height (h) of the OpenGL surface to create, but you can (and most of the time you will) use more parameters in the JNI method. Example void Java_com_mycompany_Cocos2dxJigsawPuzzle_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h, jint columnsCount, jint rowsCount) { … }.
- Add the following JNI method in the “jni/main/main.cpp" file : void Java_com_mycompany_Cocos2dxJigsawPuzzle_nativeEnd(JNIEnv* env, jobject thiz) { CCDirector::sharedDirector()->end(); }. It’s used to kill the Cocos2d-x environment when the player presses the “BACK” button.

14. Launch the Cocos2d-x activity(ies) somewhere in your project (when taping on a button for example?) :
    		Intent intent = new Intent();
    		intent.setClass(SkeletonActivity.this, Cocos2dxHelloWorld.class);
    		SkeletonActivity.this.startActivity(intent);
15. Done for the project modification! Now let’s compile all this.

16. Copy from the sample project the “build_native.sh” file. Edit it and set the right values. For the NDK_ROOT, use the directory you unpacked/moved the android NDK to. For APP_ANDROID_ROOT, use the root directory of your Android project.


17. Now we need to compile from Eclipse.

18. If it’s not already done, install the C++ environment for Eclipse. This is basically the installation of CDT C++ plugins via the “Help/Install New Software” menu in Eclipse. Perfectly explained and illustrated in the paragraph “Setting up Eclipse for Cocos2D-X Development" of this article.

19. Now we need to convert the project to a C++ project. Right click on the project in the left tree and select “New/Other”.


Then pick “Convert to a C/C++ project”.


Select “C++”/”Makefile project”/”— Other Toolchain —” and click on “Finish”


20. Now we need to tell Eclipse to run our “build_native.sh” makefile. Right click on the project in the left tree and select “Properties”. Select “C/C++ Build”, uncheck “Use default build command”, and enter “bash ${workspace_loc:/SkeletonApp}/build_native.sh NDK_DEBUG=0 V=1” in the “Build command:” field.


22. Now we need to fix the C++ compilation problems/warnings with Eclipse. Right click on the project in the left tree and select “Properties”. Select “C/C++ General”/”Path and Symbols”/”GNU C++”. Then use the “Add…” button to add directories to the path as shown below (not sure all are necessary, and don’t forget to replace the NDK path with your own path).
/Library/Android/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/include
/Library/Android/android-ndk-r8/platforms/android-8/arch-arm/usr/include
/Library/Android/android-ndk-r8/sources/cxx-stl/system/include
/Library/Android/android-ndk-r8/sources/cxx-stl/gabi++/include


23. Eclipse is not very good with C++, so in addition we need to deactivate some warnings/errors. Still in the project properties, select “C/C++ General”/”Code Analysis” and uncheck everything as shown below (not sure you really need to uncheck everything but just to be sure…).


24. We’re done. Run the project and that should work. Actually, that will certainly not work at the first try, but hey you’re a developer. You still have a working sample project to compare with your project.

25. Stay tuned @jpsarda.

Jun 12

Integrate Cocos2d-x into an UIKit application

Cocos2d-x is a multi-platform open source (MIT) C++ / OpenGL. With one source code, you can generate binaries for iPhone, Android, and more. That’s a big time saver.

Cocos2d-x is younger than its famous brother Cocos2d and despite being actively developed and quite stable already, it lacks of tutorials.

As I’ve struggled a bit to integrate Cocos2d-x into a UIKit application (UIVIewController), here is a walkthrough.

[UPDATE 2012-06-14] As pointed out in the comments, if you want to achieve the contrary (use UIKit components over a Cocos2d-x app), there is an open source project about it on GitHub shared by Di Wu.

[UPDATE 2012-06-28] New tutorial! Achieve the same thing on Android, launch a Cocos2d-x actvity in your Android apps.

http://www.youtube.com/v/J28NwrKLp50

0. Better than words, here is a sample project for people in a hurry. Sample project Cocos2dxOnUikit.zip.

1. You have a UIKit project on iPhone, at one time, you want to show a Cocos2d-x OpenGL view in a view controller.

2. Download the latest sources of Cocos2d-x (I used Cocos2d-x v1 / Opengl 1.1).

3. Unzip and have a look in cocos2dx/platform and cocos2dx/platform/third_party. There are many platforms you don’t need.

4. In Xcode (4.3 in my case), add all sources you need (of course only add the source for iOS platform in cocos2dx/platform/ios and cocos2dx/platform/third_party/ios).

5. Remove references to cocos2dx/platform/CCImage.cpp and CCThread.cpp.

6. In your “Library Search Paths” $(SRCROOT)/cocos2dx/platform/third_party/ios/libraries/ (for the curl library used by cocos2dx)

7. In your “Headers Search Paths” add $(SRCROOT)/cocos2dx and $(SDKROOT)/usr/include/libxml2 (for libxml framework)

8. In “Other C++ Flags” add -DCC_UNDER_IOS

9. Copy and add AppDelegate.cpp and AppDelegate.h from the HelloWorld example (shipped with the Cocos2d-x sources) into your project.
Comment out the applicationDidFinishLaunching() method as shown on the screenshot (this is more or less the code we will move into the ViewController later).
Side note : make sure the AppDelegate of your UIKit app is not called AppDelegate too as you would have in your project 2 AppDelegate.h files.

10. Change the extension of YourAppDelegate.m into YourAppDelegate.mm (for turning it into Objective C++ wich makes it compatible with C++ calls).

11. Add in YourAppDelegate.mm :

#import "AppDelegate.h"
static AppDelegate s_sharedApplication;

12. Now change the extension of YourViewController.m into YourViewController.mm.

13. Add this quick fix if it has not been merged in the main branch. To avoid a leak when releasing the OpenGL view.

14. In cocos2dx/support/zip_support/ioapi.cpp change fopen64 into fopen, fseeko64 into fseeko, ftello64 into ftello.

15. Add these frameworks.

OpenGLES.framework
libxml2.dylib
libz.1.2.5.dylib
QuartzCore.framework

16. Now, the last step, Cocos2d-x OpenGL view is integrated into the controller’s view (used as a modal view controller) :

-(void)loadOpenglScene:(CGRect)rect {
    cocos2d::CCApplication::sharedApplication().run();
 
    EAGLView *glView = [EAGLView viewWithFrame: rect
                                    pixelFormat: kEAGLColorFormatRGBA8
                                    depthFormat: GL_DEPTH_COMPONENT16_OES
                                    preserveBackbuffer: NO
                                    sharegroup:nil
                                    multiSampling:NO
                                    numberOfSamples:0];
    
    [self.view insertSubview:glView atIndex:0];
    
    cocos2d::CCDirector *pDirector = cocos2d::CCDirector::sharedDirector();
    
    pDirector->setOpenGLView(&cocos2d::CCEGLView::sharedOpenGLView());
    
    // enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices.
    // pDirector->enableRetinaDisplay(true);
    
    // turn on display FPS
    //pDirector->setDisplayFPS(true);
    
    // pDirector->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);
    
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);

    // create a scene. it's an autorelease object
    cocos2d::CCScene *pScene_ = cocos2d::MyGraphicsEngine::scene(myparams);
    
    // run
    pDirector->runWithScene(pScene_);

    // Retained because if not, we get an BAD ACCESS exception when we try to release the Cocos2d-x environment later
    [[EAGLView sharedEGLView] retain];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.


    // In this example we use a navigation bar and a "close" button, the Cocos2d-x view will be added below the navigation bar
    UINavigationBar *bar=[[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 49)] autorelease];
    [self.view insertSubview:bar atIndex:0];
    UIBarButtonItem *closeButton=[[[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStyleDone target:self action:@selector(close)] autorelease];
    
    UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:@""];
    item.rightBarButtonItem = closeButton;
    item.hidesBackButton = YES;
    [bar pushNavigationItem:item animated:NO];
    [item release];
    
    
    [self loadOpenglScene:CGRectMake(0, bar.frame.size.height, self.view.frame.size.width, self.view.frame.size.height-bar.frame.size.height)];
    
}

-(void)close {
    //TODO
}

-(void)viewDidDisappear:(BOOL)animated {
    //Release Cocos2d-x stack
    cocos2d::CCDirector *pDirector = cocos2d::CCDirector::sharedDirector();
    //CCDirector::end() is asynchronous. That's why you can't release [EAGLView sharedEGLView] here after (you'll get a BAD ACCESS exception), and that's why we put it un viewDidUnload.
    pDirector->end();
    
    [self checkWin];
}

- (void)viewDidUnload {
    [[EAGLView sharedEGLView] release];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

17. Stay tuned @jpsarda.

Apr 06

An upcoming game&#8230; Make your own pasting your code on Wordle.

An upcoming game… Make your own pasting your code on Wordle.

Jan 25

Recipe : “Automatic email processing with Python sauce”

Difficulty
2/5

Duration
1 hour

Knowledge
A bit of server administration and a bit of development. No need to be an expert.

What Is It
This is how I build a SMTP server with Python that can process automatically incoming emails.

Remarks
- The other usual way of processing emails, is to download periodically (every 10 minutes for example) your emails from an IMAP/POP server. You’ll get the same auto processing of your emails but with a latence.
- You have to write your own automatic actions (web services, scripts, …) to make this work. This article doesn’t not cover this aspect.

Why
On each of my iPhone games, I provide a way to subscribe to a newsletter to be notified of my new games (and it’s not a bad idea according to Andrew Garisson).
When the player tap on the button to subscribe, the native iOS email client appears prefilled with the address subscribe @ bonuslevel.org. No need to enter the email address for the user (do whatever you can to avoid people writing things on a touch device). And no need to check the validity of the email address on my side (and you’re sure it’s an email address that is used and checked on an iOS device, which is valuable if you send them itunes links). That’s perfect. Once, I used to enter the emails one by one on my database, but now, with the automatic email processing, that’s really perfect.

What You Need
So, to cook an “Automatic email processing with Python sauce”, you need :

- A linux dedicated server
- A domain name (myserver.com)
- Python (“apt-get install python" on Debian)
- Postfix (preferred to Sendmail because it’s easier to configure)

What To Do
Instructions are compatible with Debian, but that will be easily adapted for other linux distributions.

1 Open a terminal window on your server (I assume you know how to do this, if not, I don’t think this article is intended for you).

2 Install Python if not already done.
apt-get install python
3 Change Postfix listening port.
Yes, as our python SMTP server will use the port 25, will have to stop Postfix from using port 25. If you’re using Sendmail, you can install Postfix very easily.
apt-get install postfix
Debian will remove sendmail and start postfix automatically.
Then edit the configuration file of Postfix.
vi /etc/postfix/master.cf
Find the following line and change the port number.
#smtp      inet  n       -       -       -       -       smtpd
6625      inet  n       -       -       -       -       smtpd
Restart Postfix
postfix reload
4 Write the Python SMTP server.
Don’t be afraid, Python comes with a built-in SMTP server. Here is an example of code that must be adapted to your needs. The example comes with a few utilities to process emails. The web service to subscribe/unsubscribe to the newsletter is not provided (out of topic).
#! /usr/bin/env python

# Libraries
import smtplib
import smtpd
import asyncore
import email
import sys
import httplib, urllib
import re
from email.mime.text import MIMEText
from email.parser import HeaderParser


print 'Starting custom mail server'

###########
###########
# Email Tools
###########
###########

class EmailUtils:
    email_pattern = re.compile('([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+')
    @staticmethod
    def forward_message(data, redirectto):
        from_adr='redirect@myserver.com'
#      Forward a message (we change the From tag in the email headers wich I guess is not perfect, I'm not an email expert)
        msg=email.message_from_string(data)
        try:
            msg.add_header('Resent-from', from_adr);
#            msg.replace_header('Subject', '[DI] '  + msg['subject'])
        except KeyError:
            pass
#      Note we are usng port 6625 here as we've changed the Postfix port
        s = smtplib.SMTP('localhost','6625')
        s.sendmail(from_adr, redirectto, msg.as_string())
        s.quit()
        return

    @staticmethod
    def text_message(mfrom,to,topic,body):
#      Send an email with a simple text message
        msg=MIMEText(body);
        msg['Subject'] = topic
        msg['From'] = mfrom
        msg['To'] = to 
#      Note we are usng port 6625 here as we've changed the Postfix port
        s = smtplib.SMTP('localhost','6625')
        s.sendmail(mfrom, to, msg.as_string())
        s.quit()
        return


################
################
# WebService Tools
################
################

class WebServiceUtils:
    @staticmethod
    def newsletter(subscribe,email,source):
#      A method to call your newsletter webservice
#      This must be adapted to your needs
        params = urllib.urlencode({'subscribe': subscribe, 'email': email, 'source': source})
        headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
        conn = httplib.HTTPConnection("www.myserver.com")
        conn.request("POST", "/newsletter/subscribe.php", params, headers)
        response = conn.getresponse()
        print response.status, response.reason, response.read()
        conn.close()
        return


##########################################################
# Send an email to yourself to be notified of the email server being started
##########################################################
EmailUtils.text_message('auto@myserver.com','myaddress@gmail.com','mail server started','automatic email');


#############
#############
# SMTP SERVER
#############
#############

class CustomSMTPServer(smtpd.SMTPServer):

    def process_message(self, peer, mailfrom, rcpttos, data):
        print 'Receiving message from:', peer
        print 'Message addressed from:', mailfrom
        print 'Message addressed to  :', rcpttos
        print 'Message length        :', len(data)
        print data
#      Flush the output buffered (handy with the nohup launch)
        sys.stdout.flush()
#      Analyze data headers
        parser = HeaderParser()
        msg = parser.parsestr(data)
        subject=''
        try:
            subject=msg['Subject']
            subject=subject.lower()
        except:
            print "Subject error:", sys.exc_info()[0]
        print 'Message subject       :', subject

#      Determine action (0 : nothing to do, 1 : unsubscribe, 2 subscribe)
#      We will determine the action to do with the receivers of the message
#      But that could be done also with the Subject of the email (and anything else you can imagine)
        action=0
#      Unsubscribe action, parse receivers and look for 'unsubscribe' in the email address
        if (action==0):
            for to in rcpttos:
                if (to.find('unsubscribe')>=0):
                    action=1
#      Subscribe action, parse receivers and look for 'subscribe' in the email address
        if (action==0):
            for to in rcpttos:
                if (to.find('subscribe')>=0):
                    action=2

        if (action==1):
            print 'Unsubscribe';
            WebServiceUtils.newsletter(0,mailfrom,'secret')
        elif (action==2):
            print 'Subscribe';
            WebServiceUtils.newsletter(1,mailfrom,'secret')
        else:
            EmailUtils.forward_message(data, 'myaddress@gmail.com')

#      Flush the output buffered (handy with the nohup launch)
        sys.stdout.flush()
        return

#Listen to port 25 ( 0.0.0.0 can be replaced by the ip of your server but that will work with 0.0.0.0 )
server = CustomSMTPServer(('0.0.0.0', 25), None)

# Wait for incoming emails
asyncore.loop()
5 Start the python server.
nohup ./smtpserver.py > smtpserver.out 2>&1 &
6 Subscribe!
So, you want to be notified of my next iPhone game (I swear, it will be awesome!), and taste a bit of my “Automatic email processing with Python sauce”?
Well then, send an email to subscribe@bonuslevel.org.
Or more simply follow me on twitter

Jan 13

New Cocos2d-iPhone extensions, a progress bar, and a hole…

As requested in the comments of Scale9Grid for Cocos2d, I’ve uploaded my code to GitHub.
While doing this, I also added 2 extensions to Cocos2D for iPhone :

CCProgressBar
CCProgressBar uses 2 CCSpriteScale9, no OpenGL coding. You can set the size of the bar, the size of the inner bar, you can set it in “waiting mode”, and of course you can set the progress. See the video demo below. Code source available on GitHub CCProgressBar.m CCProgressBar.h

CCSpriteHole
CCSpriteHole can be useful to highlight a part of the screen in tutorials, and can replace the expensive use of masking in some situations. It’s an OpenGL class, that splits the texture in 9 parts, the same way CCSpriteScale9. In CCSpriteScale9 you can preserve the corners, in CCSpriteHole, you can scale the texture while preserving the center part. See the video demo below. Code source available on GitHub CCSpriteHole.m CCSpriteHole.h

To play with the demo, you can download the project on GitHub, launch it with Xcode, and execute the JpsardaTest target. Sorry for the bad quality of the video.

More extensions coming. Latest news on twitter @jpsarda

Aug 20

Scale9Grid for Cocos2D

I’ve spent the latest 10 days working on a iOS/Cocos2D popups engine for my games. As Paul Legato wrote on his blog, ❝custom dialog boxes are a must for any game❞, displaying system popups in a game can interrupt the gameplay experience.

I wanted a popup that can adapt its size to every kind of content. That’s where you need a Scale9Grid component. Scale9Grid was popularized by Flash and ActionScript 3. It’s a way to scale an image while preserving the corners proportions. Only the borders and the center of the sprite are scaled. Scale9Grid explanations and illustration on this page.

Scale9Grid is also provided by Apple in UIKit UIImage method - (UIImage *) stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight.
Example of Scale9Grid with UIImage:
UIImageView *theImageView=[[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"backpanel.png"] stretchableImageWithLeftCapWidth:32 topCapHeight:32]];
theImageView.frame = CGRectMake(0,0,400,300);


UPDATE [01/12/2012] Also provided natively by Android with 9-Patch (Nine-Patch), a simple guide to 9-Patch.

I was surprised not to find a Scale9Grid implementation for Cocos2D, as the community is quite active. This is fixed now, here is a CCSpriteScale9 class for Cocos2D that implements Scale9Grid.

How you use it?
CCSpriteScale9 *bg=[CCSpriteScale9 spriteWithFile:@"backpanel.png" andLeftCapWidth:32 andTopCapHeight:32];
[bg setColor:ccc3(255,0,0)];
[bg adaptiveScale9:CGSizeMake(400,300)];
[self addChild:bg];


Scale9Grid can be used for many more than popups backgrounds.
You can see here screenshots of CCSpriteScale9 in action in my games. It’s used for popups, buttons, progress bars, input fields
Next, I’ll post a CCPorgressBar class using the CCSpriteScale9 component. Stay tuned and follow me on twitter (@jpsarda) to be notified first.

Improvement idea. CCSpriteScale9 only preserves the corners proportions. That means the center of the sprite is usually made of a uniform color (or gradient). An alternative to scaling, would be to repeat the inside texture. That would constraint the size of the sprite to a multiple of the inside size, but that would allow every kind of pattern.

Here is the code.It’s based on CCSprite code. It implements the CCRGBAProtocol and the CCTextureProtocol. But it can’t be added to a CCSpriteBatchNode.
UPDATED [12/07/2012], Cocos2d v2 version on GitHub » CCSpriteScale9 by Sean Christmann.

UPDATED [01/13/2012], NOW ON GITHUB » CCSpriteScale9.m and CCSpriteScale9.h.

UPDATED [06/28/2012], Ported on cocos2d v2 by Varedis on the cocos2d forums » CCSpriteScale9 V2.zip.

Read More

Jul 06

Cow Giveaway

For the latest update of Mozzle I made a cow. The drawing was done in Flash IDE, exported as a bitmap and packed with TexturePacker (great tool highly recommended for all game developers).

I give away the textures in high and standard definition, with corresponding Cocos2D class (for iOS). You can do whatever you want with it. I guess it’s called MIT license.

How you use it?
CCCow *cow=[CCCow node];
[self addChild cow];
Download (textures+class)
If you want vectors or anything else, you can contact me on twitter.

You can see the cow in action, in the video below.



Give away a cow :Done. Achievement unlocked.

[UPDATE 08/05/2012] CCCow updated with nested CCSprites (best performances) available on GitHub CCCow.m, CCCow.h.

Jun 25

4050 hand made levels!

Blockoban just got updated with 1800 new levels for a grand total of 4050 hand made levels! Which I believe allows me to call it “the game with the most hand made levels on the appstore”. Achievement unlocked.


Let’s take a step back… How the hell is it possible to design 4050 unique levels?
Let’s assume making a level takes 15 minutes on average. 4050 levels means 15x4050=60750 minutes of work. For a level designer working 8 hours a day and 5 days a week, this is about half a year of work!


Did I spent half a year on designing levels for Blockoban? Actually no, most of the levels are not mine. They are designed by the extraordinary community of level designers at Bonuslevel.org. Before being an iOS game, Blockoban was (and is still) a Flash game, reaching 5M of plays within 3 years, and patiently building a loyal fan base. About 5000 levels were designed so far and the top rated levels (rated over 3/5) selected for the iOS game.

Even better, the best solutions recorded from the people playing the Flash game, are exported and integrated in the iOS game as well, which means the 4050 levels are provided with a solution.

The quality-and-quantity approach of Blockoban works very well on the long term and has contributed to build a trustful relationship with my customers. I would not recommend this approach for all kind of games, but this is very well suited for the Sokoban-like games.

Check it out it’s free (100 free levels), Blockoban on the appstore.
The Premium version (4050 levels with solutions) is on sale at 0.99$ (66% off)

- Side note 1 : thanks to all the Blockoban level designers.
- Side note 2 : if you are an ActionScript programmer, an API is available on BonusLevel to take advantage of all the tools we’ve built around the user generated levels (play, edit, moderate, export levels).

Jun 04

Tiny Wings Hills with Cocos2D

Not only Tiny Wings is a fun and popular game, but it has also blown our developers mind with its gorgeous hills made of procedural graphics.

I’ve spent a few days trying to make something similar with Cocos2D. I’ll share in this article a piece of code that is responsible for drawing the hills. A bit of OpenGL ES knowledge is necessary to understand it. If you want to see the code in action, there’s a free game (work in progress) using it called Space Dragons (available on the appstore for iPhone4, iPad and over).

I’ve called this Cocos2D/OpenGL object CCSpriteBiCurve. The code is forked from CCSprite.

The idea behind CCSpriteBiCurve, is to draw a texture with the top and bottom edges being curved. In the case of Tiny Wings hills, the top edge only is curved.






The initial approach was to draw one horizontal band (an OpenGL GL_TRIANGLE_STRIP command). Unfortunately, one band is not enough to get a perfectly smooth result. The final code splits the texture in N horizontal bands, N being a parameter of the object.

Note that this code doesn’t deal with the procedural generation of the striped texture. This is a totally different matter. I’ll share later a piece of code for this too (be notified first). You can see a preview of the procedural stripes here.

The texture used in Space Dragons was generated with stripegenerator.com. Noise and lights were added with Photoshop.

Read More

Space Dragons (work in progress) is available on the app store, check it out, it’s free! An update with customizable procedural graphics is almost done (picture above).

Space Dragons (work in progress) is available on the app store, check it out, it’s free! An update with customizable procedural graphics is almost done (picture above).

May 25

Space Dragons, submitted!

That went fast. 5 days after starting the project, it’s already submitted to the app store. To be fair, it relies a LOT on code developed for my previous game Mozzle.

The game will be free, and actually, despite it’s submitted to the app store, I consider it as a work in progress. A kind of public beta.

Noel Llopis, the co-author of the fantastic iPad game "Casey’s Contraption", would strongly disagree on this early submission… But you have to think different if you want to be noticed on the app store, right?

Let’s see what happens…

[update] It’s available here.