Последние записи
- Преобразовать массив байт в вещественное число (single)
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
- Взаимодействие через командную строку
- Перенести программу из Delphi в Lazarus
- Определить текущую ОС
- Автоматическая смена языка (раскладки клавиатуры)
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
30th
Июн
“Умная” футболка
Posted by bullvinkle under Журнал
Очередное забавное изобретение – футболка, которая сообщает хозяину, что на его почтовый ящик пришло письмо, и даже показывает, сколько именно писем пришло (1, 2, 4, 8, 16, 32 или 64). Эта футболка для тех, кому мало всевозможных гаджетов, чтобы быть на связи. Футболка содержит в себе пару светодиодов, токопроводящую нить и модуль блютуз, чтобы связываться с телефоном на базе Android, который в свою очередь имеет доступ к электронному ящику.
Это заметка с четвертого выпуска журнала “ПРОграммист”.
Скачать этот выпуск можно по ссылке.
Ознакомиться со всеми номерами журнала.
29th
Июн
Виртуальный радар SBS-1
Виртуальный радар SBS-1 представляет собой недорогой и легкий приемник, работающий в режиме S/ADS-B, который декодирует сигналы ретранслятора (ответчика) на частоте 1090 МГц, поступающие от воздушного судна.
Система SBS-1 Basestation воспроизводит эту информацию на экране виртуального радиолокатора и дает возможность в реальном времени отслеживать местонахождение воздушного судна.
* Комментарий редакции
(S) – ответчик RBS “режим S” с передачей опознавательного индекса воздушного судна и данных о барометрической высоте. По сути, расширение вторичного локатора, однако работать будет только там, где поблизости ВРЛ с режимом S. А иначе бортовой ответчик не ответит в режиме S, если его не запросят с земли. Что касается режима 1090ES, то его иностранцы над Россией, как правило, выключают, т.к. в России официально он не используется. Воздушную обстановку в реальном времени можно посмотреть тут http://radarspotters.eu
Это заметка с четвертого выпуска журнала “ПРОграммист”.
Скачать этот выпуск можно по ссылке.
Ознакомиться со всеми номерами журнала.
29th
Газовые паяльники Weller
Газовые паяльники Weller работают на бутане – очищенном газе для заправки газовых зажигалок. Рекомендуется применять очищенный газ производства фирм Ronson, Braun, Weller. Заправка газом осуществляется через стандартный клапан и занимает 7-10 секунд времени. К примеру, Pyropen WP 60K — недорогой портативный газовый паяльник с ручным кремниевым поджогом, малым временем нагрева и прозрачным окошком для контроля наличия газа. Длительность работы от одной заправки ~60 минут. Рабочая температура в режиме паяльника ~500°С; в режиме фена горячего воздуха ~650°С. В комплект поставки входит паяльник, защитный колпачок, сопло ? 4,7 мм для работы в режиме фена горячего воздуха и жала для паяльника: игольчатое 0,5 мм и скошенное под углом 45° типа «горячий нож» шириной 5 мм.
Скачать этот выпуск можно по ссылке.
Ознакомиться со всеми номерами журнала.
29th
Детектор лжи с электрошокером
Детектор лжи с электрошокером будет служить отличным подарком любителям розыгрыша. Достаточно просто положить руку на детектор лжи и закрепить ее манжетой, которая входит в комплект. Задайте несколько вопросов испытуемому и в случае нечестного ответа электрошокер не сильно, но ощутимо даст знать, что вас пытались обмануть. Этот гаджет показывает уровень лжи на специальной шкале и имеет отличную память, поэтому отъявленного лжеца будет бить током все сильнее с каждым неправильным ответом.
Это заметка с четвертого выпуска журнала “ПРОграммист”.
Скачать этот выпуск можно по ссылке.
Ознакомиться со всеми номерами журнала.
26th
Июн
Как работать с графикой на канве в среде Дельфи. Урок 3-4
Одним из основных методов получения эффекта движущегося объекта является принцип уничтожения объекта на текущем месте и вывод его на новом с заданным приращением координат dX и dY. Однако прямолинейное применение такого метода на практике приводит к неприятному эффекту “мерцания” объекта во время движения. Причина этого в том, что при проведении этих операций непосредственно на канве объекта, где происходит движение, мы получаем двойную перерисовку участка канвы. Такая двойная смена цвета пикселей и является причиной. Сказанное наглядно видно на рисунке (см. рис.1), во время каждого такта движения происходит два процесса рисования: сначала старое изображение «затирается» фоном, а затем рисуется новое изображение движущегося объекта на новом месте…
Владимир Дегтярь
Урок 3
Создание движущихся объектов (еще немного теории)
Рис. 1. Демонстрация эффекта «мерцания»
Избежать данной проблемы можно, объединив обе операции «стирания» изображения и вывода нового в одну. Суть этого состоит в том, чтобы на канве объекта, невидимого на экране, вывести стирающий участок фона, затем вывести изображение движущегося объекта на новом месте и уже после этих операций вывести полученную комбинацию изображения на видимую часть канвы экрана. Для этого создаем дополнительный объект со свойством канвы (лучше всего подходит дополнительный буфер типа TBitMap), на котором и проводим предварительные операции. Размер такого дополнительного буфера определяется в зависимости от величины смещения движущегося объекта.
Возможны два варианта: когда старое и новое положение объекта имеют общую область (перекрывают друг друга) и не перекрывают (см. рис.2):
Рис. 2. Перекрытие объектов
Размер буфера в первом случае, как видно из рисунка 2 по каждой из координат равен размеру объекта плюс двойное приращение координат по соответствующим координатам (берется абсолютная величина). Теперь достаточно вывести в буфер область фона, соответствующего текущему положению объекта (старое положение) и наложить поверху изображение объекта, разместив его в буфере со смещением dX и dY (опять же по абсолютной величине) относительно нулевых координат буфера. После вывода изображения всего буфера на экран изображение объекта исчезнет и появится в новом положении.
Во втором случае, когда старое и новое изображения не имеют общей области также можно применить указанный метод. Но при этом, судя по рисунку 3, значительно увеличивается размер дополнительного буфера:
Рис. 3. Случай отсутствия перекрытия изображений
Можно уменьшить размер дополнительного буфера, применив немного другой подход (см. рис.4):
Рис. 4. Принцип уменьшения буфера
Здесь размер дополнительного буфера значительно меньше, чем на рисунке 3, но вывод изображения
объекта происходит не в центр буфера, а в один из четырех секторов. Перед заполнением буфера необходимо определить величину и знак следующего приращения dx и dy. Затем заполнить буфер фоном текущего положения объекта и вывести изображение объекта с учетом следующего приращения координат:
Если
dx > 0 и dy <= 0, то bx = dx и by = 0;
dx <= 0 и dy > 0 , то bx = 0 и by = dy;
dx <= 0 и dy <= 0, то bx = 0 и by = 0;
Значения bx и by присваиваются , естественно по абсолютным величинам dx и dy. Вот код программы для первого случая (см. листинг 1):
ЛИСТИНГ-1
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormActivate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
end;
var
Form1: TForm1;
{ битовые образы рисунка, фона и дополнит. буфера, соответственно }
Pic, Fon, Buf : TBitMap;
// области вывода фона
RectFon, RectBuf : TRect;
// текущие координаты
x,y: integer;
// приращения координат
dx, dy: integer;
// размеры дополнит.рисунка и буфера
W,H,WB,HB: integer;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject);
begin // инициализация TBitMap и TRect
// загружаем рисунок фона
Fon:= TBitMap.Create;
Fon.LoadFromFile(‘fon.bmp’);
{ загружаем рисунок объекта, который будет двигаться}
Pic:= TBitMap.Create;
Pic.LoadFromFile(‘picture.bmp’);
// задаем прозрачность объекту
Pic.Transparent:= true;
Pic.TransparentColor:= Pic.Canvas.Pixels[1,1];
{ определяем и устанавливаем размеры дополнит. буфера }
W:= Pic.Width;
H:= Pic.Height;
Buf:= TBitMap.Create;
Buf.Width:= W + 2*abs(dx);
Buf.Height:= H + 2*abs(dy);
WB:= Buf.Width;
HB:= Buf.Height;
// назначаем соответствие палитр цветов
Buf.Palette:= Fon.Palette;
Buf.Canvas.CopyMode:= cmSrcCopy;
{ определяем область в дополнит. Буфере для загрузки участка фона }
RectBuf:= Bounds(0,0,WB,HB);
// инициализация координат
x:=300; y:=150;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin // выводим на экран фон и объект
Form1.Canvas.Draw(0,0,Fon);
Form1.Canvas.Draw(x,y,Pic);
end;
{ перемещение объекта на один шаг происходит после каждого нажатия
соответствующей клавиши}
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
case Key of
37: begin dx:= -3; dy:= 0; end;
38: begin dx:= 0; dy:= -3; end;
39: begin dx:= 3; dy:= 0; end;
40: begin dx:= 0; dy:= 3; end;
end;
{ определяем область фона, которую надо запомнить }
RectFon:= Bounds(x+dx,y+dy,WB,HB);
// запомним фон в буфере
Buf.Canvas.CopyRect(RectBuf,Fon.Canvas,RectFon);
// наложим в буфере на фон рисунок с прозрачным фоном
Buf.Canvas.Draw(abs(dx),abs(dy),Pic);
// выводим на форму в новой позиции
x:=x+dx; y:=y+dy;
Form1.Canvas.Draw(x,y,Buf);
end;
end.
А это для второго случая (см. листинг 2):
ЛИСТИНГ-2
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormActivate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
end;
var
Form1: TForm1;
{ битовые образы рисунка, фона и дополнит.буфера, соответственно }
Pic, Fon, Buf : TBitMap;
// области вывода фона
RectFon ,RectBuf : TRect;
// текущие координаты
x,y: integer;
// приращения координат
dx, dy: integer;
{ смещение изображения объекта
в дополнительном буфере }
bx, by: integer;
// размеры дополнит.рисунка и буфера
W,H,WB,HB: integer;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject);
begin // инициализация TBitMap и TRect
// загружаем рисунок фона
Fon:= TBitMap.Create;
Fon.LoadFromFile(‘fon.bmp’);
{ загружаем рисунок объекта, который будет двигаться}
Pic:= TBitMap.Create;
Pic.LoadFromFile(‘picture.bmp’);
// задаем прозрачность объекту
Pic.Transparent:= true;
Pic.TransparentColor:= Pic.Canvas.Pixels[1,1];
{ определяем и устанавливаем размеры дополнит. буфера }
W:= Pic.Width;
H:= Pic.Height;
Buf:= TBitMap.Create;
Buf.Width:= W + abs(dx);
Buf.Height:= H + abs(dy);
WB:= Buf.Width;
HB:= Buf.Height;
// назначаем соответствие палитр цветов
Buf.Palette:= Fon.Palette;
Buf.Canvas.CopyMode:= cmSrcCopy;
{ определяем область в дополнит. Буфере для загрузки участка фона }
RectBuf:= Bounds(0,0,WB,HB);
// инициализация координат
x:=300; y:=150;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin // выводим на экран фон и объект
Form1.Canvas.Draw(0,0,Fon);
Form1.Canvas.Draw(x,y,Pic);
end;
{ перемещение объекта на один шаг происходит после каждого нажатия
соответствующей клавиши}
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
case Key of
37: begin dx:= -3; dy:= 0; end;
38: begin dx:= 0; dy:= -3; end;
39: begin dx:= 3; dy:= 0; end;
40: begin dx:= 0; dy:= 3; end;
end;
if (dx>0) and (dy>0) then begin bx:=abs(dx); by:=abs(dy); end;
if (dx>0) and (dy<=0) then begin bx:=abs(dx); by:=0; end;
if (dx<=0) and (dy>0) then begin bx:=0; by:=abs(dy); end;
if (dx<=0) and (dy<=0) then begin bx:=0; by:=0; end;
{ определяем область фона, которую
надо запомнить }
RectFon:= Bounds(x+dx,y+dy,WB,HB);
// запомним фон в буфере
Buf.Canvas.CopyRect(RectBuf,Fon.Canvas,RectFon);
// наложим в буфере на фон рисунок с прозрачным фоном
Buf.Canvas.Draw(bx,by,Pic);
// выводим на форму в новой позиции
x:=x+dx; y:=y+dy;
Form1.Canvas.Draw(x,y,Buf);
end;
end.
В принципе обе эти программы можно объединить, введя процедуру проверки на совпадение старой и новой областей изображения. Но это уже другая тема.
В данных примерах подразумевалось, что движущийся объект состоит всего из одного изображения ‘picture.bmp’. Но на практике, обычно таких изображений несколько. Наиболее часто изображения хранятся в файле в виде набора спрайтов. Вот здесь есть один небольшой подводный камень. Обычно выбор необходимого спрайта производится процедурой CopyRect() из буфера типа TBitMap, куда предварительно загружены изображения всех спрайтов. Но, при таком методе вывода изображения в дополнительный буфер с участком фона нельзя присвоить изображению свойство прозрачности.
Для обхода этого препятствия следует ввести еще один дополнительный буфер типа TBitMap, куда методом CopyRect() загрузить изображение нужного спрайта, а затем уже, присвоив свойство прозрачности, методом Canvas.Draw вывести изображение на канву дополнительного буфера с участком фона.
Следует отметить, что для создания «эффекта» движения можно оставить изображение графического объекта неподвижным, а двигать сам фон. При этом размер фона должен быть больше размера окна формы. Также можно применять одновременно или поочередно сдвиг объекта и сдвиг фона.
Урок 4
Проект с движением звездолета.
Аналогично Уроку 2 создадим новый проект и сохраним его под именем Lesson2. Параметры формы Form1 также установим аналогично Уроку 2, изменив только заголовок Form1 на «Урок по графике № 2».
Для получения движения объекта применим метод, когда сам объект (звездолет) неподвижен на форме, а “двигается” сам фон. Фон создадим в два раза больше по высоте размера окна формы. Для этого используем файлы ‘star1.bmp’ и ‘star2.bmp’. Нам также понадобится еще один дополнительный буфер BufFonDop. Кроме этого введем еще переменные – координаты вывода на форму фона и звездолета, а также приращения к координатам (см. листинг 3 ):
ЛИСТИНГ-3
Form1: TForm1;
BufFon,BufFonDop,BufSpr,BufPic,Buffer: TBitMap;
xS1,yS1: integer; // координаты звездолета ‘ship1’
xf,yf: integer; // координаты вывода общего буфера на форму
dyf: integer = 2; // приращение изменения координаты yf по вертикали
dxS1,dyS1: integer; // приращение координат звездолета по гориз. и вертик.
ns: byte; // номер спрайта
{Здесь-же вводим начальные данные для переменных}
xs1:= 250; ys1:= 1006; // начальные значения переменных-
dxs1:= 4; dys1:= 2;
xf:= 0; yf:= -540; dyf:= 2;
{ Инициализацию буферов проведем в процедуре OnCreate() формы }
procedure TForm1.FormCreate(Sender: TObject);
begin
BufFon:= TBitMap.Create;
BufFonDop:= TBitMap.Create;
BufSpr:= TBitMap.Create;
BufPic:= TBitMap.Create;
Buffer:= TBitMap.Create;
BufFonDop.LoadFromFile(‘data/star1.bmp’); // загрузка 1-го рисунка фона из файла
BufSpr.LoadFromFile(‘data/ship1.bmp’); // загрузка спрайтов из файла
BufFon.Width:= BufFonDop.Width; // размеры общего буфера фона
BufFon.Height:= (BufFonDop.Height) * 2; { по высоте = двум Height одного
рисунка фона}
BufFon.Canvas.Draw(0,0,BufFonDop); // заносим 1-й рисунок фона
BufFonDop.LoadFromFile(‘data/star2.bmp’); // загрузка 2-го рисунка фона из файла
BufFon.Canvas.Draw(0,540,BufFonDop); // заносим 2-й рисунок фона
Buffer.Width:= BufFon.Width; // размеры общего буфера = размерам буфера фона
Buffer.Height:= BufFon.Height;
BufPic.Width:= round((BufSpr.Width) / 2); // размеры буфера рисунка одного спрайта
BufPic.Height:= BufSpr.Height;
В процедуре DrawShip1(i) добавлено условие прозрачности фона рисунка звездолета (см. листинг 4):
ЛИСТИНГ-4
begin
BufPic.Canvas.CopyRect(bounds(0, 0, BufPic.Width, BufPic.Height),
BufSpr.Canvas,bounds( i * 66, 0, BufPic.Width,
BufPic.Height));
BufPic.transparent:= true;
BufPic.transparentcolor:= BufPic.canvas.pixels[1, 1]
end;
«Эффект» движения организован в обработчике таймера. В каждом такте таймера 50 мсек:
- смещаем координату вывода общего буфера yf на dyf вниз (+ 2)
- координату yS1 вывода звездолета смещаем на dyS1 вверх (- 2). В этом случае изображение звездолета будет неизменным в координатах формы, а двигаться будет только фон
- в общий буфер (Buffer) выводим фон (при этом «уничтожается» изображение звездолета на старом месте)
- выводим в общий буфер на фон новое изображение звездолета со смещением dyS1
- выводим общий буфер на форму
В процедуре DrawShip1(ns) через переменную ns, принимающую попеременно значения 0 или 1, выводятся поочередно спрайты изображения звездолета (см. листинг 5):
ЛИСТИНГ-5
begin
ns:= ns + 1; if ns > 1 then ns:= 0; // смена спрайтов
DrawShip1(ns);
yf:= yf + dyf; if yf > 0 then begin yf:= -540; yS1:= 1006; end; // приращение yf
yS1:= yS1 — dyS1; // приращениие звездолета обратно приращению фона
Buffer.Canvas.Draw(0,0,BufFon); // выводим фон в общий буфер
Buffer.Canvas.Draw(xS1,yS1,BufPic); // выводим рисунок спрайта поверх фона
Form1.Canvas.Draw(xf,yf,Buffer); // выводим все на форму
end;
//Движение звездолета по горизонтали в пределах окна формы организовано
//в обработчике нажатия клавиши OnKeyDown
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
case Key of
37: begin // клавиша "стрелка" — влево
if xS1 <= 0 then EXIT; { если звездолет у левого края формы
xS1 не изменяется}
xS1:= xS1 — dxS1; // движение звездолета влево
end;
39: begin // клавиша "стрелка" — вправо
if xS1 >= 630 then EXIT; { если звездолет у правого края формы
xS1 не изменяется}
xS1:= xS1 + dxS1; // движение звездолета вправо
end;
end;
end;
Запустим проект на компиляцию и взглянем на результаты нашего труда (см. рис.5):
Рис. 5. Движение звездолета по-горизонтали
Заключение:
В следующих уроках добавим еще несколько движущихся объектов в проект.
Рассматриваемые в данной статье проекты полностью приведены в ресурсах к статье на http://www.programmersforum.ru в разделе «Журнал клуба программистов. Второй выпуск» (папка Lesson2*).
Обсудить на форуме – Как работать с графикой на канве в среде Дельфи. Урок 3-4
Статья из второго выпуска журнала «ПРОграммист».
24th
Июн
Гимн Программистов
Хорошая идею подал форумчанин _PROGRAMM_ : написать гимн программистов. И его быстро и весело поддержали на форуме.
На данный момент имеем:
Программисты – умный народ
И пляшет и гимны поет
Он очень весело живет
И так же весело жует
А бывает с бубном ходит
И тоску на всех наводит
Он не спит ни день, ни ночь,
Всем мечтает он помочь
Утром сядет у окна
А чуть позже у компа
Поиграет чуть в ФИФА
И давай дразнить кота
Но когда пришла зима,
Пиво кончилось тогда
Не успев никто моргнуть
В двор примчался старый друг
И позвал его гулять,
Праздник лета отмечать
Раз бокал и два бокал
И давай писать в барланд!
Это еще не релиз, это скорее всего “ночная сборка”. Возможно, в скором будущем мы создадим гимн, наложем на нег музыку, запишем хит и будем продавать на лицензионных DVD .
24th
Рассылка. Выпуск 64.
От ведущего рассылки.
Здравствуйте. Новый выпуск рассылки от клуба программистов. Сегодня подборка самых интересны тем за неделю с форума программистов.
Облако меток
css реестр ассемблер timer SaveToFile ShellExecute программы массив советы word MySQL SQL ListView pos random компоненты дата LoadFromFile form база данных сеть html php RichEdit indy строки Win Api tstringlist Image мысли макросы Edit ListBox office C/C++ memo графика StringGrid canvas поиск файл Pascal форма Файлы интернет Microsoft Office Excel excel winapi журнал ПРОграммист DelphiКупить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)