Pergunta

Eu tenho a classe UIView subclasse em uma aula de rejeição com acelerômetro. Esta aula de rejeição mostra uma imagem e mova -a na tela. Quando o dispositivo do iPhone é movido, esta imagem salta na tela.

Quando eu crio várias instâncias, apenas a última instância funciona adequada:

// in the MainViewController.m

Bounce *heart[100];


for(int i = 0; i < 10; i++) {
    rx = (arc4random() % 300) + 10;
    ry = (arc4random() % 300) + 10;
    NSLog(@"random %d %d", rx, ry);
    heart[i] = [[Bounce alloc] initWithPNG:@"Heart.png" 
                       position:CGPointMake(rx, ry) size:CGSizeMake(64, 64)];
    heart[i].velocity = CGPointMake(1.0, 1.0);
    [self.view addSubview: heart[i]];
}

Esta é a aula de rejeição:

//
//  Bounce.h
//  iMakeLove
//
//  Created by Giovambattista Fazioli on 06/11/09.
//  Copyright 2009 Saidmade srl. All rights reserved.
//

#import <UIKit/UIKit.h>


@interface Bounce : UIView <UIAccelerometerDelegate> {

    CGPoint     position;
    CGSize      size;
    CGPoint     velocity;
    NSTimer     *objTimer;
    NSString    *pngName;
    CGFloat     bounce;
    CGFloat     gravity;
    CGPoint     acceleratedGravity;
    CGPoint     lastTouch;
    CGPoint     currentTouch;
    BOOL        dragging;

    UIAccelerometer *accelerometer;

}



@property CGPoint position;
@property CGSize size;
@property CGPoint velocity;
@property(nonatomic,retain)NSString *pngName;
@property(nonatomic,retain)NSTimer *objTimer;
@property CGFloat bounce;
@property CGFloat gravity;
@property CGPoint acceleratedGravity;
@property CGPoint lastTouch;
@property CGPoint currentTouch;
@property BOOL dragging;

- (id)initWithPNG:(NSString*)imageName position:(CGPoint)p size:(CGSize)s;

- (void)update;
- (void)onTimer;
- (void)startPrevent;

@end

Implementação:

//
//  Bounce.m
//  iMakeLove
//
//  Created by Giovambattista Fazioli on 06/11/09.
//  Copyright 2009 Saidmade srl. All rights reserved.
//

#import "Bounce.h"

@implementation Bounce

@synthesize position, size;
@synthesize objTimer;
@synthesize velocity;
@synthesize pngName;
@synthesize bounce;
@synthesize gravity, acceleratedGravity;
@synthesize lastTouch, currentTouch;
@synthesize dragging;



- (id)initWithPNG:(NSString*)imageName position:(CGPoint)p size:(CGSize)s {

    if (self = [super initWithFrame:CGRectMake(p.x, p.y, s.width, s.height)]) {

        [self setPngName:imageName];
        [self setPosition:p];
        [self setSize:s];
        [self setBackgroundColor:[UIColor clearColor]];

        // Set default gravity and bounce

        [self setBounce:-0.9f];
        [self setGravity:0.5f];
        [self setAcceleratedGravity:CGPointMake(0.0, gravity)];
        [self setDragging:NO];

        UIImageView *prezzie = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, s.width, s.height)];

        prezzie.image = [UIImage imageNamed:imageName];

        [self addSubview:prezzie];

        [prezzie release];

        self.accelerometer = [UIAccelerometer sharedAccelerometer];
        self.accelerometer.delegate = self;

    }
    return self;
}

- (void)startPrevent {
    if (objTimer == nil) {
        objTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
    }
}


- (void)update {

    [self setNeedsDisplay];

    if(dragging) return;

    velocity.x += acceleratedGravity.x;
    velocity.y += acceleratedGravity.y;
    position.x += velocity.x;
    position.y += velocity.y;

    if(position.x + size.width >= 320.0) {
        position.x = 320.0 - size.width;
        velocity.x *= bounce;
    } else if(position.x <= 0.0) {
        velocity.x *= bounce;
    }

    if(position.y + size.height >= 480.0) {
        position.y = 480.0 - size.height;
        velocity.y *= bounce;
    } else if(position.y <= 0.0) {
        velocity.y *= bounce;
    }
    self.frame = CGRectMake(position.x, position.y, size.width, size.height);
}



- (void)onTimer {
    [self update];
}



- (void)drawRect:(CGRect)rect {

    // Drawing code

}

/* EVENTS */


- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    acceleratedGravity.x = acceleration.x * gravity;
    acceleratedGravity.y = -acceleration.y * gravity;
}



- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    // First, lets check to make sure the timer has been initiated

    if (objTimer == nil) {
        objTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
    }

    UITouch *touch = [touches anyObject];

    [self setCurrentTouch:[touch locationInView:self]];
    CGFloat dx = currentTouch.x - position.x;
    CGFloat dy = currentTouch.y - position.y;
    CGFloat dist = sqrt(dx * dx + dy * dy);

    if(dist < size.width) {
        [self setVelocity:CGPointMake(0.0, 0.0)];
        [self setDragging:YES];
    }
    [self setLastTouch:currentTouch];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    [self setCurrentTouch:[touch locationInView:self]];
    [self setDragging:YES];
    [self setVelocity:CGPointMake(currentTouch.x - lastTouch.x, currentTouch.y - lastTouch.y)];
    [self setLastTouch:currentTouch];

}



- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self setDragging:NO];
}





- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
    }
    return self;
}

- (void)dealloc {
    [super dealloc];
}


@end

Pode me ajudar?

Foi útil?

Solução

Isso é porque self.accelerometer.delegate = self; está mudando o sharedAccelerometerO delegado e apenas a última tarefa terá efeito.

Outras dicas

Acredito que apenas a visão mais frontal receberá as mensagens aceleradas. Você pode querer que as mensagens do AccelReter sejam enviadas ao seu ViewController.

O que eu posso fazer aqui. (Pode não ser a melhor coisa a longo prazo, mas resolverá o problema imediato) é o seguinte:

Eu tornaria a gravidade acelerada uma variável estática compartilhada entre todas as instâncias de salto. Isso faz com que o sentido, porque no mundo real (o que estamos simulando) a gravidade acelerada seria a mesma para todos os saltos. (Eu também renomearia o salto para algo como BouncingView). Eu acessaria essa variável através de alguns métodos de classe. Além disso, eu compartilharia o acelerômetro e teria seu método de delegado, um método de classe. Coloque essas coisas na sua classe e deve funcionar: (eu o testaria, mas minha máquina de desenvolvimento está na Apple Store sendo corrigida.) Além disso, existem alguns erros de sintaxe no código de exemplo que você postou.

  static CGCGPoint acceleratedGravity;
  static UIAccelerometer *accelerometer;

    -(void) init {
        /* Everything Else */
        self.accelerometer = [UIAccelerometer sharedAccelerometer];
        self.accelerometer.delegate = self;
        /*Everything Else */
    }

    +(CGPoint) acceleratedGravity {
        return acceleratedGravity;
    }

    +(void) setAcceleratedGravity:(CGPoint) _acceleratedGravity {
        acceleratedGravity = _acceleratedGravity;
    }

+ (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    acceleratedGravity.x = acceleration.x * gravity;
    acceleratedGravity.y = -acceleration.y * gravity;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top