Переменные не обновляются при использовании CADisplayLink

Я не могу изменить переменные при их обновлении. Метод «reCenterYaw» срабатывает, когда я касаюсь кнопки, и переменная «self.hasYawCenterPointBeenSet» обновляется внутри метода, но когда метод «updateCycle» возвращается, переменная не показывает, что она была обновлена. updateCycle — это мой метод, управляемый CADisplaylink. Я попытался обновить переменные до атомарных, ссылаясь на них как на свои переменные экземпляра с помощью «_» и «я». Не уверен что происходит.

#import "GameViewController.h"
#import <CoreMotion/CoreMotion.h>
#import <SpriteKit/SpriteKit.h>
#import "HUDOverlay.h"

@interface GameViewController ()
@property (strong, nonatomic) CMMotionManager *motionManager;
@property (strong, nonatomic) CMAttitude *currentAttitude;
@property (strong, nonatomic) SCNNode *cameraNode;
@property (strong, nonatomic) SCNScene *scene;
@property (nonatomic) float roll;
@property (nonatomic) float yaw;
@property (nonatomic) float pitch;

@property (atomic) float yawCenterPoint;
@property (atomic) BOOL hasYawCenterPointBeenSet;

@end

GameViewController* sharedGameViewController = nil;


@implementation GameViewController

+(GameViewController*)sharedController{
    if (sharedGameViewController == nil) {
        sharedGameViewController = [[GameViewController alloc] init];
    }
    return sharedGameViewController;
}


- (void)viewDidLoad
{
    [super viewDidLoad];

    // create a new scene
    //SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.dae"];
    _scene = [SCNScene new];
    self.hasYawCenterPointBeenSet = NO;

    // create and add a camera to the scene
    _cameraNode = [SCNNode node];
    _cameraNode.camera = [SCNCamera camera];
    [_scene.rootNode addChildNode:_cameraNode];

    // place the camera
    _cameraNode.position = SCNVector3Make(0, 0, 0);

    // create and add a light to the scene
    SCNNode *lightNode = [SCNNode node];
    lightNode.light = [SCNLight light];
    lightNode.light.type = SCNLightTypeOmni;
    lightNode.position = SCNVector3Make(0, 10, 10);
    [_scene.rootNode addChildNode:lightNode];

    // create and add an ambient light to the scene
    SCNNode *ambientLightNode = [SCNNode node];
    ambientLightNode.light = [SCNLight light];
    ambientLightNode.light.type = SCNLightTypeAmbient;
    ambientLightNode.light.color = [UIColor whiteColor];
    [_scene.rootNode addChildNode:ambientLightNode];


    // retrieve the SCNView
    SCNView *scnView = (SCNView *)self.view;
    scnView.delegate = self;
    scnView.playing = YES;


    // set the scene to the view
    scnView.scene = _scene;

    scnView.overlaySKScene = [HUDOverlay sceneWithSize:scnView.frame.size];
    // allows the user to manipulate the camera
    scnView.allowsCameraControl = NO;

    // show statistics such as fps and timing information
    scnView.showsStatistics = YES;

    // configure the view
    scnView.backgroundColor = [UIColor blueColor];

//    // add a tap gesture recognizer
//    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
//    NSMutableArray *gestureRecognizers = [NSMutableArray array];
//    [gestureRecognizers addObject:tapGesture];
//    [gestureRecognizers addObjectsFromArray:scnView.gestureRecognizers];
//    scnView.gestureRecognizers = gestureRecognizers;

    SCNNode *sampleNode = [SCNNode new];
    SCNPlane *samplePlane = [SCNPlane planeWithWidth:3 height:5];
    SCNMaterial *angryFrontMaterial = [SCNMaterial material];
    angryFrontMaterial.diffuse.contents = [UIImage imageNamed:@"angryfront110.png"];

    sampleNode.geometry = samplePlane;
    sampleNode.geometry.firstMaterial = angryFrontMaterial;
    sampleNode.position = SCNVector3Make(0, 0, -10);

    [_scene.rootNode addChildNode:sampleNode];
//  SCNAction *moveToCamera = [SCNAction moveTo:SCNVector3Make(0, 0, -10) duration:10];
//  [sampleNode runAction:moveToCamera];


    [self setupRotationGrid];
    [self setupMotionCapture];

    displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateCycle)];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

