Android үшін Qt ойынын жазудың бірінші тәжірибесінен кейін мен осы тәжірибемен бөліскім келеді және бірге «Мольді өлтіру» стилінде қарапайым ойын жазуды ұсынамын. Бұл саңылаулардан шыққан меңдерді соғуға уақыт табу керек ойын, бірақ бұл жеңілдетілген ойын болатынын ескере отырып, мольдердің орнына біз ойын алаңында пайда болатын дөңгелек нысаналарды қолданамыз. Ойын алаңы ретінде 6-ға 6 ұяшықтан тұратын тор пайдаланылады. Бірақ GridLayout сияқты кейбір арнайы нысан өрісті жасау үшін пайдаланылмайды. Ойын өрісінде тор жолдар, бағандар саны мен шаршы ұяшықтың бүйірінің ұзындығынан қалыптасады. Ұяшықтың толықтығы туралы деректер javascript компонентінде қалыптасатын екі өлшемді массивте сақталады (QML JavaScript қолдауы бар декларативті JSON тәрізді тіл екенін ұмытпаңыз).
Жоба құрылымы
Жоба келесі файлдардан тұрады:
- TargetGame.pro - жоба профилі;
- deployment.pri - жоба файлын құру және орналастыру;
- main.cpp - жобаның негізгі функциясы бар файл;
- main.qml - қолданбаның негізгі терезесінің объектісі бар QML қабатының негізгі файлы;
- Target.qml - мақсатты нысанның сипаттамасы бар QML файлы;
- Target.png - нысананың көрінісі png кескіні;
- GameArea.qml - нысаналарды қоюға арналған торы бар ойын аренасы;
- logic.js - JavaScript ойын логикасы бар файл.
Жобаны құру кезінде әдепкі мазмұннан ерекшеленетін файлдардың ғана мазмұнын зерттейік.
main.qml
Негізгі қолданба терезесінде GameArea.qml. ішінде сипатталған GameArea түріндегі нысан бар. Ойын алаңының ені мен биіктігі тор мен тор ұяшықтарының өлшеміне байланысты автоматты түрде есептелетіндіктен, біз жай ғана орналастырамыз. қолданба терезесінің ортасында ойын алаңы.
Бұл файлдың ерекшелігі logic.js файлын Logic түрі ретінде қосу болып табылады, ол ойын логикасына жауап береді және осы файлда негізгі қолданба терезесінің нысанын жасағаннан кейін ойын алаңында, біз ойын алаңының ағымдағы күйін есте сақтау және ойын өрісін, сондай-ақ ойын алаңының массивін бастапқы инициализациялауды жүзеге асыру үшін ойын логикасының өзегіне ойын алаңына көрсеткішті береміз. , ол тор ұяшықтарының мазмұнына сәйкес келеді. Бұл newGameState(), функциясын шақыру және оны аргумент ретінде ойын алаңының идентификаторын беру арқылы орындалады. Бұл оқулықта біз ойынның күйін, яғни ойынның іске қосылғанын немесе тоқтағанын бақыламаймыз, сондықтан аренадағы ойын таймері қолданба басталғаннан кейін бірден іске қосылады.
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 } // По окончании создания окна инициализируем состояние игрового поля Component.onCompleted: { Logic.newGameState(gameArea) } }
GameArea.qml
JavaScript логикалық ядросы ойынның барлық аспектілерінде пайда болғандықтан, біз бұл файлды да осында қосамыз.
Ойын аренасы – алдын ала анықталған жолдар мен бағандардың қасиеттері, сондай-ақ ұяшықтың бір жағының өлшемі бар тіктөртбұрыш. Осы қасиеттерге байланысты ойын алаңының ені мен биіктігі есептеледі. Сондай-ақ ойын алаңында таймер бар, оның жұмысы кезінде нысаналар жасалады.
Мақсаттарды құру кездейсоқ таңдалған ұяшықтың болуын тексерумен бірге жүреді. Ұяшықтарды таңдау getRandomRound(min, max) функциясын пайдаланып, таңдалған диапазондағы ең аздан максимумға дейінгі кездейсоқ бүтін санды алу арқылы кездейсоқ жолды және бағанды таңдау арқылы жүзеге асырылады, ол бөлімінде де сипатталған. logic.js.
checkEmptyField(жол, баған) функциясы берілген ұяшықта кез келген нысанның бар-жоғын тексереді, ал ұяшық бос болса, мақсат createTarget(ата-ана, жол, баған) функциясы арқылы жасалады.
import QtQuick 2.7 import "logic.js" as Logic Rectangle { id: grid property int squareSize: 64 // Размер ячейки игровой сетки property int rows: 6 // Количество строк сетки property int cols: 6 // Количество колонок сетки width: cols * squareSize // Ширина и высота игровой арены height: rows * squareSize // Будет зависеть от количества колонок, строк и размера одной ячейки // Таймер для создания мишеней Timer { id: createTargetsTimer interval: 350; running: true; repeat: true; // Раз в секунду выбираем случайную ячейку, // проверяем наличие мишени в ней, и если ячейка пустая, // то создаём мишень 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
Ойынның логикалық JavaScript ядросының мазмұнын қарастырмас бұрын, мақсатты нысанның сипаттамасын қарастырайық.
Мақсатты мінез-құлық логикасы келесідей. Жасалғаннан кейін мақсат кездейсоқ уақыттан кейін жоғалып кетуі керек. Және жай ғана жоғалып кетпейді, яғни ашықтық деңгейін өзгерту арқылы, бірақ өзін-өзі жою. Ол үшін destroy(), әдісі пайдаланылады, ол түбірлік нысанда, оның идентификаторында қолданылады: root. Сондай-ақ ойынның JavaScript өзегінде destroyTarget(жол, баған) функциясын көруге болады. Бұл функция екі өлшемді тор ақпарат массивінің ұяшығын тазалау үшін пайдаланылады.
Ұяшықтың өлшемі 64 пиксель, ал нысананың өлшемі 56 пиксель болғандықтан, қарапайым есептеулерді қолдана отырып, біз нысанның ойын өрісіндегі орнын оның алатын баған мен сызыққа байланысты анықтаймыз.
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" // Загружаем изображение мишени Timer { interval: Logic.getRandomRound(350, 1500); running: true; repeat: false onTriggered: root.opacity = 0.0 } // Когда изображение станет прозрачным. мы уничтожим сам объект onOpacityChanged: { if (opacity == 0.0) { Logic.destroyTarget(row, col) root.destroy() } } // Задаём поведение анимации свойства прозрачности объекта Behavior on opacity { PropertyAnimation { duration: 250 } } }
logic.js
Бұл файлда .pragma library *. * мәлімдемесі бар.
.pragma library
Бұл ойын күйіне ( var gameState ) осы файл QML қабатына енгізілген кез келген жерден қол жеткізу қажеттілігіне байланысты жасалады. Іс жүзінде айнымалылар ойындағы әртүрлі нысандар үшін ортақ ресурстарға айналады. Ал ең маңызды ресурс – gameState (aka ойын алаңы GameArea ). Өйткені, егер біз ойын аренасында статикалық түрде жарияланған әртүрлі нысандардан немесе аренаның өзі жарияланған файлдан ойын алаңына тікелей id арқылы қол жеткізе алатын болсақ, онда динамикалық ресурстарда, мысалы * *Target .qml , бұл әдіс біз үшін жұмыс істемейді. Ол үшін logic.js сайтынан gameState пайдаланылады, ол нысанның статикалық түрде жарияланғанына қарамастан ойын алаңының күйін тексеруге мүмкіндік береді (күй бойынша, мен ойынның іске қосылып тұрғанын немесе кідіртілді, ол келесі мақалаларда қарастырылады).
Енді logic.js файлының мазмұнына көшейік. Мұнда ең қызықты екі нүкте бар:
- Бұл торда қамтылған объектілер туралы ақпараттық модель қызметін атқаратын javascript-те екі өлшемді массив құру және ұяшықта нысанның бар-жоғын тексеру.
- Бұл динамикалық мақсаттарды құру.
Егер бірінші кодпен бәрі жеткілікті түрде түсінікті болса, мен екіншісі туралы бірнеше сөз айтамын. Мақсатты динамикалық түрде жасау үшін бұл жағдайда Target.qml. файлынан жасалған бос құрамдас пайдаланылады.Сонымен қатар, тек бір ғана бос орын қажет, тіпті бір типті көптеген элементтер үшін де ойын.
var targetComponent = Qt.createComponent("Target.qml");
Ал ойын алаңында нысанның өзін жасау төмендегі келесі функцияда жүзеге асырылады.
function createTarget(parent, row, column) { var target = targetComponent.createObject(parent, {"row": row, "col": column}) gameField[row][column] = target; }
Біздің жағдайда нысанды тектік нысанды, яғни нысана орналасатын нысанды көрсете отырып, мақсатты компонент бос бөлігінде createObject әдісін қолдану арқылы объект құру жеткілікті (бұл жағдайда ол ойын алаңы болады) ) және нысанды жасау кезінде орнатылуы тиіс параметрлерді тізімдеу, бұл жағдайда, бұл мақсат орналасатын жол мен баған.
Толық файлдар тізімі
// Объявляем, как библиотеку, чтобы иметь доступ // к разделяемым ресурсам, например состоянию игры .pragma library var gameState // Локальное объявление состояния игры // в нашем случае это будет игровая область gameArea function getGameState() { return gameState; } var gameField; // Игровое поле, игровая сетка // Создаём заготовку для мишеней var targetComponent = Qt.createComponent("Target.qml"); // Инициализируем новое состояние игры function newGameState(gameArea) { gameState = gameArea; // Игровой сеткой будет служить двумерный массив, // в котором будем сохранять информацию о наличии в ячейках объектов gameField = create2DArray(gameState.rows, gameState.cols); return gameState; } // Функция получения случайного целого числа // в диапазоне чисел включительно function getRandomRound(min, max) { return Math.round(Math.random() * (max - min) + min); } // Создаём мишень из компонента заготовки function createTarget(parent, row, column) { var target = targetComponent.createObject(parent, {"row": row, "col": column}) gameField[row][column] = target; } // Мишень удаляется из массива сетки function destroyTarget(row, column) { gameField[row][column] = null; } // Функция создания двумерного массива сетки function create2DArray(rows, columns) { var arr = []; for (var i=0;i<rows;i++) { arr[i] = []; } return arr; } // Проверка на предмет наличия какого либо объекта в выбранной ячейке function checkEmptyField(row, column) { if (gameField[row][column] == null) { return true; } else { return false; } }
Барлығы
Нәтижесінде біз 6-дан 6-ға дейінгі ойын өрісі бар бағдарламаны аламыз, онда жоғалып кететін мақсаттар іске қосу кезінде жасалады.
Дереккөзді [GitHub сайтындағы QML ойынының мысалынан] жүктеп алыңыз (https://github.com/Legotckoi/TargetGame)