Recursive UIView animation continues after ViewController destroyed, new ViewController created - iphone

UPDATE
ViewController is not destroyed, new ViewController is not created. This:
TimerViewController * timerViewController = (TimerViewController *)[segue destinationViewController];
does not create a new instance. However, this
TimerViewController *timerViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"theID"];
does. So a new instance is now being used, but the same problem.
END UPDATE
I have a simple "analog digital timer" where the minutes and seconds animate smoothly to emulate the turning of a number wheel. This is simply a ParentViewController with a list of times, selecting a time performs a segue to the TimerViewController. The TimerViewController uses a recursive UIView animation to simulate the countdown of a clock. This works well.
I want the user to be able to transition to the next timer in the list without having to go back to the ParentViewController in order to select it. This does not work well.
I've tried many variations, the basic pattern is for TimerViewController to ask its delegate (ParentViewController) to pop it and then to seque again to the TimerViewController using the next time from the list of times. The initial animation never terminates, the initial TimerViewController instance never "dies". When I segue to TimerViewController the second time, using what I thought was a new instance, the first animation appears to still be running, the duration of the animation which started at almost 1.0s is off the charts (closer to 0.).
I've tried many different, increasingly desperate, ways to stop the original animation and kill the original instance.
ParentViewController.m
-(void) timerViewControllerDidSwipe (TimerViewController *)controller {
[self.navigationController popViewControllerAnimated:NO];
controller = nil; // ?
[self performSegueWithIdentifier:#"ShowTimer" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowTimer"])
{
TimerViewController * timerViewController = (TimerViewController *)[segue destinationViewController];
[timerViewController setDelegate:self];
}
TimerViewController.m
-(void) swipe:(id)selector {
// swipe left
stop = YES; // ivar for ^after to not call [self animate]
[self.delegate timerViewControllerDidSwipe:self];
}
-(void) animate {
// anim block here..
void (^after) (BOOL) = ^(BOOL f) {
if (duration % 60 == 0 && duration >= 60) {
if (minutesAlt.center.y < minutes.center.y)
{
CGPoint a = minutes.center;
a.y -= 2 * displacement;
minutes.center = a;
minutes.text = [NSString stringWithFormat:#"%02d", (duration / 60) -1];
}
else
{
CGPoint a = minutesAlt.center;
a.y -= 2 * displacement;
minutesAlt.center = a;
minutesAlt.text = [NSString stringWithFormat:#"%02d", (duration / 60) -1];
}
}
if (duration == 0)
{
// end
}
else if (secondsAlt.center.y < seconds.center.y)
{
CGPoint a = seconds.center;
a.y -= 2 * displacement;
seconds.center = a;
duration--;
seconds.text = [NSString stringWithFormat:#"%02d",duration % 60];
if (!stop) {[self animate];}
}
else
{
CGPoint a = secondsAlt.center;
a.y -= 2 * displacement;
duration--;
secondsAlt.center = a;
secondsAlt.text = [NSString stringWithFormat:#"%02d", duration % 60];
if (!stop) {[self animate];}
}
};
[UIView animateWithDuration:0.50
delay:0.50
options:UIViewAnimationOptionCurveLinear
animations:anim
completion:after];
}
Any help greatly appreciated.

Fixed here in a related question. It was a simple syntax error (that took me weeks to find).

Related

How to complete interactive UIViewController transition?

I've been dabbling with the new iOS 7 custom transition API and looked through all the tutorials/documentation I could find but I can't seem to figure this stuff out for my specific scenario.
So essentially what I'm trying to implement is a UIPanGestureRecognizer on a view where I would swipe up and transition to a VC whose view would slide up from the bottom while the current view would slide up as I drag my finger higher.
I have no problem accomplishing this without the interaction transition, but once I implement the interaction (the pan gesture) I can't seem to complete the transition.
Here's the relevant code from the VC that conforms to the UIViewControllerTransitionDelegate which is needed to vend the animator controllers:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Swipe"]) {
NSLog(#"PREPARE FOR SEGUE METHOD CALLED");
UIViewController *toVC = segue.destinationViewController;
[interactionController wireToViewController:toVC];
toVC.transitioningDelegate = self;
toVC.modalPresentationStyle = UIModalPresentationCustom;
}
}
#pragma mark UIViewControllerTransition Delegate Methods
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController: (UIViewController *)presented presentingController: (UIViewController *)presenting sourceController:(UIViewController *)source {
NSLog(#"PRESENTING ANIMATION CONTROLLER CALLED");
SwipeDownPresentationAnimationController *transitionController = [SwipeDownPresentationAnimationController new];
return transitionController;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
NSLog(#"DISMISS ANIMATION CONTROLLER CALLED");
DismissAnimatorViewController *transitionController = [DismissAnimatorViewController new];
return transitionController;
}
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {
NSLog(#"Interaction controller for dimiss method caled");
return interactionController.interactionInProgress ? interactionController:nil;
}
NOTE: The interaction swipe is only for the dismissal of the VC which is why it's in the interactionControllerForDismissal method
Here's the code for the animator of the dismissal which works fine when I tap on a button to dismiss it:
#import "DismissAnimatorViewController.h"
#implementation DismissAnimatorViewController
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return 1.0;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
NSTimeInterval duration = [self transitionDuration:transitionContext];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
CGRect initialFrameFromVC = [transitionContext initialFrameForViewController:fromVC];
UIView *containerView = [transitionContext containerView];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
NSLog(#"The screen bounds is :%#", NSStringFromCGRect(screenBounds));
toVC.view.frame = CGRectOffset(initialFrameFromVC, 0, screenBounds.size.height);
toVC.view.alpha = 0.2;
CGRect pushedPresentingFrame = CGRectOffset(initialFrameFromVC, 0, -screenBounds.size.height);
[containerView addSubview:toVC.view];
[UIView animateWithDuration:duration
delay:0
usingSpringWithDamping:0.6
initialSpringVelocity:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
fromVC.view.frame = pushedPresentingFrame;
fromVC.view.alpha = 0.2;
toVC.view.frame = initialFrameFromVC;
toVC.view.alpha = 1.0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
#end
Here's the code for the UIPercentDrivenInteractiveTransition subclass which serves as the interaction controller:
#import "SwipeInteractionController.h"
#implementation SwipeInteractionController {
BOOL _shouldCompleteTransition;
UIViewController *_viewController;
}
- (void)wireToViewController:(UIViewController *)viewController {
_viewController = viewController;
[self prepareGestureRecognizerInView:_viewController.view];
}
- (void)prepareGestureRecognizerInView:(UIView*)view {
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
gesture.minimumNumberOfTouches = 1.0;
[view addGestureRecognizer:gesture];
}
- (CGFloat)completionSpeed {
return 1 - self.percentComplete;
NSLog(#"PERCENT COMPLETE:%f",self.percentComplete);
}
- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer {
// CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
// 1. Start an interactive transition!
self.interactionInProgress = YES;
[_viewController dismissViewControllerAnimated:YES completion:nil];
break;
case UIGestureRecognizerStateChanged: {
// 2. compute the current position
CGFloat fraction = fabsf(translation.y / 568);
NSLog(#"Fraction is %f",fraction);
fraction = fminf(fraction, 1.0);
fraction = fmaxf(fraction, 0.0);
// 3. should we complete?
_shouldCompleteTransition = (fraction > 0.23);
// 4. update the animation controller
[self updateInteractiveTransition:fraction];
NSLog(#"Percent complete:%f",self.percentComplete);
break;
}
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
// 5. finish or cancel
NSLog(#"UI GESTURE RECOGNIZER STATE CANCELED");
self.interactionInProgress = NO;
if (!_shouldCompleteTransition || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
[self cancelInteractiveTransition];
NSLog(#"Interactive Transition is cancled.");
}
else {
NSLog(#"Interactive Transition is FINISHED");
[self finishInteractiveTransition];
}
break;
}
default:
NSLog(#"Default is being called");
break;
}
}
#end
Once again, when I run the code now and I don't swipe all the way to purposefully cancel the transition, I just get a flash and am presented with the view controller I want to swipe to. This happens regardless if the transition completes or is canceled.
However, when I dismiss via the button I get the transition specified in my animator view controller.
I can see a couple of issues here - although I cannot be certain that these will fix your problem!
Firstly, your animation controller's UIView animation completion block has the following:
[transitionContext completeTransition:YES];
Whereas it should return completion based on the result of the interaction controller as follows:
[transitionContext completeTransition:![transitionContext transitionWasCancelled]]
Also, I have found that if you tell the UIPercentDrivenInteractiveTransition that a transition is 100% complete, it does not call the animation controller completion block. As a workaround, I limit it to ~99.9%
https://github.com/ColinEberhardt/VCTransitionsLibrary/issues/4
I've created a number of example interaction and animation controllers here, that you might find useful:
https://github.com/ColinEberhardt/VCTransitionsLibrary
I had this same problem. I tried the fixes above and others, but nothing worked. Then I stumbled upon https://github.com/MrAlek/AWPercentDrivenInteractiveTransition, which fixed everything.
Once you add it to your project, just replace UIPercentDrivenInteractiveTransition with AWPercentDrivenInteractiveTransition.
Also, you have to set the animator before starting an interactive transition. In my case, I use the same class for UIViewControllerAnimatedTransitioning and UIViewControllerInteractiveTransitioning, so I just did it in init():
init() {
super.init()
self.animator = self
}

UIButton IBAction method only drawing to screen once?

I am a little confused about something I was just trying for fun. I have written a little method called animateBars_V1 which uses an array of UIImageViews and alters the height of each UIImageView to show a changing set of coloured bars.
- (void)animateBars_V1 {
srandom(time(NULL));
for(UIImageView *eachImageView in [self barArray]) {
NSUInteger randomAmount = kBarHeightDefault + (random() % 100);
CGRect newRect;
CGRect barRect = [eachImageView frame];
newRect.size.height = randomAmount;
newRect.size.width = barRect.size.width;
newRect.origin.x = barRect.origin.x;
newRect.origin.y = barRect.origin.y - (randomAmount - barRect.size.height);
[eachImageView setFrame:newRect];
}
}
This works fine, I then added a UIButton with a UIAction for when the button is pressed. Each time the button is pressed animateBars_V1 is called and the coloured bars update.
- (IBAction)buttonPressed {
for(int counter = 0; counter<5; counter++) {
[self animateBars_V1];
NSLog(#"COUNTER: %d", counter);
}
}
My question is just for fun I decided that each time the button is pressed I would call animateBars_V1 5 times. What happens is that the bars don't change until after the loop has exited. This results in:
Screen as per storyboard
COUNTER: 0
COUNTER: 1
COUNTER: 2
COUNTER: 3
COUNTER: 4
Screen Updates
Is this the correct behaviour? I don't need a fix or workaround as this was just for fun, I was more curious what was happening for future reference.
If you are calling animateBars_V1 multiple times within a loop, the frames of the bars do get set multiple times, but before they can be rendered, animateBars_V1 gets called again, and the frames are set to a new position/size.
The call to render (drawRect: and related methods) doesn't occur until after the loop is finished - since it is an IBAction, it is by necessity called in the main thread, which means that all rendering is blocked until the code is completed.
There are of course several solutions to this. A simple method to do the multi-animation thing is to use UIView animateWithDuration:animations:completion: in the following manner:
- (IBAction)buttonPressed {
[self animateBarsWithCount:5];
}
- (void)animateBarsWithCount:(int)count
{
[UIView animateWithDuration:.25f animations:^{
[self animateBars_V1];
}completion:^(BOOL finished){
[self animateBarsWithCount:count - 1];
}];
}
//animateBars_V1 not repeated
Of course, if you simply wanted to run the animation one time, (but actually animated) you should do it like this:
- (IBAction)buttonPressed {
[UIView animateWithDuration:.25f animations:^{
[self animateBars_V1];
} completion:nil];
}
CrimsonDiego is right
you can try to delay each call with this:
- (IBAction)buttonPressed {
for(int counter = 0; counter<5; counter++) {
float ii = 1.0 * counter / 10;
[self performSelector:#selector(animateBars_V1) withObject:nil afterDelay:ii];
// [self animateBars_V1];
NSLog(#"COUNTER: %d", counter);
}
}
The problem is here
for(int counter = 0; counter<5; counter++) {
[self animateBars_V1];
NSLog(#"COUNTER: %d", counter);
}
This for loop is executed in nano seconds and your eye is not able to catch up that change as eye can detect only 1/16th of a second.
For testing what can run this code in a timer that runs five time.
Edited
Removed sleep call as it will sleep the main thread and everything will stop. So use Timer here

Animating sequence of images in cocos2d

i have this code to show animation of a image
-(void) blink:(ccTime) delta {
animateblink ++; //adds 1 every frame
if (animateblink <= 6 ) { //if we included frames to show for breaking and the current frame is less than the max number of frames to play
if (animateblink < 6) {
[sprite setTexture:[[CCSprite spriteWithFile:[NSString stringWithFormat:#"%#_blinkk00%i.png", baseImageName,animateblink]] texture]];
[self unschedule:_cmd];
[self schedule:#selector(openEyes:) interval:0.1f];
[self schedule:#selector(moveSprite:) interval:0.1f];
}
}
}
i have 6 images of animating like
dragonimage_blinkk001,dragonimage_blinkk002,dragonimage_blinkk003,dragonimage_blinkk004,dragonimage_blinkk005,dragonimage_blinkk006 like that
i put two methods,
1: for animation time
2: for movement of the image
the code is
-(void) openEyes:(ccTime) delta {
[sprite setTexture:[[CCSprite spriteWithFile:[NSString stringWithFormat:#"%#.png", baseImageName]] texture]];
[self unschedule:_cmd];
int blinkInterval = (arc4random() % 6) + 1; // range 3 to 8
[self schedule:#selector(blink:) interval:blinkInterval];
}
-(void)moveSprite:(ccTime)delta
{
movementCounter ++;
if (movementCounter == 1000) {
[self unschedule:_cmd];
}
else
{
spriteimagename.position = ccp(spriteimagename.position.x+10,spriteimagename.position.y);
}
}
but on the first method the animation time is not correct,there is a lot of delay of animation,i just want to show animation of the images randomly and fast,its a dragon flying animation.
my sec on method is not at all working,i didn't get any movement of that image.
i hope you understand my issue.how to solve the above two method issues.
Thanks in advance.
Quick solution is to add frameIndex member in cocos2d CCSpriteFrame class. i don't know is that allowed to change. But it works fine.
#interface CCSpriteFrame : NSObject <NSCopying>
{
int frameIndex;
....
}
//Here in code initialize frames with unique index
CCAnimation* animation;
NSMutableArray *animFrames2 = [NSMutableArray array];
for( int i=1;i<=15;i++)
{
CCSpriteFrame *frame = [cache spriteFrameByName:[NSString stringWithFormat:#"ActerSmash_%d.png",i]];
frame.frameIndex = (int)i;
[animFrames2 addObject:frame];
}
animation = [CCAnimation animationWithFrames:animFrames2];
CCAnimate *action = [CCAnimate actionWithDuration:ACTER_SMASH_SPEED animation:animation restoreOriginalFrame:YES];
action.tag = kTagAnimationSmashAnim ;
mActer.AnimSmash = action;
//Checking frame Index
CCAnimate *anim = mActer.AnimSmash ;
for(CCSpriteFrame *frame in anim.animation.frames)
{
if([mActer isFrameDisplayed:frame] ) )
{
if(frame.frameIndex == 5 )
{
//Do something..
}
}
}

Paged UIScrollview with lazy delayed loading

I need help with the uiscrollview implementation with the following requirements:
1) pagingEnabled = true.
2) lazy pages loading.
3) pages are loading in the background. So i need at first run loading the page X, then get the notification that the page is fully loaded and only then allow the user to scroll to it.
4) ability to change the current page.
My first attempt was to override the scrollViewDidEndDeacelerating and scrollViewDidScroll, but I had troubles with stucking on half of pages (when you stop the scroll on the half of the page and then wait for new page to add to the scroll) and empty pages (when the user scrolled too fast).
My second attempt was to override the layoutSubviews method of the UIScrollView and do all calculations there. But it seems to be very sofisticated.
So, I'd love to find any examples of similar implementations.
Now I have the code like this:
I've implemented scrollViewWillBeginDragging and scrollViewDidEndDecelerating:
- (void)scrollViewWillBeginDragging:(UIScrollView *)aScrollView
{
isScrolling = YES;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{
isScrolling = NO;
// Here we load the page that was prepared when the user was scrolling
if (needDisplay > -1) {
//NSLog(#"Loading queued page %d", needDisplay);
[self loadScrollViewWithPage:needDisplay forceAddToSuperview:NO animated:YES];
needDisplay = -1;
}
// minLoadedPageIndex - index of the first loaded page.
int selectedIndex = MIN(floor((aScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1 + minLoadedPageIndex, [photoItems count] - 1);
[self loadScrollViewWithPage:selectedIndex - 1 forceAddToSuperview:NO animated:YES];
[self loadScrollViewWithPage:selectedIndex forceAddToSuperview:NO animated:YES];
[self loadScrollViewWithPage:selectedIndex + 1 forceAddToSuperview:NO animated:YES];
}
In loadScrollViewWithPage I create the page view controller which loads the data from the server in the background. I don't add the view to the scrollview until it loads the data from the server.
- (void)loadScrollViewWithPage:(int)page forceAddToSuperview:(BOOL)value animated:(BOOL)animated
{
DetailController *controller = page >= viewControllers.count ? [NSNull null] :[viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{
controller = [[DetailController alloc] initWithNibName:#"DetailController" bundle:nil];
controller.delegate = self;
controller.view.hidden = NO; //this will call viewDidLoad.
if (page >= viewControllers.count) {
[viewControllers addObject:controller];
}
else {
[viewControllers replaceObjectAtIndex:page withObject:controller];
}
[controller release];
}
// add the controller's view to the scroll view
if (controller.view && controller.view.superview == nil && (controller.isLoadedOrFailed || value)) {
[self setNumberOfVisiblePages:visiblePagesCount+1];
if (page < selectedIndex) {
// We are adding the page to the left of the current page,
// so we need to adjust the content offset.
CGFloat offset = (int)scrollView.contentOffset.x % (int)scrollView.frame.size.width;
offset = scrollView.frame.size.width * (selectedIndex - minLoadedPageIndex) + offset;
[scrollView setContentOffset:CGPointMake(offset, 0.0) animated:animated];
}
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * (page - minLoadedPageIndex);
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
[controller viewWillAppear:NO];
}
}
Also I have a detailControllerDidFinishDownload method which is called when data for the page view controller has been loaded.
- (void)detailControllerDidFinishDownload:(DetailController *)controller
{
... //here I calculate new minLoadedPageIndex value
// reset pages frames
if (minLoadedPageIndex < oldMinPage) {
for(int i=oldMinPage;i < [viewControllers count]; i++) {
DetailController *detailsController = [viewControllers objectAtIndex:i];
if ((NSNull *)detailsController != [NSNull null]) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * (i - minLoadedPageIndex);
frame.origin.y = 0;
[detailsController.view setFrame:frame];
}
}
}
// load the page now or delay load until the scrolling will be finished
if (!isScrolling) {
[self loadScrollViewWithPage:[photoItems indexOfObject:controller.photoItem] forceAddToSuperview:NO animated:NO];
}
else {
needDisplay = [photoItems indexOfObject:controller.photoItem];
//NSLog(#"pageControlUsed is used!!! %d", [photoItems indexOfObject:controller.photoItem]);
}
}
The problem I have now is that sometimes the scroll stucks on the middle (or somewhere near to middle) of the pages and it won't go to the nearest page bounce until I slightly more it. My tests showed that this situation happens if I scroll out of content view frame (the scroll view have bounces on) and wait for the new page to load. In 1 of the 10 times the scroll stucks.
Thanks, Mikhail!
There are a lot of things you are requiring at the same time. I suggest you have a look at this example.
http://ykyuen.wordpress.com/2010/05/22/iphone-uiscrollview-with-paging-example/
It's a very good starting point.

How to implement powerUps and other game altering objects in objective-C or cocos2d

Ok, so I have these powerups that I want to slow/speed up the movement of the other objects in the game for a few seconds.
I have an array of objects that I have a variable called spawnInterval that gets faster and faster as the game progresses, making the ame get harder after a few mins.
But I can't really grasp how to make it so the character in the game will react differently to different objects as in when the fastPowerUp is hit by the character sprite, the spawn interval doesn't change.
And vice versa with the slowPowerUp.
the code I have at the moment is this in a move sequence method that gets called in an update method:
-
(void) updateObstacles:(ccTime)delta{
for (int i = 0; i < 20; i++) {
//int randomizer = CCRANDOM_0_1() * [obstacles count];
//NSLog(#"randomizer: %i",randomizer);
CCSprite* randomObject = [obstacles randomObject];
currentObject = [obstacles indexOfObject:randomObject];
if ([randomObject numberOfRunningActions] == 0) {
[self runObstacleMoveSequence:randomObject withTimer:delta];
break;
}
}
}
-(void) runObstacleMoveSequence:(CCSprite *)object withTimer:(ccTime)delta{
static int time;
//Slowly increase object speed
numObstaclesMoved++;
if (!slowPowerUp && !fastPowerUp) {
time += delta;
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration -= 0.2f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
}
}
}else if (slowPowerUp && !fastPowerUp) {
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration += 3.0f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
if (time >= (delta + 3)) {
slowPowerUp = NO;
obstacleMoveDuration -= 3.0f;
}
}
}
}else if (!slowPowerUp && fastPowerUp) {
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration -= 3.0f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
if (time >= (delta + 3)) {
fastPowerUp = NO;
obstacleMoveDuration += 3.0f;
}
}
}
}
CGSize screenSize = [[CCDirector sharedDirector]winSize];
CGPoint aboveScreenPosition = CGPointMake(object.position.x, screenSize.height - object.position.y);
int rotations = (CCRANDOM_0_1()*3) * 360;
float duration = (CCRANDOM_0_1()*5.0f) + 8.0f;
CCMoveTo* move = [CCMoveTo actionWithDuration:obstacleMoveDuration position:aboveScreenPosition];
CCRotateTo* rotate = [CCRotateBy actionWithDuration:duration angle:rotations];
CCSpawn* moveRotate = [CCSpawn actions: move, rotate, nil];
CCCallFuncN* call = [CCCallFuncN actionWithTarget:self selector:#selector(objectAboveScreen:)];
CCSequence* sequence = [CCSequence actions:moveRotate, call, nil];
[object runAction:sequence];
if (time >= (delta + 3)) {
fastPowerUp = NO;
}
}
-(void) objectAboveScreen:(id) sender{
//make sure sender is actually of the right class
NSAssert([sender isKindOfClass:[CCSprite class]], #"sender is not a CCSprite!");
CCSprite* obstacle = (CCSprite*)sender;
//move the back to the bottom of the screen
CGPoint pos = obstacle.position;
CGSize screenSize = [[CCDirector sharedDirector]winSize];
pos.y = (-screenSize.height - [obstacle texture].contentSize.height);
pos.x = CCRANDOM_0_1() * screenSize.width;
obstacle.position = pos;
}
I really just don't know where to go from here... Should I make the powerUps a different class? If so, how would I implement something like this? I really hate trying to ask for someone to solve my question, but I really just can't rack my brain around this and I'm rather new... if it were explained to me, then I know I would be able to implement it in future games on my own...
Thanks in advance, and let me know if more information is needed...
I'd do something like
in the .h file
float speedModifier;
-(void)resetPowerUp;
in the .m
-(void)resetPowerUp
{
speedModifier = 1;
}
wherever you are initializing the level
[self resetPowerUp];
upon collision with powerup:
speedModifier = 2;
[self performSelector:#selector(resetPowerUp) withObject:nil afterDelay:5];
then wherever you are moving whatever it is which speed should be effected by the powerup mode, multiply the speed of the animation (or divide the duration it takes for it to get wherever it's going) by speedModified
hope that helps