How to scale Cocos2d app to iPhone 5 screen? - iphone

I have a Cocos3d v1.01 app and I am currently making it try to fit the iPhone 5 full screen.
By simply stretching the background is enough for most screens as it is just a pattern that fills the screen and no need to change any UI parts, however on just one of the screens I am struggling to change.
This is the code part I believe to set the background for that;
-(void)animations
{
AppDelegate *app=(AppDelegate *)[[UIApplication sharedApplication]delegate];
CGSize size = [[CCDirector sharedDirector] winSize];
NSMutableArray *bodyanimframeBuddyBack =[[NSMutableArray alloc]init];
for(int j = 1;j<=4;++j)
{
[bodyanimframeBuddyBack addObject:[[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:[NSString stringWithFormat:#"shark_sea_waves5%d.png",j]]];
}
CCAnimation *BuddyAnimBack = [CCAnimation animationWithFrames:bodyanimframeBuddyBack delay:0.3f];
self.backgroundAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:BuddyAnimBack restoreOriginalFrame:NO]];
CCSprite *bg=[CCSprite spriteWithSpriteFrameName:#"shark_sea_waves51.png"];
bg.position=ccp(size.width/2, size.height/2);
[self addChild:bg];
[bg runAction:backgroundAction];
Is there a way of adjusting that ? I am guessing it is the bg.position part that would need changing to tell it whether it is iPhone5 or not?
Thanks in advance,
Chris

bg.scaleX = size.width / bg.contentSize.width;
This will stretch the bg width to match the screen width.

Why can't you place seperate background for iPhone5..just like you did for iPad.
#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)
#define TEX_MM_BG (IS_IPHONE5) ? ( #"shark_sea_waves51-whd.png") : ( #"shark_sea_waves51.png")
-(void)setupBackground
{
CCSprite *bg = [CCSprite spriteWithFile:TEX_MM_BG];
bg.position = ccp(mS.width*0.5f, mS.height*0.5f);
[self addChild:bg z:-3 tag:kTagBackground];
}
//Also put these image in hard disk.
shark_sea_waves51.png //480x320
shark_sea_waves51-hd.png //960x640
shark_sea_waves51-whd.png //1136x640
shark_sea_waves51-ipad.png //1024x768
shark_sea_waves51-ipadhd.png //2048x1536

Related

Cocos2D - Why is my FPS so low? Single scene with tilemap

I wrote a simple game with Cocos2D where I have an animated sprite walking around a plain green field.
The walking sprite is 64x64px, the joystick comes from the Sneakyjoystick class, and the green field is composed of a 5-6 32x32 pixels made into a tilemap using Tiled. Using Tiled, I created a 50 x 50 tile map.
I'm getting 20-30 FPS and I'm not sure why. I decreased the tilemap size to 10x10 tiles and it shot up to 50-60 FPS. I don't know what to do?
Edit: I've added the initialization block for the gameplay layer. I'm testing on the simulator.
-(id) init
{
if( (self=[super init] ))
{
self.tileMap = [CCTMXTiledMap tiledMapWithTMXFile:#"TileMap.tmx"];
self.background = [_tileMap layerNamed:#"Background"];
self.meta = [_tileMap layerNamed:#"Meta"];
self.topLayer = [_tileMap layerNamed:#"TopLayer"];
_topLayer.visible = YES;
_background.visible = YES;
_meta.visible = YES;
[self addChild:_tileMap z:-1];
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:#"male_walkcycle.plist"];
sceneSpriteBatchNode = [CCSpriteBatchNode batchNodeWithFile:#"male_walkcycle.png"];
[self addChild:sceneSpriteBatchNode z:0];
CCTMXObjectGroup *objects = [_tileMap objectGroupNamed:#"Objects"];
NSAssert(objects != nil, #"'Objects' object group not found");
NSMutableDictionary *spawnPoint = [objects objectNamed:#"SpawnPoint"];
NSAssert(spawnPoint != nil, #"SpawnPoint object not found");
int x = [[spawnPoint valueForKey:#"x"] intValue];
int y = [[spawnPoint valueForKey:#"y"] intValue];
Caster *casterPlayer = [[[Caster alloc] init] initWithSpriteFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"male_walkcycle_19.png"]];
casterPlayer.position = ccp(x, y);
casterPlayer.joystick = nil;
[sceneSpriteBatchNode addChild:casterPlayer z:1000 tag:kCasterTagValue];
[casterPlayer release];
CCSprite *sprite = [CCSprite node];
CGSize size = CGSizeMake(50,50);
GLubyte *buffer = malloc(sizeof(GLubyte)*4);
for (int i=0;i<4;i++) {buffer[i]=255;}
CCTexture2D *tex = [[CCTexture2D alloc] initWithData:buffer pixelFormat:kCCTexture2DPixelFormat_RGB5A1 pixelsWide:1 pixelsHigh:1 contentSize:size];
[sprite setTexture:tex];
[sprite setTextureRect:CGRectMake(0, 0, size.width, size.height)];
free(buffer);
sprite.position = ccp(x, y);
sprite.visible = NO;
[self addChild:sprite z:5 tag:debugBoxTagValue];
[self setViewpointCenter:casterPlayer.position];
[self scheduleUpdate];
}
return self;
}
I'm testing on the simulator.
I can't believe how often I need to repeat this:
Ignore the Simulator!
The Simulator is not an actual iOS device. It runs on your Mac. It has more memory and CPU power available. At the same time its rendering performance is severely limited because it's not hardware accelerated rendering, it's a software renderer.
Even the fastest 2012 iMac can't run scenes at 60 fps on the iPad or iPhone Retina Simulator. On the iPad Retina Simulator you'll be lucky to get 20 fps.
Moreover, developers are the only people ever to run their Apps on the Simulator. Your users, not even your testers, will be using the Simulator to run your app. They'll be using an actual device.
Any time spent optimizing performance on the Simulator is nothing but a complete waste of time. This generally applies to any issue that only occurs on the Simulator.
Test on a device! Every issue only observed on the iOS Simulator is moot, void, invalid, and utterly irrelevant, especially performance.

Setting frame of CCTexture to fit into a predefined frame CCSprite

I am downloading an image from server and displaying it on game scene. I am able to get the CCTexture2D of the image from server and display it on game scene. The problem is that the image from server may vary in size. But I have to display that image on to a predefined frame CCSprite.
CCSprite *temp = [CCSprite spriteWithTexture:[[CCTexture2D alloc] initWithImage:[UIImage imageWithData:data] resolutionType:kCCResolutioniPhoneFourInchDisplay]];
CCRenderTexture *test=[CCRenderTexture renderTextureWithWidth:70 height:70]; //set proper width and height
[test begin];
[temp draw];
[test end];
UIImage *img=[test getUIImageFromBuffer];
sprite_Temp =[CCSprite spriteWithCGImage:img.CGImage key:#"1"];
sprite_Temp.tag = K_TagUserImage;
sprite_Temp.scale=1;
sprite_Temp.position=ccp(432,273);
[self addChild:sprite_Temp z:1];
I am using this code to resize the CCTexture2D to predefined frame CCSprite. But the image gets cropped to the desired frame which is not wanted. Can someone tell me how to get the original image from server to desired frame without getting cropped. Thanks.
try :
CCSprite *temp = [CCSprite spriteWithTexture:[[CCTexture2D alloc] initWithImage:[UIImage imageWithData:data] resolutionType:kCCResolutioniPhoneFourInchDisplay]];
float scaleX = 70./temp.contentSize.width;
float scaleY = 70./temp.contentSize.height;
// if you want to preserve the original texture's aspect ratio
float scale = MIN(scaleX,scaleY);
temp.scale = scale;
// or if you want to 'stretch-n-squeeze' to 70x70
temp.scaleX = scaleX;
temp.scaleY = scaleY;
// then add the sprite *temp
usual disclaimer : not tested, done from memory, beware of divides by 0 :)

Putting two backgrounds one after the other in objective-c iphone game?

Hi I am creating an iphone game
in my game layer, I have two identical background images but I want them to go one after the other.
Once the game animal (eg a penguin) crosses the first background, I want the first background to go after the second one-- becoming a continuous background until the game is over.
I have tried everything--- for loops, while loops and such but nothing seems to work
Does anyone have an idea for how I could go about doing this?
Thank you for any help you can provide me.
this is all I have so far after many different tries
- (id) init
{
if((self = [super init]))
{
for ( int x = 0; x < 10000000; ++x)
{
CCSprite *bg = [CCSprite spriteWithFile:#"level1.png"];
[bg setPosition:ccp(160,240)];
ccTexParams params = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
[bg.texture setTexParameters:&params];
[self addChild:bg z:0];
CCSprite *bg2 = [CCSprite spriteWithFile:#"level1.png"];
[bg2 setPosition:ccp(320,480)];
ccTexParams param = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
[bg2.texture setTexParameters:&param];
[self addChild:bg z:0];
}
If the backgrounds are the identical you don't actually need 2 images, you can just set the texture rect position of the one and it will continuously move. If you call moveBackground on a timer or in the update method it will continually scroll.
-(void)init
{
if((self=[super init]))
{
background = [CCSprite spriteWithFile:#"background.png"];
ccTexParams params = {GL_LINEAR,GL_LINEAR,GL_REPEAT,GL_REPEAT};
[background.texture setTexParameters:&params];
[self addChild:background z:0];
}
}
-(void)moveBackground
{
// Scroll background 5 pixels to the left
int speed = 5;
background.textureRect = CGRectMake(background.textureRect.origin.x-speed,
background.textureRect.origin.y,
background.textureRect.size.width,
background.textureRect.size.height);
}

Parallax Scrolling for the Endless Game background using cocos2D

I am newbie programmer in cocos2D.... I wanted to create the Endless Background using the Parallax Scrolling.. I am trying to learn the Parallax but it doesn't update with the time and sprites doesn't keep on rotating from top to bottom! The snippet i tried is as below
-(id) init
{
if((self = [super init]))
{
CGSize wSize = [CCDirector sharedDirector].winSize;
self.isTouchEnabled = YES;
CGPoint topOffset = CGPointMake(wSize.width, 0);
CGPoint midOffset = CGPointMake(wSize.width/2,0);
CGPoint downOffset = CGPointZero;
CCSprite *para1 = [CCSprite spriteWithFile:#"Default.png"];
CCSprite *para2 = [CCSprite spriteWithFile:#"Icon.png"];
CCSprite *para3 = [CCSprite spriteWithFile:#"Default.png"];
CCSprite *para4 = [CCSprite spriteWithFile:#"Icon.png"];
paraNode = [CCParallaxNode node];
[paraNode addChild:para1 z:1 parallaxRatio:CGPointMake(0.5f, 0)
positionOffset:topOffset];
[paraNode addChild:para2 z:2 parallaxRatio:CGPointMake(1, 0) positionOffset:topOffset];
[paraNode addChild:para3 z:4 parallaxRatio:CGPointMake(2, 0) positionOffset:midOffset];
[paraNode addChild:para4 z:3 parallaxRatio:CGPointMake(3, 0) positionOffset:downOffset];
[self addChild:paraNode z:0 ];
[self scheduleUpdate];
}
return self;
}
-(void) update : (ccTime) dt
{
//Need to move the Parallax Node with the repetition of the background
}
This is the Implementation file... I am stuck here for moving the contiunous moving of the background in the Horizontal or Portrait mode.
Thanks for the Help in Advance
CCParallaxNode doesn't support endless scrolling, unless you modify its code. I have an example for endless parallax scrolling in my Learn Cocos2D book. From that link you can also download the book's source code where you'll find the parallax class in chapters 6 to 8.
I have created a simple class named ParallaxManager which is capable for creating infinite parallax effect for both small sprite like small cloud
as well large layer sprite like grass.
You can find out the complete project from GitHub.

Multiple animations and textures with Cocos2d - How to remove texture from memory?

I am writing an application where you push different buttons and a character gets animated. The thing is that I have many images, so I need to use one texture for each animation. Therefore I need to release sprite sheet and frame cash, but it does not seem to be working. Memory gets allocated more and more until the app crashes. Here is the code:
// **** DEFINE THE ANIMATION - EATING 1: ****
// Create a sprite sheet with all the images
CCSpriteSheet *spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"Eating4.png"];
// This loads an image of the same name (but ending in png), and goes through the
// plist to add definitions of each frame to the cache.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"Eating4.plist"];
[self addChild:spriteSheet];
///[self addChild:spriteSheet2];
// Load up the frames of our animation
NSMutableArray *eating1AnimFrames = [NSMutableArray array];
for(int i = 0; i <= 50; ++i) {
if (i<=9){
[eating1AnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"Eating4_000%d.png", i]]];
}
else if (i>9) {
[eating1AnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"Eating4_00%d.png", i]]];
}
}
CCAnimation *eatingAnim = [CCAnimation animationWithName:#"eating" delay:0.05f frames:eating1AnimFrames];
// Create a sprite for the mouse
CGSize winSize = [CCDirector sharedDirector].winSize;
self.mouse = [CCSprite spriteWithSpriteFrameName:#"Eating4_0000.png"];
_mouse.position = ccp(winSize.width/2+20, winSize.height/2);
// Adjust the size of the Sprite:
[_mouse setScaleX: 1];
[_mouse setScaleY: 1];
//self.eatingAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:eatingAnim restoreOriginalFrame:NO]];
self.eatingAction = [CCAnimate actionWithAnimation:eatingAnim restoreOriginalFrame:NO];
[spriteSheet addChild:_mouse];
[_mouse runAction:_eatingAction];
I try to release memory like this:
[[CCTextureCache sharedTextureCache] removeAllTextures];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCTextureCache sharedTextureCache] removeAllTextures];
You don't want to do this! This removes all textures from memory, then reloads all of them that are still in use or the next time they are used. This causes a significant overhead and it's generally bad for your game's performance.
Instead, remove only the texture you need to remove by calling:
[[CCTextureCache sharedTextureCache] removeTexture:tex];
For this to work, you will also have to remove (release) all references to the animation from the Cocos2D node hierarchy.
Calling removeUnusedTextures would be a better choice for clearing up memory used by unused textures:
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
Or you can ask use CCDirector::purgeCachedData that does the same thing internally:
[[CCDirector sharedDirector] purgeCachedData];