Issuu on Google+


ПРО

граммист

СОДЕРЖАНИЕ

№16 (июль) 2011

Издается с марта 2010. Выходит ежемесячно №16, июль 2011 г.

Редакция: Выпускающий редактор Алексей Шишкин Литературный редактор Utkin Редакторы Сергей Бадло, Василий Мединцев, Natali-Ka, Алексей Шульга, Егор Горохов, Виталий Желтяков Редактор-корректор Ян Липлавский

Дизайн и верстка:

Алексей Шишкин, Виталий Желтяков, Сергей Бадло, Олег Резников

Авторский состав:

Алексей Шишкин, Игорь Теслюк, Анна Голева, Михаил Жигимонт, Владимир Яковлев, Олег Александров, Дмитрий Шкаровский, Александра Кушнарева, Сергей Бадло

Официальный сайт журнала:

www.procoder.info

Контакты:

Авторские статьи направляйте на maindatacentr@gmail.com Вопросы и предложения для редакции reddatacentr@gmail.com Вопросы и предложения администратору info@procoder.info

Информационная поддержка:

Международная Академия Информатизации (МАИН) РК www.academy.kz Журнал «Радиолюбитель» www.radioliga.com Журнал «VR-ONLINE» www.vr-online.ru V.K. сайт... www.kotoff.info Free Legal Soft Group alexcones@gmail.com Некоммерческая сеть AirNet-Berdyansk www.airnet.sytes.net Электронная электротехническая библиотека www.electrolibrary.info

СЛОВО РЕДАКТОРА

Конкурс «Танцуем Рок от Метелицы» .............................. с.3 НЕВЕРОЯТНО, НО ФАКТ

Любопытные факты ............................................... с.4

VIP ПЕРСОНА

Интервью с Дарьей Ряжских ...................................... с.9

МЕРОПРИЯТИЯ, КОНФЕРЕНЦИИ

Международный академический курс по энергетике ................. с.18

Конференция по разработке ПО СEE-SECR 2011 ..................... с.20 ОБЩИЕ ВОПРОСЫ

Перфекционизм – болезнь или дар? ............................... с.21 ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

Энергоэффективность браузеров .................................. с.24 WEB ТЕХНОЛОГИИ

Анимированное меню на JQuery ................................... с.32 АЛГОРИТМЫ

Кодирование байта с помощью метода Хемминга .................... с.41

A Star. Пространство и алгоритм поиска пути .................... с.45 ЛАБОРАТОРИЯ

Система контроля неигровых персонажей .......................... с.57

ТВ для всех. Интеграция на сайт ................................ с.60 ЮМОР

Чего только не бывает .......................................... с.64

Примечание:

Издание некоммерческое. Все материалы, товарные знаки, торговые марки и логотипы, упомянутые в журнале, принадлежат их владельцам. Статьи, поступающие в редакцию, рецензируются. Мнение авторов не всегда совпадает с мнением редакции. Перепечатка материалов журнала и использование их в любой форме, в том числе в электронных СМИ, возможны только с разрешения редакции, при обязательном указании ссылки на сайт журнала http://procoder.info. Формат A4, 67 стр.

Идея создания журнала:

Алексей Шульга

Обложка номера:

Дизайн Natali-Ka и Алексея Шишкина

Архив номеров журнала!


ПРО

№16 (июль) 2011

граммист

Алексей Шишкин

http://procoder.info

СЛОВО РЕДАКТОРА

КОНКУРС «ТАНЦУЕМ РОК ОТ МЕТЕЛИЦЫ»...

Доброго времени суток, дорогой читатель. Текущий 16-й выпуск ознаменовался двумя значительными событиями для нашего журнала и редакции. Во-первых, у нашей Птицы с большой буквы, можно сказать, железного Феникса, доброго друга и незаменимого литературного редактора Уткина – Юбилей! Да еще какой, 30-ти летие. Весь дружный, хоть и разбросанный по всей территории постсоветского пространства, коллектив поздравляет тебя от всей души! Всех благ и счастья человеческого и нечеловеческого. И, конечно же, во-вторых, число 16-ти выпусков само по себе символично для программиста. Мы не могли обойти стороной такой двойной праздник и в честь события решили объявить конкурс «Танцуем Рок от Метелицы» на призы журнала «ПРОграммист». Все вы помните те золотые годы, когда по стране ходили такие шедевры игропрома как Dendy и Sega. В редакции нашего журнала тоже есть люди, которые ностальгируют по этому времени. И поэтому мы объявляем конкурс на самого-самого программиста-аналитика. Задача, которая ставится перед участниками конкурса, заключается в следующем – необходимо создать генератор паролей для игры Rock'n'Roll Racing, которая в далеком 1993 году вышла в свет для SEGA GENESIS. Под запретом только «физический» взлом ROM'а игры. Таким образом, для «честного» выигрыша в конкурсе игрок может пользоваться эмулятором (или реальной приставкой), ROM'ом игры и блокнотом.

Призы конкурса: • 1-е

место:

логотипом;

футболка

с

фирменным

• 2-е место: чашка с фирменным логотипом;

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

комбинаций, но и «откроет» дополнительные

«секреты»* Каждое воскресенье, в период проведения конкурса,

каждый

игрок,

участвующий

в

конкурсе должен сообщить, каких высот он достиг

это

позволит

контролировать

«честность» и прогресс игрока.

* Подразумеваются дополнительные, недоступные другим способом цвета, игроки и машины. ** В файле «шаблона» указаны не все возможные варианты транспорта/цветов и пр. Их гораздо больше.

игры.

Поскольку

существует

генератор паролей, то задача игрока – сделать

свой «с покером и поэтессами», причем в

конце показать весь ход рассуждений. Образ

игры и шаблон** игрока приложены в ресурсы к

журналу.

Общее

описание

http://ru.wiki-

pedia.org/wiki/Rock_and_Roll_Racing.

3


ПРО

№16 (июль) 2011

граммист

Сергей Бадло

http://procoder.info

НЕВЕРОЯТНО, НО ФАКТ

ЛЮБОПЫТНЫЕ ФАКТЫ

