After the first experience of writing games on Qt for Android, I want to share this experience together and offer to write a simple game in the style of "kill the mole." This is a game in which you need to have time to hit the moles, which climbs out of their holes, but considering that this is a simplified game, instead of moles using the circular target, which will appear on the playing field. As the playing field will use the net 6 6 cells. But to create a field will not be used to some special object of type GridLayout . In the game board will be formed of a grid of rows, columns and the side length of a square cell. Data on occupancy cells to be stored in a two-dimensional array, which will be formed in javascript component (to forget that QML - a declarative JSON-like language with javascript enabled).
Project structure
The project consists of the following files:
- TargetGame.pro - the profile of the project;
- deployment.pri - build file and project deploya;
- main.cpp - the file with the main function of the project;
- main.qml - basic QML-layer file with the object of the main application window;
- Target.qml - QML file with the description of the target object;
- Target.png - the appearance of the target pattern is png;
- GameArea.qml - gaming arena with the grid to accommodate the targets;
- logic.js - file with javascript logic games.
We will study the contents of only those files that are different from the default content when creating the project.
main.qml
The main application window is an object of type GameArea , which is described in GameArea.qml . Since the width and height of the playing area is calculated automatically depending on the mesh size and mesh, we simply arrange the gaming arena in the middle of the application window.
A distinctive aspect of this file is to connect logic.js file as Logic type that will meet with the logic of the game and in the file, after the creation of the object of the main application window with the gaming arena, we will give a pointer to the gaming arena in the core logic of the game to remember the current state of the playing field and carry the primary initialization of the playing field, as well as the playing field of the array, which will be responsible the content of grid cells. This is done by calling function newGameState() , and transfer to it as an argument id gaming arena. In this tutorial, we do not track the state of the game, that is, if the game is started or stopped, so the gaming arena timer start immediately after the application starts.
import QtQuick 2.7 import QtQuick.Controls 1.5 import "logic.js" as Logic ApplicationWindow { visible: true width: 420 height: 480 title: qsTr("Target") GameArea { id: gameArea anchors.centerIn: parent } // After creating a window initialize the state of the playing field Component.onCompleted: { Logic.newGameState(gameArea) } }
GameArea.qml
Since the core logic in javascript figures we have in all aspects of the game, then connect the file here.
Games Arena is a rectangle with properties from are preset rows and columns, as well as the size of one side of the cell. Depending on these properties and the calculated width and height of the game arena. Also in the gaming arena, there is a timer which is triggered by the target will be created.
Creating targets accompanied by checking the availability of the randomly selected cell. The choice of the cell is carried out by selecting random rows and columns, by obtaining a random integer in the selected range from minimum to maximum, inclusive using getRandomRound(min, max) function, which is also described in logic.js.
checkEmptyField(row, column) function checks whether there is any object in a given cell, and if the cell is empty, then the target is created using createTarget(parent, row, column) function.
import QtQuick 2.7 import "logic.js" as Logic Rectangle { id: grid property int squareSize: 64 // The size of the game grid cell property int rows: 6 // The number of grid lines property int cols: 6 // The number of grid columns width: cols * squareSize // The width and height of the playing area height: rows * squareSize // It will depend on the number of columns, rows, and the size of one cell // Timer to create a target Timer { id: createTargetsTimer interval: 350; running: true; repeat: true; // Every second, choose a random cell, // check the presence of a target in it, and if the cell is empty, // then create a target onTriggered: { var targetRow = Logic.getRandomRound(0, rows - 1); var targetColumns = Logic.getRandomRound(0, cols - 1); if (Logic.checkEmptyField(targetRow, targetColumns)) { Logic.createTarget(grid ,targetRow, targetColumns) } } } }
Target.qml
Before studying the contents of the logical core javascript game, read the description of the target object.
The logic of the behavior of the target Is following. Once created, the target should disappear after a random period of time. And not just disappear, that is, changing the level of transparency, and self-destruct. For this is the destroy() method, which will be applied to the root of the object, its id: root. You can also see destroyTarget(row, column) function in javascript core games. This function is used to clear the cell array of two-dimensional information grid.
Since cell size is 64 pixels, and the target size of 56 pixels, then using some simple calculations, we determine the position of the target on the playing field, depending on the columns and rows that it should occupy.
import QtQuick 2.7 import "logic.js" as Logic Image { id: root property int row: 0 property int col: 0 width: 56 height: 56 x: (col * (width + 8)) + 4 y: (row * (height + 8)) + 4 source: "Target.png" // Load the target image Timer { interval: Logic.getRandomRound(350, 1500); running: true; repeat: false onTriggered: root.opacity = 0.0 } // When the image is clear. we will destroy the object itself onOpacityChanged: { if (opacity == 0.0) { Logic.destroyTarget(row, col) root.destroy() } } // Set the behavior of the animation properties of the object transparency Behavior on opacity { PropertyAnimation { duration: 250 } } }
logic.js
This file has define .pragma library .
.pragma library
This is due to the need to be able to access the games of ( var gameState ) from any location where the attached file in QML layer. In fact, the variables are shared resources for the various objects in the game. And the most important resource is gameState (aka play arena GameArea ). The fact is that if we can refer to the playing arena directly id of various objects which are declared statically in the game arena, or in the file where the arena declared itself, the dynamic resources, such as in Target.qml , have such a the method does not work. For this and used gameState of logic.js , which allows you to check the condition of the playing area regardless of whether the object is declared statically (under the condition I understand, whether the game or put on pause, as will be discussed in the following articles in the running).
Now let us turn to the content of logic.js file. It features two of the most interesting points:
- This is creating a two-dimensional array to javascript, which serves as an information model of the objects contained in the grid, and checking for the existence of the object in the cell.
- It is the creation of dynamic targets.
If the first all is clear enough from the code, then about the second to say a few words. To dynamically create a target, in this case, a component of the workpiece, which is created from Target.qml file. Moreover, such a workpiece needs only one set even for the same elements of the game.
var targetComponent = Qt.createComponent("Target.qml");
A creation of the object directly on the playing arena is carried out below the next function.
function createTarget(parent, row, column) { var target = targetComponent.createObject(parent, {"row": row, "col": column}) gameField[row][column] = target; }
In this case it is sufficient to create an object, using createObject method for harvesting a target component indicating the parent object, i.e. the object which is placed a target (in this case it will be the game arena) and listing the parameters that must be set when an object, in this case is the row and column, which will be located a target.
Full file listing
// We declare as a library to have access to shared resources, such as state of game .pragma library var gameState // Local state of the game // in our case it will be a play area - gameArea function getGameState() { return gameState; } var gameField; // The playing field, the game grid // Create a template for the targets var targetComponent = Qt.createComponent("Target.qml"); // Initialize a new state of the game function newGameState(gameArea) { gameState = gameArea; // The game grid will serve a two-dimensional array // that will store information about the presence of objects in the cells gameField = create2DArray(gameState.rows, gameState.cols); return gameState; } // Function get a random integer in the range of numbers inclusive function getRandomRound(min, max) { return Math.round(Math.random() * (max - min) + min); } // Create the target component from the template function createTarget(parent, row, column) { var target = targetComponent.createObject(parent, {"row": row, "col": column}) gameField[row][column] = target; } // The target is removed from the grid array function destroyTarget(row, column) { gameField[row][column] = null; } // The option to create a two-dimensional array of grid function create2DArray(rows, columns) { var arr = []; for (var i=0;i<rows;i++) { arr[i] = []; } return arr; } // Checking for the presence of any object in the selected cell function checkEmptyField(row, column) { if (gameField[row][column] == null) { return true; } else { return false; } }
Conclusion
As a result, we get the program to the board 6 by 6, which will be generated when you start disappearing targets.
Download the source of Game sample on QML from GitHub