FanArt – рост pagerank

Некоторое время назад я писал про собственноручно написанное приложение для автоматической генерации контента для сайта . Доделав программу, я поюзал ее несколько дней (700+ постов) и законсервировал в ожидании результатов. Результаты не заставили себя ждать: через пару недель сайт появился в выдаче Google, с поиска начались переходы (сейчас 20-30 юников в день), а сегодня, после очередного апдейта, поисковая система добавила + 2 PR.

Автоматизированный сайт – автоматическое наполнение контентом

Сегодня я расскажу об одном моем сайд-проекте – сайте-галерее изображений . Изначально сайт был задуман таким образом, что наполнять его контентом должно быть быстро и просто. CMS была выбрана WordPress, а дизайн был создан практически с нуля. Перейдя на сайт вы не обнаружите ни стандартного расположения постов, ни привычной страничной разметки WordPress`a. По-мере скроллинга страницы, сайт автоматически догружает более старые посты – это реализовано с помощью jQuery.

Скриншот главной страницы сайта с автоматически-наполненным контентом

Как следует из названия этой записи, контент для этого сайта не создается вручную. Под контентом я имею ввиду конечные записи-посты, фотографии в галерее, которые видны при просмотре (сами фотки конечно кем-то создаются и взяты мною в качестве примера реализации сайта-решения).

Для автоматического постинга в WordPress мною была написана собственное решение – программа, которая умеет в автоматическом режиме собирать данные о фотографиях/изображениях из сети интернет, сохранять их названия, подбирать теги и выделять описание, если его оставил автор фотографии. Дальше программа может самостоятельно запостить это изображение на сайт или ждать решения о модерации данного изображения пользователем. Конечно же, программа не обучена восприятию прекрасного и не способна отличить отличную фотографию(как те, что вы видите на сайте) от ерунды, но если вам нужно добавить несколько тысяч страниц за день, разбавив их полу-уникальным контентом, то придется смириться с тем. что качество подобного контента будет не на высоте.

В противном случае (когда качество содержимого для вас имеет значение), пользователь волен использовать ручной режим и добавлять фотографии вручную. Для каждого конкретного сайта, из которого будут парсится фотографии, должен быть написан собственный модуль извлечения информации об изображении. Также программа способна отслеживать содержимое буфера обмена Windows, и если та появляется изображение или ссылка на него, автоматически формировать из этого изображения полноценный пост для сайта.

Страница сайта с одиночной фотографией

Подсчет показал, что в ручном режиме за 8-ми часовой рабочий день, один человек способен сформировать 2500-2800 постов с изображениями которым автоматически будут сопоставлены теги, описание и название. Подобного суточного потока информации более чем достаточно для функционирования полноценного ресурса.

Средства автоматизации, подобные тому, что описано в этой записи, я разрабатываю с составе студии “Новый Сайт” . Программы делаются, как для новых проектов, так и для уже существующих.

С# – Точка в полигоне

Быстро и без особых пояснений делюсь отличным (если не лучшим) алгоритмом поиска принадлежности точки полигону на двухмерной плоскости.

Алгоритм прекрасно работает со всеми видами полигонов. Для увеличения производительности можно на этапе загрузки полигонов, обрамлять его в прямоугольник и первой проверкой смотреть входит ли искомая точка в прямоугольник – это должно значительно увеличить скорость выполнения алгоритма при большом количестве сложных полигонов.

Application Updater: часть кода в клиентском приложении

Для запуска модуля обновления часть кода должна быть расположена внутри клиентского(обновляемого) приложения. Вот код, который я использую в своем проекте Timeline :

Проверяем получена ли инструкция для обновления.

Запускаем проверку на наличие более новых версий инструкции, чем текущая версия программы:

При наличии более новой инструкции, вызываем модуль обновления и закрываем текущий процесс:

Добавлены следующие функции для приложения-апдейтера :

  • выполнение файла
  • переход по url-адресу
  • копирование файла
  • удаление файла

Я думаю, что для первого приближения этих и перечисленных в предыдущих постах функций вполне достаточно, чтобы иметь необходимый минимум инструментов для обновления собственных программ.

Утрясаю некоторые сложности с платежными системами, искореняю последние баги и выпускаю Timeline.

C# Приложение для обновления собственных приложений

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

  • приложение, которое требует обновления ищет по заранее известному url-адресу xml-инструкцию с обновлениями
Пример содержимого файла xml-инструкции
  • в случае, если инструкция была создана позже, чем текущая версия приложения, то запускается приложение-апдейтер c аргументом – путем к инструкции
Пример работы программы обновления

В ходе работы программы могут выполняться несколько базовых действий: создание каталогов бекапа и загрузки файлов, бекап файлов, загрузка из интернета и обновление существующих файлов.

В случае, если приложение-апдейтер запущен без аргумента с путем к xml-инструкции, то запускается менеджер для создания или редактирования своей инструкции:

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

Diablo Item Foundry 1.0

Представляю вам релизную версию программы Diablo Item Foundry, с помощью которой можно создавать предметы из мира Диабло 3 и сохранять их в виде графического изображения.

Daibo for a diablo monk

Diablo Item Foundry позволяет добавлять более 50 различных аффиксов к предметам. При этом возможно модификация таким набором аффиксов, который не достижим в самой игре.

Изображение предмета (на картинке выше стоит изображение по-умолчанию) может быть заменено на существующее в игре (программа распространяется вместе с обширным архивом иконок предметов) или своим собственным изображением. Такое изображение должно быть размером в 64 * 128 пикселей (для однослотовых предметов 64 * 64) или с таким же соотношением сторон.

Предмет сохраняется в виде JPEG файла.

Программа требует, чтобы на компьютере был установлен пакет Microsoft Net Framework 3.5 или новее.

Скачать программу можно с Дропбокса  или RapidShare .

Changelog:

  • исправлена ошибка, возникающая с амулетами, кольцами и поясами.

Windows Forms – создание собственного интерфейса

Наверняка, вам когда-нибудь хотелось заменить стандартное оформление приложения Windows на что-то собственное. Например, как в лаунчерах современных игр:

Такое оформление не сложно создать самому (при наличии, конечно, навыков дизайнера). Для создания такого приложения будем использовать исключительно стандартные средства Windows Forms. Read the rest of this entry »

Пишем tooltip всплывающую подсказку

Привет, сегодня рассказываю примерный алгоритм того, как реализованы всплывающие подсказки в Ignite . Основным требованием к всплывающей подсказке будет ее масштабируемость в зависимости от того, сколько информации в ней рисуется. Итоговый результат выглядит вот так:

 

Первое, что необходимо сделать – это подсчитать какой размер занимает информация, содержащаяся в подсказке. Сделать это можно совершенно различными способами. Я записываю в структуру Point вектор расстояния от левого-верхнего угла до правого-нижнего:

Теперь в size записан размер всплывающей подсказки. Теперь все готово к тому, чтобы нарисовать обрамление для подсказки. Оно состоит из нескольких ключевых элементов: четырех углов и четырех сторон, которые формируют прямоугольник. Сначала я рисую четыре угла:

Я принимаю две структуры Point: положение левого-верхнего угла и размер всплывающей подсказки. gui – это текстура, с которой рисуется на экран картинка. Первый прямоугольник – положение, куда рисуется уголок, второй – его положение на текстуре gui. Заметьте, что я сдвигаю положение уголков на 5 пикселей от всплывающей подсказки. Я это буду делать и для остальных 4х сторон.

Стороны я храню, как отрезки в несколько десятков пикселей, которые последовательно рисуются несколько раз, если размер всплывающей подсказки больше размера стороны:

Рисуем стороны:

После того, как нарисованы стороны, не забудьте добавить фон. Я использую полупрозрачное изображение, которое отделяет текст подсказки от игрового поля. Это изображение я растягиваю до размера size:

После этого можно начинать добавлять элементы всплывающей подсказки. Также стоит помнить, что если вы не будете создавать новые элементы Rectangle при каждой перерисовке кадра(как это сделал я для скорого примера), а будете использовать заранее созданные константы, то это несколько уменьшит нагрузку на cpu при обработке вашей подсказки.

Алгоритм поиска пути

Привет, сегодня я расскажу о алгоритме поиска пути, который используется в Игнайте. Это алгоритм А* с некоторыми нестандартными условиями:

  • первое из них – изменяющийся размер юнитов (1 – 16 клеток)
  • второе – несмотря на свой размер, юнит всегда за раз передвигается на 1 клетку (т.е. на расстояние в 1/4 – 1 собственного размера)
  • третье – некоторые юниты должны иметь возможность проходить сквозь стены (разрушая их) в случае, если нет ближайшего обходного пути
  • четвертое – перемещение в 4-е стороны
  • и последнее – алгоритм не должен замедлять выполнение программы и, одновременно, рассчитывать собственный путь для каждого юнита отдельно

Предупреждаю сразу, что это первая итерация моего алгоритма и я приветствую любые замечания и улучшения, особенно те, которые направлены на ускорение его работы.

Итак, для начала определимся с тем, что у нас уже есть до начала работы алгоритма:

  • алгоритм пересчитывается только после изменения определенных параметров (в моем случае – это инкрементация счетчика времени)
  • путь просчитывается не для всех существ на карте, а для готовой выборки из рядом находящихся юнитов (этот список готовится отдельно)
  • более того, если существо не передвигалось в этом ходу, то для него не нужно искать новый путь

Теперь можно запускать сам алгоритм:

  • заносим клетку, на которой находится юнит, в отрытый список
  • просматриваем соседние клетки на предмет проходимости

Так как юнит может быть размером больше 1 клетки, то в этом случае нужно проверять не одну клетку, а несколько соседних, т.е. вместо проверки свойства проходимости конкретной клетки, делать проверку наподобие следующей:

, которая проверяет проходимость сразу нескольких клеток.
Для дальнейшего ускорения расчетов, можно получать от этой функции не bool, а числовое значение сложности перехода (и, например, -1, если прохода нет).

Все клетки, которые удовлетворяют критериям проверки, нужно занести в открытый список, указав в них ссылку на первую родительскую клетку.

  • Удаляем первую родительскую клетку из открытого списка, т.к. ее больше не нужно проверять и заносим ее в закрытый список. Клетки которые находятся в закрытом списке никогда не должны попадать в открытый

Оценка пути
Теперь, когда в открытом списке есть несколько элементов, встает вопрос: какой же из них нужно выбрать для последующего анализа? Единого ответа на этот вопрос существовать не может, т.к. вариантов тут такое же множество, как и задач, которые можно решить с помощью данного алгоритма.
В нашем случае должна быть предварительно проведена оценка стоимости пути для каждой клетки. Определить стоимость пути можно по следующей формуле:
F = G + H
, где F – стоимость продвижения на клетку А
G – стоимость продвижения со стартовой клетки до клетки А
H – примерная стоимость продвижения с клетки А до конечной клетки

H – это эмпирическая функция, которая определяется не точно. Зачастую используют метод Манхетенна для определения H: суммируют расстояние по абсциссе и ординате и умножают на среднюю стоимость передвижения из одной клетки в другую.

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

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

Для оптимизации вычисления выполнение данного алгоритма можно выполнять не в один момент времени, а растянуть на несколько тактов. Т.к. все вычисления связаны обработкой клеток в открытом списке, то структурно подобные отложенные вычисления можно представить в виде следующего метода:

Теперь, если мы предположим, что основным побуждением изменения таймера внутриигрового времени являются действия игрока, и эти действия имеют задержку выполнения, например 250 мс (т.е. не больше 4-х действий в секунду), то имея частоту обновления игры 60 Гц, мы получаем, что данные вычисления будут выполняться, как минимум 15 раз до того, как игрок совершит следующее действие (которое побудит существо пересчитать свой путь). Константа _MAXSTEPS должна быть вычислена экспериментально.

На тот случай, если игрок совершает новое действие, а подобный отложенный алгоритм так и не завершил свои вычисления, я задаю специальную переменную SavePath, которая хранит ближайшую к монстру наиболее пригодную для перемещения клетку.