Как практически с помощью функций WinAPI нарисовать мячик, который бы двигался горизонтально в прямоугольнике вправо-влево, "отскакивая" от боковых стенок, "пинг-понг" - ?
volvo
7.07.2009 1:24
Что именно вызывает затруднения? Рисуем шарик с помощью Ellipse, сам прямоугольник - Rectangle. Написать программу, которая будет проверять, не выходит ли шарик за пределы прямоугольника, и если выходит - изменить направление движения - не должно составить большой проблемы.
Начинай, если что непонятно - говори, что именно.
KljaGGsa
7.07.2009 1:34
В обычном пейнтбоксе и канвасе это действительно несложно, а вот как применить API сколько литературы не читаю, и бумажной и электронной, найти не могу . . . (((
volvo
7.07.2009 3:43
Так тебе совсем WinAPI-шное приложение надо, без VCL? Ну, тогда так, к примеру:
program Project1;
uses Windows, Messages;
const WM_SETUP = 500;
WinName = 'MainWClass'; R = 5;
var myTimer: THandle; delta: integer; Rec: TRect; posX, posY: integer;
function MainWndProc(Window: HWnd; AMessage: UINT; WParam: WPARAM; LParam: LPARAM): INT_PTR; stdcall; var myDC: HDC; ps: PAINTSTRUCT; begin case AMessage of WM_CREATE: // Создание окна begin myTimer := SetTimer(Window, 0, 1, nil); Result := 0; Exit; end; WM_SETUP: // "Установка" начальных значений begin myDC := GetDC(Window); GetClientRect(Window, Rec); posX := 0; posY := (Rec.Bottom - Rec.Top) div 2; delta := 5; ReleaseDC(Window, myDC); Result := 0; Exit; end; WM_SIZE: // Изменение размеров окна begin PostMessage(Window, WM_SETUP, 0, 0); // Просто вызываем "установку" Result := 0; Exit; end; WM_PAINT: begin myDC := BeginPaint(Window, ps); PostMessage(Window, WM_SETUP, 0, 0); // Тоже "установка" EndPaint(Window, ps); Result := 0; Exit; end; WM_TIMER: // Событие таймера begin myDC := GetDC(Window); // стираем старое изображение шарика SelectObject(myDC, GetStockObject(WHITE_PEN)); Ellipse(myDC, posX - R, posY - R, posX + R, posY + R);
if ((delta > 0) and (posX + delta + R > (Rec.Right - Rec.Left))) or ((delta < 0) and (posX - delta - R < 0)) then delta := -delta; posX := posX + delta;
// и рисуем в новых координатах новое SelectObject(myDC, GetStockObject(BLACK_PEN)); Ellipse(myDC, posX - R, posY - R, posX + R, posY + R); ReleaseDC(Window, myDC); Result := 0; Exit; end; WM_DESTROY: // Уничтожение окна begin KillTimer(Window, myTimer); PostQuitMessage(0); Result := 0; Exit; end; else Result := DefWindowProc(Window, AMessage, WParam, LParam); end; end;
function InitInstance: HWND; begin Result := CreateWindow( PChar(WinName), 'Ping-pong', WS_OVERLAPPEDWINDOW, Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), 0, 0, hInstance, nil); end;
var hwndMain: HWND; AMessage: msg; begin if (not InitApplication) then begin MessageBox(0, 'Ошибка регистрации окна', nil, mb_Ok) end else begin hwndMain := InitInstance; if (hwndMain = 0) then begin MessageBox(0, 'Ошибка создания окна', nil, mb_Ok) end else begin ShowWindow(hwndMain, CmdShow); UpdateWindow(hwndMain); while (GetMessage(AMessage, 0, 0, 0)) do begin TranslateMessage(AMessage); DispatchMessage(AMessage); end; end; end;
end.
Client
7.07.2009 18:25
Это же не простой проект. Куда надо это скопировать?
volvo
7.07.2009 18:35
Цитата
Это же не простой проект. Куда надо это скопировать?
Это не простой, это простейший проект. Надо создать новое консольное приложение, и заменить код, предлагаемый Дельфями на код, приведенный выше.
Client
7.07.2009 18:46
Цитата
Это не простой, это простейший проект
В смысле что там нету формы куда ложить кнопки, едиты....
volvo
7.07.2009 19:26
Это WinAPI. Какие кнопки? Какие эдиты? VCL не используется.
KljaGGsa
8.07.2009 1:18
а я в полном шоке от этого кода, совершенно растерялась и вчера даже в эфир не вышла . . . Где взять справочный и учебный материал, который мог бы хоть поверхностно объяснить откуда здесь ноги растут???
volvo
8.07.2009 15:17
Цитата
Где взять справочный и учебный материал, который мог бы хоть поверхностно объяснить откуда здесь ноги растут???
Ну, начнем с самого начала. Ты знаешь, как Windows-приложение взаимодействует с ОСью? Про механизм сообщений слышала?
KljaGGsa
8.07.2009 20:41
Нет, мне пока что это совсем незнакомо. Знаю только в первом приближении интерфейс оболочки Delphi7, основные свойства самых расхожих компонентов и простейшие алгоритмы их взаимодействия. Вот фрагмент вашего кода сразу бросился в глаза и удивил - какие-то сплошные сообщения, а не язык программирования:
while (GetMessage(AMessage, 0, 0, 0)) do begin TranslateMessage(AMessage); DispatchMessage(AMessage);
KljaGGsa
8.07.2009 21:09
Хм, но что-то цель не получилось достичь. Прямое обращение к функциям операционки по идее должно дать быструю и эффективную (плавную) работу, а шарик на экране движется явно не лучше, чем если бы я его нарисовала эллипсом в канвасе и закрашивала бы каждый раз при единичном перемещении. Дискретность и дрыганье - те же самые...
volvo
8.07.2009 21:13
Цитата
сразу бросился в глаза и удивил - какие-то сплошные сообщения, а не язык программирования:
Вот именно это и есть основной цикл обработки сообщений. Перевожу на русский:
пока (есть_сообщения_для_окна) транслировать_сообщение; переслать_сообщение_оконной_функции;
А уже внутри оконной функции (та самая MainWndProc) анализируем, собственно, какое сообщение было получено, и что надо делать в связи с его получением.
шарик на экране движется явно не лучше, чем если бы я его нарисовала эллипсом в канвасе и закрашивала бы каждый раз при единичном перемещении. Дискретность и дрыганье - те же самые...
Тебе записать видео, или ты поверишь, что никакого дерганья я у себя не наблюдаю? И с чем оно связано - не знаю.
Добавлено через 14 мин.
Цитата
шарик на экране движется явно не лучше, чем если бы я его нарисовала эллипсом в канвасе и закрашивала бы каждый раз при единичном перемещении.
Кстати, вопрос на засыпку: с чего ты взяла, что на WinAPI должно быть ЛУЧШЕ? То же самое рисование на канвасе, то же самое перемещение (только не единичное, а 5-ти единичное, что может послужить причиной "дерганья", нет DoubleBuffered, что тоже не улучшает визуализацию). Ты меня извини, конечно, но писать здесь полный код, работающий идеально, я считаю нецелесообразным. По нескольким причинам. Главная из которых - если тебя ЭТО уже вводит в ступор, то я представляю, куда тебя введет более сложный код.
Цитата
что-то цель не получилось достичь
Целью было написание приложения, перемещающего изображение мяча горизонтально, от одной стенки к другой. Про плавность перемещения и его идеальность речи не было. Если тебя это не устраивает - делай сама, больше мешать тебе своими постами не буду.
Удачи.
Client
8.07.2009 21:33
По той ссылке код для Си а примерах, а те функции и на Delphi работают? И только для консольного приложения или для VCL тоже?
KljaGGsa
8.07.2009 22:48
Владимир, прямое обращение к функциям ОС меня заинтересовало потому что Вы здесь на форуме утверждали, что это принципиальная экономия тактов и загрузки процессора, а следовательно и увеличение быстродействия программы. Использовать WinAPI правильнее, чем пытаться оптимизировать алгоритмы в графических VCL. Теперь буду пытаться разобраться, на каком этапе возникает дискретность анимации. В моем варианте мячик пинг-понга движется с видимыми хотя и незначительными рывками примерно одинаково что в канвасе пейнтбокса, что в нарисованном Вами консольном поле. Процессор Core Duo Pro с соответствующей тактовой частотой, на который грех жаловаться, другие программы отключены, резидентно висит только самый необходимый минимум. И очень огорчаюсь, если Вас чем-то ненароком обидела ..
Unconnected
8.07.2009 23:18
Дерганье и правда присутствует, даже не дёрганье, а перемещение мячика как бы маленькими рывками. Это хорошо заметно, если поставить интервал таймера равным 500, например. Но для учебных целей этого более чем достаточно, по моему:) На WinAPI вроде бы программы ещё маленькие получаются...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.