Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.04.2022, 01:14   #1
Катя93
Пользователь
 
Регистрация: 11.01.2021
Сообщений: 48
По умолчанию Как получить скорость движения курсора мыши?

У меня скролинг происходит от мышки чем быстрее двигаешь мышку тем быстрее перемещается объект. Нужно узнать скорость мыши и приплюсовать к радианам угла объекта. Как узнать скорость мыши в цифрах, чтобы можно было прибавить к объекту?
Катя93 вне форума Ответить с цитированием
Старый 19.04.2022, 02:33   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Так же как в задачке по математике про поезд выходящий из точки А в точку Б. Узнать ее положение с некоторым интервалом времени и разделить дистанцию на время.
см. также GetTickCount, GetCursorPos
Код:
время_до = GetTickCount()
GetCursorPos(курсор_до)
Через некоторое время
время_сейчас = GetTickCount()
GetCursorPos(курсор_сейчас)
дельта.x = ( курсор_сейчас.x - курсор_до.x )
дельта.y = ( курсор_сейчас.y - курсор_до.y )
дистанция = квадратный_корень( дельта.x * дельта.x + дельта.y * дельта.y )
скорость_пикселей_в_секудну = 100 * дистанция / ( время_сейчас - время_до )
cos(угла) = дельта.x / дистанция
sin(угла) = дельта.y / дистанция
время_до = время_сейчас
курсор_до = курсор_сейчас
Через некоторое время
время_сейчас = GetTickCount()
GetCursorPos(курсор_сейчас)
...
macomics вне форума Ответить с цитированием
Старый 19.04.2022, 02:48   #3
Катя93
Пользователь
 
Регистрация: 11.01.2021
Сообщений: 48
По умолчанию

Можно подробнее.Ошибку выдает:
Цитата:
Invalid floating point operation.
Код:
Код:
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var time_do:Integer;
  P: TPoint;
  P2: TPoint;
  time_now:Integer;
  delta: TPoint;
  distance: Real;
  speed_per_sec: Real;
begin
 time_do := GetTickCount();
 P:=Point(X,Y);
 GetCursorPos(P);
 time_now := GetTickCount();
 P2:=Point(X,Y);
 GetCursorPos(P2);
 delta.x := ( P2.x - P.x );
 delta.y := ( P2.y - P.y );
 distance := sqrt( delta.x * delta.x + delta.y * delta.y );
 speed_per_sec := 100 * distance / ( time_now - time_do );
 Label1.Caption:=FloatToStr(speed_per_sec);
end;
Катя93 вне форума Ответить с цитированием
Старый 19.04.2022, 03:01   #4
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Код:
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var time_do:Integer; // **
  P: TPoint; // ** В глобальные переменные или public секцию формы
  P2: TPoint;
  time_now:Integer;
  delta: TPoint;
  distance: Real;
  speed_per_sec: Real;
begin
 time_do := GetTickCount(); // *
 P:=Point(X,Y); // Вообще не нужно
 GetCursorPos(P); // * в OnCreate
 time_now := GetTickCount();
 P2:=Point(X,Y); // Вообще не нужно
 GetCursorPos(P2); // Эта функция получает координаты в пространстве экрана, те X,Y что передаются в обработчик вычисляются относительно координат окна
 delta.x := ( P2.x - P.x );
 delta.y := ( P2.y - P.y );
 distance := sqrt( delta.x * delta.x + delta.y * delta.y );
 speed_per_sec := 100 * distance / ( time_now - time_do );
 Label1.Caption:=FloatToStr(speed_per_sec);
// Добавить
  P.x := P2.x;
  P.y := P2.y;
  time_do := time_now;
end;
macomics вне форума Ответить с цитированием
Старый 19.04.2022, 04:01   #5
Катя93
Пользователь
 
Регистрация: 11.01.2021
Сообщений: 48
По умолчанию

По прежнему выдает ошибку. При отнимании time_now - time_do, получается ноль, а как известно число делить на ноль нельзя. Поэтому эта строка не работает.
Цитата:
speed_per_sec := 100 * distance / ( time_now - time_do );
И получается ошибка.
Цитата:
Floating point division by zero
Код:
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Math, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  P: TPoint; // ** В глобальные переменные или public секцию формы
implementation

{$R *.dfm}

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var time_do:Integer;
  P: TPoint;
  P2: TPoint;
  time_now:Integer;
  delta: TPoint;
  distance: Real;
  speed_per_sec: Real;
begin
 time_do := GetTickCount();
 time_now := GetTickCount();
 GetCursorPos(P2);
 delta.x := ( P2.x - P.x );
 delta.y := ( P2.y - P.y );
 distance := sqrt( delta.x * delta.x + delta.y * delta.y );
 speed_per_sec := 100 * distance / ( time_now - time_do );
 Label1.Caption:=FloatToStr(speed_per_sec);
  P.x := P2.x;
  P.y := P2.y;
  time_do := time_now;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
