Evgenii Legotckoi
Evgenii LegotckoiШілде 14, 2016, 5:57 Т.Ж.

QML ойыны - 1-сабақ. Ойын аренасы және динамикалық нысандар

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 файлының мазмұнына көшейік. Мұнда ең қызықты екі нүкте бар:

  1. Бұл торда қамтылған объектілер туралы ақпараттық модель қызметін атқаратын javascript-те екі өлшемді массив құру және ұяшықта нысанның бар-жоғын тексеру.
  2. Бұл динамикалық мақсаттарды құру.

Егер бірінші кодпен бәрі жеткілікті түрде түсінікті болса, мен екіншісі туралы бірнеше сөз айтамын. Мақсатты динамикалық түрде жасау үшін бұл жағдайда 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)

Барлық сабақтар топтамасы

Бейне оқулық

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз