AuthorJohannes Borchardt

Creating a ‘Flappy Bird’ clone

So, last week, on Thursday I sat with Felix, one of the people that are supporting us with designs, and we were talking about ‘Flappy Bird‘s tremendous success. The, now unpublished, Chopper Mission-like game at the time grossed around $50k a day and was, as you probably all know, topping app store charts around the world.

Flappy Bird

Flappy Bird

We were impressed by the simplicity of the design and the very easy gameplay. This was also what made us think that it would probably be quite easy to implement an app with similar functionalities.

$50k/day, a possibly fast implementation. That are two  pretty convincing arguments towards just trying it out.

Brainstorming

The Greek restaurant we went to

The Greek restaurant we went to

The decision was made and we headed over to the Greek restaurant next door to brainstorm a bit. The mission: Creating a game with similar behavior and and addictiveness as flappy bird while maintaining an own character.

Besides the amazing achievement of $50k/day in front of our eyes we wanted to keep up the spirit of ‘Flappy Bird’, which, in our impression, was rather the creation of games as a form of art instead of pure means to make money.

The brainstorming started. The basic wireframing was done rather quickly. A simple start menu, the game itself, a game over menu, GPGS highscores, maybe a bit of Tapjoy and a splash screen.

Left: Wireframes. Right: Design drafts

Left: Wireframes. Right: Design drafts

Then the big question arose: Where and when did we want our game to take place? We are working on another game in the steampunk genre anyway at the moment, so why not use this environment?

 Steampunk Bird by ~Adrienne-the-ripper. Click on the image for the origin.

Steampunk Bird by ~Adrienne-the-ripper. Click on the image for the origin.

While that sounded pretty cool we wanted to grab the chance to try a different setting. Ever since I first played it, Age of Empires II was my favorite computer game, which it stayed until today. This resulted in our final choice: The medieval times.

Getting started

First we created kanban-boards, each customized and simplified in the way needed them.

Left: My Kanban-board; Right: The designer's Kanban-board

Left: My Kanban-board; Right: Felix’ Kanban-board

Then we just got started.

I first began implementing the physics with Box2D but then decided it would be overkill and just used simple entity modifier. After a couple of hours the first, almost complete, game was done. On the left you can see our main menu, in the middle the game while it is playing and on the right the game over ‘menu’:

The first playable version of our 'Flappy Bird' replacement

The first playable version of our ‘Flappy Bird’ replacement

I like to call it ‘Flappy Pong’.

As with most casual games, writing the basic game logic needed the least time. We needed a decent character, the hero that would breathe life into our game. His name? Sir Flapalot.

Who is Sir Flapalot?

Who is Sir Flapalot?

We wanted a unique character. A person that’s cute, has a visual reason to fly and can still transport the adventurous aura of a knight.

Felix did an awesome job and created our flying hero:

Sir Flapalot revealed

Sir Flapalot revealed

Sir Flapalot comes in five parts: A tilesheet of the cape which consists out of four parts for a fast paced movement animation, a three-part-tilesheet of the arms with the wings, the harness with the feet, the helmet and the hemlet’s ventail, which opens when the knight flies downwards. Here you can see his first flying attempts in our virtual world:

Sir Flapalot flying and falling

Sir Flapalot flying and falling

Here’s the main menu with Sir Flapalot flying around on a Galaxy Y and a Galaxy Nexus:

Sir Flapalot on different devices

Sir Flapalot on different devices

Next was the Name and the Logo. We both were certain about the name in an instant. ‘Flappy Knight’. We couldn’t find a fitting font so Felix did another amazing job and hand-drew Flappy Knight’s own typeface:

logo

Development

After this two important decisions, the title and the main character of the game, development continued. We included backgrounds, a parallax floor like in ‘Flappy Birds’, the green rectangle barriers of the screenshots above became walls and the game over and start menu went through plenty of iterations.

Once this essential parts were done, I started integrating GPGS for highscores, ad banners (only AdMob for now) and Tapjoy.

Last Thursday, after one week of development, we presented the result to ANDLABS and started balancing the gameplay a bit more. It turned out that Sir Flapalot fell too fast so that sometimes it was too hard to stop him at the right time. With the change of giving him more time to the fall, a bigger distance between the walls came. While the game initially was much harder than ‘Flappy Bird’, it is a tiny bit easier now. My current record is 39, which makes me third out of four test players.

After the balancing, sound came into the game. This took us quite some time since we hand made almost all of them on our own. We tried to keep them as annoying yet motivating as the flappy-bird sounds, while sticking to our genre. While we may re-record some of them for an update, we are satisfied with the current state.

Flappy Knight

Today, after one week and three days of work, Flappy Knight was finished. Here are the final results:

Flappy Knight's main menu and get ready screen

Flappy Knight’s main menu and get ready screen

