• 0
Letos

Скроллинг на канве

Вопросы

Здравствуйте. Подскажите, пожалуйста, правильно ли я делаю скроллинг фона? Собственно интересует, рационально ли здесь использовать метод DrawBitmap? При этом же прорисовывается вся канва. (И да, помещать картинку на TImage и двигать её я пробовал, так ГОРАЗДО медленнее.) Ведь даже на игровых приставках имелась аппаратная функция скроллинга экрана, реализовано ли это как-то в FMX? Пример я прилагаю, включая exe файл. Как видим, двигается не идеально плавно.

//---------------------------------------------------------------------------

#include <fmx.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;

TBitmap *MapBmImage = new TBitmap;
String InitialDirectory;


float MapVx=150; // скорость по X, пиксели в секунду

float MapOutX=0, MapOutY=0; // координаты левого верхнего угла, с которого выводится фон
float ScreenMapWidth, ScreenMapHeight; // ширина и высота фона на экране
float MapOutXLimit; //крайняя правая точка карты, которая может быть отражена
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
boolean LoadMapFile() //загрузка карты
{
    String filename=InitialDirectory+"\\2dbackground_b.png";
    if(!FileExists(filename)) return false;

    MapBmImage->LoadFromFile(filename);

    return true;

}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    InitialDirectory=ExtractFileDir(ParamStr(0)); // the path and file name of the executing program
    LoadMapFile();
}
//---------------------------------------------------------------------------


void DrawBackground()
{
    TPaintBox *ScreenMap=Form1->PaintBox1; //где отрисовывается карта на экране

    TRectF MapRect = TRectF(MapOutX, MapOutY, MapOutX+ScreenMapWidth, MapOutY+ScreenMapHeight);
    TRectF ScreenRect = TRectF(0, 0, ScreenMapWidth, ScreenMapHeight);

    ScreenMap->Canvas->BeginScene();
    ScreenMap->Canvas->DrawBitmap(MapBmImage,MapRect,ScreenRect,255);
    ScreenMap->Canvas->EndScene();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    ScreenMapWidth=PaintBox1->Width;
    ScreenMapHeight=PaintBox1->Height;

    MapOutXLimit=MapBmImage->Width-ScreenMapWidth;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    if (MapOutX>=MapOutXLimit) MapVx=-1* abs(MapVx);
    else if (MapOutX<=0) MapVx=abs(MapVx);


    static DWORD LastTick=0; //из-за неравномерного срабатывания таймера
    DWORD Tick;
    float step;
    Tick=GetTickCount();
    if(LastTick!=0)
    {
        step=(float)(Tick-LastTick)/1000; // столько секунд прошло
    }
    else
    {
        step=(float)Timer1->Interval/1000;
    }


    LastTick=Tick;


    float dx; //на столько сдвигаем карту по X
    dx=MapVx*step;

    MapOutX+=dx;
    if (MapOutX>MapOutXLimit) MapOutX=MapOutXLimit;
    if (MapOutX<0) MapOutX=0;

    PaintBox1->Repaint();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::PaintBox1Paint(TObject *Sender, TCanvas *Canvas)
{
    DrawBackground();
}
//---------------------------------------------------------------------------


BackgroundScroll.zip

Изменено пользователем Letos

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

27 ответов на этот вопрос

  • 0

Добавлю. Где-то читал рекомендацию использовать т.н. мультимедийный таймер. Но что это такое? И потом, таймер таймером, но как всё же сколлировать фон, неужели перерисовкой каждый раз всей канвы?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 23.02.2019 в 12:29, Letos сказал:

Где-то читал рекомендацию использовать т.н. мультимедийный таймер. Но что это такое?

Это таймер, но "чуть более точный" чем обычный.
Ок, ну значительно более)))

В 23.02.2019 в 12:29, Letos сказал:

как всё же сколлировать фон, неужели перерисовкой каждый раз всей канвы?

Ну, как бы да 😃

Выше вы писали про игровые приставки. Да, в них имелись такие функции, но:
1) чипы проектировались специально под определенные задачи, а не как сегодняшний процессор - комбайн для любой задачи
2) это были экстремально малопроизводительные (по современным меркам) процессоры, и именно для того чтобы проц не умирал при скролле всего экрана это было реализованно аппаратно.

Если вы возьмете современную приставку (ps4 например) то внутри внезапно окажется практически обычный х86 процессор-комбайн от амд.
И внезапно, эта приставка использует всем известный OpenGL в котором нет специальной функции для сдвига фона. Говоря просто, все стирается, и отрисовывется по-новой с новыми координатами.

Изменено пользователем Barbanel

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 25.02.2019 в 11:37, Barbanel сказал:

Ну, как бы да

Это понятно. Перерисовывать фон не жалко. Но как сделать плавный скроллинг? Вы видели мой пример? Все же рывками двигается фон. 