Казалось бы, еще совсем недавно наш взор поражали полнофункциональные мобильные телефоны в виде наручных часов, к примеру, те же GD910 (см. коллекцию на http://nnorg.ru). Однако китайский дизайнер Шань Чэнь (Shan Chen) похоже пошел еще дальше и представил концепт гаджета в виде кольца. Да-да, смекалка китайской инженерной мысли позволила уместить всю электронику внутрь обычного кольца, которое надевается на палец. Вся поверхность гаджета представляет собой тачпад. Экран как и следовало ожидать – отсутствует, но при необходимости его заменяет мини-проектор, а встроенная камера позволяет совершать видеозвонки. С моей точки зрения, вместо проекции изображения на подходящую поверхность, гораздо удобнее был бы голографический 3D- проектор. Что ж, подождем еще немного, фантастика в нашей жизни – уже реальность.

размещалось бы уже по две метки. Ведь

заводы-изготовители с 2005 года и так крепят

на корпус телефонов пометку с указанием его модели, индивидуального номера, а также изображение

фирменного

логотипа

«Укрчастотнадзора» (это когда и где?).

Мобильники для пенсионеров становятся

популярны

в

Казахстане,

пишет

издание

http://tengrinews.kz. Сейчас такие телефоны

Парламент Украины ввел обязательную маркировку радиоэлектронных средств при их ввозе.

Принятый

законопроект, принцип

во

согласно

втором

которому

обязательной

чтении

вводится

маркировки*

радиоэлектронных средств при их ввозе в Украину

из-за

границы,

предполагает

есть

в

Алматы

и

Астане.

Как

рассказал

менеджер одной из компаний по продаже

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

700

телефонов.

ведутся

телефонов

Кызылорде.

для

В

приспособление

Он

переговоры

пенсионеров скором

появится

во

уточнил,

о

в

реализации Таразе

времени всех

и

это

городах

стоимость акцизной марки чуть более 5-ти

Казахстана.

связи еще в сентябре 2010 года одобрила

реализацией телефонов со своими тарифными

безотлагательном введении маркировки. Но

довольно демократичная - от восьми до девяти

грн. Национальная комиссия регулирования проект

постановления

Кабмина

о

начатая в декабре админреформа, очевидно,

заставила отложить решение вопроса до лета.

Некоторые

что

операторы

казахстанской сотовой связи уже занялись

планами.

Цена

специального

мобильника

тысяч тенге (от 54 до 61 доллара). По словам менеджера,

возможно

стоимость

оснащен

большими

понизится,

Таким

кнопками, на них ярко выведены цифры. В

на

мобильные

телефоны

образом,

на

акцизную

всех

марку.

мобильниках

* Готовимся к подорожанию и вай-фай оборудования / Редакция.

известно.

однако

даже,

Правительство уже давно пытается прицепить

Телефон

на

сколько,

пока

4

не


ПРО

№16 (июль) 2011

граммист

НЕВЕРОЯТНО, НО ФАКТ СПО в государственных структурах получает

дополнительный импульс. Однако закупать

новое

ПО

не

потребуется.

Достаточно

использовать один из свободных** офисных

пакетов. Например, таких как OpenOffice или LibreOffice. Раскрыт

механизм

бактериального

электричества. Данные, полученные учеными

него

встроены

который

FM-приемник

работает

даже

и

тогда,

фонарик, когда

аккумулятор полностью разряжен. Еще одним

преимуществом телефона стало то, что в нем есть

программируемая

на

четыре

номера

тревожная кнопка. При ее нажатии телефон

будет поочередно пытаться дозвониться на любой

номеров.

из

заранее

При

этом

запрограммированных на

включается громкая сирена.

самом

телефоне

университета

Восточной

Англии,

работаю-

щими под руководством Тома Кларка (Tom

Clarke), могут лечь в основу принципиально новых

энерготехнологий,

бактериальные

«биобатареи»,

питательные

а

также

устранения

токсичных

oneidensis,

также

таких

как

элементы

или

загрязнений

на

устройств

для

«бактериальной тяге». Бактерии Shewanella многоклеточных

как

и

организмов,

клетки

используют

получаемые при расщеплении питательных

веществ электроны для получения энергии. При

так

называемом

происходящем

в

аэробном

богатых

дыхании,

кислородом

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

путем восстановления молекулы кислорода до углекислого

газа.

Крист��ллы

MtrF,

представляющие собой кубы со стороной 135

микрометров, 1 июня 2011 в России вступил в действие

рентгеновской ватели

в

суспензии.

С

помощью

кристаллографии

университета

Восточной

Англии

нацстандарт открытых офисных приложений

расшифровали

общении

располагающегося на внешней поверхности

OpenDocument (ODF). Это значит, что при с

государственными

органами

гражданин может использовать документы,

подготовленные с использованием свободного

программного

обеспечения

(СПО).

С

утверждением формата OpenDocument (ODF) в

качестве национального стандарта внедрение

цитохрома

MtrF

молекулярную

исследо-

-

структуру

мембранного

белка,

бактериальной стенки Shewanella oneidensis и

являющегося элементом комплекса, который переносит

электроны.

По

словам

авторов,

именно этот белок является электрическим

выводом поверхности бактериальной клетки и его

изучение

поможет

разобраться

в

механизмах, с помощью которых бактерии

вступают в контакт с минералами и передают

им электрических заряд.

** Стандарт ГОСТ Р ИСО/МЭК 26300-2010 «Информационная технология. Формат Open Document для офисных приложений (OpenDocument) v1.0», утвержденный Росстандартом 21 декабря 2010 г., идентичен международному стандарту ISO/IEC 26300:2006. К нему относятся файлы, имеющие следующие расширения: .odt (текстовые документы), .ods (электронные таблицы), .odp (презентации), .odb (базы данных), .odg (графика), .odf (формулы).

5


ПРО

№16 (июль) 2011

граммист

НЕВЕРОЯТНО, НО ФАКТ

запустила

Бикини из... солнечных элементов особенно

активирована для всех пользователей сети 6

вообще на отдыхе, где всегда есть проблемы с

Соцсеть

«Одноклассники»

сервис... видеозвонков. Данная опция была июня в режиме бета-теста. Однако сам сервис видеотелефонии появился еще в декабре 2010

становится актуальным летом на пляже, да и

розеткой. Функциональный костюм изготовлен из сшитых вместе фотогальванических

года, но был доступен лишь десятой части

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

пользователи соцсети могут совершать звонки

фотогальваническую поверхность свет преоб-

Пользователи не смогут звонить на мобильные

Вскорости будет доступна мужская версия

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

или городские номера, а также на номера Skype. В

Японии

компьютерных

за

создание

вирусов

тюрьму,

согласно

рамках

международной

и

будут

новому

хранение

сажать

закону

в

оснащен USB-коннектором. Попадающий на

разуется в ток при напряжении 5 вольт.

«пляжной

охлаждения

зарядки»

бутылки

iDrink

пива.

с

функцией

Единственная

проблема – изобретение дизайнера Эндрю

Шнайдера не приспособлено для купания.

против

киберпреступности, одобренному 17 июня, в конвенции.

За

умышленное создание или распространение

вирусов будут штрафовать на 500 тысяч иен или приговаривать к тюремному заключению

на срок до трех лет. За хранение вирусов предусмотрен

штраф

в

300

тысяч

иен

и

тюремный срок до двух лет. Кроме того, закон

предоставляет властям право требовать от

интернет-провайдеров хранения логов част-

ной

переписки

в

течение

60

дней.

.

6


ПРО

№16 (июль) 2011

граммист

НЕВЕРОЯТНО, НО ФАКТ Банкоматы Сбербанка оборудуют... детек-

нием в следующем году в Украине Евро-2012,

заявления

министерства,

торами

лжи.

сканировать отпечатки

трехмерный

Новинка

на

выдачу

паспорт,

пальцев, снимок

лица вкупе с распоз-

будет

брать

а

учебный год в вузах сократится: в письме

принимать

кредитной у

также

карты,

направленном

всех уровней аккредитации, рекомендовано

делать

Процессор с трехмерными... транзисторами по 22-нанометровой

технологии под кодовым названием Ivy Bridge показала Intel. Суть

определять,

кремниевой подложки, из которой элементы как бы произрастают

позволит

устройству

говорит

человек правду или

лжет. Среди вопросов

будут: «Работаете ли

вы сейчас?» и «Есть

ли

у

вас

другие

непогашенные кредиты?».

Данная система была

разработана Центром речевых

который

технологий,

также

сот-

технологии

заключается

в

использовании

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

двухмерных

элементах.

Это

снижает

сопротивление

при

прохождении электронов через транзистор, когда он находится в

открытом

состоянии,

и

почти

полностью

блокирует

поток

в

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

более

высокой

плотности

размещения

логических

элементов,

транзисторы Tri-Gate позволяют создавать процессоры, работающие

на меньших значениях напряжения и с меньшими токами утечки,

это дает значительный (до 37%) прирост скорости работы в

сравнении

с

существующими

чипами.

Процессоры

с

новыми

транзисторами потребляют менее половины мощности, чем 32-нм

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

рудничает с ФСБ. Как

Таким образом, технология Tri-Gate позволит существенно снизить

московского филиала

зисторы Tri-Gate будет осуществлен вместе с переходом на новую

сообщил

директор

организации рий

Дмит-

Дырмовский,

программа лась

на

создаваоснове

энергопотребление чипов. Переход на новые трехмерные тран-

22-нм технологическую норму, отражающую размер элементарных

блоков интегральных схем. Компания уже располагает рабочими

образцами

новых

устройств,

а

начало

массового

процессоров Ivy Bridge намечено на конец 2011 года.

выпуска

установить

продол-

жительность первого

и

второго

семестров недель

учебных по

17

каждый

объемом

с

недельной

учебной нагрузки в

семестре 30-36 часов.

Зимняя

экзамена-

дентов,

согласно

ционная сессия сту-

рекомендациям,

сос-

тоится с 11 по 31

января

летние

2012

студенты

года,

экзамены

будут

сда-

вать с 25 мая по 5 июня 2012 года. Зимние

высших

каникулы

заведениях декабря

в

учебных

продолжаться

аудиоархива российс-

до

будут

с

29

10

января, летние – с 6

ких правоохранитель-

июня

ных органов. Снятые образцы

в

адрес ректоров высших учебных заведений

клиентов

наванием голоса. Это

предложенной

ведомством

2012

года.

Вручение дипломов о

клиентских

голосов планируется

высшем образовании

пластиковые карты, а

учебных заведений в

базе

ся

записывать

на

выпускникам высших

их

2012 году планирует-

вовсе не хранить в банка.

данных

Сбер-

щего года. В школах учебный год также будет

сокращен.

ukraina/society/6055466. В связи с проведе-

июня 2012 года.

*** Ситуация, мягко говоря, неясная. Неужели качество образования имеет меньшую важность, чем Евро-2012? Нонсенс / Редакция.

до

пятого июня следую-

Минобразования Украины сокращает***... учебный год http://news.mail.ru/inworld/

провести

Поэтому

внешнее

независимое

оценивание должны состояться с 14 мая по 7

7


ПРО

№16 (июль) 2011

граммист

НЕВЕРОЯТНО, НО ФАКТ Origin. GPS-трость для слепых со встроенным

Сюнь

GPS-чипсетом Е

(Xun

Ye).

представила Устройство

дизайнер

оснащено

встроенным микрофоном, динамиком, а также

рельефным тактильным дисплеем, который

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

микрофон,

система

распознавания

голоса

интерпретирует команду и прокладывает до

этой точки маршрут. Рекомендации о направлении движения отправляются пользователю

Знаете-ли

вы,

что

STMicroelectronics

выпустила датчик LSM320HAY30 (см. рисунок выше),

сочетающий

в

в

себе

трехосевой

акселерометр и двухосевой гироскоп? При

при

помощи

голосового

синтезатора

или

выводятся на дисплей в виде символов шрифта Брайля, и владелец всегда точно знает,

когда и в какую сторону следует повернуть.

питании от 2.7 до 3.6 вольт и диапазоне

Интернет-проект «РадиоЛоцман» выпустил

вкусное устройство. Акселерометр измеряет

журнала

температур

-40...85

°C

имеем

довольно

ускорение в координатах [x,y,z], а гироскоп в

сферической системе координат (r, teta, fi).

Преобразование систем координат простое: x

= r * sin (teta) * cos (fi), y = r * sin (teta) * sin

(fi), z = r * cos (teta). Однако не для вычисли-

пилотный номер бесплатного электронного http://www.rlocman.ru/book/book.ht

ml?di=107006. С осени 2011 года редакция

радиолоцмана

планирует

наладить

ежемесячный выпуск. Поздравляем коллег!

Успехов в столь нелегком труде / Редакция.

тельной мощи простеньких микроконтролле-

ров, поэтому данный датчик займет достой-

ную нишу среди низкобюджетных решений. Королевский

монетный

двор

Голландии

представил монеты с QR-кодом в честь 100-

летия монетного двора в Утрехте. Две монеты

достоинством €5 и €10 снабжены QR-кодами и выпущены ограниченным тиражом в золотом

и серебряном исполнениях. Золотая монета будет стоить €10, а монеты из серебра будут продаваться по

€5.

QR-

код ведет на

сайт королев-

ского

ного

монетдвора.

8


ПРО

№16 (июль) 2011

граммист

Редакция журнала

http://procoder.info

VIP ПЕРСОНА

ИНТЕРВЬЮ С ДАРЬЕЙ РЯЖСКИХ

Доброго дня, уважаемый читатель. Не секрет, что мобильная индустрия семимильными шагами осваивает новые технологии и современнейшее железо. Рынок и спрос мобильных приложений растет. И с этим нельзя не считаться. Продолжая наши интервью, сегодня мы решили пригласить к нам специалиста, непосредственно связанного с разработкой ПО под мобильные платформы. Итак, встречайте, в гостях у нас ст��рший инженерпрограммист компании I-free, разработчик под Android, ведущая один из известных блогов в области разработки приложений под Android http://megadarja.blogspot.com, Ряжских Дарья Юрьевна. Интервью по-прежнему проведем в режиме вопрос-ответ... Читайте, оценивайте, оставляйте комментарии и пожелания.

Редакция: Доброго времени суток, Дарья Юрьевна.

Добро

пожаловать

в

нашу

рубрику «VIP-персона». Есть предложение снизить уровень официоза и... перейдем

«на ты»?

Дарья: Ok. Редакция: Хотим полюбопытствовать. Расс-

кажи немного о себе?

Дарья: Я всю жизнь прожила на Дальнем

Востоке: в Петропавловске-Камчатском, Хаба-

ровске, Владивостоке. Закончила матфак ДВГУ,

работаю программистом около 5 лет. Начинала с Дельфи, участвовала в разработке инфор-

мационной системы в МГУ им. Невельского (да,

во Владивостоке там есть собственный МГУ –

Морской государственный университет). Потом

много

работала

последнее

время

с

.Net

разных

докатилась

до

версий.

В

Андроида.

Несколько месяцев назад переехала в Питер.

Редакция: Математику до сих пор хорошо

помнишь? Кто из бывших преподавателей

запомнился особо, может есть интересный

случай из студенческой жизни?

Дарья: Мне очень нравится математика, но, к

Фото 1. Дарья Ряжских – разработчик программного обеспечения.

Сферы профессиональных интересов:

Android, Microsoft .Net Framework, PHP5 сожалению, сейчас сфера моей работы от нее

далека, и помню я все меньше и меньше. Университет уже плохо помню. На младших

9


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА курсах были суровые зубры-математики, на

Есть перспективы?

говорил так: «В универе ничему не учат, но

Дарья:

старших – разгильдяи-компьютерщики. Один из

после него все умеешь». Так получилось, что у

нас

воспитывалась

самостоятельность.

главным

Помнится,

образом

на

родной

кафедре даже не озвучивали требований к диплому. Каким-то образом сами догадывались о

том,

что

руководителей. Редакция:

нужны

Как

рецензии

пришла

в

вание? С чего все началось?

и

отзывы

программиро-

Дарья: Это долгая и давняя история. До 7-го

Сподвигло

большое

количество

времени. Я тогда работала на одном полу-

живом проекте на .Net и мне часто было просто

нечем

заняться.

Андроид

тогда

только

появлялся, про него никто ничего не знал, я и

решила

успешно. Насчет

разобраться.

перспектив?

Получилось

Думаю,

довольно

Android

это

самая перспективная из мобильных платформ. Редакция:

Какие

средства

разработки

используешь? Что мешает в работе, а что

класса школы отношения с точными науками

помогает?

ушами, пропустила почти четверть, пришлось

Дарья: Под Android вся разработка идет на

мной занималась коллега моей мамы, Галина

NetBeans.

как-то не складывались. Потом сильно заболела прилагать много усилий, чтобы «нагнать». Со

Валентиновна,

в

прошлом

учительница

математики. И так хорошо у меня пошла геометрия, что я сменила школу, перешла в

Eclipse, под .Net –

на Visual Studio. На PHP –

Впечатления

разные.

Всегда

нравилась Visual Studio, очень тяжело было

переходить с нее на Eclipse, казался очень уж

кривым

и

неповоротливым.

Но

ко

всему

математический класс, и стала себя видеть

привыкаешь – теперь мне в VS не хватает

матфак и так далее.

давно не работала, но, помнится, большим

исключительно программистом. Ну, а дальше – Редакция:

Девушке

сложно

Дарья:

абстрактную

адаптиро-

ваться в среде программистов-мужчин? сказать,

За

всякое

шовинистически программистов

бывает.

мне

девушку Что

до

настроенных не

не

могу

меня,

то

коллег-

попадалось.

Мне

некоторых фич. С NetBeans уже достаточно

разочарованием

было,

когда

напрочь убрали поддержку XSLT.

в

версии

6.8

Редакция: Пользуешься такой вещью как

системы контроля версий? Какие наилуч-

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

кажется, гораздо больше проблем с женщи-

Дарья: На самом деле это значимый для меня

не понимая, что в нем написано, но только из-

специальности, у нас была довольно большая

быть мужчиной.

успешно.

Редакция: Программированием под Android

«коммиту»* и правильный его формат. Так что

нами-HR, которые могут игнорировать резюме,

за того, что программист вроде как должен

ты начала заниматься с 2008 года. Что

сподвигло к этой области деятельности? * Коммит (англ. Commit, слэнг.) – операция сохранения изменений и загрузки файлов на сервер системы управления версиями SVN (или CVS).

вопрос. Когда я только начинала работать по

команда. Мы использовали SVN, и довольно Даже

проверяющие

были

наличие

написаны

хуки,

комментария

к

у меня выработалась привычка работать с SVN, и я использую его даже если работаю в

10


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА

Фото 2. На утренней вахте одиночестве. И обязательно пишу комментарии

набор известных глюков у него имеется. Для

сэкономить

использую

к «коммитам», так как подробные логи могут массу

времени,

когда

вдруг

понадобится узнать, какие изменения были

внесены полгода назад (а такое обязательно

случается).

Однако, две вещи меня огорчают. Во-первых,

некоторые коллеги далеко не всегда видят

смысл

в

использовании

систем

контроля

небольших

проектов

Mercurial

в

последнее

http://mercurial.sele-

nic.com, но в команде с ним работать не

доводилось.

Редакция: Тестированием приложений на

работе

занимаешься

лично

специально выделенные люди?

Дарья:

А во-вторых, сами системы контроля версий

то я работаю в команде, где так и есть.

бывают

Source

неподходящими

Safe**

по-моему

для

работы.

вообще

не

Visual

имеет

смысла. Да и Subversion тоже тяжеловат, и

Тестированием

должны

или

версий, и не всегда ответственно относятся.

Вследствие этого в репозитории творится хаос.

время

есть

заниматься

отдельные люди. И я очень рада, что наконецТестирование – это не так просто, там есть свой

процесс и нужна своя квалификация.

** Microsoft Visual SourceSafe (Visual SourceSafe, VSS) – программный продукт компании Майкрософт http://msdn.microsoft.com/en-us/library/ms181038(VS.80).aspx, файл-серверная система управления версиями, предназначенная для небольших команд разработчиков. VSS позволяет хранить в общем хранилище файлы, разделяемые несколькими пользователями, для каждого файла хранится история версий.

11


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА Редакция: Приходиться заниматься игро-

выми

приложениями

или

ленные наработки?

есть

промыш-

Дарья: Странная постановка вопроса. Игровыми

приложениями

заниматься

не

прихо-

дилось. А наработки конечно есть, мне же

многие задачи приходится решать. Редакция:

человеком?

Считаешь-ли

себя

азартным

Считаешь-ли

свои

проекты

просто хобби?

Дарья: Своих проектов у меня не так много.

Если и возникают идеи, то они достаточно

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

Редакция: В лице других разработчиков, чувствуешь конкурентов? Нет,

потом

забудешь

и

очень

странному поведению программы.

удивляешься

Редакция: Какую мотивацию применяли и

применяют бывшие и нынешние работо-

датели?

Дарья: Честно говоря, я ничего не понимаю в

менеджерских штуках, так что мне сложно

лучшая

изначально коммерческими, или это было

Дарья:

всякие. Напишешь что-нибудь для отладки,

ответить на этот вопрос. По мне, так самая

Дарья: Нет. Редакция:

Дарья: Да бывает, но в основном глупости

мне

Соревновательность

неприятно

так

бессмысленна

думать.

и

неконструктивна. Лучше я буду считать себя

среди единомышленников, с которыми делаю

общее дело.

мотивация

это

отсутствие

демотивации. Однажды я оставила довольно

перспективный

проект

из-за

того,

что

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

не произошло. Другой менеджер лазил в код и

заставлял его переделывать в соответствии со

своими представлениями (например, требовал

заменить

запросы).

все

расстаться.

С

лямбда-выражения

ним

тоже

на

пришлось

LINQ-

быстро

На нынешнем же проекте процесс разработки

поставлен

очень

бюрократии

нет,

и

хорошо.

И

менеджер

лишней

помогает

программистам, а не мешает им. Работать комфортно, и это хорошая мотивация. Редакция:

С

какими

«подводными

камнями» пришлось столкнуться как разра-

ботчику под Android?

Редакция: Как хранишь бэкапы? Дарья: Работу – в svn-репозитории. Остальное

Дарья:

Одна

из

главных

сложностей

при

мне не особенно жалко потерять. Впрочем,

разработке под Андроид – это необходимость

но до того, чтобы «разресерчить» существу-

каждого

время от времени задумываюсь этим вопросом, ющие сервисы, просто руки не доходят.

Редакция:

работе?

Случались

казусы

в

твоей

поддерживать большое количество устройств, у из

соображения.

которых

Помню,

имеются

свои

разрабатывала

видеоплеер, который воспроизводил потоковое

видео, и было очень много проблем именно с

поддержкой разных телефонов. Недавно были

баги с отображением картинок в Nexus S.

12


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА

Фото 3. В Корее на японской яхте

Причем не повторялось ни на далеко уже не

топовом HTC Desire, ни на совсем бюджетном

LG Optimus One.

коллектив. Из плюсов – свобода действий и

выбора

режима

дня.

А

основной

минус

приходится все время вариться в собственном

соку. Не могу сказать, что этот период в жизни

Редакция: Как поместить свое приложение

был сильно успешным, но кое-что сделать

Дарья: Не знаю. Собственные приложения я не

Редакция:

отдельные люди.

р��зработчиком. Почему? Это был бонус в

в Android Market***?

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

Редакция: Чем привлек фриланс? Успешно,

удалось, и даже неплохо. В

твоей

деятельности,

некоторое время назад, ты была WEB-

копилку опыта?

не успешно?

Дарья: Как-то само собой получилось. Я еще в

Дарья: Во фриланс пошла, отчаявшись найти во

на Perl, сейчас уже знаю, что баловство это, а

Владивостоке хорошую работу и адекватный

*** Мы уточнили. Чтобы размещать программы на Android Market необходимо: • cоздать профиль разработчика; • заплатить регистрационный взнос 25.0 $ через Google Checkout; • принять Соглашение о распространении ПО через Android Мarket.

универе начинала заниматься вебом. Правда, не

веб.

Потом

работала

над

одной

13


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА информационной

системой

и

начинала

переводить одну ее часть на ASP.NET. Так что

веб – это ничего удивительного, с него многие

начинают.

Редакция: Чем привлекает разработка под .Net?

Дарья: Тем, что можно писать на C#. Я очень люблю C#, и это, несомненно, самый лучший язык в мире.

Редакция: Пробовала ли XNA? И если да, то какие впечатления?

Быстро все забываю, так что надо записывать. Недавно

получилась.

Редакция: Отношение к Моно****. Реальная

абсурдная

Надо

было

ситуация

настройки

в

приложении сделать. Я честно разобралась, и

еще подумала, что надо бы инструкцию сделать чтоб

потом

времени

не

терять.

А

потом

оказалось, что уже написала такую статью в

2009-м.

Написание статьи занимает у меня довольно

много времени. Почти ко всем статьям нужны

иллюстрации и исходники. Да и к стилистике я

отношусь довольно придирчиво, несколько раз перечитываю и правлю. Редакция:

Дарья: Нет, не пробовала.

совсем

Какие

планы

по

развитию

проекта? Монетизацию не планируешь?

ли альтернатива Нету?

Дарья: Буду продолжать по мере сил писать

Дарья: Нечего сказать. Не видела ни одного

вряд ли будет. Максимум контекстную рекламу

программиста под моно, и сама не пробовала, в силу сложных отношений с линуксами.

статьи на интересующие темы. Монетизация

поставлю.

Редакция:

Какова

статистика

использо-

Редакция: В конференциях довелось побы-

вания ресурса посетителями?

лекциями по Android, если пригласят?

Дарья: На блоге в день 450-500 посещений. На

вать? Будешь-ли участвовать со своими

Дарья: Однажды участвовала в холиваре iOS vs

Android. Представляла Андроид, рассказывала

сайте обычно не более 30.

Редакция: Как продвигаешь, за счет чего

про его плюсы и минусы. Вообще участвовать

растет посещаемость?

Редакция: У тебя есть собственный проект-

Андроиду, муж опубликовал ссылку на хабре

не против, но спикер из меня не ахти.

блог

http://darja.info.

Что

сподвигает

делиться личными наработками и опытом? Много-ли

времени

поддержка проекта?

отнимает

развитие

и

Дарья: darja.info – это просто сайт-визитка. Вся

полезная информация же содержится на блоге, http://megadarja.blogspot.com.

Главный двига-

тель прогресса – голова, которая стремится избавляться

от

неиспользуемых

сведений.

**** Mono – проект по созданию полноценного воплощения системы .NET Framework на базе свободного программного обеспечения. Основной разработчик проекта Mono — корпорация Novell / http://ru.wikipedia.org/wiki/Mono.

Дарья: Когда написала первую серию статей по

(там тогда только-только закрыли регистрацию,

а я не успела завести там профиль). Много

людей увидели, и отзывы были хорошими. Я очень

вдохновилась.

Вторая

серия

статей

также имела успех. Ну, а дальше про мой блог

узнал гугл, да и на других ресурсах стали

публиковать

ссылки.

Больше

специального продвижения не было.

никакого

Редакция: Видеоуроки будут, скринкасты?

14


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА Дарья: Не думаю. Видеоуроки имеют смысл,

радостью бы занялась такими проектами. Но,

основном идет речь о кодировании.

самом

когда нужно показать работу IDE, а у меня в Редакция:

Что

по

твоему

программирования?

философия

Дарья: По-моему это довольно бессмысленное

словосочетание. Попробуйте сказать «филосо-

фия

судостроения»

теплогазоснабжения».

Но

или

«философия

дело

в

том,

что

вокруг программирования достаточно много

гуманитариев,

может

промышленной добавить

и

разработки,

обычной

но

далеких

от

пытающихся

технической

профессии

некую ауру таинственности. Мастера же не

мудрствуют. Редакция:

Что

из

литературы

мендуешь начинающим? Дарья:

Смотря

что

программировании,

начинать.

думаю,

пореко-

Новичкам

подойдет

в

любая

честно говоря, не знала, что такие новации и в деле

имеют

место

быть.

Школьное

образование – создание неповоротливое (что не

всегда плохо), а издательства учебников и

вовсе должны стремиться затормозить этот процесс.

Редакция:

Какими

занята?

еще

проектами

ты

Дарья: В данный момента работаю в компании

I-Free

над

живет

в

проектом

Brainy.

Это

такой

электронный помощник: персонаж, который телефоне

и

выполняет

всякие

полезные функции. Проект достаточно новый, и функций этих пока не так много. Но планов много,

и

разрабатывать

интересно.

это

приложение

Редакция: Даша, и традиционные наши

вопросы.

бумажных

Какие

из

электронных

журналов

для

тебя

или

прио-

литература для начинающих. Переходящим на

ритетны? Какие являются ориентиром?

по этой платформе. Например, для .NET это

Дарья:

программирование с Рихтера явно не стоит.

Жаль, что сначала она все уменьшалась, а

новую платформу полезны классические книги книги Для

Рихтера.

того,

Однако,

чтобы

начинать

освоить

конкретную

технологию, полагаю, самый правильный план

Еще

со

«Компьютерра»*****

школы

нравилась

http://www.computerra.ru.

потом перестала выходить.

– читать документацию и статьи в интернете.

Редакция: Чем занимаешься в свободное

WPF или Андроиду бессодержательны и быстро

увлечениях?

Редакция: Как относишься к нынешним

ности. А потому, раз я работаю головой, то в

вания в части обучения по электронным

Делаю украшения из бисера. А летом еще и

На мой взгляд, бумажные книги по тому же

устаревают. новациям

в

системе

школьного

образо-

книгам, используя планшеты? Дарья:

Думаю

планшетов

об

можно

замечательные

интерактивные

этом

было

учебные

по

иногда.

бы

пособия,

естественным

На

базе

сделать

особенно

наукам.

С

от разработок время? Расскажи о своих

Дарья: Лучший отдых – это смена деятельсвободное время стараюсь работать руками.

всякие ремонтные-такелажные работы на яхте

начинаются. Да и само хождение под парусом – это достаточно тяжелая физическая работа. Редакция:

Даша,

ты

вот

настолько

разносторонний человек, еще и яхтами

***** «Компьютерра» – компьютерный еженедельник, издававшийся с 21 декабря 1992 года по 15 декабря 2009 года издательским домом «Компьютерра». Всего вышло 812 номеров журнала. Учредитель и владелец журнала – Дмитрий Мендрелюк / http://ru.wikipedia.org/wiki/Компьютерра.

15


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА увлекаешься. Как свела судьба с парусным

Дарья: Честно говоря, у меня сплошной Google.

Дарья: Да как-то сложилось так. Родилась у

ниях уже публиковалась?

Поехала учиться во Владивосток, тоже потому

Дарья: Не знаю :) Некоторые интернет-ресурсы

