How can I use more than one sprite sheet? cocos2d/iPhone - iphone

I'm trying to use more than one sprite sheet because I can't fit them all on one and having two makes my ordering them easier (sprite sheet one sprites are in the back and have a lower zOrder). I'm currently doing:
spriteSheet1 = [[CCSpriteSheet spriteSheetWithFile:#"spriteSheet1.png" capacity:3] retain];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"spriteSheet1.plist"];
[self addChild:spriteSheet1];
spriteSheet2 = [[CCSpriteSheet spriteSheetWithFile:#"spriteSheet2.png" capacity:4] retain];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"spriteSheet2.plist"];
[self addChild:spriteSheet2];
CCSprite *sprite = [CCSprite spriteWithSpriteFrameName:#"sprite1.png"];
The last line crashes with the error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid spriteFrame for sprite' SIGABRT
Am I not allowed to cache more than one sprite sheet? If not, is there another efficient way to handle this?

If you create your spritesheets using Zwoptex, make sure you use the version of Zwoptex and cocos2d which support each other. Recently there have been major changes to Zwoptex and if you're using an older cocos2d version this might explain your crash.
In general the code you provided should work just fine, given that all the resource files haven been added to Xcode and are named properly. Keep in mind that the iOS devices are case-sensitive, if you try to load "spriteSheet1.plist" but the file is actually named "Spritesheet1.plist" it will also lead to errors (probably an assertion or crash).

Related

Audiostreamer on iOS - Using with ARC

I'm using matt gallagaher's AudioStreamer class. I've used it before in a project before ARC came along and it worked fine. When I added the class to a project which uses ARC, I came across lots of errors which I could fix by adding __bridge references etc...
So the app now runs, but when I start the streamer with [streamer start] I keep coming across this error which I don't know how to fix. The compiler stops at the function below in Audiostreamer.m with the error Thread 8: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0) - I don't know what to do from here...please help.
if (CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue) == false)
{
[self presentAlertWithTitle:NSLocalizedStringFromTable(#"File Error", #"Errors", nil)
message:NSLocalizedStringFromTable(#"Unable to configure network read stream.", #"Errors", nil)];
return NO;
}
I have exactly error with using FreeStreamer by muhku (good library, recommended).
Check that you give correct/not nulled url to AudioStreamer.
Give my StreamingKit library a go. It has the same functionality as AudioStreamer but is built with ARC and has quite a few additionally pieces of functionality.
https://github.com/tumtumtum/StreamingKit
I was getting the same problem, but I disable arc and now is working fine, the only problem that I got is that when I slide my slider I get a new value to seekToTime: , but is not playing starting from the new value. Any idea what that is ?
CoreAudio seems to work internally using exceptions, so if you have an exception breakpoint installed, this is what you will see. Just disable the breakpoints and it'll work.

Assertion Failure in -[CCSprite setTexture:]

I am having a problem with a cocos2d app for IPhone I am developing. The prolem comes out sometimes during a scene change. The app stucks and the console starts printing this statement:
Assertion failure in -[CCSprite setTexture:]
I would like you to suggest me the right way to debug it since the problem does not always happen and there is not a precise indication of where the bug might be.
Thank you in advance
... some hours after: The problem occurs after a memory warning. It its therefore due to the sprite cache which is flushed while an animation is exploiting a cached texture atlas and related sheet. What can I do to handle it?
I would set a breakpoint in [CCSprite setTexture:] and from there check the stack trace and go back to your offending call. Of course, this will only succeed in case the failure occurs.
In my cocos2d installation (0.9.5), asserts in setTexture can be:
NSAssert( ! usesBatchNode_, #"CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode");
// accept texture==nil as argument
NSAssert( !texture || [texture isKindOfClass:[CCTexture2D class]], #"setTexture expects a CCTexture2D. Invalid argument");
So you are doing either of those wrongly.
EDIT after you comment:
your appDelegate defines presumably:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[CCDirector sharedDirector] purgeCachedData];
}
try using:
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
instead of [[CCDirector sharedDirector] purgeCachedData]. Hope things will improve.

How do I build a game that only supports Game Center if it's available on the iPhone?

I'm about to begin building an iPhone game that will make use of Game Center Achievements and high scores, but I'd also like to have a version that works on iPhones that don't have Game Center (i.e. iOS version < 4.1). Can I have two versions of the same app in the app store, one for game center, one for without? Or should I design the app such that if the iPhone doesn't have Game Center, it won't make use of it, and if it does, it will make use of it?
I'm going to continue researching this, just thought I'd post this question and get some feedback in the meantime. Thanks so much!
Here's the definitive response I received from one of the Apple engineers...
"We'd recommend making one version of the app which dynamically detects whether Game Center is available and uses it (or not) based on that."
Maybe create a game without it, then create the capabilities for the game center, but disable them, and only enable them if they have the right version.
I am doing the same thing. If you have GameCenter capabilities, you can use the features. If you don't, you can't.
I would not program a game without and then add it later. In my case I disable Multiplayer for non-GC users.
Also, you may want your game to work if the device has GC capabilities, but the user cannot, for whatever reason, connect to GC currently.
You can use the following function to detect if the device supports Game Center:
BOOL isGameCenterAvailable()
{
// Check for presence of GKLocalPlayer API.
Class gcClass = (NSClassFromString(#"GKLocalPlayer"));
// The device must be running running iOS 4.1 or later.
NSString *reqSysVer = #"4.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);
return (gcClass && osVersionSupported);
}
However I found that a lot of people have not updated to iOS 4.1 or are naive about Game Center. The number of users in my game is quite small even though there are so many downloads. I was actually considering moving over to Open Feint which is very much easier to implement than Game Kit and also supports older devices.

Set device volume on iPhone

I'm writing an app that uses AVAudioPlayers to play sounds and I need the sounds to play at absolute MAX volume. Yes you can set the relative volume for an AVAudioPlayer, but if the user has the device volume turned down, the sound will still play quietly.
I know that Apple says that the device volume cannot be overridden, but yet the Alarm Clock apps out there somehow are able to do this - so there must be a way.
I believe that this can be done using Audio Queues using the call:
AudioQueueSetParameter(aq, kAudioQueueParam_Volume, 1.0);
But my code needs to use the AVAudioPlayer to play the sounds so I don't think this approach will be of any help.
There is also a way to use an undocumented function of MPVolumeView to accomplish this, but apparently someone already had an app rejected for using this method.
Any other ideas?
The comment from the anonymous for this site:
float volume;
[[MPMusicPlayerController applicationMusicPlayer] setVolume:volume];
does actually work.
I came across this:
MPVolumeView *volumeView1 = [[MPVolumeView alloc] initWithFrame:CGRectMake(4, 316, sk.size.width, sk.size.height)];
[volumeView1 sizeToFit];
[self.view addSubview:volumeView1];
[volumeView1 release];
I'm not entirely sure if it will work, but I believe it should. It seems you might have to modify the height and width

iPhone video buffer

I'm trying to build a video recorder without jailbreaking my iPhone (i've a Developer license).
I began using PhotoLibrary private framework, but i can only reach 2ftp (too slow).
Cycoder app have a fps of 15, i think it uses a different approach.
I tried to create a bitmap from the previewView of the CameraController, but it always returns e black bitmap.
I wonder if there's a way to directly access the video buffer, maybe with IOKit framework.
Thanks
Marco
Here is the code:
image = [window _createCGImageRefRepresentationInFrame:rectToCapture];
Marco
That is the big problem. So far i've solved using some temp fixed size buffers and detach a thread for every buffer when is full. The thread will save the buffer content in the Flash memory. Launching some heavy threads, heavy beacause each thread access the flash, will slow the device down and the refresh of the camera view.
Buffers cannot be big, because you will get memory warning, and cannot be small because you will freeze the device, because of too many threads and accesses to the flash memory at a time.
The solution resides in balancing buffer size and number of threads.
I haven't already tried to use sqlite3 db to store images binary data, but i don't if will be a better solution.
PS: to speed up class methods call, avoid the common solution [object method] because of how method call works, but try to get and save the method address as below.
From Apple ObjC doc:
"The example below shows how the procedure that implements the setFilled: method might be
called:
void (*setter)(id, SEL, BOOL);
int i;
setter = (void (*)(id, SEL, BOOL))[target methodForSelector:#selector(setFilled:)];
for ( i = 0; i < 1000, i++ )
setter(targetList[i], #selector(setFilled:), YES); "
Marco
If you're intending to ever release your app on the App Store, using a private framework will ensure that it will be rejected. Video, using the SDK, simply isn't supported.
To capture the video you can see when the Camera is active requires fairly sophisticate techniques, not exposed by any framework/lib out of the box.
I used a non documented UIWindow method to get the current displayed frame as CGImageRef.
Now it works successfully!!
If you would, and if i'm allowded, i can post the code that do the trick.
Marco