Как реализовать маятниковый путь

Итак, у меня есть спрайт, и у меня есть платформа над ним. Спрайт начинается с точки (0,scene.frame.size.height/2) и платформы с (scene.frame.size.width/2,scene.frame.size.height-10). Таким образом, спрайт находится слева, а платформа находится в центре верхней части экрана.

Я собираюсь применить мощный импульс к спрайту. Вектор импульса будет иметь X, но не Y. В основном я собираюсь бросить его правильно.

Он должен пройти под платформой, и так и будет. Я хочу, чтобы он двигался по маятниковой траектории с точкой поворота в центре платформы. Более того, я хочу форсировать этот путь. Независимо от импульса объектов x, я хочу, чтобы он качался по этому пути маятника, а не просто проходил прямо под ним.

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

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

Заранее благодарим вас за всю вашу помощь.


person Ryoku    schedule 01.10.2014    source источник
comment
если вам нужно обеспечить определенное поведение, на которое вы не можете положиться, используя симуляцию физики, тем более, если тела будут сталкиваться. Просто постарайтесь заставить его работать с как можно меньшим отклонением от пути, но ожидайте неожиданного, не ожидайте, что физика никогда не сделает то, чего вы не хотите. Это не будет.   -  person LearnCocos2D    schedule 01.10.2014
comment
Из документации Apple объект SKPhysicsJointPin позволяет двум физическим телам независимо вращаться вокруг точки привязки, как если бы они были соединены вместе.   -  person 0x141E    schedule 01.10.2014


Ответы (1)


Вот пример реализации SKPhysicsJointPin:

-(id)initWithSize:(CGSize)size {

    if (self = [super initWithSize:size]) {

        CGPoint location = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);

        // Create the pendulum's pivot
        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:size];
        sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];
        sprite.physicsBody.dynamic = NO;

        sprite.position = location;
        sprite.size = CGSizeMake(8, 8);

        [self addChild:sprite];

        location = CGPointMake(self.frame.size.width/2-100, self.frame.size.height/2);
        size = CGSizeMake(50, 200);

        // Create the pendulum's bob
        SKSpriteNode *sprite2 = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:size];
        sprite2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];
        sprite2.physicsBody.dynamic = YES;
        sprite2.physicsBody.affectedByGravity = YES;
        sprite2.physicsBody.linearDamping = 0;

        sprite2.physicsBody.mass = 0.1;

        sprite2.size = CGSizeMake(32, 32);
        sprite2.position = location;
        [self addChild:sprite2];

        CGPoint point = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);

        // Create a joint that connects the pivot and the bob
        SKPhysicsJointPin *pinJoint = [SKPhysicsJointPin jointWithBodyA:sprite.physicsBody
                                                                  bodyB:sprite2.physicsBody anchor:point];

        // Add the joint to the world
        [self.physicsWorld addJoint:pinJoint];
    }
    return self;
}
person 0x141E    schedule 03.10.2014
comment
Это идеально большое спасибо. Есть только одна вещь, которой, кажется, не хватает. Для этого теста я установил для свойства effectByGravity спрайта 2 значение NO. Я запустил действие, чтобы дать sprite2 импульс с векторами (10,0). В результате спрайты вообще не двигались. Когда я приложил ту же силу вниз, все сработало почти идеально. Затем я переместил спрайт 2 вниз на 20, а затем попробовал. Это сработало, но конверсия была очень низкой. Кажется, что он преобразует только часть импульса в зависимости от угла. Как я могу обеспечить преобразование всего импульса в импульс маятника? - person Ryoku; 03.10.2014
comment
Как вы думаете, могло бы сработать, если бы я удостоверился, что применяемый импульс был под углом 90 градусов (0,5 радиана) от спрайта 1 и спрайта 2? Если да, то как мне пересчитать импульс, чтобы он соответствовал заданному углу (в основном, как мне преобразовать импульс из 10,0 во все, что ему нужно, чтобы соответствовать необходимому углу)? - person Ryoku; 03.10.2014
comment
Да, вам нужно будет применить импульс, перпендикулярный углу от спрайта и спрайта2. Я обновлю свой ответ, когда у меня будет шанс. - person 0x141E; 04.10.2014
comment
Думаю, я понял. Я знаю, что это потребует нормализации расстояния от спрайта1 до спрайта2. Собрав нормализацию, я просто взял результат, назовем его нормой. И сделал что-то вроде этого: norm = CGPointMake(norm.y, norm.x) (поменяв местами значение x на значение y и наоборот). Получив норму, я просто умножаю норму на скаляр, представляющий импульс, который я хочу передать. Это в бейсбольном парке? Кажется, это работает, но я еще не проверял его во всех ситуациях. - person Ryoku; 04.10.2014
comment
Я смотрел на это прошлой ночью. Вам нужно будет обработать случаи, когда груз маятника находится в разных квадрантах. - person 0x141E; 04.10.2014
comment
Зачем мне разделять квадранты? Если бы я просто поменял местами x и y нормализованной длины между двумя спрайтами, разве этого не было бы достаточно? Если нет, то как мне обрабатывать разные квадранты? Спасибо, кстати, за помощь, я знаю, что я немного нуждаюсь прямо сейчас. - person Ryoku; 04.10.2014
comment
Без проблем. Если вы подаете импульс в квадранте 1 (Q1), импульс должен быть +dx и -dy (фактически -dy для всех случаев). Если в Q2, это должно быть -dx и Q3: +dx и Q4: -dx. - person 0x141E; 04.10.2014
comment
Я не мог понять, как это сделать без нескольких операторов if. - person 0x141E; 04.10.2014
comment
хм. Я вижу, это довольно затруднительное положение. Давайте посмотрим. Если я возьму разницу между двумя, например: CGPoint difference = CGPointMake(sprite1.position.x - sprite2.position.x, sprite1.position.y - sprite2.position.y), а затем найду длину этой разницы, например: float length = sqrtf(difference.x*difference.x + difference.y*difference.y), то нормализую длину следующим образом: CGPoint norm = CGPointMake(difference.x/length, difference.y/length. Затем поменял местами x и y, чтобы сделать их перпендикулярными, вот так: norm = CGPointMake(norm.y, norm.x). Я думаю, это должно дать -x в Q2 и Q3? - person Ryoku; 04.10.2014
comment
Возможно, вам следует взять абсолютное значение для x и y, установить y = -|y| и установить x = -|x| если в Q3 или Q4. - person 0x141E; 05.10.2014
comment
Звучит неплохо, попробую. Эй, если вы не возражаете, так как вы так здорово ответили на этот вопрос, у меня есть еще один, опубликованный здесь, в stackoverflow, о расширяемых цепочках, вот ссылка: Как сделать удлиняющую цепочку еще раз большое спасибо, вы действительно были прекрасны. - person Ryoku; 05.10.2014