2015-08-12 2 views
0

Я пытаюсь сделать транспортное средство (в данном случае поездом) перемещаться на основе ввода проигрывателя. Если я двигаю поезд через SKAction, колеса не вращаются. Я мог бы использовать метод applyForce на физическом теле, но мне нужно больше контроля. Мне нужно сделать это на определенное расстояние за определенное время. Как это можно сделать?Использование SKPhysicsBody для создания автомобиля

-(void)didMoveToView:(SKView *)view { 
    SKTexture *trainBodyTexture = [SKTexture textureWithImageNamed:@"levelselect_trainbody"]; 
    SKSpriteNode *trainBody = [[SKSpriteNode alloc] initWithTexture:trainBodyTexture]; 
    trainBody.zPosition = 0; 
    trainBody.position = CGPointMake(300, 500); 
    trainBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:trainBody.size]; 
    [self addChild:trainBody]; 

    SKTexture *trainWheelTexture = [SKTexture textureWithImageNamed:@"levelselect_trainwheel"]; 
    SKSpriteNode *trainWheel1 = [[SKSpriteNode alloc] initWithTexture:trainWheelTexture]; 
    trainWheel1.zPosition = 1; 
    trainWheel1.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:trainWheel1.size.width/2]; 
    trainWheel1.physicsBody.allowsRotation = YES; 
    trainWheel1.position = CGPointMake(220, 400); 
    [self addChild:trainWheel1]; 

    SKSpriteNode *trainWheel2 = [[SKSpriteNode alloc] initWithTexture:trainWheelTexture]; 
    trainWheel2.zPosition = 1; 
    trainWheel2.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:trainWheel2.size.width/2]; 
    trainWheel2.physicsBody.allowsRotation = YES; 
    trainWheel2.position = CGPointMake(380, 400); 
    [self addChild:trainWheel2]; 

    SKShapeNode *dot = [SKShapeNode shapeNodeWithCircleOfRadius:10]; 
    dot.zPosition = 2; 
    dot.fillColor = [NSColor redColor]; 
    dot.position = CGPointMake(0, -20); 
    [trainWheel1 addChild:dot]; 

    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:trainBody.physicsBody bodyB:trainWheel1.physicsBody anchor:trainWheel1.position]; 
    SKPhysicsJointPin *pin2 = [SKPhysicsJointPin jointWithBodyA:trainBody.physicsBody bodyB:trainWheel2.physicsBody anchor:trainWheel2.position]; 

    [self.scene.physicsWorld addJoint:pin]; 
    [self.scene.physicsWorld addJoint:pin2]; 

    //[trainWheel1 runAction:[SKAction moveByX:300 y:0 duration:3]]; 
    [trainBody.physicsBody applyForce:CGVectorMake(3000, 0)]; 

} 



UPDATE: Реализован с поездом класса (предложенный Джафар Sheriff)

Train.h

#import <SpriteKit/SpriteKit.h> 

@interface Train : SKSpriteNode 

-(void) createPhysics; 
-(void) moveLeft; 
-(void) moveRight; 

@end 

Train.m

#import "Train.h" 

@interface Train() 

@property SKSpriteNode *trainBody, *trainWheelFront, *trainWheelRear; 
@property SKPhysicsWorld *physicsWorld; 

@end 

@implementation Train 

-(instancetype) init { 
    if (self = [super init]) { 
     [self initTrainBody]; 
     [self initWheels]; 
    } 
    return self; 
} 

-(void) initTrainBody { 
    SKTexture *trainBodyTexture = [SKTexture textureWithImageNamed:@"levelselect_trainbody"]; 
    _trainBody = [[SKSpriteNode alloc] initWithTexture:trainBodyTexture]; 
    _trainBody.zPosition = 0; 
    _trainBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_trainBody.size]; 
    [self addChild:_trainBody]; 
} 

