Android-приложения в Lazarus

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

На Snapdragon-е (Quest-3s) красивее .
Изображение
https://youtu.be/hdOmqhATKIY
(Это уже тест на реальном устройстве под управлением ОС Андроид )
Неплохо, но скорость все равно не очень радует, так что нужно будет пробовать сделать "OpenGL версию".
Seenkao
энтузиаст
Сообщения: 588
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Alex2013 писал(а): 03.07.2026 05:02:17 Исправленные версии процедур и функций ...
можешь дальше исправлять и получить выхлоп в этих местах в два а то и более раза.
Почитать можешь здесь, при чём всю тему. Полезное пишут.
Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Seenkao писал(а): 05.07.2026 14:41:49
Alex2013 писал(а): 03.07.2026 05:02:17 Исправленные версии процедур и функций ...
можешь дальше исправлять и получить выхлоп в этих местах в два а то и более раза.
Почитать можешь здесь, при чём всю тему. Полезное пишут.
1. Разумеется, я прекрасно понимаю, что причина выравнивания в оптимизации, но текущий код я пока вообще не оптимизировал (возможно, об этом позаботились его изначальные авторы (основу брал в примере из Hiasm, хотя, возможно, что это была далеко не первая его реализация), но сейчас я особо снова в этот код не вникал), к тому же вычисления с плавающей точкой требуют оптимизаций, отличных от целочисленных ухищрений.
2. Основной текущей задачей было, наоборот, избавиться от оптимизации и, получив чистый массив данных, загрузить его как шаблон «фоновой текстуры» в как бы по идее универсальный «волновой процессор».
3. Немного сомневаюсь, что в случае зоопарка реализаций ARM-платформ в принципе возможна стабильная «железячная оптимизация».
Зы.
За ссылку, разумеется, спасибо! Начал читать (с ходу такой объем информации не переварить, но попробую разобраться). :idea:
Зы. Зы.
Цель текущего проекта — самостоятельно воспроизвести на мобильной платформе что-то, что значительно отличается от стандартных примеров, и то, что может стать для меня неким «розеттским камнем» в деле переноса наработок из «мира виндовс» в «мир мобильных платформ».
(Вначале думал просто переписать, например, какой-нибудь «Терис с Дельфи» (или, например, всё тот же многострадальный «Дум»), но быстро понял, переписать что-то подобное будет, с одной стороны, черезчур простой задачей, а с другой — есть шанс погрязнуть в тонкостях реализации конкретной игры, не имеющих отношения к освоению программирования под андроид.) Так что пока как-то так.

Следующий этап развития проекта — в использовании «живого фона», получаемого с камеры мобильного устройства.

Зы Зы Зы
Как в LAMW правильно собирать "релизный APK" ?( все скрипты из примеров перепробовал работает только сборка "дебаг" версий APK, а они одна сплошная "дыра в системе" (требуют всех разрешений ОС держат открытыми проты отладки и т.п. )
Seenkao
энтузиаст
Сообщения: 588
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Tools -> [LAMW] Android Module Wizard -> Build Released Signed...

А вообще, создавая новый проект, он вроде без отладки идёт.
Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Seenkao писал(а): 05.07.2026 21:02:10 Tools -> [LAMW] Android Module Wizard -> Build Released Signed...

А вообще, создавая новый проект, он вроде без отладки идёт.
У меня работает только laz4android 2.0.12...
...создавая новый проект, он вроде без отладки идёт.
Идет то может быть без отладки но apk собирает только такие...
ХХХХХ-debug.apk и ХХХХХ-debug-unaligned.apk
Tools -> [LAMW] Android Module Wizard -> Build Released Signed...
Упс! Действительно есть такое. Спасибо! Попробую
Изображение
Seenkao
энтузиаст
Сообщения: 588
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Alex2013 писал(а): 05.07.2026 21:20:41 У меня работает только laz4android 2.0.12...
Я уже кидал тебе ссылку. Дополнительно в файле androidwidget найди строчку (функцию) procedure TAndroidWidget.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); и замени её код:

Код: Выделить всё

