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.
Related
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.
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...
Hello again (I thank you all for your previous invaluable help).
The new issue: I am working up physics simulation but have encountered a problem with a toy version. All it does is draw a random rectangle on the iPhone/Touch screen each time NSStimer timer calls the tick method. I've indexed these calls by int frameCount. What one sees is two sets of images gradually building up: one set for the even frames, another for the odd. I validated this by drawing frameCount to the screen with the even and odd counts in slightly different positions. Thus one sees the counts blinking back and forth synchronously with the image in the frame. The abbreviated code is below. I appreciate any suggestions you might have. It seems to me that there must be two offscreen buffers. But I'm in the dark here:-) And even if this is true, I don't know how to merge them, or copy one to the other.
#define MAXFRAMES 1000
// Relevant parts of implemenation of FooBar, a subclass of UIView:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
// Start a timer that will call the tick method of this class
// 30 times per second -- slowed way down for diagnostics
timer = [NSTimer scheduledTimerWithTimeInterval:(3.0/1.0)
target:self selector:#selector(tick) userInfo:nil repeats:YES];
frameCount = 0;
self.clearsContextBeforeDrawing = NO;
NSLog(#"frame initialized");
}
return self;
}
- (void)tick
{
// Tell the view that it needs to re-draw itself
if (frameCount < MAXFRAMES) {
[self setNeedsDisplay];
frameCount++;
}
}
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Draw a random rectangle with CGContextFillRect
// after calling CGContextSetRGBFillColor
// Both called with suitable random parameters
// Draw the frameCount for diagnostic purposes
}
The number of buffers that a UIView might use in its drawing layer is unspecified. If you want to copy drawings, you should draw from and into your own CG drawing context(s), and then use or draw your result into an image that you can use as a view's CALayer contents.
I need a way to create a collide effect, without the actual collision between the two images. Let me explain in more detail... If I have one fixed image and one image that is moving both images are on the same x coordinate at different positions. Basically I want the images appear to be colliding.I would want to run a check on the moving image like this...
If (front of moving image is clear)
{[move forward];}
else
{[stop];}
How would I implement this in code??? So that right before the moving image collides into the fixed image it stops, so that they appear to have collided.This check would also be running on a 1/60 NSTimer.
Any advice is welcome. Thank you.
Assuming the object is moving from the left
#define PIXELS_PER_FRAME 1
-(CGFloat) getCurrentX:(UIImage*)image
{
return image.frame.origin.x + image.frame.size.width;
}
-(void) moveImageToStableImage
{
CGFloat xTarget = stableImage.frame.origin.x;
if([self getCurrentX:movingImage] < xTarget)
{
movingImage.frame.origin.x += PIXELS_PER_FRAME;
[self performSelector:#selector(moveImageToStableImage) withObject:nil afterDelay:1.0/60];
}
}
But truth be told in this situation you would probably just be better off using an animation
I am developing an iPhone game in which birds bounce.
I have set up the images for animating the wings of the flying bird like this:
[imgBird[i] setAnimationImages:birdArrayConstant];
[imgBird[i] setAnimationDuration:1.0];
[imgBird[i] startAnimating];
Now how I make the bird move is to use an NSTimer to fire every 0.03 seconds which adds/subtracts 1 from the x or y coordinate from imgBird[i].center.
I learnt about doing it like this from here. http://icodeblog.com/2008/10/28/iphone-programming-tutorial-animating-a-ball-using-an-nstimer/
But the issue is the birds slow down as soon as another timer (for moving my ship the same way) fires and returns back to original speed as i stop moving the ship.
Is there a better way to keep the bird moving except NSTimer?
The movement of bird is an infinite loop.
You will need to import CoreGraphics and the QuartzCore frameworks into you project.
Add these lines to the top of your file.
#import <QuartzCore/QuartzCore.h>
#import <CoreGraphics/CoreGraphics.h>
...
UIImageView *bird = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bird2.png"]];
CALayer *b = bird.layer;
// Create a keyframe animation to follow a path to the projected point
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"scale"];
animation.removedOnCompletion = NO;
// Create the path for the bounces
CGMutablePathRef thePath = CGPathCreateMutable();
// Start the path at my current location
CGPathMoveToPoint(thePath, NULL, bird.center.x, bird.center.y);
CGPathAddLineToPoint(thePath, NULL,20, 500.0);
/* // very cool path system.
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL,74.0,74.0);
CGPathAddCurveToPoint(thePath,NULL,74.0,500.0,
320.0,500.0,
320.0,74.0);
CGPathAddCurveToPoint(thePath,NULL,320.0,500.0,
566.0,500.0,
566.0,74.0);
*/
//animation.rotationMode = kCAAnimationRotateAuto;
animation.path = thePath;
animation.speed = 0.011;
//animation.delegate = self;
animation.repeatCount = 1000000;
// Add the animation to the layer
[b addAnimation:animation forKey:#"move"];
Hope that helps a bit.
From your question it seems you are using more than one timer. Use just one to animate all your objects. Somewhere, when your app starts, have this:
[NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(mainLoop:) userInfo:nil repeats:YES];
Then, in main loop, something like this:
- (void)mainLoop:(NSTimer *)timer
{
// compute new position for imgBirds
for (int i=0; i<kBirdCount; i++)
{
imgBirds[i].center = CGPointMake(somex, somey);
}
// compute new position for ship
ship.center = CGPointMake(somex, somey);
}
Also, you should compute somex and somey as a function of your timer interval. In that way, if you change it, your animation will still look the same.
You'll want to use Core Animation instead of manually moving the birds. Take a look at CAAnimation in the docs. You basically set up an animation, the path you want it to move along, and just tell it to run. It'll take care of the rest. It also has support for easing which will make the pace slow down and accelerate so it looks more natural.