спортом?

океана, отец моряк, всегда стремилась к морю.

что море. Начала ходить на яхте после третьего

курса. Просто пришла в яхт-клуб и сказала «Хочу».

И

мне

сказали

«Да

пожалуйста».

Несколько лет ходила в женском гоночном

Редакция: Если не секрет, в каких изда-

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

Редакция:

Как

твои

друзья

экипаже на небольшой лодке. Потом перешла

относятся к твоей работе?

ходить

Дарья: Положительно.

на яхту побольше. А в прошлом году начала на

совсем

большой,

40-футовой,

и

почувствовала себя совсем на своем месте. Да и

выбор Санкт-Петербурга как следующего места жительства тоже во многом был обусловлен близостью к воде.

Редакция: За границей довелось побывать

и

родные

Редакция: Хватает-ли времени на личную

жизнь?

Дарья: Сложно сказать.

в ходе регат?

Редакция: Каковы планы на будущее?

Дарья: В прошлом году участвовала в двух

Дарья: Очень интересует Window Phone 7. Java

шли туда своим ходом из Владивостока четыре

обратно на C#. Занялась бы iOS, но только если

международных регатах в Южной Корее. Плюс дня.

Редакция: Поделишься парочкой фотогра-

фий из водных путешествий? Дарья: Поделюсь...

Редакция: В дороге читаешь? Какими гад-

жетами пользуешься?

Дарья: В метро читаю со своего HTC Desire.

Для более долгих поездок он, к сожалению,

подходит плохо: очень быстро садится батарея.

Приглядываюсь к планшетам и электронным

читалкам, но пока в раздумьях.

Редакция: Пятерка ежедневных просмот-

ров Интернет-ресурсов?

– дурацкий язык все-таки, иногда так хочется

бы

кто-нибудь

выдал

мне

соответствующее

железо. Я искренне восхищаюсь Apple, но

почему-то их продукция не вызывает у меня желания ее покупать и пользоваться. Редакция:

Какое

у

тебя

отношение

к

Интернету в целом и к социальным сетям в

частности?

Дарья: Интернет для меня – источник информации.

Большая

часть

того,

что

я

знаю,

найдена в гугле, на Stackoverflow и в прочих

злачных местах. Форумы не люблю, потому что

разговоры там неконструктивные. На сервисах,

в которых в каком-то виде есть механизм

кармы, ситуация получше.

Что до общения в интернете, то оно мне

неинтересно. Комментировать что бы то ни

16


ПРО

№16 (июль) 2011

граммист

VIP ПЕРСОНА было считаю лишенным смысла. К соцсетям

то там пишу, но сама не понимаю, зачем.

основных соцсетях у меня есть, но делать мне

Редакция: Даша, спасибо тебе огромное за

отношусь

индифферентно.

Профили

на

там особенно нечего. Но и удалять не стану,

потраченное время и столь увлекательное

целей (мне по работе много приходится с ними

и твоим близким!

пусть живут для связи со мной и для тестовых

работать). Твиттер и вовсе штука странная. Я

интервью. Желаем всяческих успехов тебе

завела там аккаунт с год назад, когда уходила в

И... пару слов для наших читателей?

информировать родных о том, что со мной

Дарья: Спасибо за внимание, успехов вашим

море на две недели, и исключительно чтобы

происходит. До сих пор время от времени что-

проектам.

17


ПРО

№16 (июль) 2011

граммист

МЕРОПРИЯТИЯ, КОНФЕРЕНЦИИ Анна Голева

ann.goleva@BEST.eu.org

МЕЖДУНАРОДНЫЙ АКАДЕМИЧЕСКИЙ КУРС ПО ЭНЕРГЕТИКЕ С 3 по 13 июля 2011 года в ЗНТУ прошел международный академический курс, посвященный изучению основ энергетики. Событие состоялось при поддержке ректората, а также профкома студентов, аспирантов и докторантов ЗНТУ. Организатором академического курса является международная студенческая организация BEST – Board of European Students of Technology – Совет студентов технических вузов Европы (www.BEST.eu.org). Партнером Академического курса является ПАО «ПБК» «Славутич» в городе Запорожье.

BEST – это неприбыльная неполитическая организация, в

выми знаниями по энергетике, в частности

состав которой входят 90 локальных групп в 30 странах

видам энергии, их преимуществам и недостат-

студентами, университетами и компаниями. В реальности

каким путем двигаться дальше.

Европы. Организация выступает, как связующее звено между BEST

активно

развивает

студентов

в

трех

основных

направлениях: дополнительное образование, привлечение к образованию

В

есть владение молодыми специалистами базо-

и

поддержка

современном

мире

карьерных

возможностей.

энергетика

играет

кам, ведь именно они будут в будущем решать, В мероприятии приняли участие 22 студента со

всей Европы. На протяжении курса участники

посетили предприятия Запорожской и сосед-

них областей, которые специализируются на разных

видах

энергии

неотъемлемую роль, как в бытовом смысле, так

энергия

Артем Степанченко пресс-секретарь +38 (063) 162 - 15 - 84 artem.stepanchenko@BEST.eu.org

Анна Голева главный организатор +38 (063) 216 - 16 - 21 ann.goleva@BEST.eu.org

и в глобальном масштабе. Поэтому, важнейшим

ветра).

Данная