-(void) initWheels { 
    SKTexture *_trainWheelTexture = [SKTexture textureWithImageNamed:@"levelselect_trainwheel"]; 
    _trainWheelFront = [[SKSpriteNode alloc] initWithTexture:_trainWheelTexture]; 
    _trainWheelFront.zPosition = 1; 
    _trainWheelFront.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_trainWheelFront.size.width/2]; 
    _trainWheelFront.physicsBody.allowsRotation = YES; 
    _trainWheelFront.position = CGPointMake(-80, -82); 
    [self addChild:_trainWheelFront]; 

    _trainWheelRear = [[SKSpriteNode alloc] initWithTexture:_trainWheelTexture]; 
    _trainWheelRear.zPosition = 1; 
    _trainWheelRear.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_trainWheelRear.size.width/2]; 
    _trainWheelRear.physicsBody.allowsRotation = YES; 
    _trainWheelRear.position = CGPointMake(80, -82); 
    [self addChild:_trainWheelRear]; 

    //dot used to see if wheels are rotating, no other point 
    SKShapeNode *dot = [SKShapeNode shapeNodeWithCircleOfRadius:10]; 
    dot.zPosition = 2; 
    dot.fillColor = [NSColor redColor]; 
    dot.position = CGPointMake(0, -20); 
    [_trainWheelFront addChild:dot]; 
} 

//this method is called after the train node is added to the scene in GameScene otherwise will get error adding joints before node is in scene 
-(void) createPhysics { 
    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:_trainBody.physicsBody bodyB:_trainWheelFront.physicsBody anchor:_trainWheelFront.position]; 
    SKPhysicsJointPin *pin2 = [SKPhysicsJointPin jointWithBodyA:_trainBody.physicsBody bodyB:_trainWheelRear.physicsBody anchor:_trainWheelRear.position]; 

    [self.scene.physicsWorld addJoint:pin]; 
    [self.scene.physicsWorld addJoint:pin2]; 
} 

-(void) moveLeft { 
    SKAction *rotateLeft = [SKAction rotateByAngle:6*M_PI duration:0.2]; 
    [_trainWheelFront runAction:rotateLeft]; 
    [_trainWheelRear runAction:rotateLeft]; 
} 

-(void) moveRight { 
    SKAction *rotateRight = [SKAction rotateByAngle:-6*M_PI duration:0.2]; 
    [_trainWheelFront runAction:rotateRight]; 
    [_trainWheelRear runAction:rotateRight]; 
} 


@end 

GameScene.m

#import "GameScene.h" 
#import "Train.h" 

@interface GameScene() 

@property Train *train; 

@end 

@implementation GameScene 

-(void)didMoveToView:(SKView *)view { 
    [self initTrain]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyPressed:) name:@"KeyPressedNotificationKey" object:nil]; //using notifications and custom view class to handle key presses 

} 

-(void) initTrain { 
    _train = [[Train alloc] init]; 
    _train.position = CGPointMake(500, 300); 
    [self addChild:_train]; 
    [_train createPhysics]; 
} 

-(void)update:(CFTimeInterval)currentTime { 
    /* Called before each frame is rendered */ 
} 

-(void) keyPressed:(NSNotification*)notification { 
    NSNumber *keyCodeObject = notification.userInfo[@"keyCode"]; 
    NSInteger keyCode = keyCodeObject.integerValue; 
    NSLog(@"keycode = %lu", keyCode); 
    switch (keyCode) { 
     case 123: 
      [self leftArrowPressed]; 
      break; 
     case 124: 
      [self rightArrowPressed]; 
      break; 
    } 
} 

-(void) leftArrowPressed { 
    SKAction *moveLeft = [SKAction moveByX:-200 y:0 duration:0.2]; 
    [_train runAction:moveLeft]; 
    [_train moveLeft]; 
} 

-(void) rightArrowPressed { 
    SKAction *moveRight = [SKAction moveByX:200 y:0 duration:0.2]; 
    [_train runAction:moveRight]; 
    [_train moveRight]; 
} 

@end 

Примечание: Это решение приводит к тому, весь поезд, чтобы перевернуть и урод, когда левая/правая клавиши нажаты. Похоже, что мои контактные штыри неправильны, но они кажутся мне верными:/

+0

