LGNetworkSprite *myImage = [LGNetworkSprite spriteWithFile:@"fbDefault.png"];
myImage.position = ccp(_screenSize.width * 0.75, _screenSize.height * 0.6);
[self addChild:myImage];
Then, you can set the URL of the image to download, and it will do the magic in the background:
Note: the local file name should be unique if you download different images.
[myImage loadFromURLString:imgUrl withLocalFileName:myID];
The code itself is quite simple (once you learn Steffen's teachings...):
// // LGNetworkSprite.h // CatchTheBall // // Created by Israel Roth on 5/12/12. // Based on Steffen Iterheim code: // http://www.learn-cocos2d.com/2012/02/cocos2d-webcam-viewer-part-2-asynchronous-texture-loading/ // Copyright 2012 Labgoo LTD. All rights reserved. // #import <Foundation/Foundation.h> #import "cocos2d.h" @interface LGNetworkSprite : CCSprite { } - (void) loadFromServerAddress: (NSString*) serverAddr fileName: (NSString *) fileName; - (void) loadFromURLString: (NSString *) urlString withLocalFileName: (NSString *) fileName; @end
And the m file:
// // LGNetworkSprite.m // CatchTheBall // // Created by Israel Roth on 5/12/12. // Based on Steffen Iterheim code: // http://www.learn-cocos2d.com/2012/02/cocos2d-webcam-viewer-part-2-asynchronous-texture-loading/ // Copyright 2012 Labgoo LTD. All rights reserved. // #import "LGNetworkSprite.h" #import "AsyncFileDownloadData.h" @implementation LGNetworkSprite -(NSString*) cacheDirectory { NSString* cacheDirectory = nil; NSArray* pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); if ([pathArray count] > 0) { cacheDirectory = [pathArray objectAtIndex:0]; } return cacheDirectory; } - (void) loadFromURLString: (NSString *) urlString withLocalFileName: (NSString *) fileName { NSString* localFile = [[self cacheDirectory] stringByAppendingPathComponent:fileName]; AsyncFileDownloadData* afd = [[[AsyncFileDownloadData alloc] init] autorelease]; afd.url = [NSURL URLWithString:urlString]; afd.localFile = localFile; [self performSelectorInBackground:@selector(downloadFileFromServerInBackground:) withObject:afd]; } -(void) logError:(NSError*)error { if (error) { CCLOG(@"%@: %@", error, [error localizedDescription]); } } -(void) downloadFileFromServerInBackground:(AsyncFileDownloadData*)afd { NSError* error = nil; NSData* data = [NSData dataWithContentsOfURL:afd.url options:NSDataReadingMappedIfSafe error:&error]; [self logError:error]; [data writeToFile:afd.localFile options:NSDataWritingAtomic error:&error]; [self logError:error]; // wait until done in this case means that the background thread waits for completion of the task // manipulating or creating sprites must be done on the main thread [self performSelectorOnMainThread:@selector(updateTexturesWithAsyncData:) withObject:afd waitUntilDone:NO]; } -(void) updateTexturesWithAsyncData:(AsyncFileDownloadData*)afd { [self updateTexturesFromFile:afd.localFile]; } -(void) updateTexturesFromFile:(NSString*)file { CCTextureCache* texCache = [CCTextureCache sharedTextureCache]; [texCache addImageAsync:file target:self selector:@selector(asyncTextureLoadDidFinish:)]; } -(void) asyncTextureLoadDidFinish:(CCTexture2D*)texture { CCTextureCache* texCache = [CCTextureCache sharedTextureCache]; [texCache removeTexture:self.texture]; CGSize prevSize = [self contentSize]; self.texture = texture; CGSize size = [texture contentSize]; [self setTextureRect:CGRectMake(0.0f, 0.0f, size.width,size.height)]; [self setScale:prevSize.width / size.width]; } @end
Note: Since I am updating the sprite itself, I do not need to keep the sprite tag. Also, I am using the Library/Caches directory to keep the local file. I think it is the right thing to do (in face, Apple will reject your app if you save to the Documents directory files that should not be there unless you mark them specifically).
Thank you Steffen, and to all of you doing cocos2d - go get yourself some help by purchasing Steffen's book here:
Hi I noticed,
ReplyDeleteloadFromServerAddress
and #import "AsyncFileDownloadData.h" is missing...
But thanks!
there are a few mistakes in the code, but they are obvious after pasting them...
ReplyDeleteanyway, what i a good thing to add (which I did) is to create the image to load based on the device - this way you can use a template image on the device (4 sizes for 4 devices) and it will load the correct image to replace it. otherwise you might get unexpected behavior in image sizes (like stretching)
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
if( CC_CONTENT_SCALE_FACTOR() == 2 )
// ipadhd
urlString = [NSString stringWithFormat:@"%@ipadhd",urlString];
else
// ipad
urlString = [NSString stringWithFormat:@"%@ipad",urlString];
}
else
{
if( CC_CONTENT_SCALE_FACTOR() == 2 )
// iphone hd
urlString = [NSString stringWithFormat:@"%@hd",urlString];
else
// iphone
urlString = [NSString stringWithFormat:@"%@",urlString];
}
Thanks for your comments. The import of AsyncFileDownloadData is from Stefan's original post mentioned in the text above.
ReplyDelete