Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Impuls от Октябрь 19, 2010, 18:29



Название: PacMan
Отправлено: Impuls от Октябрь 19, 2010, 18:29
Доброго времени суток уважаемые эксперты. Хочу написать клон всеми любимого PacMan-а. Кусок написал колобок может передвигаться по полю и собирать фишки. А дальше застрял. В связи с этим несколько вопросов:
1. Рисую все это дело на QGraphicsScene. Мне этого хватит, или стоит юзать что-то другое?
2. Хочу сделать PacMan-а и привидений как отдельные потоки. Как мне сделать так, чтобы этот поток мог себя отрисовывать на сцене и мог получить доступ к сцене (для обнаружения столкновений) и перемещения себя по сцене (не совсем понятно, но по другому не могу объяснить)
3. Как выводить спрайт (для отображения анимации)

Заранее спасибо


Название: Re: PacMan
Отправлено: ufna от Октябрь 19, 2010, 18:42
Начну с конца

3. по событию таймера - меняй картинки.
2. ой-ой-ой, зачем так извращаться?!
1. Я бы советовал забросить это куда подальше и поработать с QPainter. Вся игра легко делается в одном потоке, с QPainter, причем будет шустро бегать с любой нужной тебе графикой. QGV для таких вещей не шибко приспособлен и более тормозной, хотя можно и на нем, и его хватит с огроменным запасом.


Название: Re: PacMan
Отправлено: Impuls от Октябрь 19, 2010, 19:05
Начну с конца

3. по событию таймера - меняй картинки.
2. ой-ой-ой, зачем так извращаться?!
1. Я бы советовал забросить это куда подальше и поработать с QPainter. Вся игра легко делается в одном потоке, с QPainter, причем будет шустро бегать с любой нужной тебе графикой. QGV для таких вещей не шибко приспособлен и более тормозной, хотя можно и на нем, и его хватит с огроменным запасом.
Значит со спрайтами разобрался. Буду пробовать менять картинки по таймеру.
Насчет QPainter - сейчас начну курить мануалы.

Насчет извращений. Дело в том, что это курсовой проект, и тут не столько важна сама игра, как ее ИИ. ИИ привидений будет реализован при помощи нейронных сетей: 4 привидения = 4 нейроетки. И в связи с этим хотелось бы каким-нибудь хитрым способом реализовать 4 класса привидений (на мой взгляд это потоки, хотя приму и другие предложения)


Название: Re: PacMan
Отправлено: ufna от Октябрь 20, 2010, 02:19
Если работа с нейронными сетями, то можно вынести и в отдельные потоки каждый. QGV тут отлично подойдет, т.к. суть становится больше в AI, чем в игрушке и т.п.

Отрисовывать себя на поле они не смогут, да и это было бы неверно с точки зрения проектирования, но - связывай потоки и сцену посредством сигналов и слотов. За столкновения пусть отвечает сцена - когда оно произошло, кидает тем, кто столкнулся, об этом сигнал. И когда меняется состояние АИ, то он отсылает об этом сигнал в сцену (точнее, твой класс, который управляет игрой) - а там уже это обрабатывается.


Название: Re: PacMan
Отправлено: Impuls от Октябрь 20, 2010, 15:38
Если работа с нейронными сетями, то можно вынести и в отдельные потоки каждый. QGV тут отлично подойдет, т.к. суть становится больше в AI, чем в игрушке и т.п.

Отрисовывать себя на поле они не смогут, да и это было бы неверно с точки зрения проектирования, но - связывай потоки и сцену посредством сигналов и слотов. За столкновения пусть отвечает сцена - когда оно произошло, кидает тем, кто столкнулся, об этом сигнал. И когда меняется состояние АИ, то он отсылает об этом сигнал в сцену (точнее, твой класс, который управляет игрой) - а там уже это обрабатывается.
Всвязи с этим возник еще один вопрос: не могу отнаследовать класс QGraphicsPixmapItem. Делаю так:
Код:
#include <QGraphicsPixmapItem>

