Cocos2D Comparison

You love Cocos2D? We too!

In fact, our development team has worked with different versions of cocos2d in the past: When cocos2d-iphone came out, it was a joy to work with and the best open source game engine available for 2D games. With Android rising up as the biggest smartphone platform, the need to write a game only once for both iOS & Android got bigger and bigger, to prevent porting and duplicating code from Obj-C to Java. As a common ground, C++ can be used as a language both platforms work with and still have maximum performance compared to HTML5-based technology. This was the origin of cocos2d-x.

Unfortunately, working with C++ for game logic requires a multitude of development time and source code compared with scripting languages. In the Full Demo Game Comparison below the difference is even bigger than 60% what can be saved when using JavaScript and QML instead of C++. The game is still running at solid 60 fps on mobile devices, because only your game logic is written in JavaScript, whereas the core engine parts of V-Play are written in C++.

Additionally, to work with the Android NDK is a real pain and much boilerplate code is required to make native Java SDKs or 3rd party plugins work with a common C++ source. This is why V-Play chose to simplify these cross-platform pains by providing a high level API on top of cocos2d-x, which is used as the rendering engine internally. Plugins like GameCenter, Facebook or Flurry are available from JavaScript as ready-made components, without the need to reinvent the wheel with every game.

As we were using cocos2d a lot in the past as well, we believe these benefits V-Play can offer you as an existing cocos2d developer:

Build Server

... (see Target Group Benefits.docx)

Gaming Services

... (see Target Group Benefits.docx)

API Comparison

Because V-Play shares many of the concepts of cocos2d, it is straightforward to try V-Play as a cocos2d developer. To make it even easier, in the following sections cocos2d classes are compared with the V-Play counterparts. Small source code snippets explain the difference in code and allow you to get started quickly.

Scenes, Layers and Nodes

V-Play also uses the concept of a scene graph: when a parent node moves, its children move along with it. In V-Play, parent-child-relationships are defined by defining children items within the parent items. CCNode, CCLayer, CCLayerColor, CCScene and CCMenu classes can all be created with the Item, Rectangle and Scene element in QML.

import VPlay 2.0
import QtQuick 2.0

Scene {
  Rectangle {
    color: "red"
    anchors.fill: parent
  }

  Item {
    anchors.right: parent.right
    y: 15
    width: 30
    height: 20

    Rectangle {
      anchors.fill: parent
      anchors.rightMargin: 5
      color: Qt.rgba(0.5, 0.5, 0, 1)
    }
  }
}
#include "cocos2d.h"

// MyScene is another class, where we put the contents into
CCScene *scene = MyScene::scene();

CCLayerColor *layerColor = CCLayerColor::layerWithColorWidthHeight(
      ccc4(255, 0, 0, 255),
      scene->getContentSize().width,
      scene->getContentSize().height);
scene->addChild(layerColor);

CCNode *node = new CCNode::node();
node->setContentSize(CCSize(30, 20));
node->setPositionX( node->getParent()->getContentSize().width - node->getContentSize().width);
node->setPositionY(15);
layerColor->addChild(node);

CCLayerColor *layerColor2 = CCLayerColor::layerWithColorWidthHeight(
      ccc4(255*0.5, 255*0.5, 0, 255),
      node->getContentSize().width - 5,
      node->getContentSize().height);
node->addChild(layerColor2);

Images & Sprites

CCSprite and CCSpriteBatchNode have their V-Play counterparts in the Image, MultiResolutionImage Sprite, SpriteSequence and SpriteBatchContainer elements. Reading from sprite sheets generated from tools like Texture Packer is possible with the SingleSpriteFromFile component.

V-Play supports scaling to multiple resolutions out-of-the box. Please refer to the guide about How to create mobile games for different screen sizes and resolutions for more information about this topic.

The following example shows how to display an image that was saved in 3 different sizes to match common device categories best. It also demonstrates how to play a SpriteSheet animation: the jump animation is played 3 times, and then it is switched to the looping walking animation.

import VPlay 2.0
import QtQuick 2.0

Scene {

  MultiResolutionImage {
    source: "staticImage.png" // the file path gets modified automatically based on the contentScaleFactor
  }

  SpriteSequence {
    x: 200
    y: 100
    spriteSheetSource: "animated-character-spritesheet.png"

    // the first sprite gets played automatically
    Sprite {
      name: "jump"
      frameWidth: 32
      frameHeight: 32
      frameCount: 4
      startFrameColumn: 5
      frameRate: 10
      // this animation is played 4 times, and then switched to walk
      loop: false
      repeatCount: 4
      to: "walk"
    }

    Sprite {
      name: "walk"
      frameWidth: 32
      frameHeight: 32
      frameCount: 4
      startFrameColumn: 1
      frameRate: 20
    }
  }// SpriteSequence

}

Multi-Touch

Detection of touches is supported with the MouseArea element. It also supports easy drag and drop of elements. For multiple touches, you can use the MultiTouchArea which has built-in support for gestures like pinching or rotate-pinching. In cocos2d, dragging would need to be detected manually and gestures are not detected by default.

In the following source code, the red element is draggable in the scene. The blue one responds to the pinch gesture and changes by changing the scale of the Rectangle, and gets rotated by turning 2 fingers.

import VPlay 2.0
import QtQuick 2.0

