Nachdem wir Sprite in der letzten Lektion zum Arbeiten mit Adobe Illustrator gezeichnet haben, ist es an der Zeit, das resultierende Bild beim Arbeiten mit anzuwenden Qt und fügen Sie es mit QPixmap zum Programm hinzu. Außerdem werden wir ein animiertes Sprite erstellen und sehen, wie eine kleine animierte Explosion in der grafischen Szene unserer Anwendung auf Qt auftritt.
Projektstruktur für die Arbeit mit QPixmap und Sprite
Die sprite \ _example-Projektstruktur sieht wie folgt aus:
- Sprite \ _example.pro - Projektprofil;
- widget.h - Header-Datei des Hauptanwendungsfensters;
- widget.cpp - Datei mit Quellcodes des Hauptanwendungsfensters;
- widget.ui - Schnittstellendatei;
- sprite.h - Header-Datei der Klasse, die für unser Sprite bestimmt ist, in der QPixmap angewendet wird;
- sprite.cpp - Quellcodedatei für die Arbeit mit QPixmap;
- sprite.qrc - Ressourcendatei;
- Sprite \ _sheet.png ist unser Sprite, das wir für Animationen verwenden werden.
widget.ui
Diese Datei hat nichts besonderes. Strecken Sie einfach das QGraphicsView-Objekt über das gesamte Fenster, ** in das wir [QGraphicsScene] platzieren (https://evileg.com/ru/post/80/).
widget.h
In dieser Datei deklarieren wir ein Objekt der Grafikszene, in das wir ein Objekt mit einer QPixmap platzieren, in dem sich ein animiertes Sprite befindet. Vergessen Sie nicht, die Header-Datei einzubinden Sprite.h.
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QGraphicsScene> #include <QTimer> #include <QList> #include <QPixmap> #include "sprite.h" namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; QGraphicsScene *scene; // Объявляем графическую сцену }; #endif // WIDGET_H
widget.cpp
In dieser Datei initialisieren wir die Grafikszene und platzieren sie in graphicView, und erstellen außerdem ein Sprite-Objekt und platzieren es in der Szene.
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); scene = new QGraphicsScene(); // Инициализируем графическую сцену ui->graphicsView->setScene(scene); // Устанавливаем графическую сцену в graphicsView scene->addItem(new Sprite()); // Помещаем на сцену новый объект спрайта } Widget::~Widget() { delete ui; }
sprite.h
Lassen Sie uns nun darüber sprechen, wie das animierte Sprite implementiert wird. Dazu benötigen wir ein vorgefertigtes Sprite bzw. ein Sprite-Sheet, das aus 15 in einer Zeile angeordneten Frames besteht.
Technisch gesehen ist dieses Spritesheet auf ein QPixmap Objekt gesetzt, in dem es in regelmäßigen Abständen von links nach rechts gescrollt wird. Dazu erben wir eine neue Klasse von QGraphicsItem und QObject, um Signale und Slots . Und in der paint -Methode legen wir das Rendering eines Abschnitts des Bildes sprite_sheet fest, der in der Ressourcendatei angegeben ist. Der Timer steuert den Framewechsel über den nextFrame () Slot. Auf das Signal vom timer ändern wir die Rendering-Koordinate der Sprite-Sektion und zeichne das Grafikobjekt mit einem neuen Rahmen neu ...
#ifndef SPRITE_H #define SPRITE_H #include <QObject> #include <QGraphicsItem> #include <QTimer> #include <QPixmap> #include <QPainter> class Sprite : public QObject, public QGraphicsItem { Q_OBJECT public: explicit Sprite(QObject *parent = 0); signals: public slots: private slots: void nextFrame(); // Слот для пролистывания изображения в QPixmap private: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const; private: QTimer *timer; // Таймер для пролистывания изображения в QPixmap QPixmap *spriteImage; // В данный объект QPixamp будет помещён спрайт int currentFrame; // Координата X, с которой начинает очередной кадр спрайта }; #endif // SPRITE_H
sprite.cpp
Im Klassenkonstruktor initialisieren wir den Timer, und in der Methode paint zeichnen wir den benötigten Rahmen aus dem Sprite. Das Wechseln von Frames erfolgt über den Slot nextFrame ().
#include "sprite.h" Sprite::Sprite(QObject *parent) : QObject(parent), QGraphicsItem() { currentFrame = 0; // Устанавливаем координату текущего кадра спрайта spriteImage = new QPixmap(":sprite_sheet.png"); // Загружаем изображение спрайта в QPixmap timer = new QTimer(); // Создаём таймер для анимации спрайта // Подключаем сигнал от таймера к слоту перелистывания кадров спрайта connect(timer, &QTimer::timeout, this, &Sprite::nextFrame); timer->start(25); // Запускаем спрайт на генерацию сигнала с периодичность 25 мс } QRectF Sprite::boundingRect() const { return QRectF(-10,-10,20,20); } void Sprite::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { /* В отрисовщике графического объекта отрисовываем спрайт * Разберём все параметры данной функции * Первых два аргумента - это координат X и Y куда помещается QPixmap * Третий аргумент - это указатель на QPixmap * 4 и 5 аргументы - Координаты в В изображении QPixmap, откуда будет отображаться изображение * Задавая координату X с помощью перемнной currentFrame мы будем как бы передвигать камеру * по спрайту * и последние два аргумента - это ширина и высота отображаем части изображение, то есть кадра * */ painter->drawPixmap(-10,-10, *spriteImage, currentFrame, 0, 20,20); Q_UNUSED(option); Q_UNUSED(widget); } void Sprite::nextFrame() { /* По сигналу от таймера передвигаем на 20 пикселей точку отрисовки * Если currentFrame = 300 то обнуляем его, поскольку размер sprite sheet 300 пикселей на 20 * */ currentFrame += 20; if (currentFrame >= 300 ) currentFrame = 0; this->update(-10,-10,20,20); // и перерисовываем графический объект с новым кадром спрайта }
Ergebnis
Als Ergebnis haben Sie eine Anwendung mit einer blinkenden Explosion von 20 x 20 Pixeln in der Mitte des Fensters. Eine Demonstration der Anwendung können Sie im Video-Tutorial sehen.
Подскажите пожалуйста ( я новичок совсем)
Можно ли организовать спрайт без этого окошка (как в fl studio fruity dance)?
Не знаю, какой-там конкретно эффект и если честно не хочется fl studio ради того, чтобы посмотреть устанавливать, но из того, что увидел в интернете.
Предполагаю, что то, что вы хотите сделать, в данном случае нужно реализовывать точно также с окном, но с одним существенным отличием. Нужно полностью отключить обрамление окна, а в нём отрисовывать спрайт в виджете с прозрачным фоном.
Вот в этой статье было что-то похожее. Там я отключал обрамление окна и кастомизировал виджеты.
Обратите внимание вот на эти строчки
Спасибо большое!
Очень помогли!
А возможно всё кроме спрайта сделать прозрачным?
"всё" - это что?
по факту я вам уже ответил и на этот вопрос.
Извините, но дилемма в том что - Спрайт должен быть сам по себе без заднего окна и виджета. ( вот то что я хочу сделать-
Прошу прощения за надоедливые и банальные вопросы
Да не в этом дело.
По сути, там всё тоже самое, только отображайте спрайт в отдельном диалоговом окне, у которого будет полностью отключено обрамление и т.д. Просто используйте QDialog, чтобы спрайт отдельно крутился.
С Новым годом!
Всё оказалось проще:
MAIN.cpp
QML
У меня всего 2 вопроса:
\\
Как В файле QML менять значение с помощью переменной из Main frameX: 0 не через класс? ( желательно считывание из txt файла)
\\\
Как сделать так чтобы курсор мышки не реагировал на прозрачное диалоговое окно и я мог спокойно нажимать на ярлыки позади него
Ну вы здесь тоже самое сделали, что я вам и советовал... только ещё QML за уши притянули.
frameX - только через класс устанавливать. В QML все объекты наследованы от QObject и там работа с классами идёт. Максимум использовать JavaScript встроенный в QML, но опять же без C++ и классов ничего вы не сделаете.
Это было бы проще реализовать через классические виджеты, также нужно лезть в API операционной системы. Я такое не делал, небоходимости не было. Могу сказать только, что нужно искать информацию по эмулированию кликов, чтобы перекинуть клик за окно приложения. В общем в три строки эо не делается.
Планомерно изучайте Qt, с ростом опыта разберётесь, как это сделать, но я могу вам только общее направление по этой задаче подсказать и кое-какие примеры, но вопросы у вас должны быть более гранулированными, а не так, "как написать программу, которая сделает то, что вы хотите". Серьёзно, для того, что вам нужно, требуется изучить больше, чем вот эта одна строка из вашего кода
значительно больше
А как вы сделали папку ресурсы ?