class QPacMan : public QGraphicsPixmapItem
{
    Q_OBJECT
public:
    explicit QPacMan(QGraphicsItem * parent = 0);

signals:

public slots:

private:

};
....
#include "QPacMan.h"
#include <QGraphicsPixmapItem>

QPacMan::QPacMan(QGraphicsItem * parent):QGraphicsPixmapItem(parent)
{
    //
}
....
#include <QApplication>
#include <QtGui>
#include <QPacMan.h>

int main(int argc, char *argv[])
{
        QApplication app(argc, argv);
        QGraphicsView *view = new QGraphicsView;
        QGraphicsScene *scene = new QGraphicsScene;
        QPacMan *pacman = new QPacMan;
        view->setScene(scene);
        scene->addItem(pacman);
        scene->addPixmap(QPixmap("pacman.jpg"));
        view->show();
        return app.exec();
}
На что компилятор ругается диким матом.
Код:
moc_QPacMan.cpp:41: error: ‘staticMetaObject’ is not a member of ‘QGraphicsPixmapItem’
/usr/include/qt4/QtCore/qobject.h: In member function ‘virtual const QMetaObject* QPacMan::metaObject() const’:
/usr/include/qt4/QtCore/qobject.h:296: error: ‘QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> > QObject::d_ptr’ is protected
moc_QPacMan.cpp:51: error: within this context
/usr/include/qt4/QtCore/qobject.h:296: error: object missing in reference to ‘QObject::d_ptr’
moc_QPacMan.cpp:51: error: from this location
/usr/include/qt4/QtCore/qobject.h:296: error: ‘QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> > QObject::d_ptr’ is protected
moc_QPacMan.cpp:51: error: within this context
/usr/include/qt4/QtCore/qobject.h:296: error: object missing in reference to ‘QObject::d_ptr’
moc_QPacMan.cpp:51: error: from this location
moc_QPacMan.cpp: In member function ‘virtual void* QPacMan::qt_metacast(const char*)’:
moc_QPacMan.cpp:59: error: ‘qt_metacast’ is not a member of ‘QGraphicsPixmapItem’
moc_QPacMan.cpp: In member function ‘virtual int QPacMan::qt_metacall(QMetaObject::Call, int, void**)’:
moc_QPacMan.cpp:64: error: ‘qt_metacall’ is not a member of ‘QGraphicsPixmapItem’


Название: Re: PacMan
Отправлено: ufna от Октябрь 20, 2010, 15:50
Все верно - откуда Q_OBJECT, если QGrapicsPixmapItem - не является наследником QObject?


Название: Re: PacMan
Отправлено: Impuls от Октябрь 23, 2010, 00:12
Спасибо за помощь. Игра хоть и со скрипом, но идет. Если будут еще вопросы, буду обращаться)
З.Ы. Что-то я не могу найти кнопочку повышения репутации(((( Желаю поднять Вам рейтинг ;)


Название: Re: PacMan
Отправлено: ufna от Октябрь 23, 2010, 18:31
Спасибо за помощь. Игра хоть и со скрипом, но идет. Если будут еще вопросы, буду обращаться)
З.Ы. Что-то я не могу найти кнопочку повышения репутации(((( Желаю поднять Вам рейтинг ;)

Да тут такой кнопочки нет, да и ну ее к черту ;)

если что, пишите :)


Название: Re: PacMan
Отправлено: Denjs от Октябрь 23, 2010, 18:48
Я в свое время рисовал нечто отдаленно похожее на пространство в котором объекты бегают друг за другом)))
у меня был отдельный класс - сцена, или мир, в который  объекты смотрели и решали что им делать.

Мир обновлялся циклами, и на каждом цикле объекты смотрели в мир, на ячейки вокруг, и делали свой ход - решали что будут делать. Потом был обсчет движений, и применение желаемых действий "в реальность". была проблема со столкновениями - когда на одну ячейку одновременно пытаются шагнуть 2 объекта - особо я её не решал - при обнаружении столкновений "мир" случайным бразом отказывал лодному из объектов в исполнении шага.

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