Scene {
  id: scene

  Rectangle {
    color: "red"
    width: 60
    height: 40

    MultiTouchArea {
      anchors.fill: parent
      multiTouch.target: parent // the red rectangle gets draggable
    }
  }

  Rectangle {
    color: "blue"
    width: 60
    height: 40
    x: scene.width/2

    MultiTouchArea {
      anchors.fill: parent

      multiTouch.target: parent
      multiTouch.rotationMode: MultiTouch.Infinity // allow rotating when 2 fingers are twisted

      // limit the scale of the blue rectangle between 0.5 and 3
      multiTouch.minimumScale: 0.5
      multiTouch.maximumScale: 3
    }
  }

}

Labels

The CCLabelTTF equivalent is the QML Text element. Custom fonts can be loaded with the FontLoader element. In this example, the default font is used with a red color.

Text {
  text: "Hello V-Play"
  color: "black"
  pos: Qt.point(20, 30)
  font.pixelSize: 32
}
CCLabelTTF *label = CCLabelTTF::create("Goodbye Cocos2d", 32);
label->retain();
label->setColor( ccc3(0, 0, 0));
label->setPosition( ccp(20, 30));
this->addChild(label);

Actions & Transitions

CCAction in cocos2d has its equivalent in the Animation element in QML. They both support the same features: interpolate properties to a desired target value within a set duration and an optional easing type. Transitions between scenes or any QML Item can also be done with the Animation and State elements very easily. Multiple animations can be connected with the SequentialAnimation and ParallelAnimation elements.

The MovementAnimation additionally allows to modify any property of an object infinitely with a velocity and acceleration factor. This could be used for example to scroll the world in a side-scroller game.

The following example shows how to change the opacity of a rectangle from 1 to 0.5, and afterwards move it 50 px to the right.

import VPlay 2.0
import QtQuick 2.0

Scene {

  Rectangle {
    id: rectangle
    width: 100
    height: 60
    color: "red"

    SequentialAnimation {

      // makes the rectangle semi-transparent, and after it is finishedstarts to move it right
      NumberAnimation {
        target: rectangle
        property: "opacity"
        duration: 1000
        to: 0.5
      }

      // moves the rectangle 80px to the right in 1.5 seconds with an easing curve
      NumberAnimation {
        target: rectangle
        property: "x"
        duration: 1500
        to: 80
        easing: Easing.InBounce
      }

    }// SequentialAnimation
  }// Rectangle
}// Scene

Particle Effects

The V-Play Particle element can be used instead of the CCParticleSystem class of cocos2d. V-Play comes with an own Particle Editor which is available across all platforms. It supports creation of new particle effects and modifying them at runtime. As the same rendering engine is used like in your game, you can see performance impact of tweaking the effects properties immediately. Thus you can rely on the performance measurement to be the same as in your game. This is even possible on mobile devices, which makes it great for performance testing of different effects.

The Particle Editor is available with full source code and contains many popular particle types like fire and smoke. Feel free to use them in your game, or take them as a starting point to create a new type.

V-Play supports the very same particle properties as cocos2d, which makes porting the particle effects very easy. See the source code comparison below:

import VPlay 2.0
import QtQuick 2.0

ParticleVPlay {
  // Particle location properties
  x: 40; y: 50

  // Particle configuration properties
  maxParticles: 38
  particleLifespan: 0.9
  particleLifespanVariance: 0.2
  startParticleSize: 7
  startParticleSizeVariance: 2
  finishParticleSize: 45
  finishParticleSizeVariance: 10

  // Emitter behavior
  emitterType: Particle.Gravity
  duration: Particle.Infinite
  positionType: Particle.Relative

  // Gravity mode settings
  speed: 85
  speedVariance: 2

  // Appearance
  startColor: Qt.rgba(0.76, 0.25, 0.12, 1)
  finishColor: Qt.rgba(0, 0, 0, 1)
  textureFileName: "particleFire.png"

  Component.onCompleted: {
    // start when finished loading
    start()
  }

}
#include "cocos2d.h"

CCParticleSystem *emitter = new CCParticleSystemQuad();
emitter->setPosition( 40, 50);

// Particle Configuration properties
emitter->initWithTotalParticles(38);
emitter->setLife(0.9);
emitter->setLifeVar(0.2);
emitter->setStartSize(7);
emitter->setStartSizeVar(2);
emitter->setEndSize(45);
emitter->setEndSizeVar(10);

// Emitter behavior
emitter->setEmitterMode(kCCParticleModeGravity);
emitter->setDuration(kCCParticleDurationInfinity);
emitter->setPositionType(kCCPositionTypeRelative);

// Gravity mode settings
emitter->setSpeed(85);
emitter->setSpeedVar(2);

// Appearance
emitter->setStartColor(ccc4(0.76*255, 0.25*255, 0.12*255, 255));
emitter->setFinishColor(ccc4(0, 0, 0, 255));
emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("particleFire.png"));

this->addChild(emitter);

Physics

V-Play comes with full support of the latest Box2D version available from QML and JavaScript. However, internally the C++ version of Box2D is used for maximum performance. You can use Box2D either for calculating your entity positions, or just for collision detection if you want to move entities with animations for example.

The following example adds a ground rectangle and a ball-shaped image with physics colliders. The ball falls down to the ground due to gravity.

import VPlay 2.0

import QtQuick 2.0

