Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как двигать и вращать UIImage одновременно, двигать и вращать UIImage одновременно 
:(
    Опции темы
SlavaMinsk
  Дата 2.4.2014, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Помогите разобраться.


Есть персонаж. После нажатия на StartGame координатам объекта присваиваются начальные значения (X = Object.center.x;  Y = Object.center.y) и запускается таймер, который каждые 0.05 сек. выполняет метод Object.Moving. 

В нём вычисляются координаты объекта X и Y;

И таким образом задаётся движение персонажа:   Object.center = CGPointMake ((int)X , (int)Y);

Потом обращение к методу [self Object.Rotate];


В Object.Rotate:

Object.center = CGPointMake (Object.center.x, Object.center.y);

Object.transform = CGAffineTransformMakeRotation(angle);        // угол снимается со слайдера на экране


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

Как сделать чтобы вращение происходило относительно текущего центра объекта (UIImage)?


Заранее спасибо, жду ваших ответов.






Это сообщение отредактировал(а) SlavaMinsk - 2.4.2014, 17:16
PM MAIL   Вверх
Bitter
Дата 2.4.2014, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 10
Всего: 27



Object.center = CGPointMake (Object.center.x, Object.center.y);
это вообще гениально )

Это сообщение отредактировал(а) Bitter - 2.4.2014, 13:57
PM MAIL ICQ Skype   Вверх
SlavaMinsk
  Дата 2.4.2014, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Цитата(Bitter @ 2.4.2014,  13:57)
Object.center = CGPointMake (Object.center.x, Object.center.y);
это вообще гениально )

Спасибо, я знаю)

Так подсказать можете как это сделать?
PM MAIL   Вверх
Bitter
Дата 2.4.2014, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 10
Всего: 27



Если б мог, подсказал бы, а так кто его знает, что у вас там написано...
Ну попробуйте поменять местами вызовы Moving и Rotate
PM MAIL ICQ Skype   Вверх
SlavaMinsk
  Дата 2.4.2014, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Вот код для наглядности, подскажите где я ошибся.

.h

@interface Game : UIViewController{
    
    IBOutlet UIImageView *Tank;
    IBOutlet UIButton *StartGame;
    IBOutlet UISlider *Rotation;
    IBOutlet UIButton *Accelerate;
    
    NSTimer *TankMovement;
    
    
}

-(IBAction)StartGame:(id)sender;
-(IBAction)Accelerate:(id)sender;
-(IBAction)OffAccelerate:(id)sender;
-(void)TankMoving;
-(void)TankRotate;


.m

@implementation Game

-(IBAction)StartGame:(id)sender{
    
    StartGame.hidden = YES;
    AccPressed = FALSE;
    dTime = 0.5;
    X = Tank.center.x;
    Y = Tank.center.y;
    SpeedX = 0;
    SpeedY = 0;
    HorsePower = 3;
    
    TankMovement = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(TankRotate) userInfo:nil repeats:YES];
    
}

-(IBAction)Accelerate:(id)sender{
    
    AccPressed = TRUE;
  
}

-(IBAction)OffAccelerate:(id)sender{
    
    AccPressed = FALSE;

}

-(void)TankRotate{
    
    Tank.transform = CGAffineTransformMakeRotation(angle);
    
    [self TankMoving];

}

-(void)TankMoving{

    SpeedY = SpeedY + dTime;
    
    angle = Rotation.value*0.03925;
    
    if (AccPressed){
        
        // Код расчета скорости при нажатой кнопке газа
        
    }
    
        X = X + dTime * SpeedX;
        Y = Y + dTime * SpeedY;
    
    Tank.center = CGPointMake((int)X, (int)Y);
    
}

Проблема: при нажатии на слайдер объект исчезает, появляется в начальной точке и вращается. Когда слайдер отпускаю - он (повернутый как надо) появляется там, куда до этого приехал.

То есть при нажатии на слайдер координаты центра UIImage скидываются на изначальные. Почему?


Это сообщение отредактировал(а) SlavaMinsk - 2.4.2014, 22:38
PM MAIL   Вверх
likalilika
Дата 2.4.2014, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 1.4.2014
Где: Кавказ

Репутация: 1
Всего: 1



В сценах крутить текстурой большого ума не нужно:) Чет не поняла для чего так много лишнего написано?
PM MAIL WWW ICQ Skype   Вверх
SlavaMinsk
Дата 2.4.2014, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Цитата(likalilika @ 2.4.2014,  21:33)
В сценах крутить текстурой большого ума не нужно:) Чет не поняла для чего так много лишнего написано?

Информативнее пожалуйста. Что лишнее. Как вращать и двигать UIImage одновременно? Напишите как надо если знаете.

PM MAIL   Вверх
Bitter
Дата 2.4.2014, 23:05 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 10
Всего: 27



На самом деле вопрос не такой уж и простой, вы пытаетесь работать с аффинными преобразованиями, которые во-первых требуют понимания принципов этих преобразований, а во-вторых они довольно капризны. Аффинные преобразования оперируют матрицами. То есть для описания объекта в пространстве используется матрица, в которую заносятся данные о повороте по осям, масштабе и перемещении. Перемножая матрицы друг на друга, получаете комбинации преобразований поворот-перенос-масштаб.
В вашем случае свойство transform и есть та матрица. Комбинируйте матрицы поворота и переноса, чтобы добиться того чего хотите. Как их комбинировать легко найдете в инете.

Вот кстати тут похожая тема и ответ помечен решенным, так что может вам поможет
http://stackoverflow.com/questions/1983751...iimage-and-move