(атомная, тема

гидро-

курса

и

была

выбрана в виду ее чрезвычайно актуальности

18


ПРО

№16 (июль) 2011

граммист

МЕРОПРИЯТИЯ, КОНФЕРЕНЦИИ

как для Украины, так и для всего современного

ван для достижения целей нашей организации,

электростанция,

качественного образования студентам техни-

мира. Ведь в Запорожье расположена гидроа

в

Энергодаре

находится

крупнейшая в Европе атомная станция, там же

а именно – предоставление дополнительного

ческих университетов. Кроме того, это также

работают и две тепловые станции.

будет способствовать интеграции Украины в

Международный академический курс организо-

между молодежью разных стран.

* На фото выше участники международного академического курса «AC/DC: Track 02 – I’ve got the power» по энергетике.

Европейское сообщество и расширению связей

19


ПРО

№16 (июль) 2011

граммист

Александра Кушнарева

pr@cee-secr.org

МЕРОПРИЯТИЯ, КОНФЕРЕНЦИИ

КОНФЕРЕНЦИЯ ПО РАЗРАБОТКЕ ПО CEE-SECR 2011 Научно-практическая конференция «Разработка ПО 2011/ Software Engineering Conference (Russia)» – ключевое событие индустрии программирования России и стран Центральной и Восточной Европы. История конференции началась в 2005 году. Тогда это стало очень ярким событием для всего ИТ- сообщества России. За прошедшие шесть лет конференция выросла до статуса международного форума и стала знаковым событием как для российских разработчиков программного обеспечения, так и для западных ИТ- специалистов.

CEE-SECR 2011 – ежегодная независимая конференция, собирающая около 1000 участников,

среди которых разработчики ПО, исследователи, инженеры-практики, лидеры общественного

мнения, предприниматели и инвесторы. CEE-SECR завоевала заслуженный авторитет главного

профессионального события в индустрии разработки программного обеспечения в России и странах Восточной Европы. В этом году партнерами конференции уже стали: Российская

венчурная компания, Intel, EMC, Luxoft, Parallels, First Line Software, Руссофт, Высшая школа экономики, журнал ПРОграммист и ряд других компаний.

Хорошая новость для всех, кто еще не успел

• освобождает

разработке программного обеспечения – CEE-

• помогает заявить о себе;

подать доклад на главную конференцию по

SECR 2011 (31 октября – 3 ноября, Москва, Digital

October).

Заявки

на

участие

в

взноса;

от

уплаты

организационного

• ставит на одну сцену с гуру программной инженерии;

конференции с докладом принимаются до 1

• гарантирует широкое обсуждение волную-

В программу конференции входят такие темы

Внеси свой вклад в программу конференции и

августа* 2011 года.

как: облачные вычисления, Agile- методологии, разработка

языки

мобильных

приложений,

программирования,

новые

приложения

щих вас проблем;

индустрию программного обеспечения!

для

социальных сетей, надежность ПО, образование

и многие другие. Кроме

того,

докладов

на

сообщаем

о

конференцию

начале

приема

«Разработка

ПО

2011: Банки», которая пройдет в рамках CEESECR**.

Участие

в

конференции

в

качестве

докладчиков дает целый ряд неоспоримых

преимуществ:

Место проведения конференции:

Москва, Берсеневская набережная, 6, стр. 3

* О правилах и процедуре подачи докладов смотрите тут http://www.secr.ru/for-speakers. ** Подробнее на ресурсе http://www.secr.ru/banks.

20


ПРО

№16 (июль) 2011

граммист

ОБЩИЕ ВОПРОСЫ Алексей Шишкин

alexcones@gmail.com

ПЕРФЕКЦИОНИЗМ – БОЛЕЗНЬ ИЛИ ДАР?

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

Введение Начнем с того, что узнаем: что же такое

перфекционизм? В психологии, перфекционизм

убеждение,

что

наилучшего

результата

биологических

математическая линий

не

точность

это

ли

совершенство? А может где-то здесь можно

что-то улучшить? Нет. Он идеален.

можно (и нужно) достичь. В патологической форме –

убеждение, что несовершенный

результат работы неприемлем. Может быть как

«нормальной» характеристикой личности, так и невротическим психическим отклонением.

Иными

словами,

перфекционист

человек,

который всегда пытается сделать все идеально.

Но, смотря с точки зрения компьютерного

мира, болезнь ли это? Как

уже

было

сказано,

в

современном

компьютеризированном мире, где существуют

терабайтные жесткие диски, многогигабайтные

планки памяти и практически неограниченные

интернет каналы, мало, кто заботится о том,

давать ли переменной один байт или 4. Но

можно ли

совсем забыть о тех тонкостях

программирования, профессионала,

которые

способного

отличают

перепрошить

спутник на орбите и школьника, написавшего

свой первый Hello World? Я говорю – «Да» и одновременно с этим «Нет!». Но рассмотрим

же

причины,

именно так.

побудившие

меня

ответить

Посмотрим же на современные компьютеры – имея огромное число ячеек памяти, реально он

Идеал Рассмотрим

Рис. 1. Витрувианский человек*

используется «Витрувианского

человека»

Да

максимум

на

10%

своих

вычислительных способностей. Т.е. в основной

своей массе внутри процессора и оперативной

* Витрувианский человек – рисунок, сделанный Леонардо Да Винчи примерно в 1490-1492 годах как иллюстрация для книги, посвященной трудам Витрувия, и помещённый в одном из его журналов. На нём изображена фигура обнажённого мужчины в двух наложенных одна на другую позициях: с разведёнными в стороны руками и ногами, вписанная в окружность; с разведёнными руками и сведенными вместе ногами, вписанная в квадрат. Рисунок и пояснения к нему иногда называют каноническими пропорциями. Рисунок сам по себе часто используется как неявный символ внутренней симметрии и идеала человеческого тела, и далее, Вселенной в целом / Историческая справка.

21


ПРО

№16 (июль) 2011

граммист

ОБЩИЕ ВОПРОСЫ памяти гоняется «мусор». Вот например, код

высокого уровня:

которая

В IDE Lazarus он был написан примерно секунд и

и

занятой

10-20%

Но

существует

позволяет

оперативной

процессорного ли

пренебречь

ситуация,

подсчетом

ЦП? Да, такие ситуации существуют.

End;

простой

постоянно

занимаемой оперативной памяти и загрузкой

Form1.Label1.Caption := 'Just a text';

Этот

Мб

времени!**

Begin

10.

80

памяти

Procedure Tform1.Button1click(Sender: Tobject);

за

процессорного времени. В сумме это даст 70-

читаемый

код,

в

результате компиляции преобразовался в более

Как пример, рассмотрим приложение, которое

не

будет

работать

постоянно,

например

калькулятор или таблица символов (текстовый

редактор

в

качестве

данного

примера

не

чем 300 (!) строк ассемблерного кода (и это без

подходит по причине того, что он может быть

это

запускаются на 30-50 секунд �� не играют

учета вызова системных функций). Да разве же проблема?

спросите

вы.

И

будете

неприятно удивлены, узнав, что в идеальном

случае эти триста строк могут быть заменены

одним вызовом API-шной функции TextOut. К

слову

сказать,

в

скомпилированном

виде

вышеупомянутый код вызывает DrawText около

7-ми

раз!

Вот

оптимизатора!

она,

сущность

встроенного

Но все ли так плохо? Нельзя ли пренебречь

результатами данного «исследования»? И снова ответ будет двусмысленным: и «да», и «нет».

Рассмотрим ситуацию, которая отвечает на вопрос «нет»:

Представьте, что вы только что установили операционную

«облагородить»

ее

систему с

и

помощью

хотите

виджетов,

запущен большой

запускать

Существует

вы

загрузили

все

эти

виджеты, имеющиеся в W7, а к примеру, сторонние гаджеты для WinXP) и установили их

себе на рабочий стол. Что же будет в ситуации,

когда они сделаны по принципу «положил

кнопку на форму»? Произойдет следующее –

каждое приложение будет «откусывать» около

7-8

Мб

оперативной

памяти

и

1-2%

** Стандартные виджеты тоже «кушают» память, зависит от функциональности и наличия обращения к методам WMI в гаджете / Редакция.

десять

копий

не

картине

придет

в

данных.

голову

калькулятора

и

множество

программу

потреблять

программы

полностью

функций

напрямую...

способов

немного

заставить

памяти

и

ассемблере

и

процессорного времени – это и написание на

ассемблерные вставки и использование API

«ускорителем»

всегда

Но

будет

главным умение

оптимизировать код. Например, можно убирать «лишние» переменные:

Begin

что

общей

приложения

Способы ускорения программ

курсов валют, заполненности дисков и т.д.

приложения (мы рассмотрим не стандартные**

Такие

в

никому

держать их в фоне.

Var

Предположим,

роли

Разумеется,

гаджетов и прочих индикаторов. Предположим,

что вам нужны часы, календарь, индикаторы

постоянно).

A, B, C : Integer; A := 5; B := 6; // C := B; B := A; A := C; End;

Легко преобразовывается в:

22


ПРО

№16 (июль) 2011

граммист

ОБЩИЕ ВОПРОСЫ Var

A := 84;

A, B : Integer;

B := 4;

Begin

//

A := 5;

R := A * B;

B := 6;

End;

//

Оптимизируется в:

A := A + B; B := A – B; A := A – B;

Var

End;

Также,

A, B, R : LongInt;

если

медленные

возможно,

заменяйте

операции

самыми

так:

сложение,

самые

быстрыми.

В

порядке убывания скорости операции можно

расположить

умножение, деление:

вычитание,

Var A, B, R : Real; Begin A := 2; B := 0.8; // R := A / B; End;

Можно заменить на: Var A, B, R : Real; Begin A := 2; B := 1.25; //

Begin A := 84; B := 2; // R := A shl B; End;

Заключение К чему же мы пришли в споре о идеалистах?

Да все к тому же ответу: и «да», и «нет». Да, вы

ДОЛЖНЫ оптимизировать ваши приложения,

если они будут запущены в фоне или будут запускаться очень часто. И нет, вы можете не

оптимизировать их (разумеется, в разумных

пределах – например, недавно я заметил, что

при некоторых операциях мой «porthole»***

начинал «кушать» около 2 Гб памяти), если

приложения будут запускаться на короткий

срок.

Но

всегда,

прежде

чем

отдавать

созданные вами приложения заказчику или

пользователю поставьте себя на его место. Удачи!

R := A * B; End;

Не забывайте про то, что существуют операции сдвига: Var A, B, R : LongInt; Begin

*** Porthole – визуальная оболочка для системы portage linux-систем. Баг наблюдался при создании больших списков пакетов на удаление / Автор.

23


ПРО

№16 (июль) 2011

граммист

http://tigor.org.ua

Игорь Теслюк

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

ЭНЕРГОЭФФЕКТИВНОСТЬ БРАУЗЕРОВ

Энергоэффективность популярный тренд последних лет. Изначально он интересовал пользователей ноутбуков и телефонов. Производители мобильных процессоров и компонентов пристально следили за потреблением энергии и всячески пытались его минимизировать. Сейчас борьба за Ватты расширилась на стационарные компьютеры и серверы. И это логично, в масштабах датацентров или крупных офисов снижение энергопотребления на несколько процентов позволяют экономить солидные суммы. Да и об экологии модно заботиться. Как бы не старались производители железа

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

программы,

то

потребление

подскакивает. Инженеры Microsoft опублико-

вали в блоге IE отчет о потреблении энергии последними версиями популярных браузеров:

Internet Explorer 9, Chrome 10, Firefox 4, Opera 11, Safari 5. Понятно, что официальный блог

выставит свою продукцию в наилучшем свете, в частности,

графики

браузеров

ничтожна

потребления Windows,

ОС.

так

что

обрезаны

Разница на

в

фоне

бросать

на

величину

потреблении потребление

свой

любимый

браузер ради более эффективного не стоит, но

для

академического

интереса

посмотреть на поведение подопытных.

можно

Методика тестирования Самый интересный момент в тестировании –

оборудование. Интернете

В

большинстве

тестирование

производится

обзоров

в

энергопотребления

втыканием

ваттметра

между

Microsoft

может

компьютером и розеткой, либо по времени работы

от

аккумулятора.

позволить себе аппаратный тестовый комплекс, где

с

мать,

каждого

сетка

и

компонента(процессор, т.д.)

энергопотребления. точки

зрения

снимаются

Это

очень

изучения

энергопотребления.

ОЗУ,

показания

интересно

причин

с

разного

Рис. 1. Тестовый стенд, у каждого компонента

измеряется потребление энергии и передается на стойку от National Instruments

Для

чистоты

эксперимента

после

каждого

теста заново устанавливается операционная

система Windows 7 Ultimate, накатываются все

обновления

и

дефрагментируется

жесткий

диск. Это по идее должно уменьшить влияние

24


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

Рис. 2. Потребление электроэнергии в «чистой системе» ОС на результаты тестов.

Потребление с открытой пустой вкладкой

Проводилось несколько тестов:

Запускается

• голая система – для установления базового уровня потребления ОС;

• браузеры

с

открытой

about:blank

изучения потребления кода браузера;

для

• загрузка популярного новостного ресурса – потребление в HTML4;

• загрузка HTML5 Galactic – проверка работы HTML5;

• тест FishIE Tank.

браузер

и

открывается

about:blank. Результат показан на рисунке 2. С

пустой

примерно

результаты

вкладкой

устанавливает

браузеры

одинаково.

обусловлены system

ведут

себя

что

она

«Выдающиеся»

тем,

timer

resolution

стандартных 15 мс на 2 мс. Это не дает

процессору

перейти

энергопотребление.

на

пониженное

Чистая система Потребление тестовой

компонентов

системы

с

запущенной ОС Windows 7

показано на рисунке 1. В

среднем ОС потребляет 10

Ватт, что и установлено как

базовую

линию

остальных графиков.

для

со

Рис. 3. Потребление с открытой пустой вкладкой

25


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ Потребление на новостном сайте (HTML4)

перезагружалась.

Чтобы исключить влияние сети на показания,

Видно,

загружена в сетевой кеш, и все браузеры

приходится

страница популярного новостного ресурса была загружали

графикам,

идентичную эта

страницу.

страница

Судя

по

циклически

что

Chrome

активней

использует

видимо,

ускорение

ресурсы системы. Большая часть потребления на

GPU,

средствами видеокарты еще плохо допилено

(рисунок 5).

Рис. 4. Потребление Internet Explorer 9 в тесте HTML4

Рис. 5. Потребление Chrome 10 в тесте HTML4

26


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ Firefox 4 эффективно использует ресурсы, и

стал

испытания показанный на рисунке 6. Как и

тесте HTML4 на рисунке 10.

разница

с

IE9

не

заметна.

Результаты

Chrome 10, Opera 11 дергает систему, что

самым

прожорливым.

HTML5 Galactic

ресурсов (рисунок 8). Неожиданно Chrome 10

Для

равномерное

использование

видно

из

диаграммы средних результатов браузеров в

видно по графику на рисунке 7. Safari 5 же

демонстрирует

Это

теста

возможностей

HTML5

был

Рис. 6. Потребление Firefox 4 в тесте HTML4

Рис. 7. Потребление Opera 11 в тесте HTML4

27


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

Рис. 8. Потребление Safari 5 в тесте HTML4

Рис. 9. Средние результаты браузеров в тесте HTML4 использован

визуализатор

тест

Galactic.

галактики.

Чтобы

Это

такой

ничего

не

влияло на результаты тестов, все фотографии космоса хранились на локальном сервере. В

тестах

мерно

HTML5

возросло.

энергопотребление Причина

равно-

возросшее

использование видеокарты. По сравнению с

IE9, Chrome очень сильно использует CPU (рисунок 11). О причинах можно только гадать,

но это уменьшает время серфинга по тяжелым

HTML5 страницам на четверть.

Потребление Firefox 4 – тут без комментариев,

28


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

Рис. 10. Потребление Internet Explorer в тесте Galactic HTML5

Рис. 11. Потребление Chrome 10 в тесте Galactic HTML5 ноздря в ноздрю с IE9. Результаты показаны на

результатам, показанным на рисунке 13. Opera

поддерживать

тест отобразить не смогла.

рисунке

12.

Вроде

как

Safari

ускорение

5

должен

изображения

видеокартой, но тут оно как-то не до конца работает. сильно

В

итоге

возрастает.

потребление Это

хорошо

процессора видно

по

11 просто не умеет работать с ECMAScript 5, и

Общие результаты HTML5 Galactic по всем

браузерам показаны на рисунке 14. Если в

29


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

Рис. 12. Потребление Firefox 4 в тесте Galactic HTML5

Рис. 13. Потребление Safari 5 в тесте Galactic HTML5 тесте HTML4 Safari5 был на одном уровне с IE9

то FF4. Видимо Эпл может только рассказывать об

энергоэффективности

реализовать ее на практике. HTML5 FishIE Tank

HTML5,

но

не

Это собственный тест Microsoft. В каждом

браузере запускался аквариум с 10-ю рыбками.

Это позволяет всем тестируемым браузерам

выдавать стандартные 60 fps (как красиво

кинули камень в соседский огород). Почему-то

красивых и наглядных графиков нет, а только

итоговая таблица:

30


ПРО

№16 (июль) 2011

граммист

ПЕРЕВОДНЫЕ МАТЕРИАЛЫ

Рис. 14. Потребление браузеров в тесте Galactic HTML5 Таблица. Итоги сравнения браузеров

Конечно

Конечно,

же

Internet

никто

Explorer

только

по

9

победил.

причине

энергопотребления не будет менять браузер, но

как

один

использовать. По итогам браузеры разделились на: крутые

IE9 , FF4, и не такие крутые Chrome 10, Safari

5, Opera 11. Итоги

из

аргументов

можно

Основной проблемой для Safari 5 и Chrome 10 стало

потребление

процессора

в

тестах

с

HTML5. Доработав акселерацию средствами

видеокарты, эти браузеры выйдут на один

уровень с IE9 и FF4. Источники • Ресурс автора

http://tigor.org.ua/browsers-energy-efficience

• Работа с Google AdSense в Mozilla Firefox

http://tigor.org.ua/mozilla_firefox_and_google

• Оригинал статьи. Блог разработчиков IE

http://blogs.msdn.com/b/ie/archive/2011/03/28/

browser-power-consumption-leading-theindustry-with-internet-explorer-9.aspx

31


ПРО

№16 (июль) 2011

граммист

Михаил Жигимонт http://misher.ru

WEB - ТЕХНОЛОГИИ

АНИМИРОВАННОЕ МЕНЮ НА JQUERY

Одним из наиболее значимых вопросов для WEB-программистов является создание красивого дизайна сайта. В этой статье я опишу создание нескольких красивых анимированных меню с помощью библиотеки JQuery, которые вы сможете применить в своем будущем проекте.

Введение

Теперь подключим jQuery к странице:

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

щееся меню по нажатию на клавишу (пример

<script src="js/jquery.js" type="text/javascript"></script>

1). Далее мы создадим такое же меню, только

Введем функции функции, по нажатию на

чего напишем горизонтально выпадающее ме-

нажатию оно будет закрываться:

размещенное по горизонтали (пример 2). После

ню при наведении на него курсора (пример 3).

Пример первый

можно

http://jquery.com.

на

официальном

сайте

Я пишу в Notepad++ поскольку он удобен для меня.

<script type="text/javascript"> $(document).ready(function(){

Нам нужно скачать библиотеку jQuery. Скачать ее

кнопку, меню будет открываться, и по второму

Приступим

к

написанию

меню.

Открываем Notepad и добавляем в него данный код:

$(".btn-slide").click(function(){ $("#panel1").slideToggle("slow"); $(this).toggleClass("active"); return false; });

$(".btn-slide2").click(function(){ $("#panel2").slideToggle("slow"); $(this).toggleClass("active2"); return false; });

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

});

<html xmlns="http://www.w3.org/1999/xhtml">

</script>

<head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" /> <title>jQuery jQuery. Создание анимированного меню-1</title>

Добавим

функцию

клика

которая

привязывается к элементу (“.btn-slide”). Далее

мы

открываем

меню,

которое

* HTML была одной из первых вещей, которую Джон Резиг освоил, когда он только начал заниматься программированием. Резиг программировал на QBasic, когда один его знакомый показал ему, как создать веб-страницу (используя Angelfire), а также основы HTML. Отец подарил ему на Рождество две книги по HTML. Именно тогда, когда он только начал программировать на Visual Basic, HTML и веб-дизайн очень заинтересовали его. Но страсть к JavaScript пришла значительно позже, примерно в 2004 году. Тогда Резиг получал степень в области компьютерных наук и работал на полставки в местной фирме Brand Logic. Он занимался дизайном сайта, в котором создавался пользовательский скроллинг. Джон был разочарован и расстроен, особенно потому, что использовал код других разработчиков, после чего решил серьезно изучить JavaScript. Изучив, пришел к выводам, что JavaScript — это простой, но изящный язык, который является невероятно мощным для решения многих задач. В течение ближайших пары лет Д. Резиг создал множество различных JavaScript приложений, прежде чем закончить создание jQuery. Основной целью создания jQuery Резиг видел возможность закодировать многоразовые куски кода, которые позволят упростить JavaScript и использовать их так, чтобы не беспокоиться о кросс-браузерных вопросах. Библиотека была представлена общественности на компьютерной конференции «BarCamp» в Нью-Йорке в 2006 году / История создания jQuery.

плавно

32


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ выдвигается (“slow”), оно прописано у нас в

background: url(images/btn-slide-2.gif) no-repeat center top;

ссылки на (“active”).

.btn-slide, .btn-slide2 {

блоке (“#panel1”) . И изменяем класс самой

Со

скриптом

завершили,

добавить блоки и классы:

теперь

}

background: url(images/white-arrow.gif) no-repeat

нужно

right -50px;

text-align: center;

width: 144px; height: 31px;

<style type="text/css">

padding: 10px 10px 0 0;

body {

margin: 0 auto;

margin: 0 auto;

display: block;

padding: 0;

font: bold 120%/100% Arial, Helvetica, sans-serif;

width: 520px;

color: #fff;

font: 75%/120% Arial, Helvetica, sans-serif;

text-decoration: none;

}

}

a:focus {

.btn-slide2 {

outline: none;

background: url(images/white-arrow.gif) no-repeat

}

right 15px; height: 25px;

.panel {

padding: 15px 10px 0 0;

background: #ccc;

}

height: 75px;

.active {

display: none;

background-position: right 12px;

}

}

.panel ul {

.active2 {

margin: 0;

background-position: right -45px;

padding: 0 15px;

}

float:left;

.bottom {

list-style:none;

position: absolute;

border-right: 1px solid #000;

bottom:0px;

}

margin: 0 auto;

.panel ul li{

padding: 0;

margin: 6px; padding: 0;

width: 520px; }

}

</style>

.panel ul li a{

</head>

font-weight:bold; color: #333; } .slide2 { margin: 0; padding: 0; border-bottom: solid 4px #aaa;

<body>

Переходим к html: Добавляем класс panel из блока panel1 <div class="panel" id="panel1">

33


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ Пишем 4 столбца по 3 абзаца. Ссылки назовем

«Заголовок»: <ul>

panel описаны с цифрой 2: <div class="bottom">

<li><a href="#" title="Элемент 1">Заголовок 1</a></li>

<p class="slide2"><a href="#" class="btn-slide2">Меню</a></p>

<li><a href="#" title="Элемент 2">Заголовок 2</a></li> <li><a href="#" title="Элемент 3">Заголовок 3</a></li> </ul>

<div class="panel" id="panel2"> <ul>

<ul>

<li><a href="#" title="Элемент 1"> Заголовок 1 </a></li>

<li><a href="#" title="Элемент 1">Заголовок 1</a></li>

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li>

<li><a href="#" title="Элемент 2">Заголовок 2</a></li>

<li><a href="#" title="Элемент 3"> Заголовок 3</a></li>

<li><a href="#" title="Элемент 3">Заголовок 3</a></li> </ul>

</ul> <ul>

<ul>

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li>

<li><a href="#" title="Элемент 1">Заголовок 1</a></li>

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li>

<li><a href="#" title="Элемент 2">Заголовок 2</a></li>

<li><a href="#" title="Элемент 3"> Заголовок 3</a></li>

<li><a href="#" title="Элемент 3">Заголовок 3</a></li> </ul>

<ul>

<ul>

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li>

<li><a href="#" title="Элемент 1">Заголовок 1</a></li> <li><a href="#" title="Элемент 2">Заголовок 2</a></li> <li><a href="#" title="Элемент 3">Заголовок 3</a></li> </ul>

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li> <li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul> <ul>

</div>

Добавляем

</ul>

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li>

класс slide и делаем активацию

класса btn-slide при нажатии на ссылку с надписью «Меню»

<p class="slide"><a href="#" class="btn-slide">Меню</a></p>

Здесь все тоже самое только здесь пишем

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li> <li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul> </div> </div> </body> </html>

нижнее меню. В котором класс slide, btn-slide,

Все, анимированное меню (см. рисунок 1 и 2)

Рис. 1. Пример открытого верхнего меню

Рис. 2. Пример открытого нижнего меню

34


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ создано. Пример второй Подготовьте страницу... Пишем скрипт.

в css… <style type="text/css"> body { margin: 0 auto; padding: 0;

<script type="text/javascript">

/*width: 520px;*/

$(document).ready(function(){

font: 75%/120% Arial, Helvetica, sans-serif; }

$(".btn-slide").toggle(function(){ $(this).parent().parent().find(".panel").animate({"width":

.body {

"+=120px"}, "slow");

padding:0;

$(this).toggleClass("active"); return false; },function(){

border: 1px #ccc solid; }

$(this).parent().parent().find(".panel").animate({"width": "-=120px",opacity: "hide"}, "slow");

a:focus {

$(this).toggleClass("active"); return false;

outline: none;

});

}

});

.left{

</script>

Здесь мы открываем меню в ширину на 120px. После чего меняем класс на активный:

float:left; width:164px; } .right{ float:right;

$(this).parent().parent().find(".panel").animate({"width": "+=120px"}, "slow"); $(this).toggleClass("active"); return false;

width:164px; } .panel{ width:0px;

Далее следует точно такой же код, только мы

background: #ccc;

указываем такое же плавное скрытие на -120px, то есть назад. И присвоим класс активный: },function(){

height: 265px; display: none; } .left .slide {

$(this).parent().parent().find(".panel").animate({"width":

border-left:solid 4px #aaa;

"-=120px",opacity: "hide"}, "slow");

margin: 0;

$(this).toggleClass("active"); return false;

padding: 0;

});

background: url(images/btn-slide-left.gif) no-repeat left center;

});