procedure TAndroidWidget.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer);
begin
     // 18/06/2026: Lazarus 4.x up bug fix
	 // In Lazarus 4.0 and above, if we add a component by double clicking, 
	 // it doesn't appear because it has a width=0, height=0 size.	 
     if (csDesigning in ComponentState) then
     begin
          if NewWidth=0 then NewWidth:=100;
          if NewHeight=0 then NewHeight:=40;
     end; 
  if (Left=NewLeft) and (Top=NewTop) and (Width=NewWidth) and (Height=NewHeight) then Exit;
  FLeft:=NewLeft;
  FTop:=NewTop;
  FWidth:=NewWidth;
  FHeight:=NewHeight;
  if (csDesigning in ComponentState) then
    if Assigned(Parent) then
      Parent.Invalidate
end;
Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Seenkao писал(а): 05.07.2026 21:32:02 Я уже кидал тебе ссылку. Дополнительно в файле androidwidget найди строчку (функцию) procedure TAndroidWidget.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); и замени её код:
Спасибо я попробовал но что-то у меня пошло сильно не так ( пришлось откатываться к архивной копии впрочем возможно это жара так повлияла ( пару раз успел заметить заметил что монитор ресурсов показывал резкий разгон и скачек температуры встроенной видеокарты (читай ядра CPU) выше 100 градусов после чего система разумеется моментально влетала в перегрузку ( похоже эмулятор кривой))
Последний раз редактировалось Alex2013 12.07.2026 15:59:57, всего редактировалось 1 раз.
Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Запустил программу на реальном смартфоне...
1. Нужно обязательно отключать все лишение «требования разрешений» (иначе антивирус входит «в режим паники»).
2. «Сборка релиза» не работает и портит проект (APK вообще перестает собираться даже в дебуг-версии (спасает только восстановление всего проекта из бэкапа, восстановление одних лазарус-исходников проекта ничем не поможет)).
3. В интерфейсе моей программы загадочным образом пропали все кнопки (тут это некритично, можно использовать клик по картинке, но что я сделал не так — непонятно (в эмуляторе и на QUEST3S всё Ок)).
4. Огромный заголовок окна определенно действует на нервы (как убрать — не нашел, стандартные LCL-приемы не помогают).
5. Тормозит почти так же, как на эмуляторе.
Зы
https://youtu.be/RpKPGT-y9Fc
Зы Зы
(фокус с procedure TAndroidWidget.SetBounds непременно попробую, спасибо и извиняюсь за отпечатки! )
Seenkao
энтузиаст
Сообщения: 588
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Если ты про LAMW, то версия сама по себе глючная. Там в настройках, например, кнопок надо включать всякие свойства, чтоб они правильно отображались. Это что-то вроде свойства wrapcontent. Чтоб это понять, надо смотреть в java как это всё сделано. Ведь именно посредством java всё реализовано, а не посредством FPC/Lazarus.
Seenkao
энтузиаст
Сообщения: 588
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Alex2013 писал(а): 12.07.2026 13:22:00 5. Тормозит почти так же, как на эмуляторе.
код есть? Может по ZenGL попробую запустить и посмотреть результат?
Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

1 "LAMW, то версия сама по себе глючная" совершенно согласен но это пока единственная среда для программирования под ОС Андроид с которой я хоть как-то поладил ( сборка по методу предложенному в ZenGL явно перспективнее но у меня просто не хватило терпения пройти все шаги правильно, а поскольку я пока в реалиях андроида практический "не в зуб ногой" разбираться приходится с тем что хоть как-то работает)

2 Что касается исходного кода то его не жалко просто смысла публиковать его нет. Основной модуль "рендера волн" сейчас почти универсальный так что если есть желание повозиться и перенести на свою платформу то я бы посоветовал начать с простой и понятной "тестовой виндовс адаптации " (главное там костылей заметно поменьше будет хотя код все равно явно тестовый и слегка "неухоженный" ) . WinWaveDemo2.7z ( "волновой процессор"(модуль WaveEffectsBin.pas) в этой версии уже "заточен под андроид" но отлаживать его проще вначале было под виндовс (но думаю что при желании можно и под линукс( если винды под рукой нет), без особых проблемы собрать) )
Версия исправленная и конкретно ее (в виде "релиза" с кодом ) я вроде не выкладывал
У меня работает так.
https://youtu.be/oGD4FpbRmn8

Всякий пожарный "боевая" версия WaveEffectsBin (на прямую из текущей андроид версии )
( если что-то и менял от исключительно по мелочи, но пусть будет... "береженого Ада Лавлейс бережет" :wink: )

Код: Выделить всё

unit WaveEffectsBin;

{$mode delphi}
{$POINTERMATH ON}

interface

uses
  Classes, SysUtils,Graphics, Math;

type
  // Структура для хранения состояния волн
  TWaveState = record
    Height: Single;
    Speed: Single;
  end;
  TWaveStateArray= array of TWaveState;

// ☆☆☆ УНИВЕРСАЛЬНАЯ ПРОЦЕДУРА РАБОТЫ С МАССИВОМ ПИКСЕЛЕЙ ☆☆☆
procedure WaveProcessorFXBin(
  Pixels: PByte;              // указатель на данные пикселей (RGBA)
  Width, Height: Integer;     // размеры изображения
  var Waves:TWaveStateArray;  // массив волн
  GridSize: Integer;          // размер сетки
  X, Y: Integer;              // -1 = только симуляция
  Radius: Integer;            // 0 = только симуляция
  HeightWave: Single;         // 0 = только симуляция
  Viscosity, WavesSpeed, LightIntensity, Depth: Single;
  Background: PByte = nil;    // указатель на фон (nil = градиент)
  BgWidth: Integer = 0; BgHeight: Integer = 0  // размеры фона
);

// Вспомогательные функции
procedure InitWaves(var Waves: TWaveStateArray; GridSize: Integer);
procedure ClearWaves(var Waves:TWaveStateArray; GridSize: Integer);
procedure GenerateGradient(Pixels: PByte; Width, Height: Integer);
procedure InitWavesRandom(var Waves: TWaveStateArray; GridSize: Integer; Amplitude: Single);

implementation

// ☆☆☆ ИНИЦИАЛИЗАЦИЯ ВОЛН (СЛУЧАЙНЫЕ ВОЗМУЩЕНИЯ) ☆☆☆
procedure InitWavesRandom(var Waves: TWaveStateArray; GridSize: Integer; Amplitude: Single);
var
  i: Integer;
begin
  for i := 0 to GridSize * GridSize - 1 do
  begin
    // Случайные возмущения с плавным переходом на границах
    Waves[i].Height := (Random - 0.5) * Amplitude * 2;
    Waves[i].Speed := (Random - 0.5) * Amplitude * 0.1;
  end;

  // Границы затухают
  for i := 0 to GridSize - 1 do
  begin
    Waves[i].Height := Waves[i].Height * 0.5;
    Waves[i].Speed := Waves[i].Speed * 0.5;

    Waves[(GridSize - 1) * GridSize + i].Height :=
      Waves[(GridSize - 1) * GridSize + i].Height * 0.5;
    Waves[(GridSize - 1) * GridSize + i].Speed :=
      Waves[(GridSize - 1) * GridSize + i].Speed * 0.5;

    Waves[i * GridSize].Height := Waves[i * GridSize].Height * 0.5;
    Waves[i * GridSize].Speed := Waves[i * GridSize].Speed * 0.5;

    Waves[i * GridSize + GridSize - 1].Height :=
      Waves[i * GridSize + GridSize - 1].Height * 0.5;
    Waves[i * GridSize + GridSize - 1].Speed :=
      Waves[i * GridSize + GridSize - 1].Speed * 0.5;
  end;
end;

// ☆☆☆ СОЗДАНИЕ ГРАДИЕНТА ☆☆☆
procedure GenerateGradient(Pixels: PByte; Width, Height: Integer);
var
  X, Y: Integer;
  idx: Integer;
  R, G, B: Byte;
  RowPtr: PByte;
begin
  if Pixels = nil then Exit;
  
  for Y := 0 to Height - 1 do
  begin
    RowPtr := Pixels + Y * Width * 4;
    for X := 0 to Width - 1 do
    begin
      idx := X * 4;
      
      B := Round(30 + 40 * (Y / Height));
      G := Round(80 + 100 * (Y / Height));
      R := Round(180 + 55 * (1 - (Y / Height)));
      
      RowPtr[idx] := 255;      // Alpha
      RowPtr[idx + 1] := R;    // Red
      RowPtr[idx + 2] := G;    // Green
      RowPtr[idx + 3] := B;    // Blue
    end;
  end;
end;

// ☆☆☆ ИНИЦИАЛИЗАЦИЯ ВОЛН ☆☆☆
procedure InitWaves(var Waves: TWaveStateArray; GridSize: Integer);
var
  i: Integer;
begin
  for i := 0 to GridSize * GridSize - 1 do
  begin
    Waves[i].Height := 0;
    Waves[i].Speed := 1;
  end;
end;

procedure ClearWaves(var Waves:TWaveStateArray; GridSize: Integer);
begin
  InitWaves(Waves, GridSize);
end;

// ☆☆☆ СОЗДАНИЕ ВОЛНЫ ☆☆☆
procedure MakeRipple(var Waves: array of TWaveState; GridSize: Integer;
  CX, CY, Radius: Integer; HeightWave: Single);
var
  X, Y, DX, DY, Dist, RadiusSq: Integer;
  Profile: Single;
  idx: Integer;
begin
  if GridSize < 1 then Exit;
  if (CX < 0) or (CY < 0) or (CX >= GridSize) or (CY >= GridSize) then Exit;
  
  RadiusSq := Radius * Radius;
  
  for X := Max(0, CX - Radius) to Min(GridSize - 1, CX + Radius) do
  begin
    DX := X - CX;
    for Y := Max(0, CY - Radius) to Min(GridSize - 1, CY + Radius) do
    begin
      DY := Y - CY;
      Dist := DX * DX + DY * DY;
      if Dist <= RadiusSq then
      begin
        Profile := 1.0 - Sqrt(Dist) / Radius;
        Profile := Profile * Profile * (3.0 - 2.0 * Profile);
        idx := Y * GridSize + X;
        Waves[idx].Height := Waves[idx].Height + HeightWave * Profile;
      end;
    end;
  end;
end;

// ☆☆☆ СИМУЛЯЦИЯ ВОЛН ☆☆☆
procedure SimulateWaves(var Waves: array of TWaveState; GridSize: Integer;
  Viscosity, WavesSpeed: Single);
var
  X, Y, idx: Integer;
  Ddx, Ddy, Viscosity1: Single;
begin
  if GridSize < 3 then Exit;
  if Length(Waves) < GridSize * GridSize then Exit;
  
  Viscosity1 := 1.0 - Viscosity;
  
  // Обновляем скорости
  for Y := 1 to GridSize - 2 do
    for X := 1 to GridSize - 2 do
    begin
      idx := Y * GridSize + X;
      Ddx := (Waves[idx + 1].Height - Waves[idx].Height) -
             (Waves[idx].Height - Waves[idx - 1].Height);
      Ddy := (Waves[idx + GridSize].Height - Waves[idx].Height) -
             (Waves[idx].Height - Waves[idx - GridSize].Height);
      Waves[idx].Speed := Waves[idx].Speed + (Ddx + Ddy) / WavesSpeed;
    end;
  
  // Обновляем высоты
  for Y := 1 to GridSize - 2 do
    for X := 1 to GridSize - 2 do
    begin
      idx := Y * GridSize + X;
      Waves[idx].Height := (Waves[idx].Height + Waves[idx].Speed) * Viscosity1;
    end;
  
  // Границы (затухание)
  for X := 1 to GridSize - 2 do
  begin
    Waves[X].Height := Waves[GridSize + X].Height * 0.95;
    Waves[(GridSize - 1) * GridSize + X].Height := 
      Waves[(GridSize - 2) * GridSize + X].Height * 0.95;
  end;
  
  for Y := 1 to GridSize - 2 do
  begin
    Waves[Y * GridSize].Height := Waves[Y * GridSize + 1].Height * 0.95;
    Waves[Y * GridSize + GridSize - 1].Height := 
      Waves[Y * GridSize + GridSize - 2].Height * 0.95;
  end;
end;

// ☆☆☆ РЕНДЕРИНГ ВОЛН В МАССИВ ПИКСЕЛЕЙ ☆☆☆
procedure RenderWavesToPixels(
  var Waves: array of TWaveState;
  GridSize: Integer;
  Pixels: PByte;
  Width, Height: Integer;
  Background: PByte;
  BgWidth, BgHeight: Integer;
  LightIntensity, Depth: Single);
var
  X, Y: Integer;
  GridX, GridY: Integer;
  Dx, Dy, HeightFactor, WaveHeight: Single;
  Light: Integer;
  XMap, YMap: Integer;
  R, G, B: Integer;
  idx, bgIdx: Integer;
  RowPtr, BgRowPtr: PByte;
  BgX, BgY: Integer;
begin
  if Pixels = nil then Exit;
  
  for Y := 0 to Height - 1 do
  begin
    RowPtr := Pixels + Y * Width * 4;
    
    for X := 0 to Width - 1 do
    begin
      // Преобразуем координаты пикселя в координаты сетки
      GridX := (X * GridSize) div Width;
      GridY := (Y * GridSize) div Height;
      
      if GridX >= GridSize then GridX := GridSize - 1;
      if GridY >= GridSize then GridY := GridSize - 1;
      
      idx := GridY * GridSize + GridX;
      WaveHeight := Waves[idx].Height;
      
      // Вычисляем наклон
      if GridX + 1 < GridSize then
        Dx := Waves[GridY * GridSize + GridX + 1].Height - WaveHeight
      else
        Dx := 0;
        
      if GridY + 1 < GridSize then
        Dy := Waves[(GridY + 1) * GridSize + GridX].Height - WaveHeight
      else
        Dy := 0;
      
      // Фактор глубины (искажение)
      HeightFactor := WaveHeight + Depth;
      if HeightFactor < 1.0 then HeightFactor := 1.0;
      
      // Смещение пикселя (эффект преломления)
      XMap := X + Round(Dx * HeightFactor * 0.5);
      YMap := Y + Round(Dy * HeightFactor * 0.5);
      
      if XMap < 0 then XMap := 0;
      if XMap >= Width then XMap := Width - 1;
      if YMap < 0 then YMap := 0;
      if YMap >= Height then YMap := Height - 1;
      
      // Вычисляем освещение
      Light := Round((Dx + Dy) * LightIntensity * 0.5);
      Light := Max(-128, Min(127, Light));
      
      // Добавляем блик на высоких волнах
      if Abs(WaveHeight) > 3.0 then
        Light := Light + Round(Abs(WaveHeight)) * 2;
      
      // Получаем пиксель из фона
      if Background <> nil then
      begin
        // Если фон другого размера — масштабируем координаты
        if (BgWidth > 0) and (BgHeight > 0) then
        begin
          BgX := (XMap * BgWidth) div Width;
          BgY := (YMap * BgHeight) div Height;
          if BgX >= BgWidth then BgX := BgWidth - 1;
          if BgY >= BgHeight then BgY := BgHeight - 1;
          BgRowPtr := Background + (BgY * BgWidth + BgX) * 4;
        end
        else
        begin
          BgRowPtr := Background + (YMap * Width + XMap) * 4;
        end;
        
        R := BgRowPtr[1] + Light;
        G := BgRowPtr[2] + Light;
        B := BgRowPtr[3] + Light;
      end
      else
      begin
        // Если фона нет — рисуем волны на чёрном
        R := 100 + Light;
        G := 150 + Light;
        B := 255 + Light;
      end;
      
      R := Max(0, Min(255, R));
      G := Max(0, Min(255, G));
      B := Max(0, Min(255, B));
      
      // Записываем результат
      idx := X * 4;
      if Background <> nil then
        RowPtr[idx] := BgRowPtr[0]  // Alpha из фона
      else
        RowPtr[idx] := 255;          // Alpha = 255
      
      RowPtr[idx + 1] := R;
      RowPtr[idx + 2] := G;
      RowPtr[idx + 3] := B;
    end;
  end;
end;

// ☆☆☆ ГЛАВНАЯ УНИВЕРСАЛЬНАЯ ПРОЦЕДУРА ☆☆☆
procedure WaveProcessorFXBin(
  Pixels: PByte;
  Width, Height: Integer;
  var Waves:TWaveStateArray;
  GridSize: Integer;
  X, Y: Integer;
  Radius: Integer;
  HeightWave: Single;
  Viscosity, WavesSpeed, LightIntensity, Depth: Single;
  Background: PByte = nil;
  BgWidth: Integer = 0; BgHeight: Integer = 0);
var
  NeedFreeBackground: Boolean;
  GradientPixels: array of Byte;
begin
  if Pixels = nil then Exit;
  if GridSize <= 0 then GridSize := 40;
  
  // Проверяем и инициализируем массив волн
  if Length(Waves) <> GridSize * GridSize then
    SetLength(Waves, GridSize * GridSize);
  
  // Инициализация волн при первом вызове
  if Waves[0].Height = 0 then
    InitWaves(Waves, GridSize);
  
  NeedFreeBackground := False;
  
  // Если фона нет — создаём градиент
  if Background = nil then
  begin
    SetLength(GradientPixels, Width * Height * 4);
    GenerateGradient(@GradientPixels[0], Width, Height);
    Background := @GradientPixels[0];
    BgWidth := Width;
    BgHeight := Height;
    NeedFreeBackground := True;
  end;
  
  // Если заданы координаты — создаём волну
  if (X >= 0) and (Y >= 0) and (Radius > 0) and (HeightWave > 0) then
    MakeRipple(Waves, GridSize, X, Y, Radius, HeightWave);
  
  // Симуляция физики волн
  SimulateWaves(Waves, GridSize, Viscosity, WavesSpeed);
  
  // Рендеринг в пиксели
  RenderWavesToPixels(
    Waves, GridSize,
    Pixels, Width, Height,
    Background, BgWidth, BgHeight,
    LightIntensity, Depth
  );
  
  // Освобождаем временный градиент
  if NeedFreeBackground then
    SetLength(GradientPixels, 0);
end;

end.
Alex2013
долгожитель
Сообщения: 3324
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Слегка доработал (исправил вычисление "стартовой точки" для запуска волны )

https://youtu.be/p4jZ4ilSzdQ
Суть прикола в том что если использовать jImageView1.Width и jImageView1.Height
или даже Self.Height и Self.Height возникает "трагическое непонимание" а fWidth и fHeight работают нормально.
(Хотя по идее к ним вообще доступа быть не должно это-же внутренние поля класса jForm из секции protected ).

Код: Выделить всё

{-------------------------------------}
Const MB:Boolean=false;
  Xo: Integer=-10;
  Yo: Integer=-10;

procedure TAndroidModule1.jImageView1TouchDown(Sender: TObject; Touch: TMouch);
var
   X,Y,X1, Y1: Integer;
  Radius: Integer;
  Height: Single;
begin
  if not FIsRunning then exit;
X:=Trunc(Touch.Pt.X); Y:=Trunc(Touch.Pt.Y);
  If mb and ( Sqrt(Sqr(X-Xo)+Sqr(y-Yo)) >3 ) then begin
   Xo:=X;   Yo:=Y;
  end;
mb:=True;
X1:= Trunc(( X*FGridSize )/fWidth);
Y1:= Trunc(( Y*FGridSize )/fHeight);
Radius := 5 + Random(15);
Height := FRandomIntensity * (0.5 + Random * 0.5);
 MakeRippleAt(X1, Y1, 10, 12.0);
end;

procedure TAndroidModule1.jImageView1TouchMove(Sender: TObject; Touch: TMouch);
var
   X,Y: Integer;
begin
X:=Trunc(Touch.Pt.X); Y:=Trunc(Touch.Pt.Y);
  If mb and ( Sqrt(Sqr(X-Xo)+Sqr(y-Yo)) >3 ) then begin
    jImageView1TouchDown(Sender, Touch);
  end;
end;

procedure TAndroidModule1.jImageView1TouchUp(Sender: TObject; Touch: TMouch);
begin
   if mb then mb:=False;
end;
Seenkao
энтузиаст
Сообщения: 588
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Посмотрел твой код. Основная проблема производительности, это постоянная конвертация BGR2RGBA и RGBA2BGR. Если ты избавишься от этой конвертации, то производительность повысится. И, если на Android ты используешь ту же конвертацию, то это очень сильно скажется там.

На Linux твой код не работает правильно, если изначальную картинку мне удалось сделать нормальной, то при создании волн картинка ломается всегда. Проблема в том, что на Linux формат pf24bit - всегда 24-х битный и прозрачности там ни какой нет. И вся функциональность которая основана на прозрачности должна быть переделана (что я и сделал), но картинка всё равно "ломается". А искать проблему мне лень...
Ответить