//This is the update loop for the sceneView.  When the view updates per frame this is where the logic goes
-(void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time{

}

-(void)updateCycle{

    _currentAttitude = _motionManager.deviceMotion.attitude;
    _roll = _currentAttitude.roll + (.5 * M_PI);
    _yaw = _currentAttitude.yaw;
    _pitch = _currentAttitude.pitch;

    _cameraNode.eulerAngles = SCNVector3Make(-_roll, _yaw, _pitch);
    //NSLog(@"yawCenterPoint = %d", _hasYawCenterPointBeenSet);

    if (self.hasYawCenterPointBeenSet == NO) {
        _yawCenterPoint = _yaw;
        self.hasYawCenterPointBeenSet = YES;
        NSLog(@"Yawcenter point set to %f", _yawCenterPoint);
    }
    //NSLog(@"Roll: %f  Yaw: %f  Pitch: %f", _roll, _yaw, _pitch);

}

-(void)setupRotationGrid {
    double radius = 30;
    double numberOfItems = 8;
    SCNGeometry *geometry = [SCNBox boxWithWidth:4.5 height:8 length:3.25 chamferRadius:0.5];

    double x = 0.0;
    double z = radius;
    double theta = (M_PI)/(numberOfItems/2);
    double incrementalY = (M_PI)/(numberOfItems*2);

    SCNNode *nodeCollection = [SCNNode node];
    nodeCollection.position = SCNVector3Make(0, 4, 0);

    for (int index = 1; index <= numberOfItems; index++) {
        x = radius * sin(index*theta);
        z = radius * cos(index*theta);
        SCNNode *node = [SCNNode node];
        node.geometry = geometry;
        node.position = SCNVector3Make(x, 0, z);
        float rotation = incrementalY * index;
        node.rotation = SCNVector4Make(0, 1, 0, rotation);
        [nodeCollection addChildNode:node];
    }

    [_scene.rootNode addChildNode:nodeCollection];
}

- (void) handleTap:(UIGestureRecognizer*)gestureRecognize
{
    // retrieve the SCNView
    SCNView *scnView = (SCNView *)self.view;

    // check what nodes are tapped
    CGPoint p = [gestureRecognize locationInView:scnView];
    NSArray *hitResults = [scnView hitTest:p options:nil];

    // check that we clicked on at least one object
    if([hitResults count] > 0){
        // retrieved the first clicked object
        SCNHitTestResult *result = [hitResults objectAtIndex:0];

        // get its material
        SCNMaterial *material = result.node.geometry.firstMaterial;

        // highlight it
        [SCNTransaction begin];
        [SCNTransaction setAnimationDuration:0.5];

        // on completion - unhighlight
        [SCNTransaction setCompletionBlock:^{
            [SCNTransaction begin];
            [SCNTransaction setAnimationDuration:0.5];

            material.emission.contents = [UIColor blackColor];

            [SCNTransaction commit];
        }];

        material.emission.contents = [UIColor redColor];

        [SCNTransaction commit];
    }
}

-(void)reCenterYaw{
    self.hasYawCenterPointBeenSet = NO;
    NSLog(@"Tapped recenter");
}


-(void)setupMotionCapture{

    _motionManager = [[CMMotionManager alloc] init];
    _motionManager.deviceMotionUpdateInterval = 1.0/60.0;
    if (_motionManager.isDeviceMotionAvailable) {
        [_motionManager startDeviceMotionUpdates];
        _currentAttitude = _motionManager.deviceMotion.attitude;
    }

//  if (!_hasYawCenterPointBeenSet) {
//      _yawCenterPoint = _currentAttitude.yaw;
//      _hasYawCenterPointBeenSet = YES;
//  }



}


- (BOOL)shouldAutorotate
{
    return YES;
}

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return UIInterfaceOrientationMaskLandscape;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}



@end

person Metalboyblue    schedule 21.01.2015    source источник


Ответы (1)


Я понял. Я создал синглтон, чтобы ссылаться на контроллер представления из класса hud набора спрайтов. Проблема в том, что я загружаю контроллер представления из раскадровки, а затем позже, из инициализации класса hud, я создаю экземпляр нового контроллера представления, потому что «sharedViewController» никогда не инициировался при загрузке раскадровки. Итак, я только что создал свойство контроллера представления в классе hud и установил его на себя, чтобы контроллер представления загружал код.

person Metalboyblue    schedule 22.01.2015