height: 265px;

</script>

width:38px;

Со скриптом мы закончили. Теперь описываем

float:left; }

35


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ .left .panel{

border-bottom:1px solid #333;

float:left;

padding:10px;

}

margin:0;

.right .slide {

}

border-right:solid 4px #aaa; margin: 0;

.panel ul a{

padding: 0;

font-weight:bold;

background: url(images/btn-slide-right.gif) no-repeat

color: #333;

left center;

white-space: nowrap;

height: 265px;

}

width:38px;

</style>

float:right;

</head>

} .right .panel{ float:right;

Переходим к HTML:

}

<body>

.left .btn-slide {

<div class="body">

background: url(images/white-arrow-hor.gif) no-repeat

<div class="left">

-45px 80px; text-indent: -9000%; display: block;

<div class="panel"> <ul>

height: 265px;

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li>

width:38px;

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li>

}

<li><a href="#" title="Элемент 3"> Заголовок 3</a></li>

.right .btn-slide { background: url(images/white-arrow-hor.gif) no-repeat 15px 80px;

</ul> <ul> <li><a href="#" title="Элемент 1"> Заголовок 1</a></li>

text-indent: -9000%;

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li>

display: block;

<li><a href="#" title="Элемент 3"> Заголовок 3</a></li>

height: 265px;

</ul>

width:38px;

<ul>

}

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li> <li><a href="#" title="Элемент 2"> Заголовок 2</a></li>

.left .active { background-position: 10px 80px; }

<li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul> <ul>

.right .active { background-position: -45px 80px; }

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li> <li><a href="#" title="Элемент 2"> Заголовок 2</a></li> <li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul>

.panel ul {

</div>

list-style:none;

36


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ

Рис. 3. Пример открытого левого меню <p class="slide"><a href="#" class="btn-slide">Меню</a></p>

Рис. 4. Пример открытого правого меню Все, анимированное меню (см. рисунок 3 и 4)

</div>

создано.

<div class="right">

Пример третий

<div class="panel"> <ul> <li><a href="#" title="Элемент 1"> Заголовок 1</a></li> <li><a href="#" title="Элемент 2"> Заголовок 2</a></li> <li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul> <ul> <li><a href="#" title="Элемент 1"> Заголовок 1</a></li> <li><a href="#" title="Элемент 2"> Заголовок 2</a></li> <li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul> <ul> <li><a href="#" title="Элемент 1"> Заголовок 1</a></li> <li><a href="#" title="Элемент 2"> Заголовок 2</a></li> <li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul> <ul>

Немного

предыстории...

Третьим

примером

будет горизонтально выпадающее меню. На данный момент данное меню используется

редко. Чаще попадается вертикально выпадаю-

щее меню. Но есть проекты в которых без такого меню не обойтись. Поэтому напишем

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

вертикально выпадающее меню. После чего

создавал горизонтально выпадающее меню. Готовим

страничку,

приступаем к скрипту:

подключаем

jQuery.

<script type="text/javascript"> // <![CDATA[ var timeout

= 500;

<li><a href="#" title="Элемент 1"> Заголовок 1</a></li>

var closetimer = 0;

<li><a href="#" title="Элемент 2"> Заголовок 2</a></li>

var ddmenuitem = 0;

<li><a href="#" title="Элемент 3"> Заголовок 3</a></li> </ul>

function ddmenu_open(){

</div>

ddmenu_canceltimer(); ddmenu_close();

<p class="slide"><a href="#" class="btn-slide">Меню</a></p>

ddmenuitem = $(this).find('ul').css('visibility',

</div>

'visible');

</div>

}

</body> </html>

function ddmenu_close(){

37

И


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ Дальше описываем время закрытия меню. В

if(ddmenuitem) ddmenuitem.css('visibility', 'hidden');

переменной timeout установлено значение 500.

}

Т.е. время закрытия будет равно 0.5 сек:

function ddmenu_timer(){ closetimer = window.setTimeout(ddmenu_close, timeout);

function ddmenu_timer(){

}

closetimer = window.setTimeout(ddmenu_close, timeout); }

function ddmenu_canceltimer(){

После мы обновляем таймер:

if(closetimer){ window.clearTimeout(closetimer); closetimer = null;

function ddmenu_canceltimer(){

}}

if(closetimer){ window.clearTimeout(closetimer);

$(document).ready(function(){

closetimer = null;

$('#ddmenu > li').bind('mouseover', ddmenu_open) $('#ddmenu > li').bind('mouseout',

}}

ddmenu_timer)

Теперь пишем собственно работу меню. То есть

});

когда наводим мышку открывается меню и

document.onclick = ddmenu_close;

когда ее убираем она скрывается. На этом со

// ]]>

скриптом закончили:

</script>

Здесь

немного

предыдущих

сложнее

примеров.

в

отличии

Во-первых

от

мы

добавляем переменные var timeout = 500; var

$(document).ready(function(){ $('#ddmenu > li').bind('mouseover', ddmenu_open) $('#ddmenu > li').bind('mouseout',

closetimer = 0; var ddmenuitem = 0;

});

После них мы создается функция по открытию

document.onclick = ddmenu_close;

(видимый)

</script>

меню в которой мы указываем статус visible

function ddmenu_open(){ ddmenu_canceltimer(); ddmenu_close();

ddmenu_timer)

// ]]>

Теперь описываем все в css: <style type="text/css">

ddmenuitem = $(this).find('ul').css('visibility', 'visible'); }

* { border:none;

Далее создаем функцию по закрытию формы. И устанавливаем статус видимости в прячем:

margin:0; padding:0; }

function ddmenu_close(){ if(ddmenuitem) ddmenuitem.css('visibility', 'hidden'); }

body { background:#fff;

38


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ color: #000;

list-style: none;

font:12.35px "Lucida Grande", Georgia, Arial, Verdana,

font: 11px Tahoma, Arial;

sans-serif;

}

} #ddmenu li a { a:link {

background:url(images/top-dotted.gif) right no-repeat;

color:#0054a6;

display: block;

text-decoration:none;

padding: 5px 12px;

}

text-decoration: none; width: 70px;

h1 {

color: #fff;

font-size:20px;

text-transform:uppercase;

margin-bottom:20px;

white-space: nowrap;

}

text-align:center; }

#wrap { margin:10px auto;

#ddmenu li a:hover {

width:900px;

background: #000 url(images/top-dotted.gif) right no-repeat;

}

}

#header {

#ddmenu li ul {

margin-bottom:20px;

margin: 3px 0 0 10px;

}

padding: 0;

#header a {

visibility: hidden;

position: absolute;

color:#0054A6;

width:600px;

}

}

#header a:hover {

#ddmenu li ul li {

text-decoration:underline;

display:inline;

}

}

#ddmenu {

#ddmenu li ul li a {

background:url(images/menubg.gif) repeat-x;

width: auto;

margin: 0;

background: url(images/bottom-dotted.gif) right no-repeat;

padding: 0;

display: inline;

height:43px;

color: #d9d9d9;

width:700px;

font-size: 10px;

}

padding: 3px 10px; }

#ddmenu li { float: left;

#ddmenu li ul li a:hover {

39


ПРО

№16 (июль) 2011

граммист

WEB - ТЕХНОЛОГИИ background: #000 url(images/bottom-dotted.gif)

</body>

right no-repeat; padding: 3px 10px; } </style> </head>

</html>

И результат выполнения данного скрипта (см. рисунок 5 и 6):

Приступаем к HTML- части:

Рис. 5. Пример при неактивном меню

<body> <div id="wrap">

Рис. 6. Пример активного горизонтально

<div id="header">

выпадающего меню

<h1>jQuery горизонтально выпадающее меню</h1> </div>

<ul id="ddmenu"> <li><a href="#">Заголовок</a> <ul> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> </ul> </li> <li><a href="#">Заголовок</a> <ul> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> </ul> </li> <li><a href="#">Заголовок</a> <ul> <li><a href="#">Текст</a></li> <li><a href="#">Текст</a></li> </ul> </li> <li><a href="#">Заголовок</a></li> </ul> </div>

Заключение К сожалению, из меня плохой художник и если

вам данные картинки, используемые в меню, не

понравились, просьба простить. Я лишь хотел

на

практике

показать,

что

jQuery

очень

удобная и легкая в использовании библиотека. С

ее

помощью

мы

написали

различные

анимированные меню, которыми вы сможете

украсить свой сайт. Существует множество

задач которые можно легко решить с помощью

jQuery, например: создание фотогалереи не

перезагружая сайт, увеличение картинки при

наведении на нее курсора и другие задачи

связанные с дизайном сайта. Ресурсы

• Официальный сайт jQuery http://jquery.com • Tutorials по jQuery http://docs.jquery.com/ Tutorials

• Справочник по html & css http://htmlbook.ru

• Пример создания вертикально выпадающего меню http://javascript-array.com/scripts/jquery_ simple_drop_down_menu

• Подробнее о jQuery

http://ru.wikipedia.org/wiki/JQuery

40


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ Владимир Яковлев

http://avrall.com.ua

КОДИРОВАНИЕ БАЙТА С ПОМОЩЬЮ МЕТОДА ХЕММИНГА

Данная статья – один из вариантов решения контрольной задачи по дисциплине

«Цифровые устройства и микропроцессоры» (ЦУиМП). В этой дисциплине

изучается микропроцессорный комплекс на базе микропроцессора КР580ВМ50,

именуемый как Микролаб. Программа писалась на языке ассемблер к данному

микропроцессору. Задание звучало так: реализовать прием данных (256 байт),

выполнить кодирование информации с использованием метода Хемминга. В этой

статье я приведу только часть задания, в котором будет чтение байта из ОЗУ, кодирование и сохранение в ОЗУ, т.е. подпрограмму кодирования байта по методу Хемминга.

Для

того,

чтобы

закодировать

8-битное

значение, нужно разбить байт на тетрады

(полубайты):

старшую

и

младшую,

каждой тетрады выполнить кодирование.

и

для

Для того, чтобы определить какие биты в kпоследовательности

должны

быть

контроль-

ными, нужно разложить k-последовательность по степени двойки (см. табл.):

Таблица. Разложение последовательности по степени 2

последовательность будет в виде: AB1C234D

где: A - 3,5,7; B - 3,6,7; C - 5,6,7; D - бит четности всего сообщения. Т.е. необходимо,

соответственно, просумми-ровать эти биты и

посмотреть,

если

результат

нечетный,

то нулю. Алгоритм кодирования по методу

Хемминга изображен далее на рисунке.

Коды Хэмминга являются самоконтролирующимися

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

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

цифру

этого

разряда

так,

чтобы

общее

количество единиц в изображении любого числа было,

например, четным. Одиночная ошибка в каком-либо

разряде передаваемого слова (в том числе, может быть,

и

в

контрольном

разряде) изменит четность

общего количества единиц.

Счетчики

по

модулю

подсчитывающие

Контрольные

биты

выбираются

в

позициях

номера которых есть степень 2, остальные биты

биты

сообщения.

Т.е.

кодированная

то

контрольный бит равен единице, если четный,

чество

единиц,

2,

коли-

которые

содержатся среди двоичных цифр

числа,

могут

давать

сигнал о наличии ошибок.

41


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ

Рис. 1. Алгоритм кодирования по методу Хемминга HEM: MVI C,0

; установка начальных данных (обнуление счетчиков)

MOV D,C

; D=C=0

LXI H,8200h

; загрузка начального адреса

ML1:

MOV A,M

; загрузка байта в аккумулятор

RRC

; сдвиг вправо (выделяем старшую тетраду)

RRC

; сдвиг вправо (выделяем старшую тетраду)

RRC

; сдвиг вправо (выделяем старшую тетраду)

RRC

; сдвиг вправо (выделяем старшую тетраду)

L1:

42


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ MOV B,A

; сохраняем результат

MVI B,0Fh

; выделяем младшую тетраду для дальнейшего ; вычисления.См. прим *1

MOV A,D

; записываем знач-е счетч.в аккум-р для сравнения

ANA B

; логическое И

CPI A,2

; А=2?

MOV B,A

; сохраняем результат

JZ L7

; да

PUSH H

; сохраняем значение пары HL в стек ; загружаем значение L

MVI A,8

; проверяем

ANA B

; равен ли 3-й бит 1

- прыжок на L7(закодирован весь байт)

JPE L2

; Р=0 прыжок на L2

MVI A,10h

; см. прим. *2

MOV A,L

ORA B

;

LXI H,80FEh

; загружаем старший байт адреса Мх

MVI B,F7h

; см. прим. *1

MOV H,M

;

ANA B

;

RLC

; А<<1 (2*L+1) здесь циклический сдвиг

JNC N1

; был перенос? Нет – прыжок на N1

RLC

; A<<1

INR H

; H+1

MOV B,A

; сохраняем значение

L2:

MVI A,0Dh

N1:

; выделения 3,2 та 0-го бита

ANI FEh

; маска делает значение (2*L+1)-1=2*L

; (вычисление контр-го бита А)

MOV L,A

; загрузка младшего байта адреса

ANA B

;

INX H

; HL+1

JPE L3

; Р=1 прыжок на L3

MOV M,B

; сохранение в ячейке памяти байта

MVI A,80h

; установка контрольного бита А в 1

ORA B

;

MOV B,A

; сохранение байта

; (В=>Mx2i+1)

POP H

; восст-е из стека пред.значения адреса

; выделение 3,1 та 0-го бита

INX H

; HL+1

; (вычисление контр-го бита В)

MVI D,0

; обнуление счетчика тетрад

ANA B

;

INR C

; увеличение счетчика байтов

JPE L4

;

JNC ML1

; не равен 0? тогда прыжок на ML1

L3: MVI A,0Bh

MVI A,40h

;

ANA B

;

MOV B,A

; сохранение результата

; проверка был ли закод.байт последним

установка контрольного бита В в 1 RET

; выход из подпрограммы

L7: PUSH H

; сохраняем значение пары HL в стек

MVI A,07h

; выделение 2,1 та 0-го бита

MOV A,L

; загружаем значение L

; (вычисление контр-го бита С)

LXI H,80FEh

; загружаем старший байт адреса Мх

ANA B

;

MOV H,M

;

JPE L5

; Р=1 прыжок на L5

RLC

;

MVI A,10h

; установка бита С

JNC N2

;

ORA B

;

INR H

;

L4:

N2:

L5: MOV B,A

; сохраняем результат

ANI FEh

;

ANA A

; проверка на четность всего байта

MOV L,A

;

JPE L6

; Р=1 прыжок на L6

MOV M,B

; сохранение в ячейке памяти байт (В=>Mx2i)

MVI B,1

; установка бита D

POP H

;

ORA B

;

MOV A,M

; загрузка этого же байта для обработки ; младшей тетрады

L6: INR D

; инкр-т счетч.тетрад (1- старший, 2 - младший)

JMP L2

; прыжок на L2

43


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ По сути, мы выделяем старшую тетраду, так

• Регистр D - счетчик тетрад;

Начиная с этой строчки мы приводим 4-х битное значение к виду указанному в таблице:

• М=80FEh – здесь хранится старший байт адреса, по которому записываются

Далее:

Постскриптум

как перед этим сдвинули ее на место младшей.

Следующее действие A<<1 приводит к виду:

кодируем

закодированные байты.

Данный

алгоритм

небольшими

количества

можно

применить,

доработками,

принятых

для

байт.

Их

с

любого

количество

может быть ограничено только объемами ОЗУ.

Причем: • Регистр

• М=8200h – начальный адрес кодируемых;

С

256

счетчик

байт,

то

байт при

(поскольку

достижении

значения 256, регистр С обнулится);

Также этот алгоритм подойдет для других типов

систем,

микропроцессорных

микроконтроллеров

вычислительных

архитектуры и системы команд.

с

учетом

44

их


ПРО

№16 (июль) 2011

граммист

Дмитрий Шкаровский

http://scr1pter.blogspot.com

АЛГОРИТМЫ

A STAR. ПРОСТРАНСТВО И АЛГОРИТМ ПОИСКА ПУТИ

Данным материалом мы начинаем цикл статей по поиску кратчайшего пути из одной точки в другую с помощью алгоритма A star. В первых частях мы рассмотрим способы разделения игрового пространства и практические примеры, а в заключительной столкнемся с разной стоимостью проходимости (болота, реки, возвышенности) и ознакомимся с методами оптимизации пути. Цикл статей рассчитан для новичков. Каждая статья будет иметь теорию, наглядные примеры и примеры кода на языке С++ (если же вы владеете другим языком, то комментарии, которые сопровождают мой код, помогут вам в реализации на вашем языке программирования). Так же на моем блоге http://scr1pter.blogspot.com вы сможете посмотреть видео-примеры к статьям.

