iOS7 SKScene, как заставить спрайт отскакивать от края экрана?

Я создаю игру с шариками, прыгающими по экрану iPad. Похожа на игру в понг. Я вижу, что SKPhysicsWorld от SKScene имеет свойство гравитации, а также контролирует, как объекты сталкиваются друг с другом.

Могу ли я каким-то образом автоматически определить, столкнулся ли край спрайта с краем экрана, чтобы он мог отскочить от него? Или мне нужно написать собственный код столкновения?


person Alex Stone    schedule 09.11.2013    source источник


Ответы (4)


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

Во-первых, вам нужно будет установить физику сцены как таковую:

self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];

В файле .h вашей сцены создайте две категории битовых масок:

static const uint8_t ballCategory = 1;
static const uint8_t wallCategory = 2;

И присвойте физическому телу сцены категорию:

self.physicsBody.categoryBitMask = wallCategory;

Затем создайте свой спрайт:

SKSpriteNode *spriteNode = [SKSpriteNode spriteNodeWithImageNamed:@"ball.png"]; 

spriteNode.name = @"ball";

spriteNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:25];
spriteNode.position = CGPointMake(10.0,10.0); //or anything you want
spriteNode.physicsBody.dynamic = YES;
spriteNode.physicsBody.affectedByGravity = NO;

spriteNode.physicsBody.categoryBitMask = ballCategory;
spriteNode.physicsBody.collisionBitMask = wallCategory;

spriteNode.physicsBody.restitution = 1.0;
spriteNode.physicsBody.friction = 0.0;
spriteNode.physicsBody.linearDamping = 0.0;
spriteNode.physicsBody.angularDamping = 0.0;

[self addChild:spriteNode];

Вместо того, чтобы давать spriteNode [SKAction moveTo: duration:], примените импульс к его физическому телу.

CGVector impulse = CGVectorMake(1.0,1.0);
[spriteNode.physicsBody applyImpulse:impulse];

И вуаля! Мяч будет отскакивать от стен, и ничто его не остановит.

Вот как должен выглядеть файл .h:

#import <SpriteKit/SpriteKit.h>

static const uint8_t ballCategory = 1;
static const uint8_t wallCategory = 2;

@interface BallBounce : SKScene

@end

А вот как должен выглядеть файл .m:

#import "BallBounce.h"

@implementation BallBounce

-(instancetype)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
        self.physicsBody.categoryBitMask = wallCategory;

        SKSpriteNode *spriteNode = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(50, 50)];

        spriteNode.name = @"ball";

        spriteNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:25];
        spriteNode.position = CGPointMake(10.0,10.0); //or anything you want
        spriteNode.physicsBody.dynamic = YES;
        spriteNode.physicsBody.affectedByGravity = NO;

        spriteNode.physicsBody.categoryBitMask = ballCategory;
        spriteNode.physicsBody.collisionBitMask = wallCategory;

        spriteNode.physicsBody.restitution = 1.0;
        spriteNode.physicsBody.friction = 0.0;
        spriteNode.physicsBody.linearDamping = 0.0;
        spriteNode.physicsBody.angularDamping = 0.0;

        [self addChild:spriteNode];

        CGVector impulse = CGVectorMake(100.0,100.0);
        [spriteNode.physicsBody applyImpulse:impulse];

    }

    return self;
}

@end
person ZeMoon    schedule 05.12.2013
comment
мой мяч просто остается на месте, не двигаясь. Что-то не так? - person kevinl; 07.03.2014
comment
Да. Попробуйте увеличить значение импульса. Используйте 100 100 для начала - person ZeMoon; 07.03.2014
comment
странно я точно скопировал ваш код и выставил импульс 100100 а он все равно просто сидит на экране - person kevinl; 07.03.2014
comment
в самоинициации сразу после того, как я добавлю мяч в качестве подвида. - person kevinl; 07.03.2014
comment
Этот код отлично работает на моей стороне... Я меняю ответ, чтобы показать весь файл .h и .m. - person ZeMoon; 07.03.2014
comment
давайте продолжим это обсуждение в чате - person ZeMoon; 07.03.2014
comment
Я просто тестирую ваш код, он работает, если я уменьшаю значение импульса, квадрат не отскакивает от края. Он поднимается по краю. Есть идеи? - person bourvill; 20.11.2014
comment
Это зависит от вашей физической среды, а также от свойств physicsBodies. Возможно, потребуется отрегулировать свойства восстановления и трения. Идеальный отскок во всех направлениях достигается с помощью кругового физического тела. - person ZeMoon; 20.11.2014

Вы пытались установить физическое тело SKScene

[self setPhysicsBody:[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]];  //Physics body of Scene

Это должно держать ваш узел внутри фрейма.

W

person William George    schedule 10.11.2013

Это из http://www.raywenderlich.com/49721/how-to-create-a-breakout-game-using-spritekit

    SKPhysicsBody* borderBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
    // 2 Set physicsBody of scene to borderBody
    self.physicsBody = borderBody;
    // 3 Set the friction of that physicsBody to 0
    self.physicsBody.friction = 0.0f;

    // 1
    SKSpriteNode* ball = [SKSpriteNode spriteNodeWithImageNamed: @"Sphere.png"];
    ball.name = @"ball";
    ball.position = CGPointMake(self.frame.size.width/3, self.frame.size.height/3);
    [self addChild:ball];

    // 2
    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.frame.size.width/2];
    // 3
    ball.physicsBody.friction = 0.0f;
    // 4
    ball.physicsBody.restitution = 1.0f;
    // 5
    ball.physicsBody.linearDamping = 0.0f;
    // 6
    ball.physicsBody.allowsRotation = NO;
    ball.physicsBody.affectedByGravity = NO;

    [ball.physicsBody applyImpulse:CGVectorMake(10.0f, 10.0f)];
person kevinl    schedule 07.03.2014

Это перенесет ваш узел в кадр в Swift:

self.physicsBody = SKPhysicsBody (edgeLoopFromRect: self.frame)
person Raksha Saini    schedule 10.08.2015