Scene {
  id: scene

  PhysicsWorld {
    gravity.y: 10
  }

  Image {
    x: scene.width/2 // position it at the center in the beginning
    source: "ball.png"

    CircleCollider {
      radius: parent.width/2
      restitution: 0.5 // make the ball bounce on the ground
    }
  }

  // the ground, which does not move
  Rectangle {
    width: scene.width
    anchors.bottom: parent.bottom
    height: 40
    color: "grey"

    BoxCollider {
      anchors.fill: parent
      bodyType: Body.Static
    }
  }

}

Audio

The Sound and BackgroundMusic elements are similar to the API from SimpleAudioEngine in CocosDenshion. The following sample code shows how to play a sound when the scene is clicked. A looping background music is started when the application starts, and gets paused when the app is brought to the back automatically on mobile devices.

import VPlay 2.0
import QtQuick 2.0

Scene {

  // gets started once the application starts
  BackgroundMusic {
    source: "bgMusic.mp3"
  }

  SoundEffectVPlay {
    id: soundEffect
    source: "soundEffect.wav"
  }

  MouseArea {
    anchors.fill: parent
    onClicked: soundEffect.play()
  }
}

Parallax

The CCParallaxNode equivalent in V-Play is ParallaxItem. Additionally, you can use the ParallaxScrollingBackground element for side-scroller games that have an endlessly scrolling background. It is a nice convenience component which simplifies this task.

The following sample shows a slower scrolling background image with mountains and hills in the front.

import VPlay 2.0
import QtQuick 2.0

Scene {
  id: scene
  objectName: "sceneName"
  width: 480
  height: 320

  // The levelItem will be moved into the right direction to demonstrate the parallax effect.
  Item {
    id: levelItem

    // move the level item with constant speed to demonstrate the parallax effect
    MovementAnimation {
      target: levelItem
      property: "x"
      velocity: 10
      running: true
    }

    // First background image consists of an image moving slower than the level item
    ParallaxItem {
      ratio: Qt.point(0.8,1.0)
      Image {
        source: "img/background-mountains.png"
      }
    }

    // Second background image consists of 2 different images put next to each other, moving with the same speed as the level item
    ParallaxItem {
      ratio: Qt.point(1.0,1.0)
      Image {
        x: -width
        source: "img/background-hills.png"
      }

      Image {
        id: hill2
        source: "img/background-hills2.png"
      }
    }
  }
}

For a full list of the gaming components, visit the API reference. Get started with a step by step introduction to V-Play here.

Full Demo Game Comparison

As developers, we prefer source code instead of lengthy texts. So in addition to explain the benefits and API Comparison above, we show the differences & benefits in a real-game example: The popular cocos2d tutorial How To Make A Simple iPhone Game with Cocos2D is implemented both with cocos2d-x (right column) and V-Play (left column).

In the game you play a ninja and throw stars against invading monsters. There are 2 different scenes: one GameOver scene which shows if you won or lost, and the Game scene. In the V-Play version, Box2D was used for collision detection and a NumberAnimation for calculating the movement of the stars and monsters.

When comparing the source code, you will see that it is significantly faster to write the same game with V-Play and QML/JavaScript. In fact the same game is implemented with less than 40% of the original source code in C++, to achieve the same result! From 369 lines of code only 150 remain with V-Play. And that with just a simple game like this one - for more complex projects the difference gets even bigger!

In the full demo game comparison below, you can also see that far less characters are needed per loc in QML. So that's why V-Play will boost your productivity: less characters, less code, less errors, shorter time to develop. To be fair with the comparison, only real code lines are taken and comments and lines with empty spaces are left out.

For more sample games, see the V-Play documentation and its open source gaming demos, which are part of the V-Play SDK. A full list of available components including support for GameCenter, Facebook and Flurry Analytics can be found in the API reference.

/*
 In this demo you play a ninja and throw stars against invading monsters.
 This game is written in a single QML file with just 150 lines of code.

 It contains following features:
  * multi-resolution images
  * switching between 2 scenes
  * physics for collision detection
  * audio
  * animations for movement of the monsters and stars
*/
import VPlay 2.0
import QtQuick 2.0

