Сегодня мы поговорим о том, как сделать управление сценой мультитачем и жестом pinch-zoom на Android используя Linderdaum Engine.

1. Подготовка
Будем считать, что Linderdaum Engine SDK уже установлен и настроен. Про настройку SDK и то, как скомпилировать приложение, можно прочитать в посте habrahabr.ru/blogs/gdev/121062 Единственное, что нам понадобится дополнительно — это Android-девайс с поддержкой мультитача.
2. Пишем приложение
Чтобы написать самый компактный код мы воспользуемся новой фичей — классом clPinchZoomHandler. Для самостоятельной работы с мультитачем и написания обработчиков других жестов есть класс clGestureHandler. Если же вы хотите хардкор, то можно перехватывать событие L_EVENT_MOTION, в которое будут приходть все нажатия и отпускания пальцев на экране (включая мышь на PC, чтобы было удобнее отлаживать).
Запускаем Project Wizard и выбираем:
Выкидываем из .cpp файла всё, что нагенерилось, и пишем туда следующий код:
В папку Data сохраняем файл banner.jpg. Вот такой (256x128):

Запускаем cygwin и пишем:
Получаем .apk файл для девайса.
3. Результат
Вот так это выглядит на девайсе:

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

1. Подготовка
Будем считать, что Linderdaum Engine SDK уже установлен и настроен. Про настройку SDK и то, как скомпилировать приложение, можно прочитать в посте habrahabr.ru/blogs/gdev/121062 Единственное, что нам понадобится дополнительно — это Android-девайс с поддержкой мультитача.
2. Пишем приложение
Чтобы написать самый компактный код мы воспользуемся новой фичей — классом clPinchZoomHandler. Для самостоятельной работы с мультитачем и написания обработчиков других жестов есть класс clGestureHandler. Если же вы хотите хардкор, то можно перехватывать событие L_EVENT_MOTION, в которое будут приходть все нажатия и отпускания пальцев на экране (включая мышь на PC, чтобы было удобнее отлаживать).
Запускаем Project Wizard и выбираем:
- C++ empty project;
- Задаём название проекту (без пробелов);
- Project Folder ставим в подкаталог установленного движка (иначе не будет работать Android NDK);
- нажимаем Next...;
- отмечаем «Generate Android SDK and NDK configs» и «Add events processing code: Events + Scene»;
- ставим Resolution: 800x480 (это нужно, чтобы удобно отлаживать на PC).
Выкидываем из .cpp файла всё, что нагенерилось, и пишем туда следующий код:
#include "Linderdaum.h" sEnvironment* Env = NULL; clScene* g_Scene = NULL; clPinchZoomHandler* g_PinchZoomHandler = NULL; LMatrix4 Position = LMatrix4::IdentityStatic(); LMatrix4 PositionDelta = LMatrix4::IdentityStatic(); LMatrix4 ZoomDelta = LMatrix4::IdentityStatic(); int g_PlaneID; // этот обработчик будет вызываться каждый раз, когда надо нарисовать кадр void Event_DRAW( LEvent Event, const LEventArgs& Args ) { // отрисуем сцену g_Scene->RenderForward(); // если никаких валидных жестов нет, то нам здесь делать нечего if ( !g_PinchZoomHandler->IsGestureValid() ) return; if ( g_PinchZoomHandler->IsDraggingValid() ) { // обновим параметры перемещения PositionDelta = g_PinchZoomHandler->GetTranslationMatrix(); } else { // применим текущую трансформацию и сбросим её Position = Position * PositionDelta; PositionDelta = LMatrix4::Identity(); } float ZoomFactor = 1.0f; if ( g_PinchZoomHandler->IsPinchZoomValid() ) { // обновим параметры зума ZoomFactor = g_PinchZoomHandler->GetPinchZoomFactor(); ZoomDelta = g_PinchZoomHandler->GetPinchZoomMatrix(); } else { // применим текущую трансформацию и сбросим её Position = Position * ZoomDelta; ZoomDelta = LMatrix4::Identity(); } // обновим трансформацию объекта в сцене g_Scene->SetLocalTransform( g_PlaneID, Position * PositionDelta * ZoomDelta ); // вывидем инфо про текущее количество пальцев на экране и коэффициент зума size_t NumContacts = g_PinchZoomHandler->GetMotionData()->GetNumTouchPoints(); clCanvas* C = Env->Renderer->GetCanvas(); LString Str1( "Zoom factor: " + LStr::ToStr( ZoomFactor ) ); LString Str2( "Active : " + LStr::ToStr( NumContacts ) ); C->TextStrFreeType( LRect( 0.0f, 0.0f ), Str1, 0.05f, LC_White, NULL, TextAlign_Left ); C->TextStrFreeType( LRect( 0.0f, 0.05f ), Str2, 0.05f, LC_White, NULL, TextAlign_Left ); } // инициализация APPLICATION_ENTRY_POINT { Env = new sEnvironment(); Env->DeployDefaultEnvironment( "", "../../CommonMedia" ); Env->Connect( L_EVENT_DRAWOVERLAY, Utils::Bind( &Event_DRAW ) ); // создадим объект, который мы будем двигать жестом clGeom* TestGeom1 = Env->Resources->CreatePlane( 0.1f, 0.2f, 0.9f, 0.8f, -0.1f, 10 ); // создадим и настроим сцену g_Scene = Env->Linker->Instantiate( "clScene" ); g_Scene->SetCameraTransform( LMatrix4::GetTranslateMatrix( LVector3(0.0f) ) ); g_Scene->SetCameraProjection( Env->Renderer->GetCanvas()->GetOrthoMatrices()->GetProjectionMatrix() ); g_Scene->SetUseOffscreenBuffer( false, false ); // добавим в сцену нашу плоскость g_PlaneID = g_Scene->AddGeom( TestGeom1 ); // и установим ей материал clMaterial* Mtl = Env->Resources->CreateMaterial(); Mtl->SetPropertyValue( "DiffuseMap", "banner.jpg" ); g_Scene->SetMtl( g_PlaneID, Mtl ); // создадим обработчик жестов - он сам будет перехватывать все нужные события g_PinchZoomHandler = Env->Linker->Instantiate( "clPinchZoomHandler" ); Env->RunApplication( DEFAULT_CONSOLE_AUTOEXEC ); APPLICATION_EXIT_POINT( Env ); } // деинициализация APPLICATION_SHUTDOWN { delete( g_Scene ); delete( g_PinchZoomHandler ); }
В папку Data сохраняем файл banner.jpg. Вот такой (256x128):

Запускаем cygwin и пишем:
ndk-build
ant copy-common-media debug
Получаем .apk файл для девайса.
3. Результат
Вот так это выглядит на девайсе:

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