Flappy Knight's gameplay and game over screen

Flappy Knight’s gameplay and game over screen

So now, if you like (or hate) ‘Flappy Bird’ and need an adequate replacement but are not satisfied with the gazillion of copies out there, or just want to try our work, you might give Flappy Knight a try:

promo

get flappy knight on google play

Simplified Logging in Android

Logging is one of the important tools for debugging an application.

When logging in Android, one usually writes code like

public class LoggingSample {

    public static final String TAG = "LoggingSample";
    ... 

    public void loggingMethod() {   

    final String formattedTestString = "first argument = %s, " + 
             "second argument = %s";
    final String firstArgument = "abc";
    final Object secondArgument = new  Object() {
        public String toString() {
            return "123";
        }
    };
    Log.d(TAG, "loggingMethod(): " + 
           String.format(formattedTestString, firstArgument,
           secondArgument));

    }
}

This then results in an output like

D/ LoggingSample: loggingMethod(): first argument = abc, second argument = 123

We need to add a tag and many times, in order to reproduce procedures, the name of the calling method. Not much of a deal, but since logging is done frequently it is often repeated

Since we don’t like repetitions, we decided to make it a little easier. Instead of the above, we now type

    L.d(formattedTestString, firstArgument, secondArgument);

To get an output like

D/LoggingSample:26(18510): onCreate(): first argument = abc, second argument = 123

What we get is the calling class’s name and the line number as a tag, the calling methods name plus the formatted string as a message.

 

If you are interested in this type of logging, you can now git clone the ANDLABS Android Utils and add them as a library project.

 

What do you think? How do you use logging? Please share your thoughts in the comments.

Getting started with the Universal Tween Engine

This is a guest post by Alexander Fröhlich. Alexander is a freelance developer and is supporting ANDLABS at its libgdx-based development. 

If you are not familiar with libgdx yet, please check out the first part of this series, the Getting started with libgdx-guide.

 

1 Tweening?

“Tweening” in games is the process of creating intermediate states and thus frames between two or more given states.

Example (Sprite Translation):
The most simple example would be moving a sprite or image from one x1, y1 position to another x2, y2 position on the screen.

Yet, as you might already suspect, this “Universal Tween Engine” is capable of manipulating not only x, y coordinates for sprite objects…. no, this cross-platform-engine written entirely in java language lets you tween every property of any object given that it has its getter/setter methods attached.

In this tutorial I will show you how this comes in handy for game developers when building ingame hints or tutorials for their game.

The following sample code illustrates basic use and setup of the universal tween engine in a libgdx code project.

2 Ingame Tutorial Tweening

First of all, declare your tweenManager instance. The tweenManager lets you keep track and manage all your tweens (i.e. tweening, tween actions and so on)

public class MyGame implements ApplicationListener {

    // Only one manager is needed, like a 
    // libgdx Spritebatch (MyGame.java)

    private static TweenManager tweenManager;

}

Instantiate the manager inside create() of your libgdx lifecycle:

Register an accessor class, which is the key binding between the manager and the object to be tweened. Here this will be the TutorMessage class. (see below).
So after calling registerAccessor every single object of class TutorMessage we create can be tweened by the TweenManager.

@Override
public void create() {
    setTweenManager(new TweenManager());
    Tween.setCombinedAttributesLimit(4);// default is 3, yet
                                        // for rgba color setting          
                                        //we need to raise to 4! 
    Tween.registerAccessor(TutorMessage.class, new 
                             TutorMessageAccessor()); 

}

The TutorMessage’s are the internal game objects for this sample which hold the position, scale and color message attributes.

public class TutorMessage {

    private String message; // string objects can not be tweened
    private float x;
    private float y;
    private Color color;
    private float scale;

}

To tween these message properties and make them accessible by the manager we have to declare how getting and setting every single attribute works.

Getter/Setter
So we define 3 sections (POS_XY, SCALE, COLOR) that process the current float[] values, handled over by the manager during runtime when tweening is active.

Of course same applies for the setters.

public class TutorMessageAccessor implements TweenAccessor<TutorMessage> {

    public static final int POS_XY = 1;
    public static final int SCALE = 2
    public static final int COLOR = 3;

    @Override
    public int getValues(TutorMessage target, int tweenType, 
                           float[] returnValues) {
        switch (tweenType) {
            case POS_XY:
                returnValues[0] = target.getX();
                returnValues[1] = target.getY();
                return 2;

            case SCALE:
                returnValues[0] = target.getScale();
                return 1;

            case COLOR:
                returnValues[0] = target.getColor().r;
                returnValues[1] = target.getColor().g;
                returnValues[2] = target.getColor().b;
                returnValues[3] = target.getColor().a;
                return 4;

            default: 
                assert false; 
                return -1;
        }
    }

