Список действий динамической длины во время выполнения для последовательности
-
06-07-2019 - |
Вопрос
Cocos2D определяет статический метод 'actions' для класса Sequence следующим образом:
+(id) actions: (FiniteTimeAction *) action1, ... { /* omitted */ }
Как я могу составить список действий, которые нужно выполнить во время выполнения, возможно, прочитать из файла на диске или что-то подобное?
Я прочитал, что список аргументов переменной длины можно преобразовать в (char *) и передать таким образом ...
NSMutableArray *actions = [[NSMutableArray alloc] init];
[actions addObject: [DelayTime actionWithDuration:1]];
[actions addObject: [ScaleBy actionWithDuration:2 scale:4];
char *argList = (char *)malloc(sizeof(FiniteTimeAction *) * [actions count]);
[actions getObjects:(id *)argList];
[self runActions: actions];
Это «лучший» или «правильный» способ сделать это? Их лучшие альтернативы, более быстрые альтернативы?
Решение
vaargs - это просто помощник для создания вложенных объектов Sequence
. Он возвращает FiniteTimeAction *
, который создается последовательными вызовами [Sequence actionOne: one_ two: two _]
. Вы можете сделать это самостоятельно в своем коде, просматривая ваш набор или массив. Это должно идти примерно так:
FiniteTimeAction *seq = nil;
for (FiniteTimeAction *action in actions) {
if (!seq) {
seq = action;
} else {
seq = [Sequence actionOne:seq two:action];
}
}
[self runActions:seq];
Другие советы
Я бы посмотрел на использование NSInvocation - вы можете создать его, используя сигнатуру метода, на которую вы нацеливаетесь, а затем использовать установщики для каждого объекта следующим образом:
NSInvocation *invoker = setup invoker here...
for ( int i = 0; i < actions.count; i++ )
{
NSObject *arg = [actions objectatIndex:i];
[invoker setArgument:&arg atIndex:i+2];
}
[invoker setArgument:nil atIndex:i+2];
Бит i + 2 объясняется тем, что первые два аргумента действительно являются собственными и _cmd, поэтому вы устанавливаете все, начиная с индекса 2 и далее ... читайте документы по setArgument: atIndex: in NSInvocation для получения более подробной информации.
Если у вас есть это, вы можете вызвать операцию с целью. Я никогда не использовал это с переменными методами аргументов, поэтому я не уверен, насколько хорошо он там работает, но это единственный известный мне способ динамического создания вызова во время выполнения.
Учитывая предоставленные опции, кажется, что единственный реальный способ выполнить то, что я преследовал, это использовать подход, который я упомянул в вопросе, а именно:
NSMutableArray *actions = [[NSMutableArray alloc] init];
[actions addObject: [DelayTime actionWithDuration:1]];
[actions addObject: [ScaleBy actionWithDuration:2 scale:4];
char *argList = (char *)malloc(sizeof(FiniteTimeAction *) * [actions count]);
[actions getObjects:(id *)argList];
[self runActions: actions];
Возможно, набор заранее созданных последовательностей?
id move = [MoveBy actionWithDuration:3 position:ccp(350,0)];
id move_back = [move reverse];
id move_ease_in = [EaseIn actionWithAction:[[move copy] autorelease] rate:3.0f];
id move_ease_in_back = [move_ease_in reverse];
id move_ease_out = [EaseOut actionWithAction:[[move copy] autorelease] rate:3.0f];
id move_ease_out_back = [move_ease_out reverse];
id seq1 = [Sequence actions: move, move_back, nil];
id seq2 = [Sequence actions: move_ease_in, move_ease_in_back, nil];
id seq3 = [Sequence actions: move_ease_out, move_ease_out_back, nil];
[grossini runAction: [RepeatForever actionWithAction:seq1]];
[tamara runAction: [RepeatForever actionWithAction:seq2]];
[kathia runAction: [RepeatForever actionWithAction:seq3]];