Evgenii Legotckoi
Evgenii LegotckoiҚаз. 5, 2015, 10:58 Т.Ж.

GameDev on Qt - Сабақ 3. Қарсыластардың жойылуы

Алдыңғы екі мақалада біз кейіпкерге курсордың қозғалысын және [нысана бағытында атуды] үйреткен болатынбыз (https://evileg.com /kz/post/ 104/) , ойынға нысандарды қосып, оларды жоюды бастау уақыты келді. Нысаналардың өмірі таусылғанда нысаналар жойылады. Бұл жағдайда нысаналардың әрқайсысы соққы нүктелерінің кездейсоқ санына ие болады және әрбір оқ кездейсоқ мөлшерде зиян келтіреді. Сондай-ақ, әрбір нысанаға зиян келтірілген кезде азаятын өмір жолағы болады.

Қайта шақыру функциясына негізделген жою

Бұл алгоритмді жүзеге асыру үшін біз Target мақсатты класын жасаймыз, сонымен қатар Bullet ішіне CallBack функциясын шақыру мүмкіндігін қосамыз. қосымшаның негізгі терезесінің сыныбында жүзеге асырылатын және нысанаға зиян келтіретін сынып.


мақсатты.сағ

Тақырып файлында мақсатқа зақым келтіретін функцияны жариялау керек. Біз сондай-ақ мақсаттардың денсаулығына жауап беретін екі айнымалыны жариялаймыз. Бірінші айнымалы сіздің ағымдағы денсаулығыңыз болады, ал екінші айнымалы сіздің максималды денсаулығыңыз болады. Денсаулық біткенде, нысана жойылады.

#ifndef TARGET\_H
#define TARGET\_H

#include <QObject>
#include <QGraphicsItem>
#include <QPainter>

class Target : public QObject, public QGraphicsItem
{
    Q\_OBJECT
public:
    explicit Target(QObject *parent = 0);
    ~Target();
    /* Функция по нанесению урона,
     * величина урона передаётся в качестве аргумента функции
     * */
    void hit(int damage);

signals:

public slots:

protected:
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    int health;         // Текущий запас здоровья мишени
    int maxHealth;      // Максимальный запас здоровья мишени
};

#endif // TARGET\_H

target.cpp

Класс конструкторында денсаулық параметрлері орнатылады. Зақым келтіру функциясында денсаулықтың осы функцияға берілген сомаға төмендеуі байқалады. Ал денсаулық нөлге және одан төмен түсе салысымен нысана жойылады.

#include "target.h"

/* Функция для получения рандомного числа
 * в диапазоне от минимального до максимального
 * */
static int randomBetween(int low, int high)
{
    return (qrand() % ((high + 1) - low) + low);
}

Target::Target(QObject *parent) :
    QObject(parent), QGraphicsItem()
{
    health = randomBetween(1,15);   // Задаём случайное значение здоровья
    maxHealth = health;             // Устанавливаем максимальное здоровье равным текущему
}

Target::~Target()
{

}

QRectF Target::boundingRect() const
{
    return QRectF(-20,-20,40,40);   // Ограничиваем область, в которой лежит цель
}

void Target::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    /* Отрисовываем зеленый квадрат
     * */
    painter->setPen(Qt::black);
    painter->setBrush(Qt::green);
    painter->drawRect(-20,-10,40,30);

    /* Отрисовываем полоску жизни
     * соизмеримо текущему здоровью
     * относительно максимального здоровья
     * */
    painter->setPen(Qt::NoPen);
    painter->setBrush(Qt::red);
    painter->drawRect(-20,-20, (int) 40*health/maxHealth,3);

    Q\_UNUSED(option);
    Q\_UNUSED(widget);
}

void Target::hit(int damage)
{
    health -= damage;   // Уменьшаем здоровье мишени
    this->update(QRectF(-20,-20,40,40));    // Перерисовываем мишень
    // Если здоровье закончилось, то инициируем смерть мишени
    if(health <= 0) this->deleteLater();
}

bullet.h

Соңғы сабақтағы таңбалауыш сыныбында CallBack функциясының қолтаңбасының мәлімдемелерін, сондай-ақ Callback функциясын орнату функциясын қосу керек.

public:
    // Установка CallBack функции
    void setCallbackFunc(void (*func) (QGraphicsItem * item));

private:
    // Объявляем сигнатуру CallBack функции
    void (*callbackFunc)(QGraphicsItem * item);

bullet.cpp

Сондай-ақ, оқ тиетін барлық нысандарды іздейтін slotTimerBullet функциясын өзгерту қажет. Егер оқ нысанға тисе, онда біз оқты жойып, Кері шақыру функциясын шақырамыз, ол оқ нысанаға тиген жағдайда Мақсаттарды зақымдайды.

Біз сондай-ақ setCallbackFunc функциясын іске асырамыз, ол функция көрсеткішін CallBack функциясына орнатады.

