3

所以,现在我有一个火箭,它在 iphone 5 屏幕的底部左右弹跳。但是,我希望火箭停止左右移动,但一旦用户触摸屏幕就向上移动(因此触摸屏幕会使火箭起飞)。

首先,在 viewDidAppear 中,我告诉编译器在 2 秒后运行 spawnRocket 方法。

在该spawnRocket方法中,我建立了火箭图像和框架,然后将其添加到视图中并执行 uiview 动画,将火箭发送到屏幕右侧。在finisheduiview 动画方法的参数中,我告诉编译器运行 moveRocketLeft 方法。

在 moveRocketLeft 方法中,我做了一个动画,将火箭发送到屏幕左侧,在finished参数中我运行了 moveRocketRight 方法。

moveRocketMethod 基本上是 spawnRocket 方法,只是我没有建立火箭图像和框架并将其添加到视图中。

所以在这一切之后,我尝试实现 -touchesBegan:withEvent: 方法。我尝试简单地运行一个 uiview 动画,将火箭 y 更改为向上离开屏幕,并将 x 更改为用户触摸屏幕时 x 当前所处的位置。

但是,我意识到调用火箭框架并没有返回火箭在动画时看起来像的位置。它实际上只是返回完成动画后火箭框架的内容。那么,要获得我想要的框架,我应该打电话layer吗?我记得在某处读到该层将在动画期间返回 uiimageview 的实际位置。但是,图层只有属性边界而不是框架,所以我有点困惑。

我也尝试调用[self.view.layer removeAllAnimations];然后运行一个新的动画,这会拍摄尴尬,但该removeAllAnimations方法从未奏效(无论如何我并不喜欢使用它的想法,因为我听说它滞后)。

所以有人知道我如何实施touchesBegan:withEvent:方法以使火箭正确起飞吗?(或者如果您认为我必须更改整个程序,请随时提供帮助)

    #import "ViewController.h"
    #import <QuartzCore/QuartzCore.h>
    @interface ViewController ()
    @property UIImageView *rocket;
    @end

    @implementation ViewController


    @synthesize rocket=_rocket;

    - (void)viewDidLoad
    {
        [super viewDidLoad];

    }

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view.layer removeAllAnimations];
     //   [UIView animateWithDuration:3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^(){self.rocket.frame=CGRectMake(self.rocket.frame.origin.x, -40, 25, 40);} completion:^(BOOL finished){}];

    // this didn't work :(
    }



    -(void)viewDidAppear:(BOOL)animated{
        [self performSelector:@selector(spawnRocket) withObject:self afterDelay:2];
    }
    -(void)spawnRocket{
        self.rocket=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"default.png"]]; //places imageview right off screen
        self.rocket.frame=CGRectMake(-25, 420, 25, 40);

        [self.view addSubview:self.rocket];
        [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^(){self.rocket.frame=CGRectMake(295, 420, 25, 40);}  completion:^(BOOL finished){if (finished)[self moveRocketLeft]; }];


    }

    -(void) moveRocketLeft{
        [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^(){self.rocket.frame=CGRectMake(0, 420, 25, 40);} completion:^(BOOL finished){if (finished)[self moveRocketRight];}];
    }

        -(void)moveRocketRight{
          [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^(){self.rocket.frame=CGRectMake(295, 420, 25, 40);} completion:^(BOOL finished){if (finished)[self moveRocketLeft];}];
        }
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

    @end
4

1 回答 1

1

This should do the trick

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    CALayer *rocketPresentationLayer = [self.rocket.layer presentationLayer];
    self.rocket.layer.position = rocketPresentationLayer.position;
    [UIView animateWithDuration:3 delay:0 options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionBeginFromCurrentState animations:^(){self.rocket.frame=CGRectMake(self.rocket.frame.origin.x, -40, 25, 40);} completion:^(BOOL finished){}];
}

Note 1: I didn't put logic in here to check whether the user tapped the rocket again, when it is taking off vertically. You might want to add a BOOL or something to see if the user successfully hit the rocket or not, and if so, don't perform the vertical animation again.

Note 2: If in future you only want this to occur when the rocket is hit, you can use hitTest checking to call the animation conditionally.

// Get the touch
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self.view];

// See if we hit the rocket
CALayer *rocketPresentationLayer = [self.rocket.layer presentationLayer];
CALayer* hitTest = [rocketPresentationLayer hitTest:touchPoint];

// If we did, then stop animation and move upwards
if (hitTest) {
    ....
}

P.S: Also as a slight mention, @property UIImageView *rocket; should be changed to @property (nonatomic) UIImageView *rocket;. This is primarily for performance reasons, as I don't expect your rocket to be accessed by multiple threads (it shouldn't, it's the UI!).

于 2012-11-03T21:51:32.480 回答