Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Как создать свой сайт и заработать?" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Программирование с нуля - это совсем просто! 52) Таймер-лайф
Информационный Канал Subscribe.Ru |
Программирование с нуля - это совсем просто!52) Таймер-лайфКак вы помните, в 43 выпуске мы рассмотрели способ вывода на экран (на канву) графических элементов, рисование фактически. Только тот метод был незакончен в том смысле, что изображение, созданное программой, стиралось и пропадало, стоило нам переключиться на другую программу или закрыть область, на которой произошло рисование, другими окнами. Почему? Потому, что вывод графики произошел только один раз, в момент нажатия на кнопку. Когда изображение на канве PaintBox стерлось, заново ведь его никто уже не рисовал, вот оно и не появилось снова. Поэтому процесс рисования на канве правильно делать (вызывать) автоматически каждый раз, когда в этом возникает необходимость. Windows автоматически определяет такие ситуации для каждого окна, посылая тому сообщение Paint. Нам достаточно запрограммировать обработчик этого сообщения, после чего перерисовка изображения в окне будет уже происходить автоматом. Возьмем например алгоритм построения фрактала, который отыскала Екатерина на сайте http://nsft.narod.ru/ .
var d,rt:integer;
Он для ДОСа (точнее, для Turbo Pascal), а мы его немного переделаем для Дельфи.
x:=GetMaxX;{ширина экрана} мы заменим на размеры поля PaintBox1 (640 на 480 например), и PutPixel сменим на уже знакомый нам метод вывода цветной точки:
var i:longint; clBlack - это стандартная константа, задающая черный цвет. Вопрос - в какой обработчик нам этот код записать? В нажатие на кнопку неправильно, он же не будет тогда автоматом вызываться. Нам нужно создать обработчик события перерисовки формы. Для этого выбираем PaintBox1 на форме и в инспекторе находим для него на вкладке Events событие OnPaint. Дважды щелкаем на нем, появляется обработчик:
procedure TForm1.PaintBox1Paint(Sender: TObject);
end;
Вот внутрь него и записываем наш код, после чего запускаем программу - аллес! Теперь красивый фрактал будет рисоваться автоматически и показываться всегда, независимо от того, переключались мы на другие программы или нет. А вот код Екатерины на Си++,
void __fastcall TForm1::Button1Click(TObject *Sender) который переносится в полноценную программу точно так же. Просто перемещаем его в обработчик события Paint, и все. Теперь вернемся к таймеру. Этот невизуальный компонент, совсем простой, расположен на панели System. Ставим его на форму, свойство Enabled пока переводим в false. Что он делает? Он просто вызывает собственный обработчик через заданный промежуток времени. Этот промежуток, в миллисекундах (тысячных секунды) задается в свойстве Interval. Вот простейший пример учета числа секунд, прошедших с момента запуска программы. Подготовим форму, на ней разместим одно поле-надпись, в ее описании добавим поле-внутреннюю переменную seks: Integer; :) в событии создания формы (OnCreate - в нем потому, что оно вызывается всего один раз и до показа формы) занесем в нее 0 и запустим таймер переводом свойства Enabled в true:
procedure TForm1.FormCreate(Sender: TObject);
Теперь создадим обработчик таймера - на его вкладке Events дважды щелкнем на строке OnTimer. Пусть в его поле Interval пока сохраняется значение 1000 по умолчанию (одна секунда). В обработчике нам достаточно увеличить значение seks на 1 и показать в надписи общее число секунд:
procedure TForm1.Timer1Timer(Sender: TObject);
При желании вы можете улучшить форму вывода, аккуратно переводя секунды в минуты и часы. Таймеры применяются очень активно, когда надо запускать в программе всевозможные фоновые процессы, отслеживая динамически состояние различных элементов на форме. Только - важно! - не нагружать обработчик таймера какими-то объемными и интенсивными вычислениями. Он для этого не предназначен. В качестве примера создадим программу, моделирующую общеизвестную игру "Жизнь" Конвея. По ней сделано огромное число программ, для практики сделаем это и мы. Шаблон конечно будет учебный, особого качества ожидать не стоит, но общие принципы будут очень наглядно продемонстированы. Эта игра заключается в следующем. На игровой клетчатой доске расставлены неким образом фишки, имитирующие колонию например бактерий. Очередной такт ее развития состоит в том, что состояние каждой клетки меняется по простым правилам:
* если у некоторой фишки число соседей-фишек (8 клеток со всех сторон; задание такое было, помните? :) меньше двух или больше трех, она погибает от голода или перенаселения (фишка снимается); Правила крайне просты, правда? ОДнако они приводят к развитию совершенно поразительных и красивых колоний. Вот как мы эту игру реализуем. Разместим на форме компонент PaintBox размером 100 на 100 точек. Опишем два массива: L1, L2: array[0..101, 0..101] of Integer; Значение 1 в массиве будет означать наличие фишки, значение 0 - пустую клетку. Подготовим процедуру, которая будет пересчитывать конфигурации - делать один такт виртуального развития. Опишем ее в классе формы:
...
L1, L2: array[0..101, 0..101] of Integer;
procedure Turn;
Можно быстро создать пустую реализацию метода формы, поставив на его строчку курсор, и нажать Shift + Ctrl + C . В редакторе автоматом появится готовый код:
procedure TForm1.Turn;
end; Кто не понял, как это сделать, придется набирать ручками :) Как будет работать наш алгоритм? Примем, что исходная конфигурация всегда будет в массиве L1, а конечная - в L2. Поэтому будем анализировать L1, а финальную версию записывать в L2:
procedure TForm1.Turn;
for x := 0 to 101 do
else
sum := sum - L1[x,y]; // вычитаем саму клетку
L2[x,y] := L1[x,y]; // пока без изменений...
if L1[x,y]=1 then
if sum = 3 then
for x := 0 to 101 do
else Кто делал соответствующее упражнение, разберется без проблем. Здесь мы приняли для удобства, что границы массива всегда заполнены нулями, чтобы не мучаться с проверкой индексов на выход за границы. В конце мы копируем L2 обратно в L1, чтобы синхронизировать их содержимое. Делать это можно только после того, как L2 построен польностью, понятно, почему? В процессе этой синхронизации также выведем точки на экран - пустую черным, фишку - белым. Куда вставим вызов Turn? Конечно, в таймер!
procedure TForm1.Timer1Timer(Sender: TObject);
Таймер, допустим, будет активизироваться по кнопке. Пусть в исходном состоянии он будет отключен, а при нажатии на кнопку расставим произвольную базовую конфигурацию и включим таймер:
procedure TForm1.SpeedButton1Click(Sender: TObject);
Timer1.Enabled := true;
for x := 0 to 101 do
L1[50,10] := 1;L1[50,11] := 1;L1[50,12] := 1;
end; Единственная проблема - рисунок будет мелким. Попробуйте переделать так, чтобы каждая клетка была не отдельным пикселом, а достаточно большим квадратиком, со стороной 2-3-5 пикселов. Для этого надо, собственно, переписать (с умом :) две строчки с присваиванием PaintBox1.Canvas.Pixels[x,y] - вместо пикселов аккуратно рассчитать кординату x,y-квадратика, и нарисовать его черным или белым цветом в правильном месте. Тормозить такое рисование будет, наверно, прилично. Кому интересно или лень переделывать самому, можете посмотреть на сайте http://famlife.narod.ru/ . Там удобная программка для моделирования конфигураций, с встроенным редактором, симпатичным интерфейсом. Если кого-то эта тема за-интересует, пишите, дам побольше ссылочек. Задания. 45. Многострадальный музыкальный плеер :) Многие, еще программированию не научившись, спрашивали, а как сделать например ведение списка любимых композиций итд. Без программирования тогда сделать это было сложновато, зато теперь - без проблем! Делаем полноценный плеер. В нем сам компонент MediaPlayer надо спрятать, сделать невидимым на форме (свойство Visible ставим в false). А работу с ним будем эмулировать программно. Создадим (создадите вы :) на форме красивые кнопочки и скин симпатичный, нажатие на которые будет дергать этот MediaPlayer за ниточки - методы. Кстати, есть на панели Additional кнопка SpeedButton, если ее положить на графический фон и свойства Flat и Transparent в True, то сама кнопка будет прозрачной и невидимой. Ее можно поставить просто по границе нарисованной кнопки на фоне, и как будто она настоящая будет. А реагировать станет невидимая кнопка (ее границы появятся, если навести на нее курсор, но прозрачность сохранится). Для начала воспроизведения файла надо вызвать метод Play, для остановки - Stop, для перемотки к началу - Rewind итд. Файл, который будет проигрываться (а еще лучше - добавление нового элемента в плей-лист), надо выбирать с помощью диалога открытия файлов, о чем намедни я рассказывал, полный путь к нему заносится в свойство FileName, после чего проигрыватель надо открыть командой Open. Как то так:
MediaPlayer1.FileName := 'c:\muzon.mp3' ;
Более подробно про свойства и методы плеера можно узнать в хелпе к Дельфи. Важное свойство плеера Wait показывает, надо ли ждать окончания воспроизведения, блокируя все функции программы. Лучше ставить false, чтобы программа продолжала работу, а музыка играла уже в фоне. Только тогда всегда надо будет программно останавливать/закрывать плеер, если музыка еще играет, а мы хотим его заставить что-то другое делать. Закрытие плеера - метод Close. Узнать, что он делает, можно с помощью свойства Mode, которое принимает значение mpPlaying, если плеер играет музыку.
if MediaPlayer1.Mode = mpPlaying then
MediaPlayer1.FileName := 'c:\muzon.mp3' ;
Ну я уже за вас все сделал :) Ведем список желаемых композиций, в каждой строчке - путь к файлу. Они берутся и проигрываются автоматом. Файлы в список загружаем сами, список желательно также сохранять на диск. Нужные кнопки сами продумайте. А как узнать, закончил ли плеер играть текущий файл, чтобы к следующему автоматом перейти? Для этого задействуем таймер, который например раз в секунду проверяет свойство Mode плеера, и если оно не mpPlaying, значит можно пускать следующую песню. 46. Расслабитель ума :) Эта программа, скажу сразу, не шутка! В нее (будет) заложено немало замечательных идей из психологии. Окно, главная форма. В окне крупными буквами в поле-надписи пишем одно из семи слов, названий цвета (синий, зеленый, красный итд). Берем основные цвета. Размер букв выбираем очень большие, на полэкрана, под 70 (подсвойство Size свойства Font в Label). И шрифт подберите какой-нибудь (подсвойство Name в Font), чтобы выглядели слова не рубчато, а гладко. Слова предъявляются в случайном порядке. Под словом - семь квадратиков-картинок с семью цветами. Квадратики делаем с помощью компонента Shape с панели Additional. Время предъявления каждого слова - ограничено (например, 3 секунды). Это время можно корректировать в настройках программы. За время предъявления очередного слова пользователь должен щелкнуть на квадратике соответствующего цвета (другими словами, указать - "предъявлен такой-то цвет"). Для этого для каждого из семи цветных квадратиков надо сделать обработчики щелчка (событие OnMouseUp). Если человек правильно определил цвет, значит, плюс балл. Если неправильно, значит ничего не получил. Ведется статистика - число попыток, правильных ответов и процент правильности. Далее. В дополнение к каждому слову - под ним - в небольшом уже окошке, поле-надписи показывается один из четырех вариантов (тоже случайно), как надо выбирать соответствующий квадратик, какой кнопкой мыши: Левой, Правой, Левой-наоборот, Правой-наоборот. Левой - значит, надо левой кнопкой щелкнуть на квадратике, правой - правой. Левой-наоборот - значит, правой, Правой-наоборот - значит левой. А как узнать в обработчике, какая кнопка мыши использовалась? Мы взяли обработчик события OnMouseUp, который вызывается, когда над объектом отпущена любая из кнопок мыши. А какая, задается в параметре Button обработчика. Нас интересуют такие его значения, как mbLeft (левая) и mbRight (правая).
procedure TForm1.Shape1MouseUp(Sender: TObject; Button:
И еще одно, очень важное (главное!) условие. Цвет слова и само слово должны всегда отличаться. То есть если в поле показывается слово "зеленый", то оно должно быть любого цвета из семи, кроме зеленого. И правильной считается попытка, когда указан цвет, не самим словом заданный, а цвет самого слова. Например, слово "красный" показано синим цветом. Ответ красный (щелчок на красном квадратике) неправильный, ответ синий - правильный. Также, засчитывать надо, только если действие выбора выполнено правильной кнопкой мыши. Например, слово "желтый" коричневого цвета, а под ним - "Правой-наоборот" (или "Левой"). Значит, надо коричневый выбрать левой кнопкой. Еще одно, необязательное - только для продвинутых студентов :) Одновременно с предъявлением слова проигрывать файл (через плеер, MediaPlayer) с записью цвета голосом (своим собственным например :) wav-файлы можно в стандартной проге Звукозаписи подготовить). Например, слово "красный" показано синим цветом, и дополнительно звучит слово "зеленый". Выбрать надо все равно синий. То есть звук - еще один отвлекающий элемент. Слово звучащее (цвет) должно отличаться и от слова написанного, и от цвета этого написанного слова. Программа получится очень мощная. Достаточно 10-15 минут занятия с ней, чтобы полностью переключить мозги из зазомбированности :) в активный и открытый режим восприятия. Задействуется сразу несколько систем восприятия, и мозг в режиме интенсивного переключения прекрасно освобождается от разных блоков и мусора, а также активизирует творческую составляющую психики. Когда появятся хорошие варианты, я к ней еще дополнительно опишу методику наиболее правильного использования. С лямзиками проблемы появились у многих. Но, как говорил наш Великий Учитель Карлсон, "спокойствие и только спокойствие!" :) А почему проблемы? Потому что пока нету навыков алгоритмического мышления. Это нормально совершенно. Собственно, приемов правильного мышления по-программицки я лично насчитал несколько десятков, штук тридцать. Овладев :) ими всеми, нам по силам будет абсолютно любую задачу запрограммировать на автомате. То есть когда эти приемы перейдут в освоенный навык, программирование превратится в мастерство, как профессиональный водитель может уверенно вести автомобиль, даже будучи в сильном подпитии. То есть Программист, - это тот человек, который может об абсолютно любой задаче (допускающей, конечно, формальное решение) сказать, как ее решение запрограммировать. Не как найти решение (это математика), а как построить процесс ее решения, решать же будет машина. Другое дело, что ресурсов для такой работы может быть очень много. Но это уже другое дело. Так что с лямзиками разберемся в ближайшее время. Научившись их делать, и любые другие задания схожие всегда уже будете знать, как. (c) 2004-2005 Сергей Бобровский bobrovsky@russianenterprisesolutions.com
Школа программирования с нуля
|
http://subscribe.ru/
http://subscribe.ru/feedback/ |
Подписан адрес: Код этой рассылки: comp.soft.prog.prognull |
Отписаться |
В избранное | ||