Попробуйте группировать движение анимации колес вместе с движением вперед поезда. Что-то вроде этого, 'SKAction * trainMovent = [Группа SKAction: @ [колесоAnimatingAction, trainForwardMovementAction]]; [self runAction: trainMovent]; ' –

+0

Да, я подумал об этом, но разве не должно быть какой-то пользы от наличия узлов в качестве детей? Я имею в виду, в этом случае, конечно, это всего лишь пара узлов, которые мне придется группировать, но когда у меня больше машин в поезде, это становится неприятностью. Как указано в вопросе, я ищу метод, который, по возможности, больше полагается на физическое взаимодействие. – 02fentym

+0

Попробуйте реализовать класс Train с колесами в качестве своего ребенка, а также содержит массив всех его колес. Когда вы выполняете движение вперед на поезде, все колеса будут двигаться вперед, поскольку они являются детьми класса Train. Также применяйте вращающуюся анимацию колеса массив колес, который у вас есть, двигая поезд вперед. –

ответ

0

По умолчанию Initializer of SkSpriteNode - - (instancetype)initWithTexture:(SKTexture *)texture color:(SKColor *)color size:(CGSize)size; Попробуйте это,

@interface Train : SKSpriteNode 
- (instancetype)initTrainWithColor:(UIColor *) color andSize:(CGSize) size; 
-(void) animateWheelsWithTime:(float) time; 
@end 


@interface Train() 
{ 
    SKSpriteNode *wheel1; 
    SKSpriteNode *wheel2; 
    NSMutableArray *wheelsArray; 
} 
@end 

@implementation Train 
- (instancetype)initTrainWithColor:(UIColor *) color andSize:(CGSize) size 
{ 
self = [super initWithTexture:nil color:color size:size]; 
if (self) 
{ 
    [self addWheels]; 
} 
return self; 
} 
    -(void)addWheels 
    { 
    wheelsArray = [[NSMutableArray alloc]init]; 
    wheel1 = [SKSpriteNode spriteNodeWithImageNamed:@"wheel"]; 
    [wheel1 setPosition:CGPointMake(-(self.frame.size.width/2.0f-wheel1.frame.size.width/2.0f), - (self.frame.size.height/2.0f - wheel1.frame.size.height/2.0f))]; 
[self addChild:wheel1]; 

wheel2 = [SKSpriteNode spriteNodeWithImageNamed:@"wheel"]; 
[wheel2 setPosition:CGPointMake((self.frame.size.width/2.0f-wheel2.frame.size.width/2.0f), - (self.frame.size.height/2.0f - wheel2.frame.size.height/2.0f))]; 
[self addChild:wheel2]; 

[wheelsArray addObject:wheel1]; 
[wheelsArray addObject:wheel2]; 
} 

-(void) animateWheelsWithTime:(float) time 
{ 
    for (SKSpriteNode *wheel in wheelsArray) 
     { 
     SKAction *act = [SKAction rotateByAngle:3*M_PI duration:time]; 
     [wheel runAction:act]; 
    } 
} 
@end 

В GameScene.m добавить поезд, как это,

-(void) addTrain 
    { 
     Train *train1 = [[Train alloc]initTrainWithColor:[UIColor yellowColor] andSize:CGSizeMake(150, 100)]; 
     [train1 setPosition:CGPointMake(self.size.width/2.0f, self.size.height/2.0f)]; 
    [self addChild:train1]; 

    SKAction *act = [SKAction moveTo:CGPointMake(self.size.width/2.0f, self.size.height - 50) duration:2]; 
    [train1 runAction:act]; 
    [train1 animateWheelsWithTime:2]; 
} 

Я попробовал, и это работает.

+0

Я знаю, как это сделать. Взгляните на заголовок вопроса, я ищу решение, которое предполагает использование физических тел для более реалистичного взгляда. Я знаю, что это возможно, я просто не знаю, как решить проблему, которая у меня есть. Ваше решение вообще не учитывает физику. Например: [spritekit car] (http: // youtu.быть/-PtMlelU90w) – 02fentym

Смежные вопросы