GameWindow {
 // change the GameWindow size at runtime by pressing 1-7
 // the content of the logical scene size (480x320 by default)
 // gets scaled to the window size based on the scaleMode
 screenWidth: 960
 screenHeight: 640

 // gets set from Monster, after it reached the player
 property bool gameWon

 property int monstersDestroyed
 onMonstersDestroyedChanged: {
  if(monstersDestroyed > 5) {
   // you won the game, shot at 5 monsters
   changeToGameOverScene(true)
  }
 }

 // for creating monsters and projectiles at runtime dynamically
 EntityManager {
  id: entityManager
  entityContainer: scene
 }

 BackgroundMusic {
  source: "snd/background-music-aac.wav"
 }

 // make a white background for the window, default is black
 Rectangle {
  anchors.fill: parent
  color: "white"
 }

 Scene {
  id: scene
  // the "logical size", gets auto-scaled to GameWindow size
  width: 480
  height: 320

  // for collision detection between monsters and projectiles
  PhysicsWorld {}

  MultiResolutionImage {
   id: player
   anchors.verticalCenter: parent.verticalCenter
   // correct image version is used based on GameWindow size
   source: "img/Player-sd.png"
  }

  // components get not created immediately, but in addTarget()
  // could also be put into an own qml file (e.g. Monster.qml)
  Component {
   id: monster

   EntityBase {
    // required for removing all of them when the game is lost
    entityType: "monster"

    MultiResolutionImage {
     id: monsterImage
     source: "img/Target-sd.png"
    }

    y: utils.generateRandomValueBetween(0, scene.height)

    NumberAnimation on x {
     // start at the right side
     from: scene.width
     // move the monster to the left side of the screen
     to: -monsterImage.width
     // vary animation duration between 2-4 seconds
     duration: utils.generateRandomValueBetween(2000, 4000)
     onCompleted: {
      console.debug("monster reached base")
      changeToGameOverScene(false)
     }
    }

    BoxCollider {
     // make the collider as big as the image
     anchors.fill: monsterImage
     // use Box2D only for collision detection
     // move the entity with the NumberAnimation above
     collisionTestingOnlyMode: true

     fixture.onBeginContact: {
      // if the collided type was a projectile
      // both can be destroyed and the player gets a point
      var collidedEntity = other.parent.parent.parent

      if(collidedEntity.entityType === "projectile") {
       monstersDestroyed++
       // remove the projectile entity
       collidedEntity.removeEntity()
       // remove the monster
       removeEntity()
      }
     }
    }// BoxCollider
   }// EntityBase
  }// Component

  Component {
   id: projectile

   EntityBase {
    entityType: "projectile"

    MultiResolutionImage {
     id: monsterImage
     source: "img/Projectile-sd.png"
    }

    // set when a new projectile is created
    // in the MouseArea below
    property alias to: moveTo.to
    property alias duration: moveTo.duration

    PropertyAnimation on pos {
     id: moveTo
     from: player.pos
    }

    BoxCollider {
     anchors.fill: monsterImage
     collisionTestingOnlyMode: true
    }
   }// EntityBase
  }// Component

  SoundEffect {
   id: projectileCreationSound
   // gets played when a projectile is created below
   source: "snd/pew-pew-lei.wav"
  }

  MouseArea {
   anchors.fill: parent
   onReleased: {

    // see Ray Wenderlich tut for an explanation of this code

    // Determine offset of player to touch location
    var offset = Qt.point(
       mouseX - player.x,
       mouseY - player.y
       );

    // Bail out if we are shooting down or backwards
    if(offset.x <= 0)
     return;

    // Determine where we wish to shoot the projectile to
    var realX = scene.width
    var ratio = offset.y / offset.x
    var realY = (realX * ratio) + player.y
    var destination = Qt.point(realX, realY)

    // Determine the length of how far we are shooting
    var offReal = Qt.point(realX - player.x, realY - player.y)
    var length = Math.sqrt(offReal.x*offReal.x + offReal.y*offReal.y)
    // speed of the projectile should be 480pt per second
    var velocity = 480
    // seconds to milliseconds
    var realMoveDuration = length / velocity * 1000

    entityManager.createEntityFromComponentWithProperties(
          projectile, {"to": destination, "duration": realMoveDuration})

    projectileCreationSound.play()
   }
  }// onReleased
 }// MouseArea

 // switch to this scene, after the game was lost or won
 // it switches back to the gameScene after 3 seconds
 Scene {
  id: gameOverScene
  visible: false
  Text {
   anchors.centerIn: parent
   text: gameWon ? "You won :)" : "You lost"
  }

  onVisibleChanged: {
   if(visible) {
    // make the scene invisible after 3 seconds
    returnToGameSceneTimer.start()
   }
  }

  Timer {
   id: returnToGameSceneTimer
   interval: 3000
   onTriggered: {
    scene.visible = true
    gameOverScene.visible = false
   }
  }
 }// GameOverScene

 Timer {
  // only enable the creation timer when gameScene is visible
  running: scene.visible == true
  repeat: true
  // a new target(=monster) is spawned every second
  interval: 1000
  onTriggered: addTarget()
 }

 function addTarget() {
  console.debug("create a new monster")
  entityManager.createEntityFromComponent(monster)
 }

 function changeToGameOverScene(won) {

  gameWon = won

  gameOverScene.visible = true
  scene.visible = false

  // reset the game variables and
  // remove all projectiles and monsters
  monstersDestroyed = 0
  entityManager.removeEntitiesByFilter(["projectile", "monster"])
 }
}

AppDelegate.h

#ifndef  _APP_DELEGATE_H_
#define  _APP_DELEGATE_H_

#include "cocos2d.h"

/**
@brief    The cocos2d Application.

The reason for implement as private inheritance is to hide some interface call by CCDirector.
*/
class  AppDelegate : private cocos2d::CCApplication
{
public:
  AppDelegate();
  virtual ~AppDelegate();

  /**
    @brief    Implement CCDirector and CCScene init code here.
    @return true    Initialize success, app continue.
    @return false   Initialize failed, app terminate.
    */
  virtual bool applicationDidFinishLaunching();

  /**
    @brief  The function be called when the application enter background
    @param  the pointer of the application
    */
  virtual void applicationDidEnterBackground();

  /**
    @brief  The function be called when the application enter foreground
    @param  the pointer of the application
    */
  virtual void applicationWillEnterForeground();
};

#endif // _APP_DELEGATE_H_

AppDelegate.cpp

#include "AppDelegate.h"
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;

AppDelegate::AppDelegate() {

}

AppDelegate::~AppDelegate()
{
}