void Bullet::slotTimerBullet()
{
    setPos(mapToParent(0, -10));

    /* Производим проверку на то, наткнулась ли пуля на какой-нибудь
     * элемент на графической сцене.
     * Для этого определяем небольшую область перед пулей,
     * в которой будем искать элементы
     * */
    QList<QGraphicsItem *> foundItems = scene()->items(QPolygonF()
                                                           << mapToScene(0, 0)
                                                           << mapToScene(-1, -1)
                                                           << mapToScene(1, -1));
    /* После чего проверяем все элементы.
     * Одними из них будут сама Пуля и Герой - с ними ничего не делаем.
     * А с остальными вызываем CallBack функцию
     * */
    foreach (QGraphicsItem *item, foundItems) {
        if (item == this || item == hero)
            continue;
        callbackFunc(item);     // Вызываем CallBack функцию
        this->deleteLater();    // Уничтожаем пулю
    }

    /* Проверка выхода за границы поля
     * Если пуля вылетает за заданные границы, то пулю необходимо уничтожить
     * */
    if(this->x() < 0){
        this->deleteLater();
    }
    if(this->x() > 500){
        this->deleteLater();
    }

    if(this->y() < 0){
        this->deleteLater();
    }
    if(this->y() > 500){
        this->deleteLater();
    }
}

void Bullet::setCallbackFunc(void (*func)(QGraphicsItem *))
{
    callbackFunc = func;
}

виджет.h

Негізгі терезе сыныбының тақырып файлында мақсаттарды құруға арналған таймер туралы мәлімдемені, сондай-ақ осы таймерді өңдеуге арналған ұяшықты қосу керек, онда мақсаттар жасалады. Сондай-ақ біз оқ тигендерді тексеретін статикалық нысандар тізімін жариялаймыз. Ал соққыны тексеру slotHitTarget функциясының CallBack ішінде орындалады. Аргумент ретінде, оқ тиген графикалық нысан аргумент ретінде беріледі.

private:
    QTimer *timerTarget;        // Таймер для создания мишеней
    static QList<QGraphicsItem *> targets;  // Список мишеней

    static void slotHitTarget(QGraphicsItem *item); // CallBack Функция

private slots:
    void slotCreateTarget(); // Слот для создания мишеней

widget.cpp

#include "widget.h"
#include "ui\_widget.h"

/* Функция для получения рандомного числа
 * в диапазоне от минимального до максимального
 * */
static int randomBetween(int low, int high)
{
    return (qrand() % ((high + 1) - low) + low);
}

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    /* Программный код из предыдущих статей
     * */

    // Инициализируем таймер для создания мишеней
    timerTarget = new QTimer();
    connect(timerTarget, &QTimer::timeout, this, &Widget::slotCreateTarget);
    timerTarget->start(1500);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::slotBullet(QPointF start, QPointF end)
{
    /* Программный код из предыдущих уроков
     * */
}

void Widget::slotCreateTarget()
{
    Target *target = new Target();  // Создаём цель
    scene->addItem(target);         // Помещаем цель в сцену со случайной позицией
    target->setPos(qrand() % ((500 - 40 + 1) - 40) + 40,
                  qrand() % ((500 - 40 + 1) - 40) + 40);
    target->setZValue(-1);          // Помещаем цель ниже Героя
    targets.append(target);         // Добавляем цель в список
}

void Widget::slotHitTarget(QGraphicsItem *item)
{
    /* Получив сигнал от Пули
     * Перебираем весь список целей и наносим ему случайный урон
     * */
    foreach (QGraphicsItem *targ, targets) {
        if(targ == item){
            // Кастуем объект из списка в класс Target
            Target *t = qgraphicsitem\_cast <Target *> (targ);
            t->hit(randomBetween(1,3)); // Наносим урон
        }
    }

}

QList<QGraphicsItem *> Widget::targets; // реализация списка

Барлығы

Нәтижесінде, денсаулығының кездейсоқ өлшемі бар нысаналар ойын алаңына кездейсоқ орналастырылады және басты кейіпкердің атқан оқтары оларды бірте-бірте жойып жібереді. Бейне оқулық қолданбаның жұмысын көрсетеді, сонымен қатар бағдарлама кодына қосымша түсініктемелер береді.

Бейне оқулық

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

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

A
  • Қаң. 5, 2017, 3:58 Т.Қ.

Почему то у меня, на строке вызова callback функции, вылетает программа. ((( п.с. Qt 5.7 MSVC 64

A
  • Қаң. 5, 2017, 4:04 Т.Қ.

e:\work\qt_work\gamedev\les_2\mygame2\bullet.cpp:85: ошибка: Exception at 0x7ff6d35d80b3, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance) e:\work\qt_work\gamedev\les_2\mygame2\bullet.cpp:85: ошибка: Exception at 0x7ff6d35d80b3, code: 0xc0000005: read access violation at: 0x0, flags=0x0 Вот такой exeption вылетает при нажатии мышки (то есть при стрельбе)

A
  • Қаң. 5, 2017, 4:22 Т.Қ.

Нашел в чем проблема. Вообще в этих уроках, лучше выкладывать весь код каждого файла, а не только ту часть, которая отличается от предыдущего урока. В определении отличий кода между уроками, Вы делаете ошибки)))) Вот и приходится самому думать, чего еще не хватает в коде=)