Название: Re: PacMan
Отправлено: Denjs от Октябрь 23, 2010, 18:51
Да насчет спрайтов - вопрос - как это делать быстро и красиво.
а то мой реализация была очень уж тормознутой. Покажите кто нибудь пример кода/программы в которой бегает скажем 10 спрайтов, с обработкой прозрачности на фоне, который тоже сгенерирован спрайтами.?


Название: Re: PacMan
Отправлено: ufna от Октябрь 23, 2010, 20:26
Быстро и красиво делается так, как делалось черт знает сколько лет назад и до сих пор :)

А точнее - по сути спрайты - это набор картинок, одна из которых отрисовывается в данный момент времени на основе состояния объекта. Во всех игрушках во время отрисовки происходит определение "какую картинку отрисовывать" - оно и рисуется. К примеру, есть объект персонаж, статус у него - бежит, время бега - 3.257 сек. Происходит отрисовка, подходит момент отрисовки персонажа, на основе того, что бег и т.п. менеджер ресурсов должен выдать нужную картинку. При правильной организации менеджера ресурсов это просто летает.


Название: Re: PacMan
Отправлено: Impuls от Октябрь 24, 2010, 23:32
Да насчет спрайтов - вопрос - как это делать быстро и красиво.
а то мой реализация была очень уж тормознутой. Покажите кто нибудь пример кода/программы в которой бегает скажем 10 спрайтов, с обработкой прозрачности на фоне, который тоже сгенерирован спрайтами.?
Я отнаследовал класс QGraphicsPixmapItem. В конструкторе подгрузил в QVector разбитый на кадры спрайт. А дальше все просто: выводил поочередно кадры по срабатыванию таймера. Единственное в чем у меня была загвоздка, так это в том, что таймер пришлось делать в отдельном потоке. Если интересен мой код - могу выложить исходники.


Название: Re: PacMan
Отправлено: Denjs от Октябрь 25, 2010, 17:06
А точнее - по сути спрайты - это набор картинок, одна из которых отрисовывается в данный момент времени на основе состояния объекта. Во всех игрушках во время отрисовки происходит определение "какую картинку отрисовывать" - оно и рисуется. К примеру, есть объект персонаж, статус у него - бежит, время бега - 3.257 сек. Происходит отрисовка, подходит момент отрисовки персонажа, на основе того, что бег и т.п. менеджер ресурсов должен выдать нужную картинку. При правильной организации менеджера ресурсов это просто летает.
Это классно) меня интересует именно код! код в QT c QT-шными классами)))
потому что скажем рисовать сцену на QPixMap, а потом выводить её на форму например медленно получается - не находите? вопрос в том как достигать заданного результата быстро)


Название: Re: PacMan
Отправлено: ufna от Октябрь 25, 2010, 22:47
Это классно) меня интересует именно код! код в QT c QT-шными классами)))
потому что скажем рисовать сцену на QPixMap, а потом выводить её на форму например медленно получается - не находите? вопрос в том как достигать заданного результата быстро)

Без обид, советую прочесть о технике двойной буферизации как минимум. А потом - посмотреть материалы по геймдеву по 2д игрушкам по оптимизации. А затем - попробовать реализовать это на практике, и когда получится/не получится - легко подскажу советом.

У меня как-то куча векторной графике в духе - http://ufna.ru/wp-content/uploads/2010/08/uNavi_scr_june_037.png (июньский скрин) - работает отлично на медленных навигаторах под WinCE, причем с плавной анимацией и т.п. Все изначально Qt'шные классы и два месяца четкой работы над движком. Да, спрайты здесь тоже есть, хотя в релиз и не попали из-за вопросов занимаемой памяти.