GetCursorPos(P); // * в OnCreate
end;

end.
Катя93 вне форума Ответить с цитированием
Старый 19.04.2022, 04:36   #6
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

А я звездочки зачем поставил. Не хотелось загружать одинаковыми комментариями текст.
Код:
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var time_do:Integer;// переместить в глобальные переменные или public секцию формы
  P: TPoint; //убрать за ненадобностью, иначе не видно глобальной переменной
  P2: TPoint;
//  time_now:Integer;
  time_delta:Integer;
//  delta: TPoint;
  dx, dy: Integer;
  distance: Real;
  speed_per_sec: Real;
begin
 time_do := GetTickCount();// в OnCreate
// time_now := GetTickCount();
 time_delta := GetTickCount() - time_do;
 if time_delta <> 0 then // т.к. сообщения от мыши могут приходить быстрее чем 1/100 сек, то стоит дополнительно проверить на 0
 begin
   GetCursorPos(P2);
//   delta.x := ( P2.x - P.x );
//   delta.y := ( P2.y - P.y );
   dx := ( P2.x - P.x );
   dy := ( P2.y - P.y );
   distance := sqrt( dx * dx + dy * dy );
   speed_per_sec := 100 * distance / ( time_delta );
   Label1.Caption:=FloatToStr(speed_per_sec);
   P.x := P2.x;
   P.y := P2.y;
   time_do := time_do + time_delta;
  end;
end;

Последний раз редактировалось macomics; 19.04.2022 в 04:44.
macomics вне форума Ответить с цитированием
Старый 19.04.2022, 05:13   #7
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Это будет несколько не точная скорость т.к. дистанция будет учитываться от точки А до Б по прямой. Для более точного получения скорости стоит накапливать пройденную дистанцию при каждом сообщении от мыши. При каждом пересчете значения скорости использовать суммарный пройденный путь и сбрасывать накопленную дистанцию в 0.
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Math, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  P: TPoint;
  time_do:Integer;
  distance: Real;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  distance := 0;
  time_do := GetTickCount();// в OnCreate
  GetCursorPos(P); // * в OnCreate
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var
  P2: TPoint;
  time_delta:Integer;
  dx, dy: Integer;
  speed_per_sec: Real;
begin
  time_delta := GetTickCount() - time_do;
  GetCursorPos(P2);
  dx := ( P2.x - P.x );
  dy := ( P2.y - P.y );
  distance := distance + sqrt( dx * dx + dy * dy );
  if time_delta >= 10 then // т.к. сообщения от мыши могут приходить быстрее чем 1/100 сек, то стоит дополнительно проверить на 0
  begin
    speed_per_sec := 10 * distance / ( time_delta );
    Label1.Caption:=FloatToStr(speed_per_sec);
    time_do := time_do + time_delta;
    distance := 0;
  end;
  P.x := P2.x;
  P.y := P2.y;
end;

end.
ADD: Еще можно увеличить точность вычисления, если следить за курсором не только над ClientRect окна, а на всей области экрана. см. TrackMouseEvent. Тогда придется написать еще несколько обработчиков сообщений: OnMouseLave, OnDestroy.
Или можно ограничить область перемещения курсора мыши только ClientRect окна. см. ClipCursor, ClientToScreen, Form1.ClientWidth, Form1.ClientHeight. Для этого по сообщению от мыши достаточно вычислить ClientRect:
Код:
client.x := 0;
client.y := 0;
ClientToScreen(client);
rect.left := client.x;
rect.top := client.y;
rect.right := client.x + Form1.ClientWidth;
rect.bottom := client.y + Form1.ClientHeight;
ClipCursor(rect);

Последний раз редактировалось macomics; 19.04.2022 в 05:56.
macomics вне форума Ответить с цитированием
Старый 19.04.2022, 13:22   #8
Катя93
Пользователь
 
Регистрация: 11.01.2021
Сообщений: 48
По умолчанию

Протестировала, работает, спасибо за помощь. Я делаю комнату, которая будет перемещаться, когда пользователь двигает мышку. Чем быстрее двигается курсор, тем быстрее поворачивается камера нацеленная на комнату. Кажется что это камера двигается на самом деле, это помещение смещается под определенным углом.
Катя93 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
скорость движения с зонтиком и без зонтика dimon_snake Паскаль, Turbo Pascal, PascalABC.NET 12 08.01.2017 22:28
Вывести поточные координаты курсора мыши относительно формы и экрана, при нажатии на кнопку реверсивное изменение кнопок мыши C++ carrie bradshaw Помощь студентам 0 06.02.2014 00:21
Дано скорость лодки, скорость течения реки, время движения, определить путь S, пройденный лодкой (на Delphi) zhora-011 Помощь студентам 1 06.09.2013 22:05
Запрет движения курсора Ko$ Общие вопросы Delphi 0 22.05.2013 17:28
Скорость движения обьекта shepelin Общие вопросы Delphi 9 23.01.2008 11:51