bool AppDelegate::applicationDidFinishLaunching() {
  // initialize director
  CCDirector *pDirector = CCDirector::sharedDirector();

  pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

  CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();
  CCSize designSize = CCSizeMake(480, 320);
  std::vector<std::string> searchPaths;

  if (screenSize.height > 320)
  {
    searchPaths.push_back("hd");
    searchPaths.push_back("sd");
    pDirector->setContentScaleFactor(640.0f/designSize.height);
  }
  else
  {
    searchPaths.push_back("sd");
    pDirector->setContentScaleFactor(320.0f/designSize.height);
  }

  CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);

  CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder);

  // turn on display FPS
  pDirector->setDisplayStats(true);

  // 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
  CCScene *pScene = HelloWorld::scene();

  // run
  pDirector->runWithScene(pScene);

  return true;
}

// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
  CCDirector::sharedDirector()->stopAnimation();

  // if you use SimpleAudioEngine, it must be pause
  CocosDenshion::SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
  CCDirector::sharedDirector()->startAnimation();

  // if you use SimpleAudioEngine, it must resume here
  CocosDenshion::SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

#include "SimpleAudioEngine.h"

class HelloWorld : public cocos2d::CCLayerColor
{
public:
  HelloWorld();
  ~HelloWorld();

  // Here's a difference. Method 'init' in cocos2d-x returns bool,
  // instead of returning 'id' in cocos2d-iphone
  virtual bool init();

  // there's no 'id' in cpp, so we recommand to return the exactly class pointer
  static cocos2d::CCScene* scene();

  // a selector callback
  virtual void menuCloseCallback(cocos2d::CCObject* pSender);

  // implement the "static node()" method manually
  CREATE_FUNC(HelloWorld);

  void spriteMoveFinished(cocos2d::CCNode* sender);

  void gameLogic(float dt);

  void updateGame(float dt);

  void registerWithTouchDispatcher();
  void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);

protected:
  cocos2d::CCArray *_targets;
  cocos2d::CCArray *_projectiles;
  int _projectilesDestroyed;

  void addTarget();

};

#endif  // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"
#include "GameOverScene.h"
#include "SimpleAudioEngine.h"

using namespace cocos2d;

HelloWorld::~HelloWorld()
{
  if (_targets)
  {
    _targets->release();
    _targets = NULL;
  }

  if (_projectiles)
  {
    _projectiles->release();
    _projectiles = NULL;
  }

  // cpp don't need to call super dealloc
  // virtual destructor will do this
}

HelloWorld::HelloWorld()
  :_targets(NULL)
  ,_projectiles(NULL)
  ,_projectilesDestroyed(0)
{
}

CCScene* HelloWorld::scene()
{
  CCScene * scene = NULL;
  do
  {
    // 'scene' is an autorelease object
    scene = CCScene::create();
    CC_BREAK_IF(! scene);

    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();
    CC_BREAK_IF(! layer);

    // add layer as a child to scene
    scene->addChild(layer);
  } while (0);

  // return the scene
  return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
  bool bRet = false;
  do
  {
    //////////////////////////////////////////////////////////////////////////
    // super init first
    //////////////////////////////////////////////////////////////////////////

    CC_BREAK_IF(! CCLayerColor::initWithColor( ccc4(255,255,255,255) ) );

    //////////////////////////////////////////////////////////////////////////
    // add your codes below...
    //////////////////////////////////////////////////////////////////////////

    // 1. Add a menu item with "X" image, which is clicked to quit the program.

    // Create a "close" menu item with close icon, it's an auto release object.
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
          "CloseNormal.png",
          "CloseSelected.png",
          this,
          menu_selector(HelloWorld::menuCloseCallback));
    CC_BREAK_IF(! pCloseItem);

    // Place the menu item bottom-right conner.
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2,
                                origin.y + pCloseItem->getContentSize().height/2));

    // Create a menu with the "close" menu item, it's an auto release object.
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition(CCPointZero);
    CC_BREAK_IF(! pMenu);

    // Add the menu to HelloWorld layer as a child layer.
    this->addChild(pMenu, 1);

    /////////////////////////////
    // 2. add your codes below...
    CCSprite *player = CCSprite::create("Player.png", CCRectMake(0, 0, 27, 40) );

    player->setPosition( ccp(origin.x + player->getContentSize().width/2,
                             origin.y + visibleSize.height/2) );
    this->addChild(player);

    this->schedule( schedule_selector(HelloWorld::gameLogic), 1.0 );

    this->setTouchEnabled(true);

    _targets = new CCArray;
    _projectiles = new CCArray;

    // use updateGame instead of update, otherwise it will conflict with SelectorProtocol::update
    // see http://www.cocos2d-x.org/boards/6/topics/1478
    this->schedule( schedule_selector(HelloWorld::updateGame) );

    CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background-music-aac.wav", true);

    bRet = true;
  } while (0);

  return bRet;
}

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
  // "close" menu item clicked
  CCDirector::sharedDirector()->end();
}

// cpp with cocos2d-x
void HelloWorld::addTarget()
{
  CCSprite *target = CCSprite::create("Target.png", CCRectMake(0,0,27,40) );

  // Determine where to spawn the target along the Y axis
  CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
  float minY = target->getContentSize().height/2;
  float maxY = winSize.height -  target->getContentSize().height/2;
  int rangeY = (int)(maxY - minY);
  // srand( TimGetTicks() );
  int actualY = ( rand() % rangeY ) + (int)minY;

  // Create the target slightly off-screen along the right edge,
  // and along a random position along the Y axis as calculated
  target->setPosition(
        ccp(winSize.width + (target->getContentSize().width/2),
            CCDirector::sharedDirector()->getVisibleOrigin().y + actualY) );
  this->addChild(target);

  // Determine speed of the target
  int minDuration = (int)2.0;
  int maxDuration = (int)4.0;
  int rangeDuration = maxDuration - minDuration;
  // srand( TimGetTicks() );
  int actualDuration = ( rand() % rangeDuration ) + minDuration;

  // Create the actions
  CCFiniteTimeAction* actionMove = CCMoveTo::create( (float)actualDuration,
                                                     ccp(0 - target->getContentSize().width/2, actualY) );
  CCFiniteTimeAction* actionMoveDone = CCCallFuncN::create( this,
                                                            callfuncN_selector(HelloWorld::spriteMoveFinished));
  target->runAction( CCSequence::create(actionMove, actionMoveDone, NULL) );

  // Add to targets array
  target->setTag(1);
  _targets->addObject(target);
}