Название: Re: PacMan
Отправлено: Denjs от Октябрь 25, 2010, 23:56
Без обид, советую прочесть о технике двойной буферизации как минимум. А потом - посмотреть материалы по геймдеву по 2д игрушкам по оптимизации. А затем - попробовать реализовать это на практике, и когда получится/не получится - легко подскажу советом.
нене) Никаких обид) просто нужен пример и ряд готовых решений-примеров что бы от него можно было "на примерах" плясать в решении простых задач.
Есть пример какого Qt-шного гейм-примера что бы начать разбираться?

В конце концов мне не нужен совсем-совсем-серьезный гейм-движок, но что-то простое что бы "просто работало"))))


Название: Re: PacMan
Отправлено: Impuls от Октябрь 26, 2010, 17:53
нене) Никаких обид) просто нужен пример и ряд готовых решений-примеров что бы от него можно было "на примерах" плясать в решении простых задач.
Есть пример какого Qt-шного гейм-примера что бы начать разбираться?
В конце концов мне не нужен совсем-совсем-серьезный гейм-движок, но что-то простое что бы "просто работало"))))
Выкладываю код моего зверя. На вершину оптимизации не тянет, сделано по лузерски, но работает как тру решение (в плане того, что ничего не глючит))). Пробовал рисовать по 50 колобков на сцене, работало без всяких тормозов и глюков. Заодно может и посоветуете что-нибудь дельное)))


Название: Re: PacMan
Отправлено: Denjs от Октябрь 27, 2010, 00:43
спасибо большое. Буду разбираться на досуге)


Название: Re: PacMan
Отправлено: ufna от Октябрь 27, 2010, 11:51
Я счас в свободное время работаю над движковой структурой для 2д проектов на Qt, потом выложу. Пример выше со скрином мне не выложить по понятным причинам коммерции :)


Название: Re: PacMan
Отправлено: ufna от Октябрь 27, 2010, 12:04
Выкладываю код моего зверя. На вершину оптимизации не тянет, сделано по лузерски, но работает как тру решение (в плане того, что ничего не глючит))). Пробовал рисовать по 50 колобков на сцене, работало без всяких тормозов и глюков. Заодно может и посоветуете что-нибудь дельное)))

у тебя есть слайд апдейтер и сам пакман, причем они завязаны друг на друга - как следствие, это на данный момент просто лишнее разделение на два класса

"поворот" лучше реализовывать в спрайтах, а не поворотом айтема :)

решение работает, но очень не универсально. Хотя для целей начала сабжа думаю подойдет, но главная проблема что тебе встретится - для каждого индивидуального объекта, у которого чуть больше стейтов или другое поведение картинки - придется писать еще два доп. класса, или один, а апдейтер слайда расширять. Т.е. пока это грубая реализация. Я когда вот эту штуку (http://ufna.ru/wp-content/uploads/2010/04/game_koloboxer.jpg) писал, тоже сделал что все для нее работало, но код совершенно не расширяем оказался в итоге.

попробую на днях описать детальнее как лучше организовать создание спрайтов для Qt "без геммороя"


Название: Re: PacMan
Отправлено: Impuls от Октябрь 27, 2010, 13:08
у тебя есть слайд апдейтер и сам пакман, причем они завязаны друг на друга - как следствие, это на данный момент просто лишнее разделение на два класса

"поворот" лучше реализовывать в спрайтах, а не поворотом айтема :)

