• New to Game Development?

    If you're new to game development, then you'll be able to find many useful tutorials and the whole source code of real App Store games in the documentation area. Thanks to the specialization on 2D games, we're helping to ensure that creating a hit App Store game is as easy as possible.

    To support you in getting started with game development, we're here to provide you with a variety of different guides: this one is an introduction to QML & JavaScript used for V-Play. For a step-by-step tutorial on how to create a simple physics game from scratch, just follow this link. An advanced Pong game tutorial with lots of shiny additions such as particle effects, multiplayer and AI is available here. To get an overview of the V-Play gaming components, browse through the API reference and take a closer look at the fully documented components, each equipped with example source code.

    Already interested? Read below for more information on how V-Play can help you in creating a game:

    Benefits

    • Game Templates

      V-Play includes the full source code of live App Store games for some of the most popular genres. These can be used as gaming templates to rapidly create games like tower defenses, platformers like Doodle Jump, physics games, side scrollers or action games.

    • 2D Game Components

      Save development time and use the V-Play gaming components specialized for 2D games. The components include animations, particles, Box2D physics, multi-touch, gestures, auto-adoption to multiple resolutions and aspect ratios, native dialogs, AI, accelerometer and much more with the same API across all platforms. For a full list, see http://v-play.net/doc/vplay-group.html.

    • QML Declarative Language

      Your game is written in JavaScript and QML, a declarative language offering highly productive features such as property bindings, state machines or fluid animations of any property. With QML, you are able to write 10 times less code compared with C++, which also means 10 times less error sources. The great thing is, all gaming components used in QML are internally implemented in C++ with a guaranteed maximum performance. These features in conjunction with the V-Play gaming components will give the prototyping and development of your game an even bigger boost.

      import VPlay 1.0
      import QtQuick 1.1
      
      GameWindow {
        Scene {
      
          Image {
            id: image
            source: "v-play-logo.png"
      
            MouseArea {
              anchors.fill: parent
              drag.target: parent
            }
          }
      
          Text {
            text: "Hi V-Play"
            color: "blue"
            anchors.horizontalCenter: image.horizontalCenter
      
            // you may write any JavaScript expression here
            // it gets re-evaluated when the y property of image changes
            y: image.y + 100
          }
        }
      }
      Hi V-Play
    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Build Server

      Take the pain out of installing native SDKs and compiling your game for every desired target platform. Enjoy the headache-free one-click-deployment of app-store ready games: V-Play Build Server does the work for you by compiling in the cloud. E.g. You'll be able to develop your game on Windows and deploy it to iOS.

    • Support, Community & Roadmap

      And last but not least: V-Play has an open roadmap shaped by YOU, our customers. We have a team working on the improvements around the clock and provide frequent updates every two weeks. Oh, and don’t forget our supportive community and core developers in the forums who are on hand to answer questions quickly.

  • Already familiar with Qt 4 / Qt 5?

    With V-Play you get full support of iOS and Android NOW. There's no need to wait for Qt 5.1 or 5.2 with an expected release at the end of 2013. How is that possible? V-Play has a Qt 4-based core with a custom renderer optimized for performance. Once Qt 5 supports iOS and Android, we switch the renderer, but our gaming components API stays the same. This means zero effort for you to switch to Qt 5 once it is ready!

    Continue reading to find out about the benefits V-Play offers you as a Qt developer in more detail:

    Benefits

    • 2D Game Components

      Save development time and use components specialized for 2D games with a QML API and full documentation in Qt style. The components include Box2D physics, auto-adoption to multiple resolutions and aspect ratios, native dialogs, AI, multi-touch, gestures, accelerometer and particles with the same API across all platforms. For a full list, see http://v-play.net/doc/vplay-group.html.

    • Gaming Services

      With existing plugins for most important gaming services you can focus on taking your game to the next level: in-app purchases, game & social network integration (such as Game Center, Facebook), ads and analytics (such as Flurry) are available across platforms. The services are easily accessible from QML and are fully documented including example code. More plugins and even a template for providing your own are already on the way.

    • Build Server

      Take the pain out of installing native SDKs and compiling your game for every desired target platform. Enjoy the headache-free one-click-deployment of app-store ready games: V-Play Build Server does the work for you by compiling in the cloud. E.g. You'll be able to develop your game on Windows and deploy it to iOS.

    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • Multi Resolutions

      V-Play is built to handle all possible aspect ratios and resolutions for modern mobile devices. Design your game once for a logical scene and V-Play handles the rest. This means no black borders or distorted images, but a native look for smartphones, tablets and desktops with a single code version. You can even test how your game will look like on different resolutions while it's running.

      V-Play even loads different image bundles based on the devices' pixel density to save expensive memory resources. For maximum performance and an optimized workflow, we support batched rendering from sprite sheets exported with tools like Texture Packer.

    • Native Dialogs and Functionality

      Sometimes there will be situations that require some user input or notifications. V-Play has abstracted components for displaying native input dialogs and alert boxes without the need of a single native code line. It's also possible to use accelerometer or open a web view to display your website right out of your game.

    • Advanced Gaming Components

      V-Play provides advanced components for tasks needed in many games: entity pooling for performance optimizations, a customizable virtual joystick, native video player, AI components for path finding or steering behavior to name just a few. No extra plugins or expenses are involved - they're all included at no extra cost to speed up your game's development.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Support, Community & Roadmap

      And last but not least: V-Play has an open roadmap shaped by YOU, our customers. We have a team working on the improvements around the clock and provide frequent updates every two weeks. Oh, and don’t forget our supportive community and core developers in the forums who are on hand to answer questions quickly.

  • You love Cocos2d?

    So do we!

    In fact, our development team has worked with different versions of cocos2d in the past. When cocos2d-iphone came out, we found it 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, in order 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 greater than 60% on what can be saved when using JavaScript and QML instead of C++. The game is still running at a 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, working with the Android NDK can be a real pain and a lot of boilerplate code is required to make native Java SDKs or 3rd party plugins work with a common C++ source. That's why V-Play chose to simplify these cross-platform problems by providing a high level API on top of cocos2d-x, which is used internally as the rendering engine. Plugins such as GameCenter, Facebook or Flurry are available from JavaScript as ready-made components, without the need to reinvent the wheel for every new game.

    As we also used cocos2d a lot in the past, we believe int the benefits V-Play can offer you as an existing cocos2d developer:

    Benefits

    • Build Server

      Take the pain out of installing native SDKs and compiling your game for every desired target platform. Enjoy the headache-free one-click-deployment of app-store ready games: V-Play Build Server does the work for you by compiling in the cloud. E.g. You'll be able to develop your game on Windows and deploy it to iOS.

    • Gaming Services

      With existing plugins for most important gaming services you can focus on taking your game to the next level: in-app purchases, game & social network integration (such as Game Center, Facebook), ads and analytics (such as Flurry) are available across platforms. The services are easily accessible from QML and are fully documented including example code. More plugins and even a template for providing your own are already on the way.

    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • Component Documentation

      All V-Play gaming components are extensively documented. To open the help, just press F1 in the Qt Creator IDE and the context-aware documentation shows up. You can also use the online version in your favorite browser.

    • QML Declarative Language

      Your game is written in JavaScript and QML, a declarative language offering highly productive features such as property bindings, state machines or fluid animations of any property. With QML, you are able to write 10 times less code compared with C++, which also means 10 times less error sources. The great thing is, all gaming components used in QML are internally implemented in C++ with a guaranteed maximum performance. These features in conjunction with the V-Play gaming components will give the prototyping and development of your game an even bigger boost.

      import VPlay 1.0
      import QtQuick 1.1
      
      GameWindow {
        Scene {
      
          Image {
            id: image
            source: "v-play-logo.png"
      
            MouseArea {
              anchors.fill: parent
              drag.target: parent
            }
          }
      
          Text {
            text: "Hi V-Play"
            color: "blue"
            anchors.horizontalCenter: image.horizontalCenter
      
            // you may write any JavaScript expression here
            // it gets re-evaluated when the y property of image changes
            y: image.y + 100
          }
        }
      }
      Hi V-Play
    • Game Templates

      V-Play includes the full source code of live App Store games for some of the most popular genres. These can be used as gaming templates to rapidly create games like tower defenses, platformers like Doodle Jump, physics games, side scrollers or action games.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Multi-touch & Gestures

      V-Play handles as many touches as your device is able to recognize. Make objects draggable with just a single line of code, or use our available multi-touch components to work with pinch, pan, swipe and rotation gestures.

    • Multi Resolutions

      V-Play is built to handle all possible aspect ratios and resolutions for modern mobile devices. Design your game once for a logical scene and V-Play handles the rest. This means no black borders or distorted images, but a native look for smartphones, tablets and desktops with a single code version. You can even test how your game will look like on different resolutions while it's running.

      V-Play even loads different image bundles based on the devices' pixel density to save expensive memory resources. For maximum performance and an optimized workflow, we support batched rendering from sprite sheets exported with tools like Texture Packer.

    • Native Dialogs and Functionality

      Sometimes there will be situations that require some user input or notifications. V-Play has abstracted components for displaying native input dialogs and alert boxes without the need of a single native code line. It's also possible to use accelerometer or open a web view to display your website right out of your game.

    • Advanced Gaming Components

      V-Play provides advanced components for tasks needed in many games: entity pooling for performance optimizations, a customizable virtual joystick, native video player, AI components for path finding or steering behavior to name just a few. No extra plugins or expenses are involved - they're all included at no extra cost to speed up your game's development.

    • Support, Community & Roadmap

      And last but not least: V-Play has an open roadmap shaped by YOU, our customers. We have a team working on the improvements around the clock and provide frequent updates every two weeks. Oh, and don’t forget our supportive community and core developers in the forums who are on hand to answer questions quickly.

    API Comparison

    • 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.

      V-Play Code

      import VPlay 1.0
      import QtQuick 1.1
      
      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)
          }
        }
      }

      Cocos2d-x Code

      #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 informations 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 1.0
      import QtQuick 1.1
      
      Scene {
      
        MultiResolutionImage {
          source: "staticImage-sd.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 1.0
      import QtQuick 1.1
      
      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.

      V-Play Code

      Text {
        text: "Hello V-Play"
        color: "black"
        pos: Qt.point(20, 30)
        font.pixelSize: 32
      }

      Cocos2d-x Code

       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 1.0
      import QtQuick 1.1
      
      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:

      V-Play Code

      import VPlay 1.0
      import QtQuick 1.1
      
      Particle {
        // 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 behaviour
        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()
        }
      
      }

      Cocos2d-x Code

      #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 mehaviour
      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 1.0
      import Box2D 1.0
      import QtQuick 1.1
      
      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 1.0
      import QtQuick 1.1
      
      Scene {
      
        // gets started once the application starts
        BackgroundMusic {
          source: "bgMusic.mp3"
        }
      
        Sound {
          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 1.0
      import QtQuick 1.1
      
      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-sd.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-sd.png"
            }
      
            Image {
              id: hill2
              source: "img/background-hills2-sd.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

    As developers, we prefer source code to lengthy texts. So in addition to explaining the benefits and API Comparison above, what better way to show the differences and benefits than with 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 at 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++, yet achieves the same result! From 369 lines of code, just 150 remain with V-Play. Keep in mind, that that's just from 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 fewer characters are needed per loc in QML. So that's why V-Play will boost your productivity: fewer characters, less code, less errors, shorter time to develop.


    Note: In 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.



    V-Play Code


    SimpleGameCocosNinjaMain.qml
    /*
     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 loc.
    
     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 1.0
    import QtQuick 1.1
    
    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
     width: 960
     height: 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
    
        // Determinie 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"])
     }
    }

    Cocos2d-x Code


    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 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 conflit 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) );
    
            // Determinie 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(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(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(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(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;
           }
    }
  • Familiar with Corona SDK?

    Similar to Corona, V-Play is designed with mobile 2D games in mind and has a wide range of gaming components that make game creation in just a few days reality. In addition, V-Play allows targeting the desktop app stores for Windows, Mac and Linux with the same source code. As you no doubt have your favorite OS, V-Play does not limit you in the development platform decision: use the professional Qt Creator IDE including a debugger, profiler, auto-completion and more on any platform you prefer!

    Take a look at the detailed benefits V-Play can offer you below:

    Benefits

    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Game Templates

      V-Play includes the full source code of live App Store games for some of the most popular genres. These can be used as gaming templates to rapidly create games like tower defenses, platformers like Doodle Jump, physics games, side scrollers or action games.

    • QML Declarative Language

      Your game is written in JavaScript and QML, a declarative language offering highly productive features such as property bindings, state machines or fluid animations of any property. Compared with Lua, QML is easier to read and requires less code. These features in conjunction with the V-Play gaming components will give the prototyping and development of your game an even bigger boost.

    • Advanced Gaming Components

      V-Play provides advanced components for tasks needed in many games: entity pooling for performance optimizations, a customizable virtual joystick, native video player, AI components for path finding or steering behavior to name just a few. No extra plugins or expenses are involved - they're all included at no extra cost to speed up your game's development.

    • Multi-touch & Gestures

      V-Play handles as many touches as your device is able to recognize. Make objects draggable with just a single line of code, or use our available multi-touch components to work with pinch, pan, swipe and rotation gestures.

    • Support, Community & Roadmap

      And last but not least: V-Play has an open roadmap shaped by YOU, our customers. We have a team working on the improvements around the clock and provide frequent updates every two weeks. Oh, and don’t forget our supportive community and core developers in the forums who are on hand to answer questions quickly.

    Full Demo Game

    Comparing yourself with Corona is always brave. They absolutely did their job with keeping the lines of code low, and offering reusable components for various needs. But we can proudly say that we can keep up with this!

    The following Corona source codes on the right column are from the excellent tutorials on Ray Wenderlich's site. On the left column is a similar implementation with V-Play.


    In the full demo game comparison below, you can see just how few loc V-Play needs, even when splitting the project structure into several files to increase maintainability. So now you can see just how V-Play will boost your productivity: fewer characters, less code, less errors, well structured projects, shorter time to develop.


    Note: In the the comparison, only real code lines are taken and comments and lines with empty spaces are left out.


    • BalloonPop

      First game is BalloonPop. Try to pop all balloons before the timer runs out, simple as that.

      This game idea, the tutorial and its image and audio resources can be found on Ray Wenderlich's site: How to Make a Simple iOS and Android Game with Corona Tutorial.

      The V-Play version of BalloonPop, also containing a link to our tutorial, is available at the Examples and Demos site: BalloonPop Demo.

      Comparing loc, the V-Play version has 94 compared to 111 of the Corona version.



      V-Play Code


      BalloonPopMain.qml
      import VPlay 1.0
      import QtQuick 1.1
      
      GameWindow {
      
        // our scene that contains the game
        BalloonScene {}
      }
      
      BalloonScene.qml
      import VPlay 1.0
      import QtQuick 1.1
      import "entities"
      
      Scene {
        id: balloonScene
        // provide the pop sound public for the balloons
        property alias popSound: popSound
        // number of balloos currently on the scene
        property int balloons: 0
        // maximum number of balloons
        property int balloonsMax : 100
        // duration of the game
        property int time : 20
        // flag if game ist running
        property bool gameRunning: false
      
        // position the scene on the top edge
        sceneAlignmentY: "top"
      
        // used to create balloons at runtime
        EntityManager {
      	id: entityManager
      	entityContainer: balloonScene
        }
      
        // make the balloons float up
        PhysicsWorld {gravity.y:1}
      
        // add a background image
        Image {source:"img/clouds.png"; anchors.fill:gameWindowAnchorItem}
      
        // the pop sound used by balloon entities
        Sound {source:"snd/balloonPop.wav"}
      
        // add background music
        BackgroundMusic {source:"snd/music.mp3"}
      
        // the pop sound used by balloon entities
        Sound {id:popSound; source:"snd/balloonPop.wav"}
      
        // left wall
        Wall {height:parent.height+50; anchors.right:parent.left}
        // right wall
        Wall {height:parent.height+50; anchors.left:parent.right}
        // ceiling
        Wall {width:parent.width; anchors.bottom:parent.top}
      
        // HUD
        Row {
      	anchors.bottom: parent.bottom
      	z: 1 // make sure the HUD is always on top
      	// info text area
      	Text {id:infoText; width:200; height:40; text:"Loading balloons..."}
      	// display remaining time
      	Text {id:timeText; height:40; text:"Time: "+balloonScene.time}
        }
      
        // create balloons with short intervals in between
        Timer {
      	interval: 20 // milliseconds
      	running: true // start running from the beginning, when the scene is loaded
      	repeat: true
      	onTriggered: {
      	  // after every 20ms we create a new balloon
      	  entityManager.createEntityFromUrl(Qt.resolvedUrl("entities/Balloon.qml"));
      	  balloons++
      	  // if the maximum number of balloons is reached, we stop the timer and therefore the balloon creation and start the game
      	  if(balloons===balloonsMax) {
      		running = false
      		gameRunning = true
      		infoText.text = "Hurry!"
      	  }
      	}
        }
      
        // game timer, default intervall is 1 second
        Timer {
      	id: gameTimer
      	running: gameRunning // time only counts down if game is running
      	repeat: true
      	onTriggered: {
      	  time--
      	  // if time is over, or each balloon is popped, we stop the game and give the player some feedback about his success
      	  if(time === 0 || balloons === 0) {
      		gameRunning = false
      		if(balloons === 0) infoText.text = "Perfect, take a cookie!"
      		else if(balloons < balloonsMax/2) infoText.text = "Well, that was decent..."
      		else infoText.text = "Not your day huh..."
      	  }
      	}
        }
      }
      
      Balloon.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      EntityBase {
        entityType: "balloon"
      
        CircleCollider {
      	radius: sprite.width/2
      	anchors.centerIn: parent
      	// restitution is bounciness, balloons are quite bouncy
      	fixture.restitution: 0.5
        }
      
        MultiResolutionImage {
      	id: sprite
      	source: "../img/balloon.png"
      	anchors.centerIn: parent
        }
      
        MultiTouchArea {
      	anchors.fill: sprite
      	onPressed: {
      	  // if you touch a balloon and the game is running, it will pop
      	  if(balloonScene.gameRunning) {
      		balloonScene.balloons--
      		balloonScene.popSound.play()
      		removeEntity()
      	  }
      	}
        }
      
        // gives the balloon a random position when created
        Component.onCompleted: {
      	x = utils.generateRandomValueBetween(15,balloonScene.width-15)
      	y = balloonScene.height
        }
      }
      
      Wall.qml
      import QtQuick 1.1
      import VPlay 1.0
      import Box2D 1.0 // for accessing the Body.Static type
      
      EntityBase {
        entityType: "wall"
        // default width and height
        width: 1
        height: 1
      
        // only collider since we want the wall to be invisible
        BoxCollider {
      	anchors.fill: parent
      	bodyType: Body.Static // the body shouldn't move
        }
      }
      

      Corona Code


      config.lua
      application = {
      	content = {
      		fps = 60,
      		width = 320,
      		height = 480,
      		scale = "zoomStretch",
       
      		imageSuffix = {
      			["@2x"] = 2;
      		},
      	},
      }
      
      main.lua
      local background = display.newImage("images/clouds.png");
      
      display.setStatusBar(display.HiddenStatusBar);
      
      local physics = require("physics");
      
      -- 1. Enable drawing mode for testing, you can use "normal", "debug" or "hybrid"
      physics.setDrawMode("normal")
       
      -- 2. Enable multitouch so more than 1 balloon can be touched at a time
      system.activate("multitouch");
       
      -- 3. Find device display height and width
      _H = display.contentHeight;
      _W = display.contentWidth;
       
      -- 4. Number of balloons variable
      balloons = 0;
       
      -- 5. How many balloons do we start with?
      numBalloons = 100;
       
      -- 6. Game time in seconds that we'll count down
      startTime = 20;
       
      -- 7. Total amount of time
      totalTime = 20;
       
      -- 8. Is there any time left?
      timeLeft = true;
       
      -- 9. Ready to play?
      playerReady = false;
       
      -- 10. Generate math equation for randomization
      Random = math.random;
       
      -- 11. Load background music
      local music = audio.loadStream("sounds/music.mp3");
       
      -- 12. Load balloon pop sound effect
      local balloonPop = audio.loadSound("sounds/balloonPop.mp3");
      
      -- Create a new text field using native device font
      local screenText = display.newText("...Loading Balloons...", 0, 0, native.systemFont, 16*2);
      screenText.xScale = 0.5
      screenText.yScale = 0.5;
       
      -- Change the center point to bottom left
      screenText:setReferencePoint(display.BottomLeftReferencePoint);
       
      -- Place the text on screen
      screenText.x = _W / 2 - 210;
      screenText.y = _H - 20;
      
      -- Create a new text field to display the timer
      local timeText = display.newText("Time: "..startTime, 0, 0, native.systemFont, 16*2);
      timeText.xScale = 0.5
      timeText.yScale = 0.5;
      timeText:setReferencePoint(display.BottomLeftReferencePoint);
      timeText.x = _W / 2;
      timeText.y = _H - 20;
      
      local gameTimer;
       
      -- Did the player win or lose the game?
      local function gameOver(condition)
      	-- If the player pops all of the balloons they win
      	if (condition == "winner") then
      		screenText.text = "Amazing!";
      	-- If the player pops 70 or more balloons they did okay
      	elseif (condition == "notbad") then
      		screenText.text = "Not too shabby."
      	-- If the player pops less than 70 balloons they didn't do so well
      	elseif (condition == "loser") then
      		screenText.text = "You can do better.";
      	end
      end 
       
      -- Remove balloons when touched and free up the memory they once used
      local function removeBalloons(obj)
      	obj:removeSelf();
      	-- Subtract a balloon for each pop
      	balloons = balloons - 1;
       
      	-- If time isn't up then play the game
      	if (timeLeft ~= false) then
      		-- If all balloons were popped
      		if (balloons == 0) then
      			timer.cancel(gameTimer);
      			gameOver("winner")
      		elseif (balloons <= 30) then
      			gameOver("notbad");
      		elseif (balloons >=31) then
      			gameOver("loser");
      		end
      	end
      end
      
      local function countDown(e)
      	-- When the game loads, the player is ready to play
      	if (startTime == totalTime) then
      		-- Loop background music
      		audio.play(music, {loops =- 1});
      		playerReady = true;
      		screenText.text = "Hurry!"
      	end
      	-- Subtract a second from start time
      	startTime = startTime - 1;
      	timeText.text = "Time: "..startTime;
       
      	-- If remaining time is 0, then timeLeft is false 
      	if (startTime == 0) then
      		timeLeft = false;
      	end
      end
      
      -- 1. Start the physics engine
      physics.start()
       
      -- 2. Set gravity to be inverted
      physics.setGravity(0, -0.4)	
       
      local function startGame()
      	-- 3. Create a balloon, 25 pixels by 25 pixels
      	local myBalloon = display.newImageRect("images/balloon.png", 25, 25);
       
      	-- 4. Set the reference point to the center of the image
      	myBalloon:setReferencePoint(display.CenterReferencePoint);
       
      	-- 5. Generate balloons randomly on the X-coordinate
      	myBalloon.x = Random(50, _W-50);
       
      	-- 6. Generate balloons 10 pixels off screen on the Y-Coordinate
      	myBalloon.y = (_H+10);
       
      	-- 7. Apply physics engine to the balloons, set density, friction, bounce and radius
      	physics.addBody(myBalloon, "dynamic", {density=0.1, friction=0.0, bounce=0.9, radius=10});
      	
      	-- Allow the user to touch the balloons
      	function myBalloon:touch(e)
      		-- If time isn't up then play the game
      		if (timeLeft ~= false) then
      			-- If the player is ready to play, then allow the balloons to be popped
      			if (playerReady == true) then
      				if (e.phase == "ended") then
      					-- Play pop sound
      					audio.play(balloonPop);
      					-- Remove the balloons from screen and memory
      					removeBalloons(self);
      				end
      			end
      		end
      	end
      	-- Increment the balloons variable by 1 for each balloon created
      	balloons = balloons + 1;
       
      	-- Add event listener to balloon
      	myBalloon:addEventListener("touch", myBalloon);
      	
      	-- If all balloons are present, start timer for totalTime (10 sec)
      	if (balloons == numBalloons) then
      		gameTimer = timer.performWithDelay(1000, countDown, totalTime);
      	else
      		-- Make sure timer won't start until all balloons are loaded
      		playerReady = false;
      	end
      end
       
      -- 8. Create a timer for the game at 20 milliseconds, spawn balloons up to the number we set numBalloons
      gameTimer = timer.performWithDelay(20, startGame, numBalloons);
      
      --[[ Create "walls" on the left, right and ceiling to keep balloon on screen
      	display.newRect(x coordinate, y coordinate, x thickness, y thickness)
      	So the walls will be 1 pixel thick and as tall as the stage
      	The ceiling will be 1 pixel thick and as wide as the stage 
      --]]
      local leftWall = display.newRect (0, 0, 1, display.contentHeight);
      local rightWall = display.newRect (display.contentWidth, 0, 1, display.contentHeight);
      local ceiling = display.newRect (0, 0, display.contentWidth, 1);
       
      -- Add physics to the walls. They will not move so they will be "static"
      physics.addBody (leftWall, "static",  { bounce = 0.1 } );
      physics.addBody (rightWall, "static", { bounce = 0.1 } );
      physics.addBody (ceiling, "static",   { bounce = 0.1 } );
      
       
    • ZombieBreak

      A small BreakOut game with 2 Scenes and 2 levels.

      Another great tutorial with resources from Ray Wenderlich's site: How To Make a Breakout Game with Corona.

      The V-Play version VZombieBreak is also available at the Examples and Demos site: VZombieBreak Demo.

      Comparing loc, the V-Play version has 276 compared to 288 of the Corona version.



      V-Play Code


      VZombieBreakMain.qml
      import VPlay 1.0
      import QtQuick 1.1
      
      GameWindow {
        id: window
      
        // we define all scenes as invisible by default
        MenuScene {
      	id:menuScene
      	opacity:0
      	// if the start button in the MenuScene is pressed we set the state to game
      	// this will hide the menuScene and make the gameScene visible
      	onStartPressed: window.state = "game"
        }
      
        GameScene {id:gameScene; opacity: 0}
      
        // default state is "menu"
        state: "menu"
      
        //state machine used to set only one scene visible at a time
        states: [
      	State {
      	  name: "menu"
      	  // by switching the propery to 1, which is by default set to 0 above,
      	  // the Behavior defined in SceneBase takes care of animating the opacity of the new Scene from 0 to 1,
      	  // and the one of the old scene from 1 to 0
      	  PropertyChanges { target: menuScene; opacity: 1}
      	},
      	State {
      	  name: "game"
      	  PropertyChanges { target: gameScene; opacity: 1}
      	}
        ]
      }
      
      
      MenuScene.qml
      import VPlay 1.0
      import QtQuick 1.1
      
      Scene {
        id: menuScene
      
        // listen to the start button from anywhere, in our case the GameScene
        signal startPressed
      
        // background for the menu
        Image {source:"img/titleScreen.png"; anchors.fill:gameWindowAnchorItem}
      
        // background music for the menu
        BackgroundMusic {id: backgroundMusic; source:"snd/ZombieBreakTheme.mp3"}
      
        // custom made play button
        Image {
      	anchors.centerIn: parent
      	source: "img/playButton.png"
      	MouseArea {
      	  anchors.fill: parent
      	  // when pressed we stop the music and call the signal startPressed
      	  onPressed: {
      		backgroundMusic.stop()
      		startPressed()
      	  }
      	}
        }
      }
      
      GameScene.qml
      import VPlay 1.0
      import QtQuick 1.1
      
      import "entities"
      
      Scene {
        id: gameScene
      
        // the currently loaded level
        property variant activeLevel
        // the name of the currently loaded level
        property string activeLevelString : "Level1"
        // the sound of dying zombies, publicly available for the zombies
        property alias breakSound: breakSound
        // the number of zombies killed
        property int killedZombies: 0
      
        // state of the current game(level), ready/running/finished/failed
        state: "ready"
      
        // for our entities
        EntityManager {id:entityManager; entityContainer: gameScene}
      
        // use a high update rate for physic driven games
        PhysicsWorld {updatesPerSecondForPhysics:60}
      
        // background image is defined by the loaded level
        Image {source:activeLevel.background; anchors.fill:gameWindowAnchorItem}
      
        // sound for breaking zombies
        Sound {id:breakSound; source:"snd/ow.wav"}
      
        // left wall
        Wall {height:parent.height; anchors.right:parent.left}
        // right wall
        Wall {height:parent.height; anchors.left:parent.right}
        // ceiling
        Wall {width:parent.width; anchors.bottom:parent.top}
        // floor, if bullet hits it, the player failed the level
        Wall {
      	width: gameScene.width
      	anchors.top: parent.bottom
      	collision.onBeginContact: {
      	  levelFailed()
      	}
        }
      
        // heads up display
        HUD {
      	id: hud
      	width: gameScene.width
      	height: 30
      	cityText: "City: " + activeLevel.city
      	killedText: "Zombies killed: " + gameScene.killedZombies
        }
      
        // paddle, placed in the center of the scene
        Paddle {
      	id: paddle
      	width: 88
      	height: 34
      	x: parent.width/2 - width/2
      	y: parent.height - height
      
      	// drag the paddle left and right when touched
      	MouseArea {
      	  id: paddleTouchArea
      	  // a bigger touch area should be used so the fingers of the user do not block the view
      	  width: paddle.width*2
      	  height: paddle.height*2
      	  anchors.centerIn: paddle
      	  // the drag should target the paddle
      	  drag.target: paddle
      	  // the paddle should move only into X direction therefore block Y direction
      	  drag.axis: Drag.XAxis
      	  // limit the minimum and maximum of the touch area, because the paddle should not move into the wall
      	  drag.minimumX: gameScene.x
      	  drag.maximumX: gameScene.width-paddle.width
      	  // the paddle is only enabled if the game is ready or running
      	  enabled: gameScene.state === "ready" || gameScene.state === "running"
      	  // additionally, if the game is ready to be started, we start it when the paddle is touched
      	  onPressed: {
      		if(gameScene.state === "ready")
      		  startGame()
      	  }
      	}
        }
      
        // the bullet, placed right above the paddle
        Bullet {
      	id: bullet
      	x: paddle.x + paddle.width/2
      	y: paddle.y - 5
        }
      
        // load levels at runtime
        Loader {
      	id: loader
      	source: activeLevelString + ".qml"
      	onLoaded: {
      	  loadItemWithCocos(item)
      	  activeLevel = item
      	  item.width = gameScene.width
      	  item.height = gameScene.height/2
      	  gameScene.killedZombies = 0
      	  gameScene.state = "ready"
      	}
        }
      
        // if a zombie is killed, check if all are dead
        onKilledZombiesChanged: {
      	if(gameScene.killedZombies === activeLevel.maxZombies)
      	  levelFinished()
        }
      
        // button to get to Level2 after finishing Level1
        SimpleButton {
      	id: nextCity
      	anchors.centerIn: parent;
      	text: "Next City"
      	visible: false
      	onClicked: {
      	  nextCity.visible = false
      	  gameScene.activeLevelString = "Level2"
      	}
        }
      
        // button to restart the current level if player fails
        SimpleButton {
      	id: restartCity
      	anchors.centerIn: parent;
      	text: "Restart City"
      	visible: false
      	onClicked: {
      	  restartCity.visible = false
      	  // forcing the Loader to reaload the current level
      	  loader.source = ""
      	  loader.source = gameScene.activeLevelString + ".qml"
      	}
        }
      
        // text displayed when Level2 is finished
        Text {
      	id: survived
      	color: "red"
      	text: "You survived!"
      	anchors.centerIn: parent;
      	visible: false
        }
      
        // launch bullet
        function startGame() {
      	bullet.reStart(width/2,height - 50)
      	state = "running"
        }
      
        // reset bullet and display dialog
        function levelFinished() {
      	bullet.reset(width/2,height - 50)
      	state = "finished"
      	if(activeLevelString === "Level1") nextCity.visible = true
      	else survived.visible = true
        }
      
        // reset bullet and display dialog
        function levelFailed() {
      	bullet.reset(width/2,height - 50)
      	state = "failed"
      	restartCity.visible = true
        }
      }
      
      HUD.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      Item {
        // our GameScene will set the texts, so we make them publicly accessible
        property alias killedText : killed.text
        property alias cityText : city.text
      
        // display number of killed zombies
        Text {
      	id: killed
      	color: "red"
        }
      
        // display city name
        Text {
      	id: city
      	color: "red"
      	anchors.right: parent.right
        }
      }
      
      Level1.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      import "entities"
      
      Item {
        id: level1
      
        // number of total zombies
        property int maxZombies : 6
        // path to background image for this level
        property string background: "img/atl.png"
        // name of the city will be displayed in the HUD
        property string city: "Atlanta"
      
        // add some zombies
        Zombie {x:zombieWidth*1; y:zombieHeight*1;}
        Zombie {x:zombieWidth*2; y:zombieHeight*1;}
        Zombie {x:zombieWidth*4; y:zombieHeight*2;}
        Zombie {x:zombieWidth*5; y:zombieHeight*2;}
        Zombie {x:zombieWidth*7; y:zombieHeight*1;}
        Zombie {x:zombieWidth*8; y:zombieHeight*1;}
      }
      
      Level2.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      import "entities"
      
      Item {
        id: level2
      
        // number of total zombies
        property int maxZombies : 8
        // path to background image for this level
        property string background: "img/nyc.png"
        // name of the city will be displayed in the HUD
        property string city: "New York City"
      
        // add some zombies
        Zombie {x:zombieWidth*1; y:zombieHeight*1;}
        Zombie {x:zombieWidth*2; y:zombieHeight*1;}
        Zombie {x:zombieWidth*1; y:zombieHeight*2;}
        Zombie {x:zombieWidth*2; y:zombieHeight*2;}
        Zombie {x:zombieWidth*7; y:zombieHeight*1;}
        Zombie {x:zombieWidth*8; y:zombieHeight*1;}
        Zombie {x:zombieWidth*7; y:zombieHeight*2;}
        Zombie {x:zombieWidth*8; y:zombieHeight*2;}
      }
      
      Bullet.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      EntityBase {
        id: entity
        entityType: "bullet"
      
        // the speed of the bullet, needed in different functions so we define it as global property
        property int speed
      
        // for collision detection of the bullet
        CircleCollider {
      	id: circleCollider
      	radius: sprite.width/2
      	// entity does not have width and height, therefore we center the CircleCollider in the entity.
      	anchors.centerIn: parent
      	// the bullets speed should stay the same on each collision
      	// so we set restitution(bounciness) to 1 and the friction to 0
      	fixture.friction: 0
      	fixture.restitution: 1
      	// the ball is a fast and small object therefore, we set the bullet flag to true
      	// to get better physic results during collision detection.
      	bullet: true
        }
      
        // the image of the bullet
        Image {
      	id: sprite
      	source: "../img/bullet.png"
      	anchors.centerIn: circleCollider
        }
      
        // set the bullet to the defined position and start it
        function reStart(posx,posy) {
      
      	// set the bullet to the defined position without starting it
      	reset(posx,posy)
      
      	// generate random angle for the bullet
      	var angle = utils.generateRandomValueBetween(-135,-115)
      
      	// add a toRad() function to the angle, to change the grades to radians
      	if (typeof(Number.prototype.toRad) === "undefined") {
      	  Number.prototype.toRad = function() {
      			return this * Math.PI / 180;
      		  }
      	}
      
      	// do the trig to get the x and y components
      	var x = Math.cos(angle.toRad())*speed
      	var y = Math.sin(angle.toRad())*speed
      
      	// apply phscis impulse to start the bullet
      	circleCollider.applyLinearImpulse(Qt.point(x, y), circleCollider.pos)
        }
      
        // set the bullet to the defined position without starting it
        function reset(xpos,ypos) {
      	x = xpos
      	y = ypos
      	speed = 350
      	//entity.rotation = 0.0;
      	// set linear velocity of the entity to 0
      	circleCollider.linearVelocity = Qt.point(0, 0)
        }
      }
      
      Paddle.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      EntityBase {
        id: entity
        entityType: "paddle"
      
        // for collision detection of the paddle
        BoxCollider {
      	id: boxCollider
      	width: sprite.width
      	height: sprite.height
      	// the paddle should be static
      	bodyType: Body.Static
      	// entity does not have width and height, therefore we center the BoxCollider in the entity.
      	anchors.centerIn: parent
        }
      
        //the image for the paddle
        Image {
      	id: sprite
      	source: "../img/player.png"
      	anchors.centerIn: boxCollider
        }
      }
      
      Wall.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      EntityBase {
        entityType: "wall"
        // default width and height
        width: 1
        height: 1
      
        // make this public so we can check from anywhere if there is a collision,
        // will be needed to check if the bullet hits the floor
        property alias collision: collider.fixture
      
        // walls should be invisible so we only need to put a collider here for collision detection
        BoxCollider {
      	id: collider
      	anchors.fill: parent
      	// walls should be static
      	bodyType: Body.Static
        }
      }
      
      Zombie.qml
      import QtQuick 1.1
      import VPlay 1.0
      
      EntityBase {
        id: entity
        entityType: "zombie"
        // the dimensions of this entity result in the dimensions of the zombie image,
        // we define those public, because we will need it for calculations
        property alias zombieWidth : sprite.width
        property alias zombieHeight : sprite.height
      
        // for collision detection of the zombies
        BoxCollider {
      	id: boxCollider
      	width: sprite.width
      	height: sprite.height
      	// walls should be static
      	bodyType: Body.Static
      	anchors.centerIn: parent
      	// after collision (after the bullet fully bounced off) we destroy the zombie
      	fixture.onEndContact: {
      	  gameScene.killedZombies++
      	  gameScene.breakSound.play()
      	  entity.removeEntity()
      	}
        }
      
        //the image for the zombie
        Image {
      	id: sprite
      	source: "../img/zombie.png"
      	// this is the size compared to the scene size (480x320) - it will automatically be scaled when the window size is bigger than the scene
      	// the image will automatically be scaled to this size
      	anchors.centerIn: boxCollider
        }
      }
      

      Corona Code


      config.lua
      application =
      {
      	content =
      	{
      			width = 320,
      			height = 480, 
      			scale = "letterbox",
      			fps = 60,
      	},
      }
      
      main.lua
      display.setStatusBar(display.HiddenStatusBar);
      -- Physics Engine
      local physics = require("physics")
      physics.start()
      physics.setGravity(0, 0)
      -- Load Sounds
      local bgMusic = audio.loadStream("sounds/ZombieBreakTheme.mp3")
      local zombieKill = audio.loadSound("sounds/ow.mp3");
      -- Constants
      local _W = display.contentWidth / 2;
      local _H = display.contentHeight / 2;
      -- Variables
      local zombies = display.newGroup();
      local zombieWidth = 50;
      local zombieHeight = 50;
      local row;
      local column;
      local score = 0;
      local currentLevel;
      local velocityX = 3;
      local velocityY = -3;
      local gameEvent = "";
      -- Menu Screen
      local titleScreenGroup;
      local titleScreen;
      local playBtn;
       
      -- Game Screen
      local background;
      local player;
      local zombie;
      local bullet;
       
      -- Score/Level Text
      local zombieKillText;
      local zombieKillNum;
      local levelText;
      local levelNum;
       
      -- textBoxGroup
      local textBoxGroup;
      local textBox;
      local conditionDisplay;
      local messageText;
      
      
      -- Main Function
      function main()
      	showTitleScreen();
      end
      
      -- Show the Title Screen
      function showTitleScreen()
      
      	-- Place all title elements into 1 group
      	titleScreenGroup = display.newGroup()	
      	
      	titleScreen = display.newImage("images/titleScreen.png", 0, 0, true);
      	titleScreen.x = _W;
      	titleScreen.y = _H;
      
      	-- Display play button image
      	playBtn = display.newImage("images/playButton.png")
      	playBtn.x = _W;
      	playBtn.y = _H + 50;
      	playBtn.name = "playbutton";
      
      	-- Insert backgroudn and button into group
      	titleScreenGroup:insert(titleScreen);
      	titleScreenGroup:insert(playBtn);
      
      	-- Make play button interactive
      	playBtn:addEventListener("tap", loadGame);
      
      end
      
      -- When play button is tapped, start the game
      function loadGame(event)
      	if event.target.name == "playbutton" then
      		audio.play(bgMusic, {loops =- 1});
      		audio.setVolume(0.2)
      		transition.to(titleScreenGroup,{time = 0, alpha=0, onComplete = initializeGameScreen});
      		playBtn:removeEventListener("tap", loadGame);
      	end
      end
      
      -- Set up the game space
      function initializeGameScreen()
      	-- Place the player on screen
      	player = display.newImage("images/player.png");
      	player.x = _W;
      	player.y = _H + 140;
      	player.name = "player";
       
      	-- Place bullet on screen
      	bullet = display.newImage("images/bullet.png");
      	bullet.x = _W;
      	bullet.y = player.y - 30;
      	bullet.name = "bullet";
       
      	-- Score text
      	zombieKillText = display.newText("Zombies Killed: ", 25, 2, "Arial", 14);
      	zombieKillText:setTextColor(255, 255, 255, 255);
      	zombieKillNum = display.newText("0", 150, 2, "Arial", 14);
      	zombieKillNum:setTextColor(255, 255, 255, 255);
       
      	-- Level text
      	levelText = display.newText("City:", 360, 2, "Arial", 14);
      	levelText:setTextColor(255, 255, 255, 255);
      	levelNum = display.newText("Atlanta", 400, 2, "Arial", 14);
      	levelNum:setTextColor(255, 255, 255, 255);
       
      	-- Run level 1 
      	changeLevel1();
      end
      
      function changeLevel1()
      	-- Level 1 background image will be Atlanta
      	bg1 = display.newImage("images/atl.png", 0, 0, true );
      	bg1.x = _W;
      	bg1.y = _H;
      	bg1:toBack();
       
      	-- Start
      	player:addEventListener("tap", startGame)
       
      	-- Reset zombies
      	gameLevel1();
      end
      
      -- When the game starts, add physics properties to player and bullet
      function startGame()
      	physics.addBody(player, "static", {density = 1, friction = 0, bounce = 0});
      	physics.addBody(bullet, "dynamic", {density = 1, friction = 0, bounce = 0});
      	player:removeEventListener("tap", startGame);
      	gameListeners("add");
      end
      
      -- Bullet properties
      function updatebullet()
       
      	-- Movement
      	bullet.x = bullet.x + velocityX;
      	bullet.y = bullet.y + velocityY;
       
      	-- If bullet hits the ceiling or left or right wall, bounce off of it
      	if bullet.x < 0 or bullet.x + bullet.width > display.contentWidth then  
      		velocityX = -velocityX;
      	end
       
      	if bullet.y < 0  then 
      		velocityY = -velocityY;
      	end
       
      	-- If the bullet hits the bottom wall, the player has lost the game
      	if bullet.y + bullet.height > player.y + player.height then 
      		textBoxScreen("MY BRAINS!!", "Try Again") gameEvent = "lose";
      	end
      end
      
      -- Listen for bullet and player collisions and user dragging player
      function gameListeners(event)
      	if event == "add" then
      		Runtime:addEventListener("enterFrame", updatebullet);
      		player:addEventListener("touch", movePlayer);
      		player:addEventListener("collision", bounce);
      		bullet:addEventListener("collision", zombieDestroyed);
      		-- Bookmark A: You'll be adding some code here later
      	-- Remove listeners when not needed to free up memory
      	elseif event == "remove" then
      		Runtime:removeEventListener("enterFrame", updatebullet);
      		player:removeEventListener("touch", movePlayer);
      		player:removeEventListener("collision", bounce);
      		bullet:removeEventListener("collision", zombieDestroyed);
      		-- Bookmark B: You'll be adding some code here later too
      	end
      end
      
      function gameLevel1()
       
      	currentLevel = 1;
       
      	-- Place the zombies on the top layer
      	zombies:toFront();
       
      	-- Number of zombies on level 1
      	local numOfRows = 2;
      	local numOfColumns = 2;
       
      	-- Zombie position on screen
      	local zombiePlacement = {x = (_W) - (zombieWidth * numOfColumns ) / 2  + 20, y = 70};
       
      	-- Create zombies based on the number of columns and rows we declared
      	for row = 0, numOfRows - 1 do
      		for column = 0, numOfColumns - 1 do
      			local zombie = display.newImage("images/zombie.png");
      			zombie.name = "zombie";
      			zombie.x = zombiePlacement.x + (column * zombieWidth);
      			zombie.y = zombiePlacement.y + (row * zombieHeight);
       
      			-- Add physics properties to zombies
      			physics.addBody(zombie, "static", {density = 1, friction = 0, bounce = 0});
      			zombies.insert(zombies, zombie);
      		end
      	end
      end
      
      -- Player movement on user's drag
      function movePlayer(event)
      	if event.phase == "began" then
      		moveX = event.x - player.x;
      	elseif event.phase == "moved" then
      		player.x = event.x - moveX;
      	end
       
      	if((player.x - player.width * 0.5) < 0) then
      		player.x = player.width * 0.5;
      	elseif((player.x + player.width * 0.5) > display.contentWidth) then
      		player.x = display.contentWidth - player.width * 0.5;
      	end
      end
      
      -- Determines bullet movement by where it hits the player
      function bounce()
      	velocityY = -3
      	if((bullet.x + bullet.width * 0.5) < player.x) then
      		velocityX = -velocityX;
      	elseif((bullet.x + bullet.width * 0.5) >= player.x) then
      		velocityX = velocityX;
      	end
      end
      
      -- Zombies are exterminated, remove them from screen
      function zombieDestroyed(event)
       
      	-- Where did the bullet hit the zombie?
      	if event.other.name == "zombie" and bullet.x + bullet.width * 0.5 < event.other.x + event.other.width * 0.5 then
      		velocityX = -velocityX;
      	elseif event.other.name == "zombie" and bullet.x + bullet.width * 0.5 >= event.other.x + event.other.width * 0.5 then
      		velocityX = velocityX;
      	end
       
      	-- Ricochet the bullet off the zombie and remove him from the screen
      	if event.other.name == "zombie" then
      		-- Bounce the bullet
      		velocityY = velocityY * -1;
      		-- Zombie says "ow" when hit by a bullet
      		audio.play(zombieKill);
      		-- Remove zombie instance
      		event.other:removeSelf();
      		event.other = nil;
      		-- One less zombie
      		zombies.numChildren = zombies.numChildren - 1;
       
      		-- Score
      		score = score + 1;
      		zombieKillNum.text = score;
      		zombieKillNum:setReferencePoint(display.CenterLeftReferencePoint);
      		zombieKillNum.x = 150;
      	end
       
      	-- Check if all zombies are destroyed
      	if zombies.numChildren < 0 then
      		textBoxScreen("City: Zombie Free", "Next City");
      		gameEvent = "win";
      	end
      end
      
      -- Level 2 zombies
      function gameLevel2()
       
      	currentLevel = 2;
      	bg1.isVisible = false;
       
      	-- This code is the same to gameLevel1(), but you can change the number of zombies on screen.
      	zombies:toFront();
      	local numOfRows = 2;
      	local numOfColumns = 8;
       
      	-- Zombie position on screen
      	local zombiePlacement = {x = (_W) - (zombieWidth * numOfColumns ) / 2  + 20, y = 100};
       
      	-- Create zombies based on the number of columns and rows we declared
      	for row = 0, numOfRows - 1 do
      		for column = 0, numOfColumns - 1 do
      			local zombie = display.newImage("images/zombie.png");
      			zombie.name = "zombie";
      			zombie.x = zombiePlacement.x + (column * zombieWidth);
      			zombie.y = zombiePlacement.y + (row * zombieHeight);
       
      			-- Add physics properties to zombies
      			physics.addBody(zombie, "static", {density = 1, friction = 0, bounce = 0});
      			zombies.insert(zombies, zombie);
      		end
      	end
      end
      
      function cleanupLevel()
      	-- Clear old zombies 
      	zombies:removeSelf();
      	zombies.numChildren = 0;
      	zombies = display.newGroup();
       
      	-- Remove text Box
      	textBox:removeEventListener("tap", restart);
      	textBoxGroup:removeSelf();
      	textBoxGroup = nil;
       
      	-- Reset bullet and player position 
      	bullet.x = _W;
      	bullet.y = player.y - 30;
      	player.x = _W;
       
      	score = 0;
      	zombieKillNum.text = "0";
      end
      
      -- New York City (Level 2)
      function changeLevel2()
       
      	-- Display background image and move it to the back
      	bg2 = display.newImage("images/nyc.png", 0, 0, true);
      	bg2.x = _W;
      	bg2.y = _H;
      	bg2:toBack();
       
      	-- Reset zombies 
      	gameLevel2();
       
      	-- Start
      	player:addEventListener("tap", startGame)
      end
      
      function textBoxScreen(title, message)
      	gameListeners("remove");
       
      	-- Display text box with win or lose message
      	textBox = display.newImage("images/textBox.png");
      	textBox.x = 240;
      	textBox.y = 160;
       
      	-- Win or Lose Text
      	conditionDisplay = display.newText(title, 0, 0, "Arial", 38);
      	conditionDisplay:setTextColor(255,255,255,255);
      	conditionDisplay.xScale = 0.5;
      	conditionDisplay.yScale = 0.5;
      	conditionDisplay:setReferencePoint(display.CenterReferencePoint);
      	conditionDisplay.x = display.contentCenterX;
      	conditionDisplay.y = display.contentCenterY - 15;
       
      	--Try Again or Congrats Text
      	messageText = display.newText(message, 0, 0, "Arial", 24);
      	messageText:setTextColor(255,255,255,255);
      	messageText.xScale = 0.5;
      	messageText.yScale = 0.5;
      	messageText:setReferencePoint(display.CenterReferencePoint);
      	messageText.x = display.contentCenterX;
      	messageText.y = display.contentCenterY + 15;
       
      	-- Add all elements into a new group
      	textBoxGroup = display.newGroup();
      	textBoxGroup:insert(textBox);
      	textBoxGroup:insert(conditionDisplay);
      	textBoxGroup:insert(messageText);
       
      	-- Make text box interactive
      	textBox:addEventListener("tap", restart);
      end
      
      -- See if the player won or lost the level
      function restart()
      	-- If the player wins level 1, then go to level 2
      	if gameEvent == "win" and currentLevel == 1 then
      		currentLevel = currentLevel + 1;
      		cleanupLevel();
      		changeLevel2();
      		levelNum.text = tostring("NYC");
       
      	-- If the player wins level 2, tell them they won the game
      	elseif gameEvent == "win" and currentLevel == 2 then	
      		textBoxScreen("  You Survived!", "  Congratulations!");
      		gameEvent = "completed";
       
      	-- If the player loses level 1, then make them retry level 1 and reset score to 0
      	elseif gameEvent == "lose" and currentLevel == 1 then
      		cleanupLevel();
      		changeLevel1();
       
      	-- If the player loses level 2, then make them retry level 2 and reset score to 0
      	elseif gameEvent == "lose" and currentLevel == 2 then
      		cleanupLevel();
      		changeLevel2();
       
      	-- If the game has been completed, remove the listener of the text box to free up memory
      	elseif gameEvent == "completed" then
      		textBox:removeEventListener("tap", restart);
      	end
      end
      
      -- See if the player won or lost the level
      function restart()
      	-- If the player wins level 1, then go to level 2
      	if gameEvent == "win" and currentLevel == 1 then
      		currentLevel = currentLevel + 1;
      		cleanupLevel();
      		changeLevel2();
      		levelNum.text = tostring("NYC");
       
      	-- If the player wins level 2, tell them they won the game
      	elseif gameEvent == "win" and currentLevel == 2 then	
      		textBoxScreen("  You Survived!", "  Congratulations!");
      		gameEvent = "completed";
       
      	-- If the player loses level 1, then make them retry level 1 and reset score to 0
      	elseif gameEvent == "lose" and currentLevel == 1 then
      		cleanupLevel();
      		changeLevel1();
       
      	-- If the player loses level 2, then make them retry level 2 and reset score to 0
      	elseif gameEvent == "lose" and currentLevel == 2 then
      		cleanupLevel();
      		changeLevel2();
       
      	-- If the game has been completed, remove the listener of the text box to free up memory
      	elseif gameEvent == "completed" then
      		textBox:removeEventListener("tap", restart);
      	end
      end
      
      main();
      			 
  • Using Unity?

    Unity was made for desktop 3D games. Although 2D games can be made with Unity, you often find yourself with many components and editor settings that you'll never actually need for a 2D game. V-Play is specialized for 2D games on mobile devices and was designed especially for this purpose. The performance is heavily optimized for mobile and all kinds of components that are required for successful mobile games are already included in the engine. That means there's no need to buy dozens of plugins to produce a great 2D game.

    As a Unity developer, these are the coolest benefits V-Play can offer you:

    Benefits

    • QML Declarative Language

      Your game is written in JavaScript and QML, a declarative language offering highly productive features such as property bindings, state machines or fluid animations of any property. These features in conjunction with the V-Play gaming components will give the prototyping and development of your game an even bigger boost.

    • Advanced Gaming Components

      V-Play provides advanced components for tasks needed in many games: entity pooling for performance optimizations, a customizable virtual joystick, native video player, AI components for path finding or steering behavior to name just a few. No extra plugins or expenses are involved - they're all included at no extra cost to speed up your game's development.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • Build Server

      Take the pain out of installing native SDKs and compiling your game for every desired target platform. Enjoy the headache-free one-click-deployment of app-store ready games: V-Play Build Server does the work for you by compiling in the cloud. E.g. You'll be able to develop your game on Windows and deploy it to iOS.

    • Gaming Services

      With existing plugins for most important gaming services you can focus on taking your game to the next level: in-app purchases, game and social network integration (such as Game Center, Facebook), ads and analytics (such as Flurry) are available across platforms. All services are fully documented and come with example code. More plugins and even a template for providing your own are already on the way.

    • Multi Resolutions

      V-Play is built to handle all possible aspect ratios and resolutions for modern mobile devices. Design your game once for a logical scene and V-Play handles the rest. This means no black borders or distorted images, but a native look for smartphones, tablets and desktops with a single code version. You can even test how your game will look like on different resolutions while it's running.

      V-Play even loads different image bundles based on the devices' pixel density to save expensive memory resources. For maximum performance and an optimized workflow, we support batched rendering from sprite sheets exported with tools like Texture Packer.

    • Multi-touch & Gestures

      V-Play handles as many touches as your device is able to recognize. Make objects draggable with just a single line of code, or use our available multi-touch components to work with pinch, pan, swipe and rotation gestures.

    • Native Dialogs and Functionality

      Sometimes there will be situations that require some user input or notifications. V-Play has abstracted components for displaying native input dialogs and alert boxes without the need of a single native code line. It's also possible to use accelerometer or open a web view to display your website right out of your game.

    • Game Templates

      V-Play includes the full source code of live App Store games for some of the most popular genres. These can be used as gaming templates to rapidly create games like tower defenses, platformers like Doodle Jump, physics games, side scrollers or action games.

  • Coming from Marmalade SDK?

    Compared with Marmalade, V-Play is a higher level framework specialized for mobile 2D games. V-Play includes the full source code of live App Store games for some of the most popular genres. These can be used as gaming templates to rapidly create games such as tower defenses, platformers like Doodle Jump, physics games, side scrollers or action games.

    As a Marmalade developer, these are the benefits V-Play can offer you:

    Benefits

    • QML Declarative Language

      Your game is written in JavaScript and QML, a declarative language offering highly productive features such as property bindings, state machines or fluid animations of any property. With QML, you are able to write 10 times less code compared with C++, which also means 10 times less error sources. The great thing is, all gaming components used in QML are internally implemented in C++ with a guaranteed maximum performance. Compared with Lua, QML is easier to read and requires less code. These features in conjunction with the V-Play gaming components will give the prototyping and development of your game an even bigger boost.

    • Gaming Services

      With existing plugins for most important gaming services you can focus on taking your game to the next level: in-app purchases, game and social network integration (such as Game Center, Facebook), ads and analytics (such as Flurry) are available across platforms. All services are fully documented and come with example code. More plugins and even a template for providing your own are already on the way.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • Component Documentation

      All V-Play gaming components are extensively documented. To open the help, just press F1 in the Qt Creator IDE and the context-aware documentation shows up. You can also use the online version in your favorite browser.

    • Multi-touch & Gestures

      V-Play handles as many touches as your device is able to recognize. Make objects draggable with just a single line of code, or use our available multi-touch components to work with pinch, pan, swipe and rotation gestures.

    • Multi Resolutions

      V-Play is built to handle all possible aspect ratios and resolutions for modern mobile devices. Design your game once for a logical scene and V-Play handles the rest. This means no black borders or distorted images, but a native look for smartphones, tablets and desktops with a single code version. You can even test how your game will look like on different resolutions while it's running.

      V-Play even loads different image bundles based on the devices' pixel density to save expensive memory resources. For maximum performance and an optimized workflow, we support batched rendering from sprite sheets exported with tools like Texture Packer.

    • Advanced Gaming Components

      V-Play provides advanced components for tasks needed in many games: entity pooling for performance optimizations, a customizable virtual joystick, native video player, AI components for path finding or steering behavior to name just a few. No extra plugins or expenses are involved - they're all included at no extra cost to speed up your game's development.

    • Build Server

      Take the pain out of installing native SDKs and compiling your game for every desired target platform. Enjoy the headache-free one-click-deployment of app-store ready games: V-Play Build Server does the work for you by compiling in the cloud. E.g. You'll be able to develop your game on Windows and deploy it to iOS.

  • Not satisfied with HTML5?

    As a web developer, you're faced with a whole host of problems when developing mobile games: weak performance, dozens of different devices and screen sizes, no access to native services like Game Center, or the desire for a complete IDE with debugger, profiler, auto-completion and integrated docs.

    Luckily, V-Play has solved these problems for you and the great news is: you already know the weapon to create stunning and high-performance games in no time: JavaScript.

    Continue reading to find out about how V-Play can help you with game development…

    Benefits

    • QML Declarative Language

      Your game is written in familiar JavaScript and QML, a declarative language offering highly productive features such as property bindings, state machines or fluid animations of any property. With QML, you are able to write 10 times less code compared with C++, which also means 10 times less error sources. The great thing is, all gaming components used in QML are internally implemented in C++ with a guaranteed maximum performance. These features in conjunction with the V-Play gaming components will give the prototyping and development of your game an even bigger boost.

    • Qt Creator IDE

      V-Play comes with Qt Creator IDE, featuring a GUI-designer, debugger, profiler, code completion, support for version control and integrated docs for V-Play components. Just press “Ctrl + Space” to auto-complete component names, properties or function names. If you ever need help for a component, the context-sensitive documentation within the IDE is only an “F1” keystroke away. Just like spelling errors in your text program, Qt Creator highlights syntax error or broken paths in your QML source files, without the need to build your game first. Qt Creator is cross-platform too, allowing you to choose your favorite development system, whether it's Windows, Mac OS X or Linux.

    • 2D Game Components

      V-Play is specialized for 2D games and provides components for animations, particles, physics, AI, multi-touch and much more to prototype and build games within days.

    • Game Templates

      V-Play includes the full source code of live App Store games for some of the most popular genres. These can be used as gaming templates to rapidly create games like tower defenses, platformers like Doodle Jump, physics games, side scrollers or action games.

    • Multi Resolutions

      V-Play is built to handle all possible aspect ratios and resolutions for modern mobile devices. Design your game once for a logical scene and V-Play handles the rest. This means no black borders or distorted images, but a native look for smartphones, tablets and desktops with a single code version. You can even test how your game will look like on different resolutions while it's running.

      V-Play even loads different image bundles based on the devices' pixel density to save expensive memory resources. For maximum performance and an optimized workflow, we support batched rendering from sprite sheets exported with tools like Texture Packer.

    • Gaming Services

      With existing plugins for most important gaming services you can focus on taking your game to the next level: in-app purchases, game and social network integration (such as Game Center, Facebook), ads and analytics (such as Flurry) are available across platforms. All services are fully documented and come with example code. More plugins and even a template for providing your own are already on the way.

    • Native Dialogs and Functionality

      Sometimes there will be situations that require some user input or notifications. V-Play has abstracted components for displaying native input dialogs and alert boxes without the need of a single native code line. It's also possible to use accelerometer or open a web view to display your website right out of your game.

    • Multi-touch & Gestures

      V-Play handles as many touches as your device is able to recognize. Make objects draggable with just a single line of code, or use our available multi-touch components to work with pinch, pan, swipe and rotation gestures.

    • Level Editor

      Use the built-in Level Editor components to give your players the power to quickly create their own levels and share and rate them over social networks directly on their device. Give them the ability to create a community around your game and save time on content production.

      You can also use the editor to create levels quickly during development and further cut development time and costs. You'll also be able to see the balancing changes immediately while your game is running, without having to restart the app.

    • Build Server

      Take the pain out of installing native SDKs and compiling your game for every desired target platform. Enjoy the headache-free one-click-deployment of app-store ready games: V-Play Build Server does the work for you by compiling in the cloud. E.g. You'll be able to develop your game on Windows and deploy it to iOS.