задача легкая, поэтому усложним ее. Так как в

дальнейшем мы будем рассматривать алгоритм

поиска пути A* (A star), хотелось бы отметить главный из его недостатков. Он состоит в том,

что для нахождения пути к недоступному

участку, алгоритм будет искать путь на всей

карте, потратив много времени. Этого можно

избежать, если разделить карту на закрытые

участки (недоступные друг для друга). Об этом

мы и поговорим.

Итого наша задача не только создать «карту»

пути, но и сделать так, чтобы она делилась на Пространство поиска пути – это территория

зоны («острова»). Как вы заметили по видео,

если был изменен цвет в какой то области, то

разделенная на части, где будет искаться путь

там

множество способов разделить пространство

либо на их слияние.

из

одной

поиска

точки

пути.

Это

в

другую.

клетки,

Существует

шестиугольники,

путевые точки (waypoints) и полигонная сетка (navigation

mesh).

использовать клетки.

Для

простоты

я

буду

Краткий экскурс... Мы создадим пространство поиска пути в виде

прямоугольника и разделим его на квадратики

(такой квадрат называют еще – chunk), но это

происходила

проверка

либо

на

существование отделенных друг от друга зон, Давайте

алгоритма:

пройдемся

по

этапам

нашего

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

с

в

массив для обработки. Этот квадрат будет являться частью новой зоны;

45


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ • берем первый элемент из массива клеток,

// освобождение памяти

которые нам нужно проверить, и ищем для

#define SafeDelete(b) if (b) { delete b; b = NULL;}

добавляться в тот же массив. После чего

// cетка, которая состоит из наших клеток

присваиваем новый номер зоны и удаляем

// ширина сетки

него проходимых соседей, которые будут

элементу, который мы проанализировали, мы

CMapChunk * m_Grid;

его. Этот этап мы повторяем до тех пор, пока

int m_iGridWidth;

наш массив не станет пустым;

// высота сетки

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

int m_iGridHeight; // размер чанка (клетки)

будет обнаружено.

int m_iChunkSize; // счетчик зон int m_iCountZone; // разделение клеток с определенным // типом проходимости на зоны void SplitZones(int iPassabilityType); // создание зоны void CreateZone(int iChunkID, int NewZone); // проверки на воможность перемещения по диагонали bool CheckDiagonals(int iNeighborX, int iNeighborZ, int iMasterX, int iMasterZ);

Рис. 1. Игровое поле

public: CWayMap(int iWidth, int iHeight, int iSize); ~CWayMap(void);

Пора переходить к практике. Создадим класс

// проверка существует ли клетка с

поиска пути с именем «CWayMap», который

// указанной шириной и высотой в сетке

(A star):

// смена значения проходимости клетки

потом будет использоваться и для алгоритма А*

bool CheckRange(int iChunkX, int iChunkZ); void ChangePassability(int x, int z);

class CWayMap

// возвращаем ID клетки по его ширине и высоте

{

int GetIDByPos(int iChunkX, int iChunkZ);

private:

// проверка на диапазон и проходимость клетки

// структура, которая будет являться каждой ячейкой сетки struct CMapChunk {

// проходимость int Passability;

}; // тип переменной для проходимости, // означающий что нужна проверка #define NO_INIT –1

bool CheckPassability(int iChunkX, int iChunkZ); };

Passability

у

нас

будет

отвечать

за

проходимость каждой ячейки сетки. Так же

ячейку сетки я буду называть – клетка и чанк. Таким образом, сравнив значение Passability

стартовой и конечной точки пути, можно будет

46


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ сразу узнать – можно туда попасть или нет. А если оно равно нулю, то эта зона не проходима, таким

образом

проверить:

можно

легко

это

будет

В деструкторе освобождаем память, которую

выделяли для нашей сетки: CWayMap::~CWayMap(void) {

Если (Passability) То можем_пройти;

// освобождение памяти SafeDelete(m_Grid);

Начнем с конструктора:

}

Функция «CheckRange» проверяет, существует

CWayMap::CWayMap(int iWidth, int iHeight, int iSize)

ли указанная ячейка в диапазоне нашей сетки,

{

это понадобится при поиске соседей у клетки.

// запоминаем размер ячейки

Ведь на границе карты у нашей клетки может

m_iChunkSize = iSize;

отсутствовать несколько соседей:

// вычисляем кол-во ячеек в ширину m_iGridWidth = iWidth/iSize; // вычисляем кол-во ячеек в высоту

bool CWayMap::CheckRange(int iChunkX, int iChunkZ)

m_iGridHeight = iHeight/iSize;

{ // если ширина ячейки меньше 0 или больше

m_Grid = NULL;

// ширины сетки, возвращаем false,

// создаем нашу сетку с нужным кол–ом ячеек

// с высотой так же.

m_Grid = new CMapChunk[m_iGridWidth*m_iGridHeight];

if ( iChunkX < 0 || iChunkZ < 0 ||

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

iChunkX > m_iGridWidth–1 || iChunkZ > m_iGridHeight–1)

for (int x = 0; x < m_iGridWidth*m_iGridHeight; x++)

return false;

{

return true; m_Grid[x].Passability = NO_INIT;

}

}

Функция

// у нас пока 0 зон, указываем это

«GetIDByPos»

возвращает

клетки по высоте и ширине сетки:

int m_iCountZone = 0; // делим нашу сетку на зоны, если они есть SplitZones(NO_INIT);

номер

int CWayMap::GetIDByPos(int iChunkX, int iChunkZ)

}

{

Тут все просто… мы передаем в функцию

размеры

нашей

игровой

карты

и

размер

ячейки, на которые будет разбита эта карта. Разбиваем

карту,

сохраняем

нужные

нам

return iChunkZ*m_iGridWidth + iChunkX; }

«CheckDiagonals»

проверяет,

является

ли

найденный сосед (клетка находящаяся рядом с

параметры и присваиваем каждой созданной

исследуемой) «мастер» клетки диагональным,

на данный момент нет зон, и используем

срезав углы недоступных клеток.

клетки

В моем примере я решил не допускать срезы

ячейке значение NO_INIT. Указываем, что у нас

функцию

с

«SplitZones», типом

которая

проходимости

проверяет

NO_INIT

и

разделяет их на зоны, если они есть, но об этом

позже.

и если да, то можно ли туда переместиться, не

углов (см. рисунок 2):

47


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ return false; } // в противном случае сосед «мастера» проходимый return true; }

«CheckPassability» проверяет, существует ли

такой чанк в диапазоне нашей сетки и если

существует, то является ли он проходимым: Рис. 2. Неразрешенный срез угла недоступной

ячейки (красная точка – мастер точка, зеленая

bool CWayMap::CheckPassability(int iChunkX, int iChunkZ) { // если сосед существует в нашем диапазоне

точка – ее диагональный сосед)

if (CheckRange(iChunkX, iChunkZ)) {

В эту функцию мы передаем «координаты»

// если этот сосед еще не проверялся и является проходимым

соседа и его хозяина:

if (m_Grid[GetIDByPos(iChunkX, iChunkZ)].Passability) return true;

bool CWayMap::CheckDiagonals(int iNeighborX, int iNeighborZ, }

int iMasterX, int iMasterZ)

return false;

{ // вычисяем разницу в ширине между соседем и «хозяином» int iDiffX = iNeighborX – iMasterX; // вычисяем разницу в высоте между соседем и «хозяином» int iDiffZ = iNeighborZ – iMasterZ; // если сосед является диагональным if (iDiffX && iDiffZ) { // находим первого соседа для соседа //

соприкасающимся с «хозяином»

int iContact1X = iMasterX + iDiffX; int iContact1Y = iMasterZ; // если найденный сосед не проходимый, возвращаем false if (!m_Grid[GetIDByPos(iContact1X, iContact1Y)].Passability) return false; // находим второго соседа для // соседа соприкасающимся с «хозяином» int iContact2X = iMasterX; int iContact2Y = iMasterZ + iDiffZ; // если найденный сосед не проходимый, возвращаем false if (!m_Grid[GetIDByPos(iContact2X, iContact2Y)].Passability)

}

«CreateZone» это функция непосредственного

создания зоны. В нее мы передаем номер

клетки, с которой начнется исследование по

определению закрытой зоны, а так же новый

номер зоны, который мы будем присваивать: void CWayMap::CreateZone(int iIDChunk, int iNewZone) {

// вектор номеров ячеек, для которых надо найти всех соседей std::vector

aListForCheck;

// добавляем туда номер ячейки из параметра функции aListForCheck.push_back(iIDChunk); // до тех пор пока наш вектор не пуст while(aListForCheck.size() != 0) { // вычисляем по номеру ячейки его ширину и высоту в сетке int iChunkX = aListForCheck[0] % m_iGridWidth; int iChunkZ = aListForCheck[0] / m_iGridWidth; // проходимся по всем соседям for (int i = –1; i <= 1; i++)

48


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ {

Ну и вот наша главная функция «SplitZones»,

for (int j = –1; j <= 1; j++)

которая использовалась в конструкторе:

{ int iNeighborX = iChunkX+i;

void CWayMap::SplitZones(int iPassabilityType) {

int iNeighborZ = iChunkZ+j; // проверка на диапазон и проходимость клетки

// пробегаемся по всем ячейкам сетки

if (CheckPassability(iNeighborX, iNeighborZ))

for (int x = 0; x < m_iGridWidth*m_iGridHeight; x++)

{

{ // по его ширине и высоте находим номер в сетке

// если это та зона, которую нужно проверить

int iNeighborID = GetIDByPos(iNeighborX,

if (m_Grid[x].Passability == iPassabilityType) {

iNeighborZ);

// увеличиваем наши зоны

if (m_Grid[iNeighborID].Passability != iNewZone)

if (++m_iCountZone > INT_MAX –1) // ошибка, счетчик переполнится и будет баг

{

showerror("ошибка, счетчик переполнится!");

// если он является диагональным, то можно ли // пройти в него не срезав углы

// создаем новую зону

if (CheckDiagonals(iNeighborX, iNeighborZ,

CreateZone(x, m_iCountZone); }

iChunkX, iChunkZ)) }

{ // устанавливаем ему новую зону m_Grid[iNeighborID].Passability = iNewZone; // добавляем его в вектор, // для поиска его соседей aListForCheck.push_back(iNeighborID); } } } } } // удаляем из вектора проверенную ячейку aListForCheck.erase(aListForCheck.begin()); } }

Суть такова: мы добавляем номер ячейки в

вектор, в котором каждый элемент проверяется

на возможных проходимых соседей, которые

тоже потом добавляются в вектор. И так до тех

}

Наверное уже понятно как она работает. Мы

указываем

номер

зоны,

который

надо

нужной

зоной,

проверить (в конструкторе это NO_INIT), при

первом

функция

поиске

элемента

«CreateZone»

с

находит

всех

ее

соседей... потом соседей соседей… и так далее,

присваивая им новое значение зоны… Но если

мы потом опять в цикле встретим указанный

номер зоны для проверки, то эта зона отделена от первой и проделываем для нее тоже самое.

Ну и так далее пока не найдем все отделенные

друг от друга зоны.

Как же быть, если произошли изменения на карте? Я сделал так:

пор, пока количество элементов в векторе не

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

будет искать всех соседей и метить их до тех

включая ее саму), то делаю проверку на

будет равно нулю. А это значит, что функция пор, пока мы не найдем закрытую зону.

непроходимых соседей, если больше 1 (не

разделение той зоны, в которой появилась

49


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ новая «стенка»;

• если же «стенка» наоборот убралась, я устанавливаю новую зону всем ее уникальным

по

зонам

соседям,

проверку этой новой общей зоны.

и

делаю

void CWayMap::SetPassability(int x, int z)

int iNeighborX = iChunkX+i; int iNeighborZ = iChunkZ+j; // по ширине и высоте находим номер в сетке int iNeighborID = GetIDByPos(iNeighborX, iNeighborZ); // проверка на диапазон и проходимость клетки if (CheckPassability(iNeighborX, iNeighborZ)) { // если по клику мыши мы убрали «стену»

{ // x и z это оконные координаты клика мыши,

if (iChangePassability == NO_INIT)

//

{

по ним находим ширину и высоту

// уникальна ли зона

// в сетке ячейки на которую тыкнули int iChunkX = int(x)/m_iChunkSize;

bool bNewSplitZone = true;

int iChunkZ = int(z)/m_iChunkSize;

for (unsigned int i = 0; i < aZoneForSplit.size(); i++ )

// по ширине и высоте ячейки находим ее номер в сетке {

int iChunkID = GetIDByPos(iChunkX, iChunkZ);

// если зона уже есть в списке, // запоминаем значение проходимости, так как мы его изменим

// то она не уникальна

int iChangePassability = m_Grid[iChunkID].Passability;

if (aZoneForSplit[i] == m_Grid[iNeighborID].Passability)

// если мы убираем препятствие

bNewSplitZone = false;

if (!iChangePassability) }

{ // указываем что нужна проверка

// если зона уникальная, то добавляем

iChangePassability = NO_INIT;

if (bNewSplitZone)

m_Grid[iChunkID].Passability = NO_INIT; aZoneForSplit.push_back(

}

m_Grid[iNeighborID].Passability);

else // меняем на непроходимую

// меняем цвет зоны, где убрали

m_Grid[iChunkID].Passability = 0;

// стенку, на цвет соседа // вектор зон, которые возможно соединятся

m_Grid[iChunkID].Passability =

std::vector< int > aZoneForSplit;

m_Grid[iNeighborID].Passability; }

// кол–во найденных непроходимых соседей

}

int iCountBlock = 0;

// иначе увеличиваем счетчик «плохих» соседей

// пробегаемся по соседям

else iCountBlock++;

for (int i = –1; i <= 1; i++) // если найденных непроходимых соседей больше 1

{ for (int j = –1; j <= 1; j++)

if (iCountBlock > 1)

{

{ // если это и есть ячейка, соседей

// если по клику мыши мы убрали «стену»

// которых мы ищем, то пропускаем

if (iChangePassability == NO_INIT)

if (!j && !i)

{

continue;

// пробежимся по всем ячейкам и из // всех зон в aZoneForSpli

50


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ // делаем одну общую for (int x=0; x < (m_iGridWidth * m_iGridHeight); x++) { for (unsigned int i = 0; i < aZoneForSplit.size(); i++ ) { if (aZoneForSplit[i] == m_Grid[x].Passability) { m_Grid[x].Passability = NO_INIT; break;

Рис. 3. Иллюстрация работы программы

} } }

список.

}

точку

с

наименьшим

оцененным путем в открытом списке (как

// перепроверяем и делим зону, если это требуется

будем оценивать, написано ниже) и ищем для

SplitZones(iChangePassability);

нее проходимых соседей. Найденные новые

return;

точки мы оцениваем путь и добавляем их в

}

открытый список. А исследуемую точку мы

}

удаляем из открытого списка и добавляем в

}

закрытый, чтобы больше ее не проверять.

}

Вот

Находим

и

все!

пространство

которым

Мы

поиска

сможем

реализовали

создали пути

искать

«островную»

и

на

разделили

клетки,

путь.

систему,

по

Также

которая

Повторяем предыдущий пункт до тех пор, пока не найдем конечную точку (а не найти мы ее не

сможем

закрытых

из-за друг

«островного»

от

друга

зон,

разделения

которое

мы

рассмотрели в прошлой статье). По закрытому

автоматически разделяет и делает слияние

списку строим наш путь. Работу программы,

мы можем сразу определить до поиска пути:

рисунке 3.

непроходимых зон на нашей карте. А значит,

можно ли добраться из одной клетки в другую

или нет?

Теперь рассмотрим поиск пути. У нас будет два списка, которые будут хранить номера клеток. первом

будут

клетки,

которые

нужно

проверить, во втором – клетки, которые уже

проверены. Первый список обычно называют «открытым»,

второй

Для

начала

«CWayMap»:

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

В

которую мы создадим, можно посмотреть на

«закрытым».

Мы

добавляем стартовую точку в наш открытый

немного

подправим

класс

class CWayMap { private: ... public: ... // эту функцию мы просто перенесли из private в public bool CheckDiagonals(int iNeighborX, int iNeighborZ,

51


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ Так же у нас появится еще одна структура

int iMasterX, int iMasterZ);

«WayChunk». Она пригодится для оценки пути

// функция, возвращает true если из одной точки

определенной клетки. Давайте взглянем на

// можно пройти в другую

нее:

bool IsCanWay(int iStartID, int iEndID); // возвращаем ширину сетки int GetGridWidth() {return m_iGridWidth;}

struct WayChunk

// возвращаем размер ячейки сетки

{ int ID;

int GetChunkSize() {return m_iChunkSize;}

int MasterID;

};

int G;

Тут вроде ничего серьезного кроме «IsCanWay»,

но комментарии в коде дают нам понять, что

можно смело двигать дальше, не тратя времени на ерунду:

int H; int F; };

где: ID – номер ячейки в сетке; MasterID – ее

родитель;G

bool CWayMap::IsCanWay(int iStartID, int iEndID)

стоимость

передвижения

стартовой клетки к данной. В моем примере

{

каждое

// не равны ли начальная и конечная точки пути

передвижение

вертикале

if (iStartID == iEndID)

будет

стоить

по

10

горизонтали единиц,

а

пройденного

конкретно

// за счет разделения зон

расстояния

от

рассматриваемой

начала

точки;

H

до

конечной по методу Манхеттена* (Manhattan

_Grid[iEndID].Passability) return false; // проверив одну из точек, мы сразу отсекаем случаи: // конечная точка – препятствие

method); F – сумма G и H.

Теперь становится ясно, что каждый раз, мы

будем искать точку с наименьшем значением F.

// начальная точка – препятствие

Давайте же взглянем на объявление нашего

if (!m_Grid[iEndID].Passability)

класса:

return false; return true;

class CPathfinding

}