решение работает, но очень не универсально. Хотя для целей начала сабжа думаю подойдет, но главная проблема что тебе встретится - для каждого индивидуального объекта, у которого чуть больше стейтов или другое поведение картинки - придется писать еще два доп. класса, или один, а апдейтер слайда расширять. Т.е. пока это грубая реализация. Я когда вот эту штуку (http://ufna.ru/wp-content/uploads/2010/04/game_koloboxer.jpg) писал, тоже сделал что все для нее работало, но код совершенно не расширяем оказался в итоге.

попробую на днях описать детальнее как лучше организовать создание спрайтов для Qt "без геммороя"
Дело в том, что мне нужно было сделать таймер в отдельном потоке (ибо в потоке есть цикл обработки событий). В общем, у меня не получилось сделать все в одном классе(((

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

Кстати, у меня назрел еще один вопрос: как мне сделать сглаживание картинки?


Название: Re: PacMan
Отправлено: ufna от Октябрь 27, 2010, 13:23
поворот в спрайтах - это подсказка насчет необходимости наличия менеджера ресурсов как большой единицы архитектуры :)

т.к. ладно счас у тебя колобок бегает в четырех направлениях. А если ты захочешь менять картинку для движения? К примеру вверх - ты видишь его попу, вниз - перед и т.п. - и в таком случае возможны проблемы с текущей реализацией. Обычно все возможные состояния объектов прорисовываются отдельно.

таймер в отдельный поток то зачем совать? QTimer и так по-моему создает себе нечто подобное.


сглаживание - посмотри флаги для вьюпорта какие есть, смотри setRenderHints(..)


Название: Re: PacMan
Отправлено: Impuls от Октябрь 27, 2010, 14:39
таймер в отдельный поток то зачем совать? QTimer и так по-моему создает себе нечто подобное.
сглаживание - посмотри флаги для вьюпорта какие есть, смотри setRenderHints(..)
Такое я могу сделать:
Код:
timer = new QTimer(this);
timer->start(100);
А такое не могу:
Код:
QPacMan::QPacMan(QGraphicsItem * parent):QGraphicsPixmapItem(parent)
{
  timer = new QTimer(this);
  Start(100);
}
QPacMan::Start(int timeOut)
{
  timer->start(timeOut);
}
Все из за того, что в QGraphicsPixmapItem нет цикла обработки событий.
А сглаживание я могу поставить только для QPainter. Для QPixmap такого метода нету((((


Название: Re: PacMan
Отправлено: ufna от Октябрь 27, 2010, 14:55
QPixmap он себя не рисует, поэтому у него сглаживания и нет - это просто контейнер данных

рисует QPainter, а у тебя в данном случае - QGrapicsView, ему и задаются эти параметры - рисовать со сглаживанием или нет.


делай timer = new QTimer();, а затем в декструкторе delete timer; вручную и все.


Название: Re: PacMan
Отправлено: Impuls от Октябрь 27, 2010, 15:50
QPixmap он себя не рисует, поэтому у него сглаживания и нет - это просто контейнер данных
рисует QPainter, а у тебя в данном случае - QGrapicsView, ему и задаются эти параметры - рисовать со сглаживанием или нет.

делай timer = new QTimer();, а затем в декструкторе delete timer; вручную и все.
Такс... Со сглаживанием разобрался...
А вот с таймером понапряжней будет.
class QPacMan : public QGraphicsPixmapItem - не наследуется от QObject, следовательно я не могу вызвать connect(timer,SIGNAL(timeout()),this,SLOT(UpdateSlide())); Вот такая вот трагедия.
Или я туплю и чего-то не понимаю?
___________________________________________________________________
А все. Это я туплю))) Сделал без отдельного потока


Название: Re: PacMan
Отправлено: ufna от Октябрь 27, 2010, 18:27
как сделал? :) (обычно принято решения в темы показывать, т.к. по поиску люди ищут)


Название: Re: PacMan
Отправлено: GreatSnake от Октябрь 27, 2010, 21:21
Цитировать
QPixmap он себя не рисует, поэтому у него сглаживания и нет - это просто контейнер данных
Зато у него есть такой метод:
Код
C++ (Qt)
QPixmap QPixmap::scaled ( const QSize & size, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation ) const


Название: Re: PacMan
Отправлено: ufna от Октябрь 27, 2010, 21:23
и что? тем не менее он себя не рисует, это лишь выбор алгоритма, которым изменяется размер пиксмапа :))


Название: Re: PacMan
Отправлено: Impuls от Октябрь 28, 2010, 10:43
как сделал? :) (обычно принято решения в темы показывать, т.к. по поиску люди ищут)
Обязательно выложу. Вот подправленные исходники.