void HelloWorld::spriteMoveFinished(CCNode* sender)
{
  CCSprite *sprite = (CCSprite *)sender;
  this->removeChild(sprite, true);

  if (sprite->getTag() == 1)  // target
  {
    _targets->removeObject(sprite);

    GameOverScene *gameOverScene = GameOverScene::create();
    gameOverScene->getLayer()->getLabel()->setString("You Lose :[");
    CCDirector::sharedDirector()->replaceScene(gameOverScene);

  }
  else if (sprite->getTag() == 2) // projectile
  {
    _projectiles->removeObject(sprite);
  }
}

void HelloWorld::gameLogic(float dt)
{
  this->addTarget();
}

// cpp with cocos2d-x
void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
  // Choose one of the touches to work with
  CCTouch* touch = (CCTouch*)( touches->anyObject() );
  CCPoint location = touch->getLocation();

  CCLog("++++++++after  x:%f, y:%f", location.x, location.y);

  // Set up initial location of projectile
  CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
  CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
  CCSprite *projectile = CCSprite::create("Projectile.png", CCRectMake(0, 0, 20, 20));
  projectile->setPosition( ccp(origin.x+20, origin.y+winSize.height/2) );

  // Determine offset of location to projectile
  float offX = location.x - projectile->getPosition().x;
  float offY = location.y - projectile->getPosition().y;

  // Bail out if we are shooting down or backwards
  if (offX <= 0) return;

  // Ok to add now - we've double checked position
  this->addChild(projectile);

  // Determine where we wish to shoot the projectile to
  float realX = origin.x+winSize.width + (projectile->getContentSize().width/2);
  float ratio = offY / offX;
  float realY = (realX * ratio) + projectile->getPosition().y;
  CCPoint realDest = ccp(realX, realY);

  // Determine the length of how far we're shooting
  float offRealX = realX - projectile->getPosition().x;
  float offRealY = realY - projectile->getPosition().y;
  float length = sqrtf((offRealX * offRealX) + (offRealY*offRealY));
  float velocity = 480/1; // 480pixels/1sec
  float realMoveDuration = length/velocity;

  // Move projectile to actual endpoint
  projectile->runAction( CCSequence::create(
                           CCMoveTo::create(realMoveDuration, realDest),
                           CCCallFuncN::create(this,
                                               callfuncN_selector(HelloWorld::spriteMoveFinished)),
                           NULL) );

  // Add to projectiles array
  projectile->setTag(2);
  _projectiles->addObject(projectile);

  CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("pew-pew-lei.wav");
}

void HelloWorld::updateGame(float dt)
{
  CCArray *projectilesToDelete = new CCArray;
  CCObject* it = NULL;
  CCObject* jt = NULL;

  // for (it = _projectiles->begin(); it != _projectiles->end(); it++)
  CCARRAY_FOREACH(_projectiles, it)
  {
    CCSprite *projectile = dynamic_cast<CCSprite*>(it);
    CCRect projectileRect = CCRectMake(
          projectile->getPosition().x - (projectile->getContentSize().width/2),
          projectile->getPosition().y - (projectile->getContentSize().height/2),
          projectile->getContentSize().width,
          projectile->getContentSize().height);

    CCArray* targetsToDelete =new CCArray;

    // for (jt = _targets->begin(); jt != _targets->end(); jt++)
    CCARRAY_FOREACH(_targets, jt)
    {
      CCSprite *target = dynamic_cast<CCSprite*>(jt);
      CCRect targetRect = CCRectMake(
            target->getPosition().x - (target->getContentSize().width/2),
            target->getPosition().y - (target->getContentSize().height/2),
            target->getContentSize().width,
            target->getContentSize().height);

      // if (CCRect::CCRectIntersectsRect(projectileRect, targetRect))
      if (projectileRect.intersectsRect(targetRect))
      {
        targetsToDelete->addObject(target);
      }
    }

    // for (jt = targetsToDelete->begin(); jt != targetsToDelete->end(); jt++)
    CCARRAY_FOREACH(targetsToDelete, jt)
    {
      CCSprite *target = dynamic_cast<CCSprite*>(jt);
      _targets->removeObject(target);
      this->removeChild(target, true);

      _projectilesDestroyed++;
      if (_projectilesDestroyed >= 5)
      {
        GameOverScene *gameOverScene = GameOverScene::create();
        gameOverScene->getLayer()->getLabel()->setString("You Win!");
        CCDirector::sharedDirector()->replaceScene(gameOverScene);
      }
    }

    if (targetsToDelete->count() > 0)
    {
      projectilesToDelete->addObject(projectile);
    }
    targetsToDelete->release();
  }

  // for (it = projectilesToDelete->begin(); it != projectilesToDelete->end(); it++)
  CCARRAY_FOREACH(projectilesToDelete, it)
  {
    CCSprite* projectile = dynamic_cast<CCSprite*>(it);
    _projectiles->removeObject(projectile);
    this->removeChild(projectile, true);
  }
  projectilesToDelete->release();
}