Это сообщение отредактировал(а) Bitter - 2.4.2014, 23:17
PM MAIL ICQ Skype   Вверх
SlavaMinsk
Дата 3.4.2014, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Цитата(Bitter @ 2.4.2014,  23:05)
В вашем случае свойство transform и есть та матрица. Комбинируйте матрицы поворота и переноса, чтобы добиться того чего хотите. Как их комбинировать легко найдете в инете.

Спасибо за подсказку - очень помогла. Проблема решилась именно так:

Tank.transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle),
                                                               CGAffineTransformMakeTranslation(X,Y));

Но появился новый косяк - картинка вращается не относительно центра - при повороте против часовой (слайдер влево) - относительно левого края, по часовой - относительно правого. C чем это может быть связано?

Это сообщение отредактировал(а) SlavaMinsk - 3.4.2014, 10:57
PM MAIL   Вверх
Shklyar
Дата 3.4.2014, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: нет
Всего: 3



Посмотрите не Tank.transform = CGAffineTransformMakeRotation(angle). Так тоже вращение относительно края?

Цитата(SlavaMinsk @  3.4.2014,  00:19 Найти цитируемый пост)
C чем это может быть связано?


Цитата(SlavaMinsk @  3.4.2014,  00:19 Найти цитируемый пост)
CGAffineTransformConcat(CGAffineTransformMakeRotation(angle),
                                                               CGAffineTransformMakeTranslation(X,Y));

Вот блин, вы то зачем делаете CGAffineTransformMakeTranslation(X,Y)?

Это сообщение отредактировал(а) Shklyar - 3.4.2014, 16:51
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
SlavaMinsk
Дата 3.4.2014, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Цитата(Shklyar @ 3.4.2014,  16:48)
Посмотрите не Tank.transform = CGAffineTransformMakeRotation(angle). Так тоже вращение относительно края?

Цитата(SlavaMinsk @  3.4.2014,  00:19 Найти цитируемый пост)
CGAffineTransformConcat(CGAffineTransformMakeRotation(angle),                        CGAffineTransformMakeTranslation(X,Y));


Вот блин, вы то зачем делаете CGAffineTransformMakeTranslation(X,Y)?

CGAffineTransformMakeRotation(angle) я и так использую,

CGAffineTransformMakeTranslation(X,Y) - чтобы обрабатывать перемещение объекта,

CGAffineTransformConcat - чтобы объединить вращение и перемещение (по сути перемножение матриц вращения и перемещения как я понял).

CGAffineTransform может применять к объекту только одну матрицу - поэтому чтобы применить их надо перемнодить и получить одну с помощью CGAffineTransformConcat.


Остаётся вопрос - почему он вращает объект не относительно его центра, а относительно краёв, да ещё разных.



Это сообщение отредактировал(а) SlavaMinsk - 3.4.2014, 17:53
PM MAIL   Вверх
Bitter
Дата 3.4.2014, 18:53 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 10
Всего: 27



Если я правильно понимаю, поворот в данном случае происходит не относительно какой-то точки. Вьюха поворачивается, и как бы прилипает к верхнему краю, либо углом либо ребром (попробуйте проверить это поворачивая квадрат).

Добавлено через 4 минуты и 14 секунд
Если быть точнее, то она выравнивается по левому верхнему углу после поворота
PM MAIL ICQ Skype   Вверх
SlavaMinsk
Дата 3.4.2014, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Цитата(Bitter @ 3.4.2014,  18:53)
Если я правильно понимаю, поворот в данном случае происходит не относительно какой-то точки. Вьюха поворачивается, и как бы прилипает к верхнему краю, либо углом либо ребром (попробуйте проверить это поворачивая квадрат).

Добавлено @ 18:57
Если быть точнее, то она выравнивается по левому верхнему углу после поворота

Да, именно так. Вы знаете как это исправить?
PM MAIL   Вверх
Bitter
Дата 4.4.2014, 00:04 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 10
Всего: 27



нет, не знаю. Если бы знал, то уже написал бы.
Могу только предположить, что при вращении нужно отнимать от Х и Y какое-то значение, на которое смещается центр картинки относительно верхнего левого угла.
Если это квадрат, то возможно что эта величина может быть рассчитана как-то через синус, то есть delta = sin(angle) * radius. где радиус это половина ширины квадрата. Кроме того надо отбрасывать отрицательные величины, то есть delta = ABS(sin(angle) * radius). ну и напоследок угол для синуса скорее всего тоже надо увеличивать быстрее чем для поворота, например в два раза.
То есть финальная дельта delta = ABS(sin(angle * 2) * radius)

В итоге вы должны писать 
Код

double delta = ABS(sin(angle * 2) * radius);
CGAffineTransformMakeTranslation(X - delta, Y - delta);


Но это только теория, возможно что к практике оно не имеет никакого отношения

Это сообщение отредактировал(а) Bitter - 4.4.2014, 00:11
PM MAIL ICQ Skype   Вверх
SlavaMinsk
Дата 4.4.2014, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 29.3.2014

Репутация: нет
Всего: нет



Спасибо, я примерно так и сделал. Правда всё равно получилось не идеально.  При сдвиге слайдера влево и вправо (положительный и отрицательный угол) вращение происходит относительно разных точек.

Но это уже не так принципиально.

Появился ещё один серьезный вопрос: как получить событие столкновения. Если бы вьюшка не подвергалась трансформациям - всё было бы просто:


if (CGRectIntersectRect(Tank.frame, Wall.frame))

                 [self bounce];

Но после трансформаций свойство frame использовать не получится:

http://www.iphones.ru/forum/index.php?showtopic=37301


Здесь предлагается использовать  "bounds" - границы. Кто-нибудь знает как их использовать чтобы получить событие столкновения?

Это сообщение отредактировал(а) SlavaMinsk - 4.4.2014, 13:16
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | iOS | Следующая тема »


 




[ Время генерации скрипта: 0.0895 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.