Cocos2D iPhone Effect - iphone

trying to play around with the Cocos2d effects and created to methods to display and stop the Liquid action. My application however drops from 60fps down to 30fps when the effect is applied but the fps doesnt increase again when the scheduled stop action is called.
I originally thought that while the action has been completed the effect is still being rendered but after reading through the EffectsTest.h/.m in the Cocos2D 0.8 zip I cant find any reference to how this is achieved. Can anyone shed some light on this issue?
// effects
-(void)enableLiquidEffect
{
id liquid = [Liquid actionWithWaves:6 amplitude:20 grid:ccg(15, 10) duration:3];
[self schedule:#selector(disableLiquidEffect) interval:(3.0)];
[self runAction:liquid];
}
-(void)disableLiquidEffect
{
[self unschedule:#selector(disableLiquidEffect)];
[self stopAllActions];
}
Cheers,
AntonMills

Just a little tip here i know this was asked years ago, but someone might still come here
the code is a little bit overkill, here's how to do it:
// effects
-(void)enableLiquidEffect
{
id liquid = [Liquid actionWithWaves:6 amplitude:20 grid:ccg(15, 10) duration:3];
//No need to unschedule after 3 seconds since you already set duration-^ to 3 seconds.
[self runAction:liquid];
}
-(void)disableLiquidEffect
{
[self stopAllActions];
}
besides that the code is perfect

Just a guess but since the item will still have a transform set to liquid that it is still trying to apply a more complex transform then needed after its done. Save off your transform prior to starting and then when it stops set it back. You could try just setting it to nil.

Related

performance issues in sprite kit with efficient code

I read all the posts I found about improving performance but my problem is a bit different.
I have a simple physics-based game. no super fancy stuff.
I´ve got max. 40 nodes on the screen and a few sklabelnodes.
my code is efficient - every node which moves outside the screen gets removed from his parent and Iv'e got just 4 physicBodys at once. textures are not to big - max 250x250 which are preloaded in an atlas.
the problem is that it works for a minute or so and then it starts to stutter for 4-5 sec and then it works fine again. that stuttering doesn't appear on a certain point. sometimes it does on startup and sometimes after a few minutes.
I don´t know what to do.
I load my ad´s on another thread and otherwise there isn't anything to load.
EDIT:
NO shapeNodes.
XCode 7 + iPhone 6plus (9.3.2)
#Alessandro Ornano
my update method only handles the background images. i already tried without bg´s. same problem. i read about performance issues in iOS9
do you know something about that?
-(void)update:(NSTimeInterval)currentTime{
//BG
if (self.background1.position.x >= self.size.width*1.5) {
self.background1.position = CGPointMake(self.background2.position.x - self.background1.size.width+1, self.size.height/2);
}
if (self.background2.position.x >= self.size.width*1.5) {
self.background2.position = CGPointMake(self.background1.position.x - self.background2.size.width+1, self.size.height/2);
}
//BG CLOUDS
if (self.backgroundClouds1.position.x >= self.size.width*1.5) {
self.backgroundClouds1.position = CGPointMake(self.backgroundClouds2.position.x - self.backgroundClouds1.size.width+1, self.size.height/2);
}
if (self.backgroundClouds2.position.x >= self.size.width*1.5) {
self.backgroundClouds2.position = CGPointMake(self.backgroundClouds1.position.x - self.backgroundClouds2.size.width+1, self.size.height/2);
}
}

When are a methods GUI operations actually carried out?

I am working on a web-services data processing app and I am trying to make the app run as quickly as possible. When a certain 3 finger pan gesture is performed, I call a method that sends updated information off to the server to get a new batch of images to update the existing ones with.
So lets say there are 15 images in an array, I filter through them with a 2 finger gesture, and then if I want to change something about them, I can do the 3 finger gesture, and I get that same set back, just tweaked a bit (contrast/brightness, etc.).
Is what I want though is to be able to update the imageView that is displaying the images after the first image has been retrieved, so as to give the user a feel for what the rest in the series are going to look like. But no matter what I try, and no matter how many different threads I try and implement, I can't get the imageView to update before the entire download is complete. Once the batch download is done (which is handled on a separate thread) the imageView updates with the new images and everything is great.
The first step in the process is this:
if(UIGestureRecognizerStateEnded == [recognize state]){
[self preDownload:windowCounter Level:levelCounter ForPane:tagNumber];// Where this method is what gets the first image, and tries to set it to the imageView
[self downloadAllImagesWithWL:windowCounter Level:levelCounter ForPane:tagNumber]; //And this method goes and gets all the rest of the images
}
This is my preDownload method:
-(void)preDownload:(int)window Level:(int)level ForPane:(int) pane{
int guidIndex = [[globalGuids objectAtIndex:pane] intValue];
UIImage *img = [DATA_CONNECTION getImageWithSeriesGUID:[guids objectAtIndex:guidIndex] ImageID:counter Window:window Level:level];
if(pane==0){
NSLog(#"0");
[imageView3 setImage:img];
}else if(pane==1){
NSLog(#"1");
[imageView31 setImage:img];
}else if(pane==2){
NSLog(#"2");
[imageView32 setImage:img];
}else if(pane==3){
NSLog(#"3");
[imageView33 setImage:img];
}
}
So by separating this out into two different methods (there are no threads being implemented at this point, these methods are being called before all that) I was thinking that after the preDownload method completed, that the imageView would update, and then control would continue on down into the downloadAllImagesWithWL method, but that doesn't appear to be the case.
Am I missing something simple here? What can I do to update my GUI elements before that second method is through running?
You are right. However the viewn won't refresh until your code reaches runloop. You can do 2 things:
Make your downloadAllImagesWithWL method async, so it will return after you called it, your main thread reaches runloop, gui updates, and the download method will tell your logic through a callback when its done.
OR
A simplier hackier (and bad) solution would be to run runloop for some time before you call your download method. Something like this: [[NSRunloop currentRunLoop] runUnitlDate: [Date dateWithTimeIntervalSinceNow: 0.1]]; It will run runloop for 0.1 second.
When the image is set, the image view will mark itself as needing display. The actual display won't occur until the beginning of the next run loop. In OS X, you can use -display to draw the view immediately, but I don't think Apple created a public method to do this on iOS. However, if the next method simply creates the background thread, then it will return quickly and the display update will probably occur before the thread finishes.

How to switch sprite animation with cocos2d?

I have two animations of a goalkeeper with two different states (with ball and without ball). After keeper jumps I want to switch to a different action but I want to stay at the same frame index.
I mean if goalkeeper collides with the ball in the frame 19, the second action should start at frame 19 too.
I'm still not quite sure if I completely understand what your trying to do but I can help you with that action. If you want to run a check every frame you should do somethng like this
At the end of your scenes init method add:
` [self schedule: #selector(tick:) interval: 0.3f];
-(void)tick:(ccTime) dt {
if(CGRectIntersectsRect(goalKeeper.textureRect, ball.textureRect) {
[goalKeeper stopAction: myAction]; //where myAction is previously defined
} //now you can start the new action because you're using a timer, it'll be the same frame
That should do it. I hope that helps, if I still didn't quite answer your question feel free to clarify what in more vivid what exactly you're going for. `

iPhone : Best way to detect the end of UIImageView image sequence animation

We know that UIImageView has a very nice support for image sequence animation. We can easily create an array of UIImage objects, set the animationImages property, configure animation duration, repeat count etc. and then just fire. But there seems to be no way to know when this animation has ended.
Say I have ten images and then I want to run an animation (repeat count = 1) with them. And when the animation is over, I want to run some other code. What is the best way to know that animation has ended?
I already understand that I can create a NSTimer and schedule it to fire after animation duration. But you really cannot rely on timer if you need good precision.
So my question is, is there any better way to know that an UIImageView image sequence animation has ended without using the timer?
The code is something like this
myImageView.animationImages = images; // images is a NSArray of UIImages
myImageView.animationDuration = 2.0;
myImageView.animationRepeatCount = 1;
[myImageView startAnimating]
The isAnimating property on UIImageView should go to NO when it's done animating. It's not a formal property, though, so you can't set up observation on it. You can poll it on a fine-grained timer (like CADisplayLink's).
There's no "animation completed" delegate for this, if that's the sort of thing you're looking for. The timing can be variable based on loading delay of the images, etc, and no, there's no sure-fire way to know precisely when it's done.
The image animation stuff on UIImageView is a convenience, and not heavyweight enough to do serious animation work with. Consider rolling your own if you need that kind of precision.
I made this (method of my UIImageView subclass).
-(void)startAnimatingWithCallback:(UIImageViewAnimationCompletitionBlock) completitionCallback
{
[self startAnimating];
dispatch_queue_t animatingQueue = dispatch_get_current_queue();
dispatch_queue_t pollingQueue = dispatch_queue_create("pollingQueue", NULL);
dispatch_async(pollingQueue, ^{
while(self.isAnimating) { usleep(10000); }
dispatch_async(animatingQueue, ^{ if (completitionCallback) completitionCallback(); });
});
}
Simple usage:
[self.oneView fadeOut];
[self.otherView startAnimatingWithCallback:^
{
[self.oneView fadeIn];
}];
Furthermore I could recommend setting default image of the UIImageView (property image) on the first frame of the animation and changing it to the last frame just after launching the animation (startAnimating method). This way we avoid the ugly blick which can occur when the animation is finished but the callback is not invoked.

Heeelp! Debugger says "out of scope"!

I just cannot imagine what the hell the problem could be.
I made a pretty app, and decided to use only CALayers to "render".
When I saw that the changes in the position property gets animated, decided to implement a custom getter-setter "abstract" property called tanCenter to set the position without animating.
-(void) setTanCenter: (CGPoint) sentCenter
{
//Remove any transactions.
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
//Set position.
self.position = sentCenter;
[CATransaction commit];
//Set value.
tanCenter = sentCenter;
}
-(CGPoint) tanCenter { return tanCenter; }
Since I merged this into the project, it crashes without any "understandable" (for me) error message. I can see only those "out of scope"-s. I cant even get this tanCenter property NSLog-ged without crash.
Help me, Obi-Wan Kenobi; you're my only hope.
If you run in the debugger (Command-Y) and make sure you have global breakpoints enabled, the debugger should stop at the place where the crash occurred giving you an idea of what is nil or over-released.
hey I had the same problem till now. Finally I have found my bug after investigating 2 weeks of bug tracking (it really sucks)
maybe my problem helps you:
I started with a TableView that opens on click another view. So I created in:
-(void)tableView:didSelectRowAtIndexPath:
first the controller for the other view and set the value for a global variable:
SomeView *dtview = [[SomeView alloc] initWithNibName:#"SomeView" bundle:nil];
dtview.lblTitle = cl.textLabel.text; // cl is the cell
[self presentModalViewController:dtview animated:NO];
[dtview release];
So opened the other view and done much functions with much memory usage :)
When I after that close the other view and go back to the table and scroll some times the App terminates with the message "out of scope"
I searched really, really long to find out what was the effect. It seems that when the other view is released also the text of the first table is released.
After putting a copy to the call it worked for me:
dtview.lblTitle = [cl.textLabel.text copy];
For int and bool the first solutions works fine, because these aren't objects but for NSObject's you should copy the values to another view.