void HelloWorld::registerWithTouchDispatcher()
{
  // CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,0,true);
  CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0);
}

GameOverScene.h

/****************************************************************************
 Copyright (c) 2010-2011 cocos2d-x.org
 Copyright (c) 2010      Ray Wenderlich

 http://www.cocos2d-x.org

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/

#ifndef _GAME_OVER_SCENE_H_
#define _GAME_OVER_SCENE_H_

#include "cocos2d.h"

class GameOverLayer : public cocos2d::CCLayerColor
{
public:
  GameOverLayer():_label(NULL) {};
  virtual ~GameOverLayer();
  bool init();
  CREATE_FUNC(GameOverLayer);

  void gameOverDone();

  CC_SYNTHESIZE_READONLY(cocos2d::CCLabelTTF*, _label, Label);
};

class GameOverScene : public cocos2d::CCScene
{
public:
  GameOverScene():_layer(NULL) {};
  ~GameOverScene();
  bool init();
  CREATE_FUNC(GameOverScene);

  CC_SYNTHESIZE_READONLY(GameOverLayer*, _layer, Layer);
};

#endif // _GAME_OVER_SCENE_H_

GameOverScene.cpp

/****************************************************************************
 Copyright (c) 2010-2011 cocos2d-x.org
 Copyright (c) 2010      Ray Wenderlich

 http://www.cocos2d-x.org

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/

#include "GameOverScene.h"
#include "HelloWorldScene.h"

using namespace cocos2d;

bool GameOverScene::init()
{
  if( CCScene::init() )
  {
    this->_layer = GameOverLayer::create();
    this->_layer->retain();
    this->addChild(_layer);

    return true;
  }
  else
  {
    return false;
  }
}

GameOverScene::~GameOverScene()
{
  if (_layer)
  {
    _layer->release();
    _layer = NULL;
  }
}

bool GameOverLayer::init()
{
  if ( CCLayerColor::initWithColor( ccc4(255,255,255,255) ) )
  {
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    this->_label = CCLabelTTF::create("","Artial", 32);
    _label->retain();
    _label->setColor( ccc3(0, 0, 0) );
    _label->setPosition( ccp(winSize.width/2, winSize.height/2) );
    this->addChild(_label);

    this->runAction( CCSequence::create(
                       CCDelayTime::create(3),
                       CCCallFunc::create(this,
                                          callfunc_selector(GameOverLayer::gameOverDone)),
                       NULL));

    return true;
  }
  else
  {
    return false;
  }
}

void GameOverLayer::gameOverDone()
{
  CCDirector::sharedDirector()->replaceScene( HelloWorld::scene() );
}

GameOverLayer::~GameOverLayer()
{
  if (_label)
  {
    _label->release();
    _label = NULL;
  }
}

Voted #1 for:

  • Easiest to learn
  • Most time saving
  • Best support

Develop Cross-Platform Apps and Games 50% Faster!

  • Voted the best supported, most time-saving and easiest to learn cross-platform development tool
  • Based on the Qt framework, with native performance and appearance on all platforms including iOS and Android
  • Offers a variety of plugins to monetize, analyze and engage users
FREE!
create apps
create games
cross platform
native performance
3rd party services
game network
multiplayer
level editor
easiest to learn
biggest time saving
best support
Sign up for Free and start developing right away!
I want to make Games
I want to make Apps
Game Development
Cross-Platform, Any Resolution

Use one IDE to deploy to all supported platforms, including iOS and Android, from a single code base.

Support all screen resolutions, aspect ratios and sizes with auto-adapting UI elements, smart scene scaling and memory efficient asset selection.

Learn More

V-Play ranked #1 at research2guidance cross-platform tool benchmarking 2014 by 2188 developers comparing 40 leading tools.

Multiplayer

V-Play Multiplayer supports both real-time and turn-based gameplay, so you can use it to make many different types of cross-platform multiplayer games. It's perfect for making player-vs-player games like 'Words with Friends' or games for a large amount of players, such as 'Clash of Clans'.

Learn More Video

Highscores & Achievements

The V-Play Game Network is a cross-platform gaming service that allows players around the world to compare game highscores and achievements. Players can also challenge each other across multiple platforms and share their progress on Facebook.

Learn More

QML & JavaScript

Qt Meta Language is a highly intuitive reactive language, which is super easy to learn, yet it's extremely powerful and flexible. Mix it with JavaScript to create awesome stuff, with just a few lines of code.

import QtQuick 2.0
import VPlay 2.0

GameWindow {
  Scene {
    
    SimpleButton {
      anchors.centerIn: parent
      text: "Press Me"
      onClicked: {
        console.debug("Wow you pressed me!")
      }
    }
  }
}

Learn More

Monetize & Analyze

With V-Play, you can use many 3rd party services for ads, in-app purchases, analytics and more, with just a few lines of code. All of these plugins work cross-platform, which allows you to maintain a single code base.

Learn More

Level Editor

The LevelEditor can be used during development to create and modify levels for your game, which you can then bundle in your final publishing build. Additionally, you can also integrate the in-game level editor to your published game and let your gamers create new levels.

Learn More Video

Card Game like UNO, Hearthstone or Poker

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/OneCard/OneCard.pro

Match-3 like Candy Crush Saga

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/JuicySquash/JuicySquash.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/JuicySquashAdvanced/JuicySquashAdvanced.pro

Puzzle like 2048 or Threes!

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/2048/2048.pro

Casino like Big Win Slots

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/FlaskOfRum/FlaskOfRum.pro

Side Scroller like Jetpack Joyride or Flappy Bird

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/FlappyBird/FlappyBird.pro

Tower Defense like Castle Defense or Bloons TD

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/Squaby/Squaby.pro

Falldown & Jump like Doodle Jump or Mega Jump

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/ChickenOutbreak/ChickenOutbreak.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/ChickenOutbreak2/ChickenOutbreak2.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/DoodleJump/DoodleJump.pro

Platformer like Super Mario or Lep's World

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/Platformer/Platformer.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/PlatformerWithLevelEditor/PlatformerWithLevelEditor.pro

Action like Angry Birds, Fruit Ninja, Cut the Rope

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/StackTheBoxWithCommunityEditor/StackTheBoxWithCommunityEditor.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/BalloonPop/BalloonPop.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/CarChallenge/CarChallenge.pro

Arcade like Arkanoid or Space Invaders

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/demos/ZombieBreak/ZombieBreak.pro

Community like Super Mario Maker or Minecraft

We got a demo game for you!

The V-Play SDK includes an open-source demo for this game genre. You can use its source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/examples/Squaby/Squaby.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/StackTheBoxWithCommunityEditor/StackTheBoxWithCommunityEditor.pro

<Path to V-PlaySDK>/Examples/V-Play/demos/PlatformerWithLevelEditor/PlatformerWithLevelEditor.pro

Any other Idea? let us know how we can help you

You are looking for another demo?

The V-Play SDK includes many open-source demos for different game genres. You can use their source code and build your game in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

If you do not find your game genre in this list and wonder if V-Play is the right choice, just contact us, we are happy to help!

Contact Us

App Development
Better Apps, Less Effort

Develop feature-rich, cross-platform mobile apps from a single code base.

V-Play apps look, feel and perform exactly like native iOS, Android and Desktop apps. With less code & much faster development time.

Learn More Highlights Video

V-Play ranked #1 at research2guidance cross-platform tool benchmarking 2014 by 2188 developers comparing 40 leading tools.

Save Time, Code & Money

Save up to 90% source code with V-Play, compared to frameworks like Xamarin, Titanium, React Native and others.

Learn More

QML & JavaScript

Qt Meta Language is a highly intuitive reactive language, which is super easy to learn, yet it's extremely powerful and flexible. Mix it with JavaScript to create awesome stuff, with just a few lines of code. QML also allows you to easily create smooth and complex animations.

import QtQuick 2.0
import VPlayApps 2.0

App {
  Page {
    
    AppButton {
      anchors.centerIn: parent
      text: "Press Me"
      onClicked: {
        console.debug("Wow you pressed me!")
      }
    }
  }
}

Learn More

Monetize & Analyze

With V-Play, you can use many 3rd party services for ads, in-app purchases, analytics and more, with just a few lines of code. All of these plugins work cross-platform, which allows you to maintain a single code base.

Learn More

Native Sensors & More

V-Play Apps harness the power of Qt, the leading cross-platform development framework used by over 1,000,000 developers.

This gives your access to native device features like sensors, camera, file system as well as multimedia, networking, localization and much more.

Learn More

Responsive Design

V-Play has built in responsive design capabilities, you can target phones and tablets with the same source code.

Learn More

Highly Extensible

You have existing JavaScript, C++ or native code? You want to add any 3rd party SDK that we do not offer already?

No worries, you can add any JS, C++, Java or Objective-C code to your project.

Learn More

Component Showcase App shows the most important V-Play features and components

We got a demo app for you!

The V-Play SDK includes an open-source demo for this app type. You can use its source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/appdemos/showcase/Showcase.pro

Qt World Summit Conference App a full-featured conference management app made by V-Play

We got a demo app for you!

The V-Play SDK includes an open-source demo for this app type. You can use its source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/appdemos/qtws2016/QtWS2016.pro

Twitter App how to build layouts like in the official Twitter app for iOS and Android

We got a demo app for you!

The V-Play SDK includes an open-source demo for this app type. You can use its source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/appdemos/twitter/Twitter.pro

Maps App displays free bikes or boxes at bike stations for Vienna's bike sharing service Citybike Wien

We got a demo app for you!

The V-Play SDK includes an open-source demo for this app type. You can use its source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/appdemos/maps/Maps.pro

Messaging App demonstrates how to create the UI of a Facebook Messenger like app

We got a demo app for you!

The V-Play SDK includes an open-source demo for this app type. You can use its source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/appdemos/messaging/Messaging.pro

Weather App how to include powerful animations into your user interface

We got a demo app for you!

The V-Play SDK includes an open-source demo for this app type. You can use its source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play.

<Path to V-PlaySDK>/Examples/V-Play/appdemos/waether/Weather.pro

Any other Idea? let us know how we can help you

You are looking for another app demo?

The V-Play SDK includes many open-source demos for different app types. You can use their source code and build your app in record time. After installing V-Play, you can simply open the .pro file with Qt Creator, the development environment used for V-Play..

If you do not find your app type in this list and wonder if V-Play is the right choice, just contact us, we are happy to help!

Contact Us