Я еще ввел структуру «MapPoint», она будет ячеек

по

стоимость передвижения от данной клетки до

if (m_Grid[iStartID].Passability !=

позиции

и

диагонали 14. Так вот, G –это сумма единиц

return false; // проверяем, сможем туда попасть или нет,

хранить

из

сетки

в

экранных

координатах, но можно обойтись и без нее.

{ private: // стоимость передвижения по горизонтали и вертикали #define WeightLine 10 // стоимость передвижения по диагонали

struct MapPoint

#define WeightDiag 14

{

// возможные результаты int x;

enum

int z;

{

};

* Этот метод состоит в том, что мы рассчитываем расстояние только по горизонтали и вертикали, игнорируя препятствия и диагональные перемещения / Автор.

SEARTH_COMPLETED = –1,

52


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ WayMap = new CWayMap(iWidth, iHeight, iSize);

NOT_FIND_END = –2, }

FIND_END = –3 }; // наша карта

CPathfinding::~CPathfinding(void)

CWayMap* WayMap;

{

// Список, который надо проверить

SafeDelete(WayMap);

std::vector < WayChunk > m_aOpenList;

}

// Проверенный список std::vector < WayChunk > m_aCloseList;

// ищем в закрытом списке клетку по ID

// точка, до куда мы должны найти путь

int CPathfinding::GetMasterID(int iChunkID)

int iEndX;

{

// и возвращаем его мастера

int iEndZ;

for (unsigned int i=0; i < m_aCloseList.size(); i++) {

// возвращает клетку с наименьшим F

if (m_aCloseList[i].ID == iChunkID)

int GetMinWayChunk();

return m_aCloseList[i].MasterID;

// проверяем клетку, ищем ее соседей

}

bool DoSearchStep(int iChunkNum);

return –1;

// поиск в открытом списке

}

int FindInOpenList(int iChunkID); // поиск в закрытом списке

// есть ли в закрытом списке клетка с указанным ID

int FindInCloseList(int iChunkID);

int CPathfinding::FindInCloseList(int iChunkID)

// возвращаем мастер клетку по ID

{

int GetMasterID(int iChunkID);

for (unsigned int i=0; i < m_aCloseList.size(); i++)

public:

{

CPathfinding(int iWidth, int iHeight, int iSize);

if (iChunkID == m_aCloseList[i].ID)

~CPathfinding(void);

return i;

void DrawGrid(HDC dc);

}

// наша функция, которой мы будем пользоваться

return –1;

bool GetWay(MapPoint From, MapPoint To,

}

std::vector< MapPoint >* Way); };

// есть ли в открытом списке клетка с указанным ID

Не стоит пугаться, здесь большинство функций работают

с

нашими

списками,

и

ничего

int CPathfinding::FindInOpenList(int iChunkID) { for (unsigned int i=0; i < m_aOpenList.size(); i++)

сложного в них нет. Я даже не буду их

{

комментировать, просто пробежимся по ним,

if (iChunkID == m_aOpenList[i].ID)

но только после конструктора и деструктора:

return i; }

CPathfinding::CPathfinding(int iWidth, int iHeight, int iSize) {

return –1; }

WayMap = NULL; // создаем нашу карту

Функция «GetMinWayChunk» ищет в открытом

53


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ списке

клетку

с

наименьшим

F

для

ее

дальнейшего анализа (возвращает порядковый номер открытого списка):

// Родительский ID, для которого ищем соседей int iMasterID = m_aOpenList[iChunkNum].ID; // вычисляем по номеру ячейки ширину и высоту в сетке int iMasterX = iMasterID % WayMap–>GetGridWidth();

int CPathfinding::GetMinWayChunk()

int iMasterZ = iMasterID / WayMap–>GetGridWidth();

{

// проходимся по всем соседям // если открытый список пуст, то мы не нашли путь

for (int i = –1; i <= 1; i++)

if (!m_aOpenList.size())

{ for (int j = –1; j <= 1; j++)

return NOT_FIND_END;

{ // если это и есть яч��йка, соседей которых

// ищем в открытом списке клетки с наименьшим F int iMinWay = m_aOpenList[0].F;

// мы ищем, то пропускаем

int ID = 0;

if (!j && !i) continue;

for (unsigned int i=0; i < m_aOpenList.size(); i++) {

int iNeighborX = iMasterX+i;

if (m_aOpenList[i].F < iMinWay)

int iNeighborZ = iMasterZ+j;

{ iMinWay = m_aOpenList[i].F;

// проверка на диапазон и проходимость клетки

ID = i;

if (WayMap–>CheckPassability(iNeighborX, iNeighborZ)) {

}

// если он является диагональным, то можно ли

} // если H этой клетки не 0, то это не конец пути

// пройти в него не срезав углы

if (m_aOpenList[ID].H != 0)

if (WayMap–>CheckDiagonals(iNeighborX, iNeighborZ,

return ID; else

iMasterX,

{

iMasterZ)) // иначе добавляем конечную точку и сообщаем об этом

{

m_aCloseList.push_back(m_aOpenList[ID]);

// по ширине и высоте находим

return FIND_END;

// номер соседа в сетке int iNeighborID = WayMap–>GetIDByPos(

}

iNeighborX, iNeighborZ);

}

«DoSearchStep»

получает

номер

элемента

открытого списка, из которого определяет ID клетки, для которой будем искать проходимых

соседей. Каждого «хорошего» мы добавляем в

открытый список, оценивая его путь. В конце

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

bool CPathfinding::DoSearchStep(int iChunkNum) {

// если клетка проверялась, пропускаем if (FindInCloseList(iNeighborID) > –1) continue; // начинаем оценивать путь этой точки WayChunk Chunk; // устанавливаем ID клетки Chunk.ID = iNeighborID; // устанавливаем родителя клетки Chunk.MasterID = iMasterID; // стоимость передвижения Манхеттена

54


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ Chunk.H = (abs(iNeighborX – iEndX) + abs(iNeighborZ – iEndZ)) * 10;

который мы наполним точками найденного

пути. Мы будем анализировать каждый раз клетку с наименьшим F, пока не добавим

конечную точку в открытый список. Далее мы

// рассчитываем длину пути от // начальной точки до нынешней int iDiffX = abs(iMasterX – iNeighborX); int iDiffZ = abs(iMasterZ – iNeighborZ); int iDiag = min(iDiffX, iDiffZ); int iDirect = max(iDiffX, iDiffZ) –

будем следовать с конца через мастер точки,

добавляя их в путь, до тех пор, пока не дойдем

до стартовой точки. Это и будет наш путь: bool CPathfinding::GetWay(MapPoint From, MapPoint To,

min(iDiffX, iDiffZ);

std::vector< MapPoint >* Way)

Chunk.G = iDiag*WeightDiag +

{

iDirect*WeightLine +

// очищаем вектор, который мы передали в

m_aOpenList[iChunkNum].G;

// функцию, вдруг он не пустой

// вычисляем наш F

Way–>clear();

Chunk.F = Chunk.H + Chunk.G; // переводим стартовую точку в координаты сетки // есть ли наша клетка в открытом списке

int iStartX = From.x/WayMap–>GetChunkSize();

int iNumChunk = FindInOpenList(Chunk.ID);

int iStartZ = From.z/WayMap–>GetChunkSize();

if (iNumChunk == –1)

// проверяем, есть ли такая точка на карте

// если нет, то добавлем

if (!WayMap–>CheckRange(iStartX, iStartZ))

m_aOpenList.push_back(Chunk);

return false;

else

// переводим конечную точку в координаты сетки

{

iEndX = To.x/WayMap–>GetChunkSize(); // если есть, то не короче

iEndZ = To.z/WayMap–>GetChunkSize();

// ли наши новые расчеты

// проверяем, есть ли такая точка на карте

if (m_aOpenList[iNumChunk].G > Chunk.G)

if (!WayMap–>CheckRange(iEndX, iEndZ))

m_aOpenList[iNumChunk] = Chunk;

return false;

} }

// находим их ID

}

int iIDFromChunk = WayMap–>GetIDByPos(iStartX, iStartZ);

}

int iIDToChunk = WayMap–>GetIDByPos(iEndX, iEndZ);

}

// если туда добраться нельзя, возвращаем false if (!WayMap–>IsCanWay(iIDFromChunk, iIDToChunk))

// после того как с нашей точкой мы поработали,

return false;

// пора ее перенести в другой список

// добавляем в открытый список стартовую точку

m_aCloseList.push_back(m_aOpenList[iChunkNum]);

WayChunk Chunk;

m_aOpenList.erase(m_aOpenList.begin() + iChunkNum);

Chunk.ID = iIDFromChunk;

return true;

Chunk.MasterID = iIDFromChunk;

}

Chunk.G = 0;

И последняя функция, которая собирает все

части паззла. В нее мы передаем начальную

точку,

конечную

и

указатель

на

вектор,

Chunk.H = (abs(iStartX – iEndX)+ abs(iStartZ – iEndZ))*WeightLine; Chunk.F = Chunk.G + Chunk.H; m_aOpenList.push_back(Chunk);

55


ПРО

№16 (июль) 2011

граммист

АЛГОРИТМЫ // находим номер элемента, у которого минимальный F int iNumInOpenList = GetMinWayChunk(); // до тех пор пока поиск не завершится, // делаем анализ клетки с минимальным F // а после опять ищем новую клетку с минимальным F for (; iNumInOpenLis > SEARTH_COMPLETED; iNumInOpenLis = GetMinWayChunk()) { DoSearchStep(iNumInOpenLis); } bool bDone = false; if (iNumInOpenLis == FIND_END) { // добавляем конечную точку в наш вектор пути MapPoint PointOfWay; PointOfWay.x = iEndX * WayMap–>GetChunkSize(); PointOfWay.z = iEndZ * WayMap–>GetChunkSize(); int ID = –1; int iMasterID = WayMap–>GetIDByPos(iEndX, iEndZ); // до тех пор пока мы в обратном порядке // не найдем стартовую точку // через мастер точки движемся с конца в начало, // добавляя путь в вектор while (ID != iMasterID) ID = iMasterID; iMasterID = GetMasterID(ID); PointOfWay.x = ID % WayMap–>GetGridWidth()* WayMap–>GetChunkSize(); PointOfWay.z = ID / WayMap–>GetGridWidth()* WayMap–>GetChunkSize(); Way–>push_back(PointOfWay); } bDone = true; } // очищаем наши открытый и закрытый списки

return bDone; }

Рис. 5. Слева-сверху

Этот вариант реализован в коде данной статьи

(см.

рисунок

вариант:

2).

нужно

к

Чтобы

реализовать

каждой

путевой

этот

точке

добавить половину размера клетки карты по x

и z. Именно этот вариант я и буду использовать в дальнейшем.

Постскриптум Вот

мы

и

заполнили

вектор

точками

найденного пути. В общем, все просто! А еще

говорят, что алгоритм поиска пути A* сложен

для новичков.

Стоит обратить внимание на то, что мы в наш

путь добавляем все путевые точки подряд, что

совсем

{

m_aCloseList.clear();

в центре квадрата

Путевая точка, находящаяся на пересечении.

// если конечная точка найдена

m_aOpenList.clear();

Рис. 4. Путевая точка,

не

правильно.

В

дальнейшем

мы

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

А следующая статья будет посвящена опять таки алгоритму A star, но только уже в виде

картинок,

для

полного

закрепления наших знаний.

понимания

и

Ресурсы • Блог

автора.

Пространство

поиска

пути

http://scr1pter.blogspot.com/2011/05/blog–post_ 13.html

• Блог

автора.

Алгоритм

поиска

пути

http://scr1pter.blogspot.com/2011/05/blog–post_ 21.html

56


ПРО

№16 (июль) 2011

граммист

ЛАБОРАТОРИЯ Дмитрий Шкаровский

http://scr1pter.blogspot.com

CИСТЕМА

КОНТРОЛЯ

НЕИГРОВЫХ

ПЕРСОНАЖЕЙ

Rule Based Systems (cистема, основанная на правилах) – это система контроля неигровых персонажей (Non-Player Character – NPC), состоящая из ситуаций и действий (ЕСЛИ – ТО). RBS относится к рефлексивным детерминированным методам, а значит можно полностью предсказать реакцию поведения. Это, пожалуй, самый простой способ реализации ИИ в играх. Так как он прост, то и задача, с которой он должен справляться, тоже должна быть проста. При реализации AI в этой

статье (и в последующих

тоже), я буду использовать

скрипты

на

LUA.

Очень часто приходится корректировать / менять /

поэтому

улучшать поведение NPC,

использование

LUA тут очень кстати.

скриптового

языка

Давайте сформулируем очень простую задачу:

{ printf("Error Initializing lua\n"); return; } // загружает указанный файл luaL_dofile(pLua, "ai.lua"); // эта функция расшаривает функции и классы С++, // которые мы будем использовать в скрипте LuaShareNPC(pLua);

Функцию LuaShareNPC, которую мы использо-

нашими NPC будут квадратики;

вали выше, мы рассмотрим позже. Так же не

как только враг будет в поле зрения, NPC

функцию, которая закроет состояние lua:

врагом NPC будет курсор;

будет убегать от него, пока не упрется в

преграду.

Перейдем к реализации. Так как мы будем

использовать LUA для скриптинга, то давайте

с ним ознакомимся. Его исходники можно

скачать тут, так же нам потребуется LuaBind.

Я не буду рассказывать, как их собирать и подключать,

это

можно

найти

на

сайтах, поэтому перейдем сразу к делу.

других

забудьте в конце программы, использовать

lua_close(pLua);

Создадим новый класс CNpc, который мы унас-

ледуем от CPathUser (этот класс отвечает за перемещение, смотрите его реализацию в

предыдущих статьях). class CNpc: public CPathUser { private:

// создаем состояние lua

// необходимое время для паузы

lua_State* pLua = lua_open();

int m_iPouseNeed;

// инициализация luabind

// сколько времени уже прошло с последнего апдейта

luabind::open(pLua);

int m_iPouseNow;

// функция, которая открывает все стандартные библиотеки

// имя скрипта

luaL_openlibs(pLua);

std::string m_sScriptName;

// если ошибка при создании if (NULL == pLua)

.* Работу программы, которую мы создадим, можно посмотреть в ресурсах к журналу.

public: CNpc(void);

57


ПРО

№16 (июль) 2011

граммист

ЛАБОРАТОРИЯ ~CNpc(void);

if (Len < VIEW_RADIUS)

// установка имени скрипта

return true;

void SetScriptName(std::string sScriptName); // установка времени для паузы между обновлением AI void SetPauseTime(int iMilliSecond); // видим ли врага bool IsSeeEnemy(vector2f Target); // рассчитываем путь, чтобы убежать от врага

return false; };

Функция задания нового пути, следуя по кото-

рому, мы будем убегать от врага.

void RunFromEnemy(vector2f EnemyPos);

void CNpc::RunFromEnemy(vector2f EnemyPos)

// функция обновления

{

void Update(int iDeltaMilliSeconds);

vector2f Diff = normalize(GetPos() – EnemyPos);

}

SetWay(Diff*CHUNK_SIZE*2 + GetPos());

Конструктор, деструктор, установка времени для паузы и имени скрипта. CNpc::CNpc() { m_iPouseNow = 0; m_iPouseNeed = 1000; } CNpc::~CNpc() { } void CNpc::SetPauseTime(int iMilliSecond) { m_iPouseNeed = iMilliSecond;

}

Функция обновления нашего NPC. Обратите

внимание, что скрипт срабатывает не каждый кадр,

а

в

зависимости

от

параметра

m_iPouseNeed, значение которому мы устанав-

ливаем опять же по желанию (у меня это 300

миллисекунд). Таким способом мы уменьшаем

нагрузку на наш компьютер и создаем иллю-

зию того, что NPC "думает" перед принятием решения. При такой реализации нам придется

функцию передвижения использовать не в

скрипте (иначе он бы у нас ходил раз в 300

миллисекунд).

}

void CNpc::Update(int iDeltaMilliSeconds)

void CNpc::SetScriptName(std::string sScriptName)