В 25.02.2019 в 11:37, Barbanel сказал:

чипы проектировались специально под определенные задачи, а не как сегодняшний процессор - комбайн для любой задачи

Сейчас специально делается видеокарта - со своим(и) процессором(и). (Это тогда процессор, как Z80 в ZX Spectrum, должен был справляться со всеми задачами.)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 25.02.2019 в 11:37, Barbanel сказал:

И внезапно, эта приставка использует всем известный OpenGL в котором нет специальной функции для сдвига фона.

В приставках есть видео-сопроцессор (был даже ещё в Амиге в 80-х годах), и в Амиге сколлировалось именно аппаратно. А в моём примере - скроллируется программно, процессором. Неужели графическая видеокарта PC не умеет? Умеет, но как?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 25.02.2019 в 11:37, Barbanel сказал:

Это таймер, но "чуть более точный" чем обычный.
Ок, ну значительно более)))

Извини, если вопрос нубский, но где его взять?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Помню, на Спектруме в ассемблере (Z80) была команда HALT, чтобы дождаться обратного хода луча на кинескопе (если успел прорисовать) и тем самым обеспечить плавность. Тут же, в FMX синхронизация с дисплеем обеспечивается размещением прорисовки в OnPaint? Тогда почему же дёргается фон?

И да, видал эмуляторы приставок, там фон двигается плавно, значит, как-то можно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

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

видел игрушки на Delphi все плавно и хорошо было.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
34 минуты назад, #WAMACO сказал:

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

Вот я и размышляю, и пытаюсь привлечь к этому уважаемых участников форума.

35 минут назад, #WAMACO сказал:

видел игрушки на Delphi все плавно и хорошо было.

И я о том же.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Дался вам этот аппаратный скроллинг!!!

Чтобы скроллить что-то, нужно сначала это что-то отрендерить полностью. FM не рендерит скроллбокс целиком, только его видимую часть. Чтобы проскроллить контент, FM каждый раз заново перерисовывает контент.

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

Забудьте о этом и живите дальше. Перепишите приложение либо разберитесь с тем что у вас происходит в момент фризов.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
3 минуты назад, Barbanel сказал:

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

Переписать? Я и обратился с просьбой совета - как написать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
40 минут назад, Letos сказал:

Переписать? Я и обратился с просьбой совета - как написать.

В RAD есть GetIt, там есть примеры игрушек. В частности, в одной из них плавно движется фон и еще объекты летают шустро достаточно.

посмотрите...

есть еще открытый движок (сделан на Delphi)

https://github.com/castle-engine

тоже интересный. 

Изменено пользователем #WAMACO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
23 минуты назад, #WAMACO сказал:

В RAD есть GetIt, там есть примеры игрушек. В частности, в одной из них плавно движется фон и еще объекты летают шустро достаточно.

спасибо за совет! Посмотрю. Но как понимаю, пока нет уважаемых форумчан, готовых в коде написать и показать...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
5 минут назад, Letos сказал:

спасибо за совет! Посмотрю. Но как понимаю, пока нет уважаемых форумчан, готовых в коде написать и показать...

Приходите в чат в Telegram., там был человек, который пишет игрушки на Delphi (по крайней мере был)

Там если что, старожилы подскажут!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
16 минут назад, #WAMACO сказал:

Там если что, старожилы подскажут!

Спасибо. Но этот форум-то для чего? Тем более, что Brovin Yaroslav просматривал мою тему и позиционирует себя как один из разработчиков FMX!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Лет 10 назад делал проект по 3Д измерения (vcl проект). Массив точек был на гигабайт. Он сам в память минуту грузился. Но далее я его в вершины (opengl) перегружал и все манипуляции с отражениями (поворот, сдвиг) делались уже силами ОСи и аппаратной части. Прекрасно работало.

Неужто какой-нибудь mash в FMX иначе работает? Лет 5 назад FMX приложение делал - с солнышком, планетой Земля (с текстурами), с метеоритом по эллипсу летающему - всё порхало. Под виндой... хотя вроде разок на мобиле запустили и там тоже летало.

Ну так и сделать - попиксельно картинку в mash толщиной в 1 пиксель загрузить и двигать как угодно.

 

update: я это баловство даже нашел - кучу вершин крутит FMX прекрасно. 

4534545.jpg

Изменено пользователем POV

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 02.03.2019 в 17:27, Letos сказал:

Переписать? Я и обратился с просьбой совета - как написать.

Доброго времени.

Я не могу вам сказать где именно ошибка (я даже не уверен что она есть), вы пишете я С++, а у меня лишь Delphi под руками. Я скачал ваш проект и запустил ехе. К сож. он не запустился на моей матине из-за отсутсвующих библиотек rtl250.bpl
Соотв. я не вижу как работает приложение, и как выглядят ваши фризы.
Судя по всему вы пытаетесь сделать игрушку, либо что-то аналогичное. Делать игрушку используя один лишь FMX или VCL имхо нелогично, т.к. эти платформы не предназначены для быстрой и плавной отрисовки графики.
Если вам реально необходима плавная отрисовка - используйте либо OpenGL либо DirectX. Вот здесь то и будет на все 100% "аппаратный скролл".
Это и есть тот совет, "как" написать.

