Перейти к содержанию
Fire Monkey от А до Я

Akromd

Пользователи
  • Постов

    43
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Akromd

  1. В 07.01.2017 в 22:42, krapotkin сказал:

    ничего не понял

    что не так с датаснапом?

    сервер кладется на форму вроде как обычно, не?

     

    Да, именно так, только некоторые компоненты datasnap server не компилируются под андройд.

    Для того, чтобы понятно было, что я хочу, прилагаю простой проект для примера с датаснапом.

    В проекте сервер и клиент. Сервер достаточно запустить, а клиент по каждому нажатию "Получить id" эмулирует подключение нескольких клиентов, что приводит к вычислению некой суммы от каждого клиента.

    А возвращаясь к задаче, хочется чтобы все вычисления были у клиента.

    Проверка сервера.zip

  2. 1 час назад, kami сказал:

    В данном случае под сервером понимается серверный сокет с необходимыми обработчиками событий. Смотрите индейцев и выбирайте любой понравившийся.

    Но гораздо проще взять готовую технологию - AppTethering. С самостоятельной реализацией вы рискуете погрязнуть в энтомологоии, особенно - если возьмете минималистичный протокол (TCP/IP).

    Обратите внимание, что в любом случае устройства сконнектятся друг с другом только если они находятся в одной подсети.

    Об телеринге я уже задумался. Однако первоначальная идея что устройства соединяются не в одной подсети.

    Видимо все таки придется копать инди, а так хотелось с датаснапом легко и быстро)

  3. 3 часа назад, GASCHE сказал:

    Перефразирую, читать данные других клиентов с сервера, проводить вычисления, итоги и свои данные скидывать на сервер.

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

    И мы опять возвращаемся к вопросу как поднять сервер на android)

  4. 1 час назад, GASCHE сказал:

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

    Проблема в том что все вычисления зависят от данных других клиентов. Без них никаких вычислений не будет.

  5. 4 минуты назад, krapotkin сказал:

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

    можно и датаснап использовать

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

    С тетерингом какие то проблемы, но это другая тема, мне еще разбираться и разбираться.

    С разными сетями все работает, но все вычисления производятся на сервере (их довольно много),а клиенты запросами получают данные. Чем больше клиентов, тем больше вычислений. Соответственно и хотелось бы скинуть вычисления на клиентов (Разбить на группы) и данные будут передаваться между этими группами. А на сервер посылаются только итоги.

  6. 7 минут назад, ZuBy сказал:

    такс, давайте разберемся. для ясности

    1) приложения на каких платформах будет работать?

    2) будет использоваться БД?

    3) всегда приложения в одной сети будет?

    4) datasnap обязательно?

    Да, отбъясняю я не очень)

    1. Приложение мультиплатфотрменное. Все что поддерживает FMX на тех платформах и будет приложение.

    2. БД пока не используется, и не планируется. Но мало ли.

    3. Не всегда. Чаще всего не в одной сети, для этого использую стационарный сервер со статическим ip. Но хотелось бы чтоб когда два и более приложения были в одной сети, они имели возможность соединятся без стационарного сервера.

    4. Не обязателен. Просто ничего другого мультиплатформенного не придумал. И с Datasnap уже что-то понял и это работает.

  7. 6 минут назад, krapotkin сказал:

    ну, ладно, пусть становится, а по какому IP доступ-то? 192.168.143.41 ?

    Имеет значение? Я не понимаю технологии процесса,через какие компоненты все это осуществить в Delphi. Если использовать datasnap то все понятно, когда у нас сервер на компе и через него все запросы. Но что сделать, если мы хотим сервер облегчить, оставив в функционале только связывание клиентов друг с другом.

  8. 2 минуты назад, krapotkin сказал:

    и как же два клиента общаются, минуя сервер, интересно? 

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

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

  9. 1 час назад, ZuBy сказал:

    даже в теории сервер на мобиле не должен быть)

    может кто пользуется (я нет) оф. приложение фейсбука и есть сервер.

    в теории: 3rd party приложения общаются не с сервером (api facebook.com), а приложением установленным в телефоне через SDK.

    что в реале: батарейка улетает в 0, дробление единого сервиса на несколько приложении (имхо)

     

    Да, идейно все это правильно, что сервер на мобиле ересь)

    Но как тогда поступают в случае общения двух клиентов минуя сервер?

    То есть обычно (в моем понимании) реализуется запрос клиента у сервера чего либо, таким образом получая и изменяя данные на сервере. В результате другой клиент может получить измененную информацию с сервера. А если мы хотим миновать сервер? чтобы клиент делал запрос сразу другому клиенту? А сервер используем только для того, чтобы в первый раз лишь сказать клиентам где они находятся.

  10. Добрый вечер.

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

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

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

  11. При включенной функции ReportMemoryLeaksOnShutdown  заметил, что при вызове Tdialogservice.inputquery после закрытия формы выходит ошибка утечки памяти связанный с TWinAcceleratorKeyRegistry, с чем может быть связано?

    Утечка памяти TdialogService.png

    пример кода:

      TDialogService.InputQuery('Имя игрока',['Имя'],[PlayerNameText.Text],
        procedure (Const AResult: TModalResult; const AValues: array of string)
        begin
          if not AValues[0].Equals(PlayerNameText.Text) then
            begin
              Hero.NamePlayers := AValues[0];
            end;
        end);

     

  12. Добрый день.

    Первое. Не работает свойство StartFromCurrentPosition. При любом значении берет то, что записано в StartValue.

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

    dfsdf.png

  13. 20 минут назад, Rusland сказал:

    Криво как-то рисует

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

  14. Проект прикреплен к посту.

    Код:

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
      FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects, FMX.Edit;
    
    type
      TForm1 = class(TForm)
        Path1: TPath;
        Button1: TButton;
        Button2: TButton;
        Edit1: TEdit;
        Label1: TLabel;
        Edit2: TEdit;
        Label2: TLabel;
        Label3: TLabel;
        Edit3: TEdit;
        Label4: TLabel;
        Edit4: TEdit;
        Label5: TLabel;
        Label6: TLabel;
        Label7: TLabel;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
      TAnimationPath = class(TThread)
      public
      private
        countflash: byte;
        tmpline: TLine;
        NowP,EndP: TPoint;
        Sender: TObject;
        duration: single;
        Step: TPoint;
        updateinterval: integer;
        { Private declarations }
      protected
        procedure Execute; override;
        constructor Create(StartPos,EndPos:TPoint;induration:single;inSender:TObject);
        procedure update;
        procedure flashanim;
        procedure flashcreate;
        procedure delassept;
      end;
    
    var
      Form1: TForm1;
      Assept: array of Integer;
    
    implementation
    
    {$R *.fmx}
    
    constructor TAnimationPath.Create(StartPos, EndPos: TPoint; induration: single; inSender: TObject);
    begin
       inherited Create(false);
       NowP := StartPos;
       EndP := EndPos;
       Sender := inSender;
       countflash := 5;
       duration := induration*1000;
       updateinterval := 50;
       Step := (EndP - NowP);
       Step.X := abs(Step.X * updateinterval);
       Step.Y := abs(Step.Y * updateinterval);
       Step.X := Trunc(Step.X / duration);
       Step.Y := Trunc(Step.Y / duration);
       tmpline := Tline.Create(nil);
       tmpline.Parent := TPath(sender);
       tmpline.Position.X := NowP.X;
       tmpline.Position.Y := NowP.Y;
       tmpline.Width := 1;
       tmpline.Height := 1;
       tmpline.Stroke := TPath(Sender).Stroke;
    end;
    
    procedure TAnimationPath.delassept;
      var I: integer;
          J: integer;
          L: TLine;
    begin
      I := Trunc(tmpline.Width)-1;
      J := Trunc(tmpline.Height)-1;
    
      Tpath(Sender).Data.Data := Tpath(Sender).Data.Data + ' M' + IntToStr(Trunc(tmpline.Position.X)) + ',' + IntToStr(Trunc(tmpline.Position.Y)) + ' L' + IntToStr(Trunc(tmpline.Position.X + I)) + ',' + IntToStr(Trunc(tmpline.Position.Y + J));
    
      for I := TPath(Sender).ChildrenCount-1 downto 0
        do if TPath(Sender).Children[I] is TLine then
          if (TLine(TPath(Sender).Children[I]) = tmpline) then
          begin
            L := TLine(TPath(Sender).Children[I]);
            TPath(Sender).RemoveObject(L);
            L.Free;
            Exit;
          end;
    end;
    
    procedure TAnimationPath.Execute;
    begin
      if (NowP.X <> EndP.X) and (NowP.Y <> EndP.Y) then tmpline.LineType := TLineType.Diagonal
      else
        begin
          if (NowP.X <> EndP.X) then tmpline.LineType := TLineType.Top;
          if (NowP.Y <> EndP.Y) then tmpline.LineType := TLineType.Left;
        end;
      try
      while (NowP.X <> EndP.X)or(NowP.Y <> EndP.Y) do
        begin
          Synchronize(Update);
          Synchronize(Flashcreate);
          Synchronize(flashanim);
          Sleep(updateinterval);
        end;
      while (tmpline.ChildrenCount > 0) do
        begin
          Synchronize(flashanim);
          Sleep(updateinterval);
        end;
      except
      end;
      Synchronize(delassept);
    end;
    
    procedure TAnimationPath.flashanim;
      var C: TCircle;
          I: integer;
    begin
      for I := Tmpline.ChildrenCount-1 Downto 0
        do if tmpline.Children[I] is TCircle
          then
            begin
              C := TCircle(tmpline.Children[I]);
              C.Position.Point := C.Position.Point + C.Position.DefaultValue;
              if C.TagFloat / 10 < 1 then C.Opacity := C.TagFloat / 10;
              C.TagFloat := C.TagFloat - 1;
              if C.TagFloat < 0
                then
                  begin
                    Tpath(Sender).RemoveObject(C);
                    C.Free;
                  end;
            end;
    end;
    
    procedure TAnimationPath.flashcreate;
      var I: Integer;
          C: TCircle;
          P: TPointF;
    begin
      for I := 0 to countflash do
        begin
          C := TCircle.Create(nil);
          C.Parent := tmpline;
          C.Width := 2 + Random * 4;
          C.Height := C.Width;
          C.fill.Color := TAlphaColors.Yellow;
          C.Stroke.Kind := TBrushKind.None;
          if NowP.X < EndP.X then P.X := tmpline.Width
          else P.X := 0;
          if NowP.Y < EndP.Y then P.Y := tmpline.Height
          else P.Y := 0;
          C.Position.Point := P;
          C.Position.DefaultValue := PointF(0.5 - Random,0.5 - Random).Normalize * (1 + random * 2);
          C.TagFloat := 10 + Random(15);
          C.Opacity := 1 - Random;
        end;
    end;
    
    procedure TAnimationPath.update;
    begin
      if (NowP.X < EndP.X) then
        begin
          if (NowP.X + Step.X > EndP.X) then
            begin
              tmpline.Width := tmpline.Width + EndP.X - NowP.X;
              NowP.X := EndP.X;
            end
          else
            begin
              NowP.X := NowP.X + Step.X;
              tmpline.Width := tmpline.Width + Step.X;
            end;
        end;
      if (NowP.Y < EndP.Y) then
        begin
          if (NowP.Y + Step.Y > EndP.Y) then
            begin
              NowP.Y := EndP.Y;
              tmpline.Height := tmpline.Height + EndP.Y - NowP.X;
            end
          else
            begin
              NowP.Y := NowP.Y + Step.Y;
              tmpline.Height := tmpline.Height + Step.Y;
            end;
        end;
      if (NowP.X > EndP.X) then
        begin
          if (NowP.X - Step.X < EndP.X) then
            begin
              NowP.X := EndP.X;
              tmpline.Position.X := tmpline.Position.X - (NowP.X - EndP.X);
              tmpline.Width := tmpline.Width + (NowP.X - EndP.X);
            end
          else
            begin
              NowP.X := NowP.X - Step.X;
              tmpline.Position.X := tmpline.Position.X - Step.X;
              tmpline.Width := tmpline.Width + Step.X;
            end;
        end;
      if (NowP.Y > EndP.Y) then
        begin
          if (NowP.Y - Step.Y < EndP.Y) then
            begin
              NowP.Y := EndP.Y;
              tmpline.Position.Y := tmpline.Position.Y - (NowP.Y - EndP.Y);
              tmpline.Height := tmpline.Height + (NowP.Y - EndP.Y);
            end
          else
            begin
              NowP.Y := NowP.Y - Step.Y;
              tmpline.Position.Y := tmpline.Position.Y - Step.Y;
              tmpline.Height := tmpline.Height + Step.Y;
            end;
        end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
      var TmpAnim: TAnimationPath;
          X,Y: Integer;
    begin
      TmpAnim := TAnimationPath.create(Point(0,0),Point(0,200),1,Path1);
    
      TmpAnim := TAnimationPath.create(Point(0,200),Point(400,200),2,Path1);
    
      TmpAnim := TAnimationPath.create(Point(400,200),Point(400,0),3,Path1);
    
      TmpAnim := TAnimationPath.create(Point(400,0),Point(0,0),4,Path1);
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      Path1.Data.Clear;
    end;
    
    end.

     

    Постоепенная отрисовкаTPath.zip

  15. Немного пояснения: требовалось анимировать объект Tpath (не путать с TpathAnimation!) - то есть анимировать отрисовку "сложных" объектов через SVG.

    За отрисовку объектов отвечает свойство data.data, которое в виде строки хранит SVG код.

    Первое мое решение как раз и было связано с постепенным изменением этого свойства, для плавного отображения, но я столкнулся с проблемой "быстрых" тормозов, собственно из-за чего и возникла эта тема.

    Немного подумав, оказалось, что из постоянного дополнения этого свойства (data.data), оно очень быстро "переполнялось" и отрисовка занимала очень длительное время. Поэтому было решено использовать другой метод: вместо того чтобы постепенно изменять это свойство, мы создаем новый объект типа Tline и изменяя его размер как будто рисуем постепенно новую линию, а в конце уничтожаем ее, заменяя начало и конец добавлением в то самое свойство data.data тем самым экономя и память, и размер свойства.

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

    Если кому интересно, выложу исходники

  16. 3 минуты назад, Brovin Yaroslav сказал:

    Скачайте пакет и посмотрите на TfgBitmapLinkAnimationTfgPositionAnimationTfgPosition3DAnimation (Модуль FGX.Animations). И обратите внимание, что все это не простые типы. 

    Спасибо, сейчас ознакомлюсь

  17. 8 минут назад, Brovin Yaroslav сказал:

    Не делайте велосипед. Посмотрите в исходниках, как реализована анимация любого свойства. Можете взять из моих компонентов аниматоров FGX. 

    А где связь с анимацией любого свойства? ведь мы пытаемся анимировать не просто свойство opacity или width, а именно отрисовку TPath. И где можно найти аниматоры FGX?

  18. 4 минуты назад, krapotkin сказал:

    1. все, что происходит с КОМПОНЕНТОМ, придется делать в ГП. Это заполнение св-ва Path

    2. НО! все, что нужно предварительно рассчитать, не должно быть в ГП

    Как вариант 

    
    procedure TMyThread.Execute;
    begin
      while not Terminated do
      begin
        ProcessCurrentState();
        Synchronize(UpdateUserInterface);
        sleep(UpdateInterval);
      end;
    end;

    при этом ПО-ЛЮБОМУ будет уходить время на UpdateUserInterface/ Линейно увеличиваясь с кол-вом компонентов

    То есть использование synchromize не рентабельно, и лучше использовать заполнение в ГП? Тогда вопрос зачем он нам в потоке для UpdateUserInterface? Или этот метод в ГП?

    Не совсем понимаю конструкцию while not Teminated. Получается мы бесконечно выполняем цикл?

  19. 4 минуты назад, krapotkin сказал:

    нет

    имеется в виду что Synchronize - это выполнение в главном потоке

    если весь код вашего потока выполняется в главном потоке, то зачем заводить поток???

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

    т.к. это всяко компонент и тут без ГП никак

    Мне кажется я ответил выше, но все же поясню. Тут принцип тот же: задается ключевая точка и рисуется, проблема в том, что отдновременно их может рисоваться огромное количество на разных объектах и в то же время пользователь можето что то делать и поэтому я не понимаю как можно из главного потока это все сделать.

×
×
  • Создать...