A
  • Қаң. 5, 2017, 4:25 Т.Қ.

И так, главный вопрос по этому уроку у меня такой: зачем мы используем callback-функцию, вместо слота+сигнала?

Evgenii Legotckoi
  • Қаң. 5, 2017, 10:44 Т.Қ.

Наверное, это прозвучит странно, но просто так. Чтобы сделать через callback-функцию . Чтобы показать один из возможных вариантов работы в Qt/C++. Случается же так, что те, кто изучает Qt и даже работают с ним некоторое время, не имеют представления о callback-функциях.

S
  • Шілде 8, 2017, 3:14 Т.Қ.
  1. /* После чего проверяем все элементы.
  2. * Одними из них будут сама Пуля и Герой - с ними ничего не делаем.
  3. * А с остальными вызываем CallBack функцию
  4. * */
  5. foreach (QGraphicsItem *item, foundItems) {
  6. if (item == this || item == hero)
  7. continue;
  8. callbackFunc(item); // Вызываем CallBack функцию
  9. this->deleteLater(); // Уничтожаем пулю
  10. }
Проработав Ваш код появился вопрос:  кто такой - hero - в данном исполнителе. Не подключали вроде в предыдущих уроках класс треугольника...решил вопрос с помощью RTTI.
S
  • Шілде 8, 2017, 3:17 Т.Қ.

И еще для чего нужна конструкция: foreach если есть эквивалент for( : )

S
  • Шілде 8, 2017, 3:29 Т.Қ.

И к верхнему посту AndreyHudz не надо весь код выкладывать, а лучше сделать преднамеренные ошибки.

Evgenii Legotckoi
  • Шілде 8, 2017, 4:04 Т.Қ.

да, foreach - это Qt-шный макрос, который эквивалентен for, который появился позже чем foreach.
Я длительное время работал с foreach, пока не решил заняться плотнее новыми стандартами C++ :-)

Evgenii Legotckoi
  • Шілде 8, 2017, 4:07 Т.Қ.

Поэтому в пятом уроке есть исходники всего проекта )))).

Вообще, все эти материалы были не предыдущей версии сайта, которая на WordPress. Во время переноса мог что-то потерять.
Д
  • Қаз. 25, 2018, 10:10 Т.Ж.

Не подскажите в чем проблема. При нажатии аварийно выходит из программы. Не могу додуматься.

Evgenii Legotckoi
  • Қаз. 25, 2018, 5:17 Т.Қ.

Скачайте просто из пятого урока полностью готовый пример.

VB
  • Маусым 25, 2020, 12:35 Т.Қ.

А откуда взялся hero? Никак не могу понят секрет его происхождения...

Evgenii Legotckoi
  • Маусым 25, 2020, 2:36 Т.Қ.

Сам уже не помню. 5 лет назад говнокодил это )) В 5-й части есть полный код, думаю, что там найдёте ))

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
m
  • molni99
  • Қаз. 26, 2024, 11:37 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
m
  • molni99
  • Қаз. 26, 2024, 11:29 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

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

C++ - Тест 003. Условия и циклы

  • Нәтиже:42ұпай,
  • Бағалау ұпайлары-8
Соңғы пікірлер
i
innorwallҚар. 10, 2024, 3:31 Т.Қ.
QMYSQL драйверін құру (MariaDB) Windows 10 x64 QT 5.13.0 Mingw73_64 amazon priligy Conclusion This is the first study of the adverse effects of quetiapine ingestion by children under 7 years of age
i
innorwallҚар. 10, 2024, 10:14 Т.Ж.
ТОБЖ – Сабақ 002. Оптикалық талшық және оның түрлері can you buy priligy Uric acid reduction rectifies prehypertension in obese adolescents
i
innorwallҚар. 10, 2024, 7:59 Т.Ж.
Audiere кітапханасымен mp3 файлдарын ашу Cook meat all the way through priligy otc Note stages 2 3 AKI here exclude patients on dialysis, which are shown in a separate bar graph
i
innorwallҚар. 9, 2024, 11:34 Т.Қ.
Qt/C++ - 017-сабақ. QGraphicsScene немесе Qt тілінде графикамен жұмыс істеу жолы Sort of the world congress on only the fluid seen attached to conceive where to buy priligy in malaysia Depressive symptoms have been associated with digoxin in small trials and case …
Енді форумда талқылаңыз
i
innorwallҚар. 10, 2024, 7:22 Т.Қ.
добавить qlineseries в функции The information provided in Dosage Posology and method of administration of Tamoxifen Actavis is based on data of another medicine with exactly the same composition as the Tamoxifen Actavis …
9
9AnonimҚаз. 25, 2024, 7:10 Т.Қ.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
F
FynjyШілде 22, 2024, 2:15 Т.Қ.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

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