{

{

m_iPouseNow += iDeltaMilliSeconds; m_sScriptName = sScriptName;

if (m_iPouseNow > m_iPouseNeed)

}

{ if (myLua)

Следующая функция возвращает true, если

// вызываем функцию из скрипта

враг виден. VIEW_RADIUS – это радиус взора

luabind::call_function<void>(myLua,

нашего NPC, устанавливаем значение этого

m_sScriptName.c_str(), this, CurPos);

параметра по своему желанию (у меня он

m_iPouseNow = 0;

равен 200).

} // передвигаемся

bool CNpc::IsSeeEnemy(vector2f EnemyPos)

Move(iDeltaMilliSeconds); }

{ vector2f Diff = GetPos() – EnemyPos; float Len = length(Diff);

Давайте рассмотрим функцию, которая рас-

58


ПРО

№16 (июль) 2011

граммист

ЛАБОРАТОРИЯ шаривает классы и функции для их исполь-

новый

простая, то нам потребуется всего две функ-

делаем.

зования в скриптах. Так как задача у нас ции класса CNpc, и сам класс vector2f. void LuaShareNPC(lua_State* pLua) { using namespace luabind; module(pLua) [ class_<CNpc>("Npc") .def("RunFromEnemy", &CNpc::RunFromEnemy ) .def("IsSeeEnemy", &CNpc::IsSeeEnemy ), class_<vector2f>("vec2") ]; }

И наконец, наш скрипт. Он очень прост: function Update(npc, enemy) if npc:IsSeeEnemy(enemy) then npc:RunFromEnemy(enemy) end end

Если мы видим врага (ситуация), находим

путь

(действие),

чтобы

от

него

удалиться, в противном случае ничего не Заключение Мы

убедились,

что

это

достаточно

примитивный и простой способ для органи-

зации простого ИИ в играх. При большом

объеме поставленных задач для ИИ, этот

способ

крайне

неэффективен.

В

нашем

примере всего одно условие и одно действие,

как

бы

одна

частичка

(по

поставленным

изначально задачам, нам больше и не надо).

При объединении этих частиц получается –

автоматизированная система, основанная на

правилах (проверках). Как только одно из

условий

этой

выполняется

системы.

цепи

его

возвращает

действие

и

истину,

выход

из

Ресурсы • Блог автора. – Пространство поиска пути http://scr1pter.blogspot.com/2011/06/rule–bas ed–systems.html

59


ПРО

№16 (июль) 2011

граммист

Олег Александров

smith5989@yandex.ru

ЛАБОРАТОРИЯ

TВ ДЛЯ ВСЕХ. ИНТЕГРАЦИЯ НА САЙТ...

За последние годы популярность онлайн телевидения возросла многократно, в основном за счет того, что Интернет-соединение стало лучше и позволяет смотреть потоковое видео без задержек. Если ваш сайт имеет широкую аудиторию, обязательно найдутся люди, которым будет интересен просмотр ТВ, не покидая сайт. Поэтому это позволит не только увеличить аудиторию сайта, но и сделать его более привлекательным для пользователей. Сегодня вы узнаете как организовать просмотр телеканала на личной WEB страничке или корпоративном портале.

Так-с чего начать? Для

Пройдя

нам

предпочтительными являются:

потребуется хостинг

1. Использование сторонних сервисов, таких

создать

2. Использование ActiveX технологии.

и

uCoz.

начала

Из вариантов интеграции ТВ на сайт наиболее

сайт.

Предпочту

новый,

к

примеру, на основе

несложный

процесс

как MY-TVset.ru.

3. Использование флеш-технологии.

регистрации, создадим новый сайт*. Зайдем в

Рассмотрим подробнее...

рисунок 1):

Интеграция сторонних сервисов

панель управления, в редактор страниц (см.

Рис. 1. Визуальный HTML-редактор * Всю проделанную мной работу можно посмотреть на http://tv-onliner.ucoz.ru / Автор.

60


ПРО

№16 (июль) 2011

граммист

ЛАБОРАТОРИЯ Теперь перейдем к сервису http://module.my-

<script type="text/javascript" charset="windows-1251"

tvset.ru и зарегистрируемся. Пройдя регист-

language="javascript" src="http://inoculation.my-tvset.ru/

онлайн ТВ на сайт.

<!--Вставьте эту строку в любом месте ниже блока

Код блока меню

тэгом </body>-->

рацию, сможем получить код для добавления

Для интеграции блока меню Вам необходимо

установить на свой сайт нижеприведенный код со страницы сервиса:

<!--Вставьте эту строку туда, где вы планируете разместить меню онлайн телевидения--> <div id="MY-TVset-Include"></div> <!--Вставьте эту строку в любом месте ниже блока <div id="MY-TVset-Include">...</div> </body>--> <script type="text/javascript" charset="windows-1251" language="javascript" src="http://inoculation.my-tvset.ru/ menu.php?width=241&height=490"></script>

Код трансляции

menu.php?width=241&height=490"></script> <div id="MY-TVset-Stream">...</div> или перед закрывающим <script type="text/javascript" charset="windows-1251" language="javascript" src="http://inoculation.my-tvset.ru/ stream.php?ch=1182"></script>

Добавив код, увидим что-то вроде показанного на рисунке 2.

Для активации нужно перейти по ссылке

http://module.my-tvset.ru/add-site.

Закон-

чив активацию, получим полностью рабочее ТВ.

Также можно еще взять код с сайта http:// www.piranya.com/promo.php:

<a href="http://www.piranya.com/video-russia.php"

<!--Вставьте эту строку туда, где вы планируете разместить

target="_blank">

трансляцию-->

<img width="468" height="60" border="0"

<div id="MY-TVset-Stream"></div>

src="http://www.piranya.com/promo/onlinetv.png"

<!--Вставьте эту строку в любом месте ниже строки

title="Онлайн телевидение" alt="Онлайн телевидение"></a>

<div id="MY-TVset-Stream"></div> или перед закрывающим тэгом </body>--> <script type="text/javascript" charset="windows-1251" language="javascript" src="http://inoculation.my-tvset.ru/ stream.php?ch=1182"></script>

Код меню с трансляцией <!--Вставьте эту строку туда, где вы планируете разместить трансляцию--> <div id="MY-TVset-Stream"></div> <!--Вставьте эту строку туда, где вы планируете разместить меню онлайн телевидения--> <div id="MY-TVset-Include"></div> <!--Вставьте эту строку в любом месте ниже блока <div id="MY-TVset-Include">...</div> или перед закрывающим тэгом </body>-->

Есть-ли альтернатива? Конечно есть. Это ActiveX и флэш. ActiveX –

это технология, при помощи которой браузер Internet Explorer (IE) использует другие при-

ложения внутри себя. С помощью ActiveX IE

загружает Windows Media Player (WMP), Flash,

Quicktime

и

другие

приложения,

которые

могут воспроизводить файлы, внедренные в

веб-страницы. ActiveX не поддерживается дру-

гими операционными системами, такими как

Mac или Linux.

Для добавления потокового видео на сайт

можно использовать следующий скрипт для

интеграции WMP:

61


ПРО

№16 (июль) 2011

граммист

ЛАБОРАТОРИЯ

Рис. 2. Тестирование работы скрипта** на сайте <object codebase=http://activex.microsoft.com/activex/ controls/mplayer/en/nsmp2inf.cab #Version=5,1,52,701 classid=CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95 type=application/x-oleobject standby="Loading Microsoft Windows Media Player components..."> <param name="ShowControls" value="1"> <param name="ShowDisplay" value="0"> <param name="ShowStatusBar" value="1"> <param name="AutoSize" value="1"> <param name="Filename" value="http://195.14.212.230/ stream.jsp?format=wm&bandbreite=gross&usa= mms://a236.v143427.c14342.g.vm.akamaistream.net/7/236/14342/ v0001/ondemand.dw-world.de/dwtv_video/geol/usa-gross.wmv"> <embed type="application/x-mplayer2" pluginspage="http://www.microsoft.com/Windows/Downloads/ Contents/Products/MediaPlayer/"> </embed> </object>

Где:

http://195.14.212.230/stream.jsp

адрес трансляции.

К сожалению, скрипт работает только под IE

и FF (из-за ActiveX)***.

Желаете онлайн-вещание? Рассмотрев способы реализации потокового видео на сайтe, будет нелишним обратить

внимание на способы реализации своего он-

лайн-вещания, это хоть и не так актуально, но может пригодится.

В

этом

нам

поможет

сервис

http://

ru.justin.tv. Данный портал позволяет:

1. Создавать расписание предстоящих выпусков передач (канал-расписание)

2. Задавать время эфира, длительность передачи

** Не забудьте зарегистрировать свой ресурс для установки ТВ-модуля. *** Это не совсем так. Как мы уже упоминали, в одной из наших статей, безоговорочную его поддержку обеспечивает всем известный ослик IE (Internet Explorer) и один из браузеров SpeedFirefox за счет использования NPAPI. NPAPI (Netscape Plugin Application Programming Interface) – программный интерфейс подключаемых модулей Netscape. NPAPI выполняет функции, аналогичные из ActiveX / Редакция.

62


ПРО

№16 (июль) 2011

граммист

ЛАБОРАТОРИЯ 3. Осуществлять подписку на уведомления до начала эфира передачи по расписанию, чтобы не пропустить это событие

4. Вести архив передач, выбор по датам из календаря

5. Встраивать плеер с трансляцией прямого эфира и чатом на сайт или в блог – очень удобно

во

время

проведения

тренинга,

когда участники могут задавать ведущему вопросы

6. Модерировать чат, что позволяет импортировать

(все

видео

трансляции

с

YouTube

в

плейлист

архивируются).

Можно

выделять эпизоды и экспортировать их на

Заключение Вот и все, что я хотел рассказать в рамках

этой небольшой статьи. Добавление**** он-

лайн-ТВ на свой ресурс не такая и сложная

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

твенного ТВ, о котором более подробно мы

поговорим в следующих материалах журнала.

Помните, совершенству нет предела. И удачи всем!

Ресурсы

YouTube или сохранять на свой компьютер

1. Блог автора. Создание видео для бизнеса

ным

2. Сервис MY-TVset.ru http://module.my-tvset.ru

7. Делать вещание доступным только избран-

http://blog.sozdanievideo.ru/?p=29

**** Иногда спрашивают: «На сайте установлено флэш-радио или плеер с онлайн-вещанием, но при переходе по страницам сайта, воспроизведение останавливается и начинается снова. Как сделать чтобы радио или ТВ постоянно работало?». Отвечаем: «Без ухищрений, никак». Сделайте либо фреймовую структуру c плеером на главном фрейме или смотрите в сторону WEB2.0 с динамической сменой содержимого, либо организуйте вывод Popup-окна при заходе на главную сайта. К примеру, таким кодом: <a onclick="window.open('адрес/','TIP','width=200,height=230,status=0,menubar=0, location=0,resizable=0,directories=0,toolbar=0,scrollbar=0');return false;" href="адрес/"> / Редакция.

63


ПРО

№16 (июль) 2011

граммист

ЮМОР Айтишник в доме – счастье для многих, а

отбыла в мир иной, не выдержав юношеского (а

добрый айтишник, работающий в солидной

может,

желая,

живет

конторе, – счастье вдвойне. Вот и я, сам того не стал

счастьем

для

немногих,

но

избранных. Избранные в моем случае – это те,

кто наделен толикой сокровенного знания о

том, что есть сеть и как ее халявно юзать. А

и

не

юношеского)

напора.

Сейчас

вместо простенького роутера у меня на шкафу монстр,

который

содержит

в

себе

столько всяких софтовых и хардовых примочек для порчи жизни любителям лезть куда не

просят, что бороться с ним можно только при

суть дела вот в чем: есть у меня толстый канал,

помощи кувалды. Да и на шкаф зверь был

режиме 24/365. Пока о таких вкусностях не

прекрасно

пробивает

сочетания

законов

статический IP и вайфай–точка, работающая в

знал никто, все было хорошо, но в какой–то

момент

где–то

появилось

в

некое

радиусе

охвата

дарование,

«вафли»

переселен

только

окружающим

потому,

ничего

всю

не

что

оттуда

квартиру,

достается

физики

и

в

а

он

вот

силу

особенностей

возжелавшее

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

нудно – для начала при помощи паролей,

почтовом ящике листок бумаги с просьбой

Дарование не сдавалось, регулярно наглухо

интернета хочется, что аж переночевать негде.

халявы. Борьба с дарованием велась долго и шифрования

и

прочей

софтовой

ерунды.

вешая точку. Потом был свободный канал на 128К,

но

это

почему–то

дарованию

не

нравилось, и точка в один прекрасный день

выигранной, пока сегодня не обнаружил в

открыть хоть какой–нибудь канал, а то так Вот сижу и думаю: действительно открыть

канал и успокоиться или все–таки вычислить

нахала

и

поговорить

с

ним

по

душам?

64


ПРО

№16 (июль) 2011

граммист

ЮМОР

Начало 80-х. Монголия. Город Арвай-Хээр

80-х. Но КАЛЕНДАРЬ до сих пор существует и

(административный центр аймака Уверхангай).

его

находилась военная база ГРУ Генштаба МО

и на боковой панели «Поиск» в закладке

В 10-ти километрах севернее (и чуть восточнее)

отлично

видно

из

космоса!

Хотите

посмотреть? Запустите программу Google Earth

СССР. Отец служил, мать работала, я учился в

«Перелет» наберите 46 21' 54"N, 102 49' 31"E.

Цурцула. Так вот, на горе был самый настоя-

Глаза покрасневшие, опухшие, резь ужасная...

день, месяц и год! Все цифры были аккуратно

интернет...

младших классах. База располагалась у горы

щий КАЛЕНДАРЬ, который отображал текущий выложены большими белыми досками и их

отлично видели с любого места военного город-

ка. Наверное, наибольшую пользу календарь

приносил офицерам, которые «после вчераш-

него» забывали, какой сегодня день. Для нас,

пацанов,

интерес

представлял

про-цесс

изменения даты. Он проводился каждое утро

под руководством младшего офицера, который по рации отдавал не всегда цензурные команды

солдатам, перекладывающим доски на склоне

горы. Анекдот про тетрис и рядом не валялся!

p.s.: базу расформировали во второй половине

Весенний

конъюнктивит?

Безлимитный

Что было бы, если бы BMP кодировался в

XML:

<?xml version="1.0" encoding="UTF–8"?> <bitmap width="5" height = "5"> <line> <pixel> <red>54</red> <green>43</green> <blue>123</blue> </pixel> <pixel>

67 65 9


ПРО

№16 (июль) 2011

граммист

ЮМОР <red>54</red>

<blue>15</blue>

<green>23</green>

</pixel>

<blue>126</blue>

<pixel>

</pixel>

<red>56</red>

<pixel>

<green>73</green>

<red>13</red> <green>56</green> <blue>77</blue> </pixel> <pixel>

<blue>154</blue> </pixel> </line> <line> <pixel>

<red>84</red>

<red>54</red>

<green>93</green>

<green>43</green>

<blue>15</blue>

<blue>123</blue>

</pixel>

</pixel>

<pixel>

<pixel>

<red>56</red>

<red>54</red>

<green>73</green>

<green>23</green>

<blue>154</blue>

<blue>126</blue>

</pixel> </line> <line> <pixel> <red>54</red>

</pixel> <pixel> <red>13</red> <green>56</green> <blue>77</blue>

<green>43</green>

</pixel>

<blue>123</blue>

<pixel>

</pixel>

<red>84</red>

<pixel>

<green>93</green>

<red>54</red>

<blue>15</blue>

<green>23</green>

</pixel>

<blue>126</blue>

<pixel>

</pixel>

<red>56</red>

<pixel>

<green>73</green>

<red>13</red> <green>56</green> <blue>77</blue> </pixel> <pixel>

<blue>154</blue> </pixel> </line> <line> <pixel>

<red>84</red>

<red>54</red>

<green>93</green>

<green>43</green>

66


ПРО

№16 (июль) 2011

граммист

ЮМОР <blue>123</blue>

<pixel>

</pixel>

<red>84</red>

<pixel>

<green>63</green>

<red>54</red>

<blue>15</blue>

<green>23</green>

</pixel>

<blue>126</blue>

<pixel>

</pixel>

<red>51</red>

<pixel>

<green>43</green>

<red>13</red> <green>56</green> <blue>77</blue> </pixel> <pixel> <red>84</red> <green>93</green> <blue>15</blue> </pixel> <pixel> <red>56</red>

<blue>164</blue> </pixel> </line> </bitmap>

Lynx: эйвон уже резину выпускает. Шины Avon Ice Touring (185 / 70R14 88T) купить за 547 грн в REZINA.CC

RA: шины с запахом? потри и понюхай? :) Lynx: притормози и понюхай :–D RA: на баш :)

<green>73</green> <blue>154</blue> </pixel> </line> <line> <pixel> <red>54</red> <green>43</green> <blue>123</blue> </pixel> <pixel> <red>12</red> <green>200</green> <blue>196</blue> </pixel> <pixel> <red>14</red> <green>56</green> <blue>77</blue> </pixel>

67


PROgrammist, №16