    @Override
    public void setValues(TutorMessage target, int tweenType, 
                            float[] newValues) {
        switch (tweenType) {
            case POS_XY: 
                target.setPosition(newValues[0], newValues[1]); 
                break;

            case SCALE: 
                target.setScale(newValues[0]); 
                break;

            case COLOR:
                Color c = target.getColor();
                c.set(newValues[0], newValues[1], newValues[2], 
                        newValues[3]);
                target.setColor(c);
                break;

            default: 
                assert false;
        }
    }
}

Having bind our TutorMessage class to the TweenManager we can now integrate it into the game.
Remember? We want to provide a kind of ingame tutorial system. So every time our user should see an animated on-screen help, we call the now defined method. The tweenHelpingHand method takes the parameter targetX, targetY that indicate the position where the helping hand (sprite) and its bound message (bitmapfont) should move to.

Then we say Tween
  .to (
      – TutorMessage currentTm ( the message to be moved )
      – int TutorMessageAccessor.POS_XY (constant to select which property should be tweened)
      – float 3f (total tweening duration)
  )
  .target (
    – targetX, targetY ( the final screen position of our tweened message )
  )
  .ease (
    – TweenEquations.easeOutCirc ( one possible interpolation pattern – i.e. moving pattern here)
  )
  .start (
    – MyGame.getTweenManager()  ( binds this tween to the manager )
  )

private void tweenHelpingHand(int targetX, int targetY) {

    // kill current tween - or pre-existing
    MyGame.getTweenManager().killTarget(currentTm);

    // move
    Tween.to(currentTm, TutorMessageAccessor.POS_XY, 3f)
         .target(targetX, targetY)
         .ease(TweenEquations.easeOutCirc)
         .start(MyGame.getTweenManager());

    // colorize
    Tween.to(currentTm, TutorMessageAccessor.COLOR, 3f)
         .target(1f, 1f, 1f, 1f)
         .ease(TweenEquations.easeOutCirc)
         .start(MyGame.getTweenManager());

}

Finally we have to call update inside the libgdx render() method to have the started Tween be updated constantly.

MyGame.getTweenManager().update(delta);

Here you go!
Enjoy this very powerful any easy to use tweening library.

Combining Scene2d animations and Tweening is also possible. You just have to write the ActorAccessor binding class and provide access (getter/setter) to its properties.
Like with Scene2d actions, the universal tween engine also allows sequencing of multiple tweens!

 

If you have any questions or suggestions, please leave a comment.

Income Report #17: Sept 12 – Aug 13

If you are new to this series, let me explain it to you: Since Android is an open platform, I decided to be open about the income I’m making with my private Android apps too. 

For all income reports, please click here.

 

The last income report lies back almost a year. We’ve had a big job at ANDLABS which consumed almost all my time and also stopped me from working on my apps and also reduced my post frequency. Since this job is done now, there will be more reports and even a newsletter.

For now, here’s a summary of the income my Android apps generated in the last year.

 

Which Apps?

3D Invaders – about 350,000 installs,

AL Voice Recorder – about 1,027,000 installs,

AL Voice Recorder Ad Free – 1,117 installs,

SmsToSpeech full – 750 installs,

The careful reader might recognize that SmsToSpeech full and AL Voice Recorder Ad Free have a decline in installs, which should technically not be possible. I ascribe this to a different way of counting Google is using.

 

Advertising Stats

Please read the second income report for an explanation of the following numbers.

Here are some statistics of the Ad frameworks I’m using. Unfortunately there seem to be issues with madvertise’s reporting system, which is why I’m only showing AdMob numbers here. To summarize madvertise’s performance in the last year though: It was underwhelming.

AdMob

Requests: 2,732,264

Impressions: 2,700,974

Fill Rate: 98.94%

Clicks: 95,954

CTR: 3.55%

eCPM: $1.70

House Ads: 104,351


Here’s the distribution over the months:

AdMob Income

AdMob Income Sept 12 – Aug 13

 

How much?

Here are the numbers:

AdMob:

3D Invaders: $1,596.55

AL Voice Recorder: $3,010,52

AdMob Total: $4,607.19

Market sales: ~$407.55

In-App purchases: ~$41.25

Distributed Google Play Sales, including In App Purchases

Distributed Google Play Sales, including In App Purchases

Total: ~$5,056.35

It’s obvious that my app’s performance was not good compared to the months before, where I put a little more emphasis on maintaining their market position. Still, $200-$300 extra on the bank account every month don’t hurt.

 

What’s next?

For now I will focus on the development of a new game. Hence I don’t expect my income to rise until it’s published.

 

Please feel free to share your own experiences and hints in the comments. Ask questions, share, do whatever you like.

© 2024 Droid-Blog

Theme by Anders NorenUp ↑