I have a big problem with my app.
I am few steps before the end of my app and today I wanted to add a background image.
My normal FPS is 180 during black background and when I added my background for iphone 4 sized 960/640 my FPS changed to 20-30 so its impossible to play. And next thing what happens is, when my player and enemy has a collision they stop their actions, but only if there is my background. I am using SpaceManager so maybe its because of its shapes. So does anyone know how to add background in another way in SpaceManager to do not slow my FPS? Here is the way I try to add Background:
-(id) init
{
CCSprite *background = [CCSprite spriteWithFile:#"Background.png"];
background.anchorPoint = ccp(0, 0);
[self addChild:background z:-1];
}
the most likely cause for the drop in fps is because the picture is designed for the retina display, and since it is a large file it slows down the app. the device which you are using also has an effect on how fast the game works, so if its slow only on a 3gs or something like that just drop support for it.
So my Objects are statit mass, so I dont have there [sm addcollision] but I have there this code
-(void) KolizeHraceSProtiHracem
{
if (player.position.x - enemy.position.x < 40 )
{
[enemy stopAllActions];
[player stopAllActions];
[player runAction:[CCMoveTo actionWithDuration:0.2 position:ccp(player.position.x + 40, 10)]];
[enemy runAction:[CCMoveTo actionWithDuration:0.1 position:ccp(enemy.position.x - 10, 10)]];
}
I dont think, this code is bad, because if I dont have a background this code works but if i do this code stops all actions.
Related
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.
I have a sprite sheet PNG sent to me by an artist. Inside the sprite sheet, there are 4 sprites, each 32x32, and they make an animation. I want to be able to have a CCSprite on screen, who goes through the animation. I've tried all kinds of things, but truth be told, I really just don't understand the concept of Sprite Sheets. I'm seeing all kinds of things around the web of needing property lists and such. All I got from my artist is a simple PNG.
Please help?
I also had this problem and this is the solution I came up with,
no plists and no Zwoptex needed,
but this assumes each frame is exactly 32x32 and perfectly aligned at 32 intervals.
#interface GameLevelLayer()
{
CCSpriteBatchNode *trexSheet;
int aniCount;
NSTimer *autoWalker;
}
#end
in your init or wherever add the spritesheet
trexSheet = [CCSpriteBatchNode batchNodeWithFile:#"dinosss.png"];
[self addChild:trexSheet];
aniCount=1;
Use an NSTimer to stop and Start an animation
-(void)stopWalker{
aniCount =1;
//set to start frame
[self.player setDisplayFrame:
[CCSpriteFrame frameWithTexture:trexSheet.texture rect:
CGRectMake(0,0,32,32)]];
if (autoWalker){
[autoWalker invalidate];
autoWalker = nil;
}
}
and to start...
-(void)startWalker{
if (!autoWalker){
[self walkimate];
//Change the timeInterval to adjust animation speed
autoWalker = [NSTimer scheduledTimerWithTimeInterval:0.15
target:self
selector:#selector(walkimate)
userInfo:nil
repeats:YES];
}
}
the looped function
-(void)walkimate{
///loop through animation
if (aniCount>4) {
///set to 0 because we add one at the end before the next call
aniCount =0;
}
//this finds the 32x32 pa
[self.player setDisplayFrame:
[CCSpriteFrame frameWithTexture:trexSheet.texture rect:
CGRectMake(32*i,0,32,32)];
aniCount++;
}
You can use Zwoptex tool to export spriteSheet with cocos2D plist. Its free tool and easy to use.
I'm trying to make my sprite have a shake effect. However, while the sprite does shake, the entire background turns black. Can anybody help me with this?
Here's the code that I've written to add the sprite to my layer along with the action that I run right after.
CCSprite * picture = [CCSprite spriteWithFile:#"picture.png"];
picture.position = ccp(winsize.width/4,
picture.contentSize.height * 0.8);
[self addChild:picture];
CCShaky3D * shake = [CCShaky3D actionWithRange:4
shakeZ:NO
grid:ccg(12, 12)
duration:0.5];
[picture runAction:shake];
Can anybody help me?
Have you enabled depth buffering of the EAGLView? Most 3D actions require depth buffering (GL_DEPTH_COMPONENT16_OES or GL_DEPTH_COMPONENT24_OES) to avoid visual artifacts. You may also have to use a 32-Bit frame buffer with alpha channels by using the kEAGLColorFormatRGBA8 instead of kEAGLColorFormatRGB565.
EAGLView is initialized in the app delegate class:
EAGLView* glView = [EAGLView viewWithFrame:[window bounds]
pixelFormat:kEAGLColorFormatRGBA8
depthFormat:GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:0
numberOfSamples:0];
I have an iOS game, and when a ball hits a target it explodes.
What would be the best way to animate this explosion?
If you're looking for something simple.
Make a series of images that animate the explosion. Add those to a UIImageView and start the animation. Something like this:
UIImage *image0 = [UIImage imageNamed:#"explosion0.png"];
UIImage *image1 = [UIImage imageNamed:#"explosion1.png"];
UIImage *image2 = [UIImage imageNamed:#"explosion2.png"];
UIImage *image3 = [UIImage imageNamed:#"explosion3.png"];
myImageView.animationImages = [NSArray arrayWithObjects:image0, image1, image2, image3, nil];
[myImageView setAnimationDuration:0.75f];
[myImageView startAnimation];
For a bouncing ball game, the Cocos2D game- and Box2d physics- (included with Cocos2D) engines are a great way to go.
Ray Wenderlich has three great tutorials on exactly what you want to do:
Intro to Box2D with Cocos2D Tutorial: Bouncing Balls
How To Create A Breakout Game with Box2D and Cocos2D Tutorial: Part 1
How To Create A Breakout Game with Box2D and Cocos2D Tutorial: Part 2
Once you get past the basics of working with Box2d objects, the key step is to create a Contact Listener (as described in the tutorials) which will tell you when you have a collision. Check (by iterating over contacts in your tick method) if the colliding objects are the ones you want for the explosion, and if so add them to a vector of objects to be destroyed (we can't do this while iterating over contacts or we will invalidate the iterator). Remember the coordinates of the collision and set a flag for explosion.
After exiting the loop destroy the bodies and run the explosion effect at the saved position.
Cocos2D has some very nice built-in explosion effects, and the one I am using for my project is CCParticleSun. You can find some screenshots of someone using this effect here. (The curiously named CCParticleExplosion just gave a lot of confetti flying around the screen.)
Here is the relevant portion from some preliminary code I have working, which is mostly from the tutorial. You will still need to do everything else, eg. create and set up your world and bodies in your init method, update positions, apply forces, and draw in your tick method, implement your Contact Listener class, etc. For all this refer to the tutorials.
std::vector<b2Body *>toDestroy;
std::vector<MyContact>::iterator pos;
CGPoint p;
bool explode = FALSE;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
if ((contact.fixtureA->GetBody() == _moonBody && contact.fixtureB->GetBody() == _moon2Body) ||
(contact.fixtureA->GetBody() == _moon2Body && contact.fixtureB->GetBody() == _moonBody)) {
NSLog(#"Moons collided!");
explode = TRUE;
p = CGPointMake(PTM_RATIO*(_moonBody->GetPosition().x + _moon2Body->GetPosition().x)/2.,PTM_RATIO*(_moonBody->GetPosition().y + _moon2Body->GetPosition().y)/2.);
if (std::find(toDestroy.begin(), toDestroy.end(), _moonBody) == toDestroy.end()) {
toDestroy.push_back(_moonBody);
}
if (std::find(toDestroy.begin(), toDestroy.end(), _moon2Body) == toDestroy.end()) {
toDestroy.push_back(_moon2Body);
}
}
}
std::vector<b2Body *>::iterator pos2;
for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
b2Body *body = *pos2;
if (body->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *) body->GetUserData();
[sprite.parent removeChild:sprite cleanup:YES]; }
world->DestroyBody(body);
}
if (explode)
{
explosion = [[CCParticleSun alloc]initWithTotalParticles:250];
explosion.texture = [[CCTextureCache sharedTextureCache] addImage:#"fire.png"];
explosion.autoRemoveOnFinish = YES;
explosion.startSize = 15.0f;
explosion.speed = 30.0f;
explosion.position = p;
explosion.duration = 1.0f;
[self addChild:explosion z:self.zOrder+1];
}
What you want, then, is a way to create a particle emission system. My suggestion is to use a CAEmitterLayer. Ray Wenderlich has a great tutorial: UIKit Particle Systems in iOS 5 Tutorial
iPhone Programming Tutorial: Animating a Game Sprite
If you need to make an explosion another alternative would to use Cocos2d and do:
CCParticleSun *anExplosion=[CCParticleGalaxy node];
[kk setPosition:ball.position];
[self addChild:anExplosion];
Not really an animation, also, from the question you don't seem to be using Cocos2d, but if you start using it you can do this...
I have gotten 0 response from the Cocos2D board so thought Id try here.
Ok. Im ripping out my hair over this. I did a complete re-haul of my code last night in hopes of fixing some iphone4 framerate issues. I created sprites in advance instead of doing some of the creation during the update methods. I only add them to the spritesheet now in the update method as needed.
However, this really didnt fix the issue. So I changed one thing out of curiosity. My main sprite sheet is 2048x2048 and contains 24 frames and one static frame. I used to pull my static image from the frames i generated using spriteWithSpriteFrameName. Instead I just decided to make another image file for it and create it from that. Framerate issue solved mostly...I dont understand why. I thought the texture was already in memory to begin with? Is anything wrong with my code?
circleSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"spritesheetbase.png"];
//Load Note Animations
for (int i = 0; i < 25; i++)
{
int x = i % 5;
int y = i / 5;
CCSpriteFrame* frame = [[CCSpriteFrame alloc] initWithTexture:circleSpriteSheet.textureAtlas.texture rect:CGRectMake(x * 200, y * 200, 200, 200)];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFrame:frame name:[NSString stringWithFormat:#"noteFrame%d.png", i]];
[frame release];
}
CCSprite *s = [CCSprite spriteWithFile:#"staticRing.png"];
//CCSprite *s = [CCSprite spriteWithSpriteFrameName:#"noteFrame0.png"]; <--- Old way I used to create it
If someone could help I would be in your debt! I am so confused.
I have found performance issues when building/run in debug mode. Try building/run in release mode and see if that happens to fix your frame-rate issues. This resolved a similar frame-rate issue under this post:
water effect in cocos2d
I hope it happens to solve it for you too!