Сейчас на форуме: (+5 невидимых) |
eXeL@B —› Дневники и блоги —› ARCHANGEL's blog |
. 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8 . 9 . 10 . >> |
Посл.ответ | Сообщение |
|
Создано: 13 июля 2012 18:28 · Личное сообщение · #1 Добрый день, уважаемые форумчане. Ни для кого не секрет, что решил я с недавних пор пойти учиться программированию. Поэтому стали меня интересовать практические аспекты кодинга, иногда весьма далёкие от вопросов реверсинга. Поэтому чтоб не засорять форум, решил создать этот блог. Стоит сказать, что вопросы, которые планируется тут разбирать, не такие уж и бесполезные. Они часто могут возникать при написании тех же кейгенов или тулз для реверсинга, так что, надеюсь, каждый сможет найти здесь что-нибудь интересное. Как некоторые уже догадались, вопросы Common Controls, простым числам, и сегодняшний вопрос по OpenGL как раз из серии учебных. Теперь о самом вопросе. На днях выполнял задание про отрисовку простых фигур: треугольника, квадрата и т.д. Решено было выполнять рисование средствами OpenGL. Литературы по этому делу много, поэтому я разобрался, что и как. Т.е. в литературе советовали использовать бибилиотеку glut.dll, которая сама не относится к стандартному OpenGL, но её применение, как я понял, упрощает использование OpenGL в своих проектах. Далее я решил создать базовый класс для отрисовки треугольника, а от него создать производные классы для отрисовки других геометрических фигур. Но на практике получилась вот такая сложность. Дело в том, что glut, по сути, инкапсулирует функции Windows и OpenGL, что упрощает операции с ними. Но от базовых вещей же никуда не деться. Т.е. если процедура обработки оконных сообщений (CALLBACK WindowProc) должна присутствовать, то в классе она должна быть статической. Так и здесь: Code:
Но вот проблема - мне нужно передать внутрь Draw несколько параметров. Являясь статическим методом, Draw не имеет указателя this, а значит не видит обычных полей. Статические поля он видит, но при попытке в конструкторе присвоить значения этим полям появляется ошибка линковки. Понятное дело, что по-хорошему, можно обойтись совсем без классов, но это превратит код в кашу - большое количество глобальных переменных, почти одинаковые функции со схожим функционалом принесут путаницу раньше, чем будут отрисованы несколько фигур. Кто посоветует, как быть в такой ситуации и как решить проблему со статическими функциями-членами? ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 13 июля 2012 18:49 · Поправил: neomant · Личное сообщение · #2 На самом деле проблемы никакой нет. Ошибка при линковке может быть потому, что статические члены в классе объявлены, но их экземпляры не созданы. То есть их нужно объявить в .h в теле класса и создать(можно сразу и проинициализировать) в .cpp Для отрисовки фигуры лучше создать базовый класс Shape c виртуальной функцией Draw. В производных классах фигур определять свой метод Draw. Профит - полиморфизм в действии. ----- Следуй за белым кроликом | Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 13 июля 2012 20:18 · Личное сообщение · #3 neomant Да, помогло. Теперь другой бок появился - вот никогда такого не было, а тут вылезло, и как же так получилось? В общем, есть у меня 4 radiobutton, но прикол в том, что можно сделать один из них checked при том, что другой тоже останется checked. Как я так умудрился-то? И как это убрать? ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 13 июля 2012 21:48 · Личное сообщение · #4 |
|
Создано: 13 июля 2012 22:05 · Личное сообщение · #5 Исправил бок с radiobutton'ами. Похоже, что тут важна очерёдность создания. Т.е. если вначале создаётся GROUPBOX, потом RadioButton, потом опять GROUPBOX, и опять RadioButton, то ониотносятся к разным групбоксам, и, став checked, не влияют друг на друга, т.е. uncheck не происходит. Выходом было создание всех GROUPBOX, а потом - всех RadioButton. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 16 июля 2012 22:39 · Личное сообщение · #6 Сейчас стоит задача построения лабиринта в в иде матрицы, в которой элемент равен нулю, если данный участок непроходим, и равен 1 если проходим. Нужно строить лабиринт случайным образом. Т.е. заранее известны только длина и ширина матрицы (всего лабиринта). Лабиринт, конечно, не должен быть слишком простым, т.е. это не должно выглядеть, как прямая линия к выходу, обрамлённая непроходимыми участками, ведь это, всё-таки, лабиринт. Но и не должен быть испещрён ходами, т.е. перемещаться по нему должно быть трудно, выражаясь яснее, человек должен в нём блуждать, и выйти из него должно быть непросто. Теперь, выражаясь языком математики, у нас должен быть связный неориентированный граф, не являющийся деревом. Как в таком случае определить оптимальное число ребёр в графе, чтоб добиться описанного выше эффекта труднопроходимости лабиринта? Ну, или есть какие-то эффективные общеизвестные методы построения лабиринтов? В гугле находил ссылки на алгоритмы, но опасаюсь, что это необоснованный самопал. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 17 июля 2012 01:36 · Личное сообщение · #7 ARCHANGEL Тут приводится алгоритм построения лабиринта на основе эйлеровых графов По поводу сложности решения поиска выхода, то все упирается в размер лабиринта и количество тупиков, в общем бери то что тебе удобнее использовать ибо супер алгоритма нет. | Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 17 июля 2012 20:30 · Личное сообщение · #8 |
|
Создано: 18 июля 2012 14:56 · Личное сообщение · #9 |
|
Создано: 22 июля 2012 14:09 · Личное сообщение · #10 ARCHANGEL, для твоей задачи. Если еще актуально. 1) Есть конкретная реализация на C++: поиск по кратчайшему пути в лабиринте от пункта A в пункт B, сам же лабиринт условно задается в виде матрицы и сгенерирован рандомно, - 2) Классическая книга "Роберт Седжвик. Фундаментальные алгоритмы на C++". Там есть отдельный раздел по теории графов, с примерами на С++, можно найти почти любой алгоритм, и доработать под свои нужды. 3) Хороший учебник "Максим Динман. C++. Освой на примерах". Книга хоть и ориентирована на людей, которые только начинают изучение C++, однако очень интересны и нетривиальны примеры, демонстрируемые читателям: множество алгоритмов шифрования, и почти половина книги - алгоритмы, построенные на графах, с минимально необходимой для понимания теорией. Очень много исходного кода, с большим числом комментариев. Возможно, окажется полезной. ----- Программист SkyNet | Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 24 июля 2012 22:50 · Личное сообщение · #11 FrenFolio Ещё актуально. Правда, в гугле поиском нашлась книга Мозгового "Занимательное программирование", где всё вполне доступно изложено. Конечно, теория не идеальна, например, не рассказывается, почему адаптированный алгоритм Прима для построения минимального остова следует применять для построения лабиринта, и как, с математической точки зрения, так получается, что алгоритм Крускала подходит для этой цели лучше. Поиск пути тут можно выполнять методом волновой трассировки. Седжвика читаю потихоньку, но до графов пока не дошёл. За линк спасибо, кстати, по этому линку лабиринты получаются с коридорами! ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 30 июля 2012 21:57 · Личное сообщение · #12 Сейчас делаю программу "Электронные часы". Суть простая - нужно в стиле электронных часов отрисовать текущее время, при этом обновлять его каждую секунду. Циферки в фотошопе уже сделаны, в общем, и программа вся уже накатана, но есть одна (впрочем, весьма небольшая) проблемка... она НЕ РАБОТАЕТ! Идея состоит в том, чтоб в ответ на сообщение WM_PAINT получать клиентскую область окна и в ней черз BitBlt рисовать времечко. И время действительно рисуется - один раз. Но при WM_INITDIALOG создаётся поток, который шлёт в очередь сообщений заветное WM_PAINT, но картинка почему-то не перерисовывается, несмотря на то, что сообщение доходит до адресата, и, в общем-то, корректно обрабатывается. Что за нах? Или для решения такой задачи действовать надо как-то по-другому? Код в виде проекта студии прилагаю. 7acb_30.07.2012_EXELAB.rU.tgz - Forum WatchShow.rar ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 30 июля 2012 22:29 · Личное сообщение · #13 ARCHANGEL Как то так: Code:
| Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 30 июля 2012 22:51 · Личное сообщение · #14 F_a_u_s_t Блин, а я был так близко. И ведь искал же по MSDN что-то подобное, правда, искал InvalidateRectangle, а полученный результат меня сбил с толку - думал, что не туда куда-то меня повело. В общем, добавил, заработало. Спасибо. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 30 июля 2012 22:55 · Личное сообщение · #15 |
|
Создано: 30 июля 2012 23:08 · Личное сообщение · #16 Для отправки собщения WM_PAINT не нужно заводить поток, достаточно обычного таймера. Чистый WIN32 - это брутально, но можно хотя бы CString или std::string попользовать чтобы не заморачиваться с выделением/возвращением памяти. Класс используется не рационально, постоянно выполняются лишние действия по подгрузке картинок. Не совсем красиво написано условие окончания цикла по выводу времени. ----- Следуй за белым кроликом |
|
Создано: 31 июля 2012 00:04 · Личное сообщение · #17 neomant пишет: Для отправки собщения WM_PAINT не нужно заводить поток, достаточно обычного таймера. Вот с таймером я крутил всякие заманухи, и так, и эдак. Взял SetTimer, добавил обработчик WM_TIMER, но тут или я что-то не понимаю, или делать надо как-то не так, но если я буду внтри обработчика WM_TIMER юзать SendMessageA(...,WM_PAINT,...), то т.к. обработка SendMessageA синхронна, то оно так и будет висеть, ничего не отрисовывая. Хотя в МСДН написано, что напрямую слать окну WM_PAINT нельзя. Значит, видимо, есть способ какой-то. Чистый WIN32 - это брутально, но можно хотя бы CString или std::string попользовать чтобы не заморачиваться с выделением/возвращением памяти. Возможно. Класс используется не рационально, постоянно выполняются лишние действия по подгрузке картинок. Есть такое дело. Но т.к. не тормозит, то подумал - пусть будет так. Хоть по быстродействию и не оптимально, зато как-то гармонично. Не совсем красиво написано условие окончания цикла по выводу времени. А вот этого не понял. А как красиво надо? ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 31 июля 2012 00:20 · Поправил: neomant · Личное сообщение · #18 ARCHANGEL пишет: Хотя в МСДН написано, что напрямую слать окну WM_PAINT нельзя. Значит, видимо, есть способ какой-то. UpdateWindow, RedrawWindow. Проблем с отсылкой сообщения SendMessge так же быть не должно. Можно ещё PostMessage. ARCHANGEL пишет: А вот этого не понял. А как красиво надо? Code:
И соответственно break для выхода из цикла тоже не нужен. Ещё несколько замечаний. Код правильнее писать в cpp-файлах, в заголовках - прототипы функций, константы. inline лучше делать ОЧЕНЬ маленькие функции. Конструктор и деструктор реализованы при описании класса - автоматом считаются инлайн. ----- Следуй за белым кроликом |
|
Создано: 31 июля 2012 01:50 · Личное сообщение · #19 neomant пишет: Конструктор и деструктор реализованы при описании класса - автоматом считаются инлайн. inline или public (access control)? . Рисовать лучше таки в другом потоке, а таймер это костыль, по поводу разбиения класса на *.h и *.cpp тоже спорно, зависит от потребностей и размера самого класса, если класс в 1,5 строки и в будущем не планируется расширять можно и в один всунуть, а есчо есть amalgamation header, например так SQLite идет. Использование winapi, тут на вкус и цвет, хотя сам бы не стал извращаться с ним. |
|
Создано: 31 июля 2012 10:18 · Личное сообщение · #20 |
|
Создано: 31 июля 2012 12:34 · Личное сообщение · #21 |
|
Создано: 31 июля 2012 12:52 · Личное сообщение · #22 F_a_u_s_t пишет: Но тогда что бы автоматом считалось inline это должно быть в стандарте А вот в VC есть ещё и принудительное требование __forceinline. ----- Следуй за белым кроликом |
|
Создано: 31 июля 2012 13:13 · Личное сообщение · #23 neomant В стандарте подробнее расписано. Code:
|
|
Создано: 01 августа 2012 15:04 · Личное сообщение · #24 Теперь новый трабл. Создаю окно, на клиентской области которой и будет отображаться долгожданный лабиринт. Вот код: Code:
Но проблема в том, что как только я закрываю это окно - всё приложение завершает работу. На самом же деле это окно создаётся после нажатия кнопки на главном диалоговом окне. Т.е. программа-часы имеет кнопку "Играть", я давлю на эту кнопку, а в ответ должен появиться лабиринт. И он появляется, но стоит мне закрыть окно лабиринта, как программа тут же завершается. Что это? Может, какие-то стили окна отвечают за это? В мсдн ничего не нашёл, знать бы, где искать. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 01 августа 2012 15:38 · Личное сообщение · #25 Не увидел WindowProc. Могу предположить, что используется общаяя с часами, которая и посылает PostQuitMessage потоку. ----- Следуй за белым кроликом | Сообщение посчитали полезным: ARCHANGEL |
|
Создано: 01 августа 2012 15:47 · Личное сообщение · #26 neomant Не общая, но получается, что PostQuitMessage действительно посылается тому же потоку, который и создавал диалоговое окно с часами. Спасибо, что я делал бы без neomant`a и F_a_u_s_t`a? Будем исправлять... Да, кстати, в часах вместо SendMessageA поставил UpdateWindow. Работает, ещё и баг один исправился - раньше стоило переключиться на другое окно, а потом обратно на "часы" - и кнопки пропадали, пока не переместишь окно. А теперь без всяких манипуляций появляются. ----- Stuck to the plan, always think that we would stand up, never ran. |
|
Создано: 01 августа 2012 17:17 · Личное сообщение · #27 ARCHANGEL Хз из за чего, причин много может быть, если что выкладывай прожект. Кстати у тебя получение времени страшное какое то, не проще так: Code:
Писал в браузере, но не думаю что бы в 5-и строчках накосячил. |
|
Создано: 01 августа 2012 17:44 · Личное сообщение · #28 |
|
Создано: 01 августа 2012 18:26 · Поправил: F_a_u_s_t · Личное сообщение · #29 |
|
Создано: 01 августа 2012 19:18 · Личное сообщение · #30 ARCHANGEL пишет: А, может, так: Как раз только так и нужно, так как функе нужно передать указатель на структуру, а не непроинициализированный указатель. Но лучше пользоваться уже готовыми библиотечными обёртками: Code:
----- Следуй за белым кроликом |
. 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8 . 9 . 10 . >> |
eXeL@B —› Дневники и блоги —› ARCHANGEL's blog |