В 02.03.2019 в 18:59, Letos сказал:

Спасибо. Но этот форум-то для чего? Тем более, что Brovin Yaroslav просматривал мою тему и позиционирует себя как один из разработчиков FMX!

Этот форум как раз для этого предназначен, и количество постов как раз тому подтверждение. Есть только одно НО:
никто здесь не обязан сразу броситься и настрочить вам готовое решение. Если человек имеет представление где может быть проблема, и что еще более важно - имеет время и желание писать ответ - он вам ответит.
Далеко не каждый из тех кто прочитал тему может или хочет вам (или мне, или кому-либо еще) отвечать.

Ярослав же и так имеет чем заняться и совершенно не обязан отвечать в каждой теме. Вы не спрашиваете на форуме MSDN почему вам лично мистер Гейтс не отвечает.

Ок, это было отступление.
Если вы хотите примеры как использовать графические библиотеки - вам на немного другие специализированные форумы типа gamedev.ru
Конкретно для Delphi и OpenGL я могу дать такую ссылку sulaco Здесь множество простейших примеров использования OpenGL, я в свое время именно здесь его и осваивал. 

Изменено пользователем Barbanel

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 05.03.2019 в 13:20, Barbanel сказал:

К сож. он не запустился на моей матине из-за отсутсвующих библиотек rtl250.bpl

Прикрепляю скомпилированный exe, который должен у вас запуститься.

 

В 05.03.2019 в 13:20, Barbanel сказал:

никто здесь не обязан сразу броситься и настрочить вам готовое решение.

Да, конечно, понимаю это. Я всегда благодарен за помощь и понимаю, что никто тут отвечать мне не обязан. Если где-то мои обращения могли показаться как требования, то прошу прощения за неточность выражения мыслей.

Project1.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 05.03.2019 в 13:20, Barbanel сказал:

Судя по всему вы пытаетесь сделать игрушку, либо что-то аналогичное.

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

 

В 05.03.2019 в 13:20, Barbanel сказал:

Если вам реально необходима плавная отрисовка - используйте либо OpenGL либо DirectX.

Да, там должно быть плавно (правда пока опыта нет). Но слышал, что эти методы используются в FMX, поэтому и обратился на форум, чтобы узнать реализованы ли они полностью в FMX.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 минуту назад, Letos сказал:

слышал, что эти методы используются в FMX

Насколько мне известно, эти методы не используются. Может использоваться GDI (это из другой области) либо ЦПУ.

 

22 минуты назад, Letos сказал:

Если где-то мои обращения могли показаться как требования, то прошу прощения за неточность выражения мыслей.

Аналогично, сори за грубость)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 05.03.2019 в 13:20, Barbanel сказал:

Ярослав же и так имеет чем заняться и совершенно не обязан отвечать в каждой теме.

Конечно, согласен. Но я не предполагал, что вопрос настолько сложный, допускал, что ответ мог быть: "просто поставь такое-то свойство в компоненте", или "просто используй такую-то команду"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
27 минут назад, Letos сказал:

Прикрепляю скомпилированный exe, который должен у вас запуститься.

Посмотрел. Возможно у меня слишком производительный пк, потому что я ничего критичного не вижу.
На глаз выводится 20-30 фпс, каких-либо рывков я не вижу. ¯\_(ツ)_/¯

Имхо, для диспетчера депо вполне норм)

Изменено пользователем Barbanel

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
Только что, Barbanel сказал:

Имхо, для диспетчера депо вполне норм)

Наверное. (У меня тоже не самый старый (i5-6400), но у диспетчера слабее). И потом, мне стало интересно - а как можно выводить быстрее? И так ли плавно у тебя выводится? У меня - плавно, плавно, а потом маленький скачок глаз замечает. Похоже, что с таймером это связано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Это связано с тем, что у таймена не наивысший приоритет, а как раз наоборот. События таймер выполняются когда приложение (и сама ОС) простаивает.
Т.о. пауза между вызовами событий таймера не всегда одинакова, а сдвиг же в свою очередь всегда на фиксированное значение.
Если же вы будете сдвигать изображение на значение пропорциональное реальному интервалу между событиями - рывки будут менее заменты на глаз (хотя все еще будут возникать).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 минуту назад, Barbanel сказал:

Если же вы будете сдвигать изображение на значение пропорциональное реальному интервалу между событиями - рывки будут менее заменты на глаз

В моём примере это учитывается - расстояние сдвига зависит от прошедшего времени (не так уж сильно Паскаль от Си отличается, чтоб дельфисту не понять)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу