所以,现在我有一个火箭在iphone 5屏幕的底部左右反弹。我希望火箭能够停止左右移动,但是一旦用户触摸屏幕就会向上移动(因此触摸屏幕会使火箭起飞)。
首先,在viewDidAppear中,我告诉编译器在2秒后运行spawnRocket方法。
在spawnRocket
方法中,我建立了火箭图像和框架,然后我将其添加到视图中并执行uiview动画,将火箭发送到屏幕的右侧。在uiview动画方法的finished
参数中,我告诉编译器运行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
答案 0 :(得分:1)
这应该可以解决问题
-(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){}];
}
注1:我没有在这里放置逻辑来检查用户是否在垂直起飞时再次点击火箭。您可能需要添加BOOL
或其他内容以查看用户是否成功点击了火箭,如果是,则不要再次执行垂直动画。
注2:如果将来你只想在火箭被击中时发生这种情况,你可以使用hitTest
检查来有条件地调用动画。
// 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:稍微提一下,@property UIImageView *rocket;
应更改为@property (nonatomic) UIImageView *rocket;
。这主要是出于性能原因,因为我不希望你的火箭被多个线程访问(它不应该是UI!)。