Nachdem die Spielarena erstellt und die Scheiben hinzugefügt wurden, war es an der Zeit, die Treffer auf die Scheiben, Fehlschüsse und das System für die Wertung und den Abzug von Punkten zu implementieren.
Das System zum Bewerten und Abschreiben von Punkten sieht wie folgt aus:
- Im Falle von Fehlschüssen schlage ich vor, Spuren von Einschusslöchern verschiedener Art zu machen und einen Punkt vom Spielkonto abzuschreiben.
- Im Falle des Verschwindens des Ziels, ohne es zu treffen, schreiben Sie auch einen Punkt vom Spielkonto ab.
- Im Falle eines Treffers auf das Ziel werden ein bis fünf Punkte vergeben, je nachdem, wie nahe der Treffer am Zentrum war.
Die Punktzahl wird oben auf dem Spielfeld angezeigt.
Projektstruktur
Um diese Idee zu implementieren, müssen Sie zusätzlich zur Änderung einiger Dateien die folgenden Dateien hinzufügen:
- InfoBar.qml - zeigt Informationen über das Konto an;
- Bullet.qml - eine Datei mit einer Beschreibung des Typs des Einschusslochs;
- bullet-1.png, bullet-2.png, bullet-3.png, bullet-4.png, bullet-5.png, bullet-6.png – Dateien mit Bildern von Einschusslöchern;
Mögliche Optionen für Einschusslöcher werden in den Grafikordner gelegt, das Zielbild wurde auch dorthin verschoben.
Bilder von Einschusslöchern
Zur Abwechslung werden mehrere Arten von ähnlichen Einschusslöchern verwendet.
GameArea.qml
Bevor wir uns mit den Inhalten der neuen Dateien befassen, wenden wir uns den geänderten Inhalten der Datei GameArea.qml sowie dem Javascript-Logikkern in der Datei logic.js zu.
Die wichtigsten Neuerungen hier sind das Erscheinen der Eigenschaft scores für die Wertung, das Erscheinen der InfoBar und der Mausklick-Handler innerhalb der Spielarena.
Die Eigenschaft scores enthält die aktuelle Punktzahl und ihr Wert wird an die Eigenschaft scores in der infoBar übergeben, um dem Spieler die aktuelle Punktzahl anzuzeigen.
Bei einem Klick auf die Spielarena, der einem Fehlschuss gleichkommt, wird ein Einschussobjekt erstellt und der aktuelle Punktestand um eins reduziert. Das Einschussloch wird auf die gleiche Weise erstellt, wie die Erstellung von Zielen in der vorherigen Lektion implementiert wurde, d. h. unter Verwendung des Logic-Logikkerns, der sich in der Datei logic.js befindet.
import QtQuick 2.7 import "logic.js" as Logic Rectangle { id: grid ... property int scores: 0 // Очки ... InfoBar { id: infoBar scores: grid.scores } // Создаём след от пули при клике по игровой арене MouseArea { anchors.fill: parent onClicked: { Logic.createBullet(grid, mouse.x, mouse.y) grid.scores--; } } ... }
logic.js
Wir werden nur die Schaffung von Einschusslöchern zum logischen Kern des Spiels hinzufügen. Die Verarbeitung der Zieltrefferlogik wird in der Datei hinzugefügt, die das Ziel beschreibt.
... // Создаём заготовку для мишеней var bulletComponent = Qt.createComponent("Bullet.qml"); ... // Создаём след от пули function createBullet(parent, x, y) { bulletComponent.createObject(parent, {"x": x, "y": y}); } ...
InfoBar.qml
Die InfoLeiste ist ein normales RowLayout , das an den oberen Rand der Spielarena genagelt und auf seine Breite gestreckt wird. Die aktuelle Punktzahl wird im Textfeld mit id: scores angezeigt. Um den externen Zugriff auf die Texteigenschaft eines bestimmten Textfelds festzulegen, verwenden Sie die Eigenschaft Eigenschaftsalias .
import QtQuick 2.7 import QtQuick.Layouts 1.1 RowLayout { height: 40 anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.leftMargin: 6 anchors.rightMargin: 6 spacing: 6 z: 100 // Данное свойство устанавливает доступ к текстовому полю, // в которое будет устанавливаться текущий счёт property alias scores: scores.text Text { text: qsTr("Scores") font.pixelSize: 20 verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } Text { // Текстовое поле с текущим счётом id: scores font.pixelSize: 20 verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } // Своеобразный Spacer, который в RowLayout сдвинет текстовые поля к левому краю InfoBar Item { Layout.fillHeight: true Layout.fillWidth: true } }
Bullet.qml
Das Verhalten des Einschusslochs ähnelt dem Verhalten des Ziels. Die Lebensdauer eines Einschusslochs ist begrenzt und nach dem Verschwinden wird dieses Objekt zerstört. Der Unterschied besteht darin, dass die Koordinate (0, 0) auf die Mitte des Objekts verschoben wird, sodass die Mitte des Objekts genau mit der Mitte des Klickpunkts zusammenfällt. Der Unterschied besteht auch darin, dass das Objekt über ein Array mit Bildern verfügt, aus denen während der Erstellung eine zufällige Auswahl des Aussehens des Einschusslochs durchgeführt wird.
import QtQuick 2.7 import QtQuick.Window 2.2 import "logic.js" as Logic Image { id: root width: 40 height: 40 // Устанавливаем смещение координаты (0, 0) в центр изображения transform: Translate { x: -width / 2 y: -height / 2 } // Задаём список массив возможных изображений выстрела пули property variant bullets: ["graphics/bullet-1.png", "graphics/bullet-2.png", "graphics/bullet-3.png", "graphics/bullet-4.png", "graphics/bullet-5.png", "graphics/bullet-6.png"] // При создании объекта выбираем случайное изображение source: bullets[Logic.getRandomRound(0, 5)] // Таймер, который будет отсчитывать случайную величину от 3500 до 10000 мс // и по окончании запускать исчезновение следа от пули Timer { interval: Logic.getRandomRound(3500, 10000); running: true; repeat: false onTriggered: root.opacity = 0.0 } // Когда изображение станет прозрачным. мы уничтожим сам объект onOpacityChanged: { if (opacity == 0.0) { root.destroy() } } // Задаём поведение анимации свойства прозрачности объекта Behavior on opacity { PropertyAnimation { duration: 100 } } }
Target.qml
Nun, das ganze Salz trifft das Ziel. Wie Sie sehen, gibt es hier fünf Felder, denen wir einen unterschiedlichen Wert von 1 bis 5 Punkten zuweisen werden.
Um den Treffer auf diesen Flächen korrekt zu berechnen, müssen wir den Satz des Pythagoras anwenden. Denken Sie daran? Aus dem Kurs der Schultrigonometrie. Das Quadrat der Hypotenuse ist gleich der Summe der Quadrate der Schenkel.
[latex]a 2 + b 2 = c^2[/latex]
Dieselbe Hypotenuse ist also der Abweichungsbereich des Treffers von der Mitte des Ziels, aber die Tatsache, dass ein bestimmter Bereich getroffen wird, wird durch den Radius des Kreises bestimmt, beginnend mit dem kleinsten Kreis. Diese Prüfungen werden in der in dieser Datei deklarierten Funktion isHit() durchgeführt.
Auch hier ist eine Nuance, dass das Zielbild in einem Quadrat platziert ist, was bedeutet, dass der Klickbereich auch quadratisch ist. Wenn der Klick also nicht in den Bereich des größten Kreises des Ziels fällt, geben wir 0 und zurück Pass den Klick weiter zur Spielarena. Dazu müssen Sie propagateComposedEvents auf true setzen und accept -Mausereignisse deaktivieren, dann wird es zu den zugrunde liegenden Objekten in der Z-Koordinate gehen.
Vergessen Sie auch nicht, die Punktzahl des Spiels um eins zu verringern, wenn das Ziel von selbst ohne Einfluss des Spielers verschwunden ist. Dies erfolgt über ein gemeinsam genutztes Objekt aus dem logischen Kern des Spiels, das den Zustand der Spielarena speichert. Das heißt, durch Logic.gameState.scores.
import QtQuick 2.7 import "logic.js" as Logic Image { id: root ... // Когда изображение станет прозрачным. мы уничтожим сам объект onOpacityChanged: { if (opacity == 0.0) { Logic.gameState.scores-- Logic.destroyTarget(row, col) root.destroy() } } MouseArea { id: mouseArea anchors.fill: parent // Данное свойство определяет, будут ли передаваться события клика // в ниже лежащие элементы, то есть те, которые по координате z // находятся ниже мишени propagateComposedEvents: true onClicked: { var scores = isHit(root.width/2, root.height/2, mouse.x, mouse.y); if (scores != 0) { // Если количество очков отлично от нуля, то фиксируем попадание // Увеличиваем счёт и уничтожаем мишень Logic.gameState.scores += scores; Logic.destroyTarget(row, col); root.destroy(); } else { // В противном случае передаём событие клика в ниже лежащие элементы // по координате z mouse.accepted = false; } } } ... // Проверка попадания по мишени. // Проверяем длину линии от центра до места попадания по мишени // В зависимости от длины этой линии относительно радиуса 5-ти окружностей, из которых состоит мишень // определяем сколько очков получаем за попадание // a, b - координаты центра мишени // x, y - координаты точки попадания function isHit(a, b, x, y) { var length = Math.sqrt(Math.pow(Math.abs(a - x), 2) + Math.pow(Math.abs(b - y), 2)); if (length <= 5.6) { return 5; } else if (length <= 11.2) { return 4; } else if (length <= 16.8) { return 3; } else if (length <= 22.4) { return 2; } else if (length <= 28) { return 1; } else { // В данном случае мы попали в зону MouseArea, // которая является прямоугольником, но промахнулись // по самой мишени, которая является кругом return 0; } } }
Insgesamt
Jetzt haben wir ein Konto und das Aussehen der Anwendung ist wie folgt.
Quelle herunterladen von QML-Spielbeispiel von GitHub