Перейти к содержанию
Fire Monkey от А до Я
  • 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
Ссылка на комментарий
  • Ответы 61
  • Создана
  • Последний ответ

Лучшие авторы в вопросе

Рекомендуемые сообщения

  • 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

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

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

Ссылка на комментарий
  • 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 сказал:

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

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

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

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

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