Wednesday, August 19, 2020

Qt & Android: Create a 2D Game using QML

Description

This tutorial describes how to easily create a Qt app for Android using an open source physics simulator engine.

The Github project Box2D is a feature rich 2D rigid body physics engine, written in C++ by Erin Catto. It has been used in many games.  The Github project qml-box2d was created by Thorbjørn Lindeijer.  He states the goal of the qml-box2d plugin is to expose the functionality of Box2D (C++) as a QML plugin in order to make it easier to write physics based software in QML by using simple QML commands to create Box2D bodies, joints, sensors etc.

Source code

This post is going to describe  how to get started with the QML plugin qml-box2d in just a few easy steps.  The complete sample app is found in Github at https://github.com/pgulotta/TestBox2D


Step 1

Clone qml-box2d from Github, https://github.com/qml-box2d/qml-box2d.   The project's README.md provides instructions on how to install the Qt plugin. Take a look  at the README.md to learn how robust BOX2D is. Note, for this example, there is no need to install the Qt plugin because the qml-box2d plugin will be statically linked to this sample project.  

Step 2

Create a new Qt Quick empty project named TestBox2D at the same directory level as the cloned qml-box2d Github project.   To the project file TestBox2D.pro, add a reference to the static library:
INCLUDEPATH += ../qml-box2d/Box2D
include(../qml-box2d/box2d-static.pri)

Build the TestBox2D for both Desktop and Android kits: armeabi-v7a. arm64-v8a. x86. x86_64.  Verify the apps run successfully.


Step 3

Since the qml-box2d Github project provides many QML examples, we will use one of the examples.  Copy the files and the images directory from qml-box2d/examples/mouse into the TestBox2D project directory. The file main.qml is overwritten. Next, copy the qml-box2d/examples/shared directory into TestBox2D project directory.  Update the file qml.qrc to reflect the additional files.  The contents of qml.qrc will look like:
<RCC>
    <qresource prefix="/">

        <file>main.qml</file>
        <file>Wall.qml</file>

        <file>shared/BoxBody.qml</file>
        <file>shared/ChainBody.qml</file> 
        <file>shared/CircleBody.qml</file>
        <file>shared/EdgeBody.qml</file>
        <file>shared/ImageBoxBody.qml</file>
        <file>shared/PhysicsItem.qml</file>
        <file>shared/PolygonBody.qml</file>
        <file>shared/RectangleBoxBody.qml</file>
        <file>shared/ScreenBoundaries.qml</file>

        <file>images/wall.jpg</file>

    </qresource>
</RCC>

Step 4

Since the TestBox2D is statically linked, all QML files must import Box2DStatic 2.0 and not Box2D 2.0.  So every QML file, including those in the shared directory, should have an entry such as:

//import Box2D 2.0
import Box2DStatic 2.0

For this project, the import statements in files main.qml and Wall.qml need to updated:

//import "../shared"
import "shared"  

Finally, in main.qml, change the Rectangle type to Window, visible: true,  and add the import of QtQuick.Window. Resulting in something like:

import QtQuick 2.2
//import Box2D 2.0
import Box2DStatic 2.0
import "shared"
import QtQuick.Window 2.15
Window {
visible:true
width: 800
height: 600
property Body pressedBody: null
... 

Step 5

To make the qml-box2d types available to the TestBox2D app, register the Box2DStatic plugin in main.cpp by adding a couple of lines of code resulting in:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <box2dplugin.h>

int main( int argc, char* argv[] )
{
  QCoreApplication::setAttribute( Qt::AA_EnableHighDpiScaling );
  QGuiApplication app( argc, argv );

  Box2DPlugin plugin;
  plugin.registerTypes( "Box2DStatic" );

  QQmlApplicationEngine engine;
  const QUrl url( QStringLiteral( "qrc:/main.qml" ) );
  QObject::connect( &engine, &QQmlApplicationEngine::objectCreated,
  &app, [url]( QObject * obj, const QUrl & objUrl ) {
    if ( !obj && url == objUrl ) {
      QCoreApplication::exit( -1 );
    }
  }, Qt::QueuedConnection );
  engine.load( url );
  return app.exec();
}


Step 6

Clean, build, and run the TestBox2D app on both for both the desktop and Android platforms (or any other Qt supported platform).  Try out the app by tossing and stacking the different sized boxes (rectangles) around.  Note how the boxes appear to have gravity, friction, and restitution.  

You can try out other examples by following the steps described above or by using the Qt qmlscene tool. Pretty darn awesome, right!

No comments:

Post a Comment

Qt & Android: Create a 2D Game using QML

Description This tutorial describes how to easily create a Qt app for Android using an open source physics simulator engine. The Github proj...