I have 4 sprites, every time the game starts it would randomly choose 1 from the 4 sprites to be the main sprite.
How can I do this?
I know I would need to use arc4random
The easiest way would be -- First name you image (.png) files with some numbers for e.g. sprite1.png, sprite2.png ....
int rndSprtNum = (arc4random() % 4) + 1;
CCSPrite *mainSprite = [CCSprite spriteWithFile:[NSString StringWithFormat:#"sprite%d.png",rndSprtNum]];
mainSprite.position = ccp(x,y);
[self addChild:mainSprite];
This way you no need to take a mutable array etc. Hope this helps.
First of all you are add all sprite in NSMutableArray as below code.
Allocate Array
NSMutableArray *AryT = [[NSMutableArray alloc]init];
Differnt sprite
CCSprite *torpedoOne1 = [CCSprite spriteWithFile:#"A#2x.png"];
CCSprite *torpedoOne2 = [CCSprite spriteWithFile:#"B#2x.png"];
CCSprite *torpedoOne3 = [CCSprite spriteWithFile:#"C#2x.png"];
Add All This sprite in define Array
[AryT addObject:torpedoOne1];
[AryT addObject:torpedoOne2];
[AryT addObject:torpedoOne3];
Take Random number from array
int RandomIndex = arc4random_uniform(AryT.count);
Randomaly sprite
[self addchild:[AryT objectAtIndesx:RandomIndex]];
Here's another approach, in case you don't want to rename your files you can simply put their names in an array:
NSString *names[4] = {#"RedSprite.png", #"GreenSprite.png", #"YellowSprite.png", #"PurpleSprite.png"};
CCSprite *sprite = [CCSprite spriteWithFile:names[arc4random_uniform(4)]];
[self addChild:sprite];
Related
I have some sprite-sheet that i have to animate forever , and i would like to add it as a CCLayer
to my scene .
Later on , i have to move this whole animation sprite on the screen.
So, for example, i have some animation of a dog walking, from sprite sheet, this one is running forever. than i want to be able to move this dog on screen while animating.
What is the best way to do this ? (or the right way)
This is how i animate the frames :
CCSprite *boom;
boom = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:#"%#_00000.png",file]];
boom.position=touch;
[self addChild:boom];
NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 0; i < 5; i++)
{
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:
#"%#_0000%i.png",file,i]];
[animFrames addObject:frame];
}
CCAnimation* boxAnimation = [CCAnimation animationWithSpriteFrames:animFrames delay:0.075f];
CCAnimate * boxAction = [CCAnimate actionWithAnimation:boxAnimation];
CCAction *call=[CCCallBlock actionWithBlock:^{[self removeFromParentAndCleanup:YES];}];
CCAction * sequence=[CCSequence actions:boxAction,[CCHide action],call,nil];
[boom runAction:sequence];
return self;
How would you move this whole thing ?
There are a few ways to do this. If you are not preocupied with collision detection, then one way would be to :
CGPoint egressPosition = ccp(0,0); // figure this out in your app
float moveDuration = 1.5f ; // whatever time you compute for desired speed and distance
id move = [CCMoveTo actionWithDuration:moveDuration position:egressPosition];
id spawn = [CCSpawn actions:sequence,move,nil];
[boom runAction:spawn];
otherwise, using your code as is
[self schedule:#selector(moveBox:)]; // optional, you could do this in update method
[boom runAction:sequence];
-(void) moveBoom:(CCTime) dt {
CGPoint newPosition;
delta = ccp(dt*speedX,dt*speedY); // crude , just to get the idea
newPosition = ccpAdd(boom.position,delta);
// here you can figure out collisions at newPosition before the collision
// and do whatever seems appropriate
boom.position = newPosition;
}
I am adding sprites to a NSMutableArray like this:
NSMutableArray * movableSprites;
NSString *image = [images objectAtIndex:3];
CCSprite *sprite = [CCSprite spriteWithFile:image];
sprite.position = ccp(AREA_A2_X2 - (i * 56), AREA_A3A5A4_Y);
[self addChild:sprite];
[movableSprites addObject:sprite];
So far so good.
Now I am trying to detect collisions among them. The user is able to move the sprites around, but I want the sprites to be blocked by one another.
So, when I am working on the translation of them I want it to happen there. By the way, is it the best place to go for a collision detection?
- (void)panForTranslation:(CGPoint)translation {
if (selSprite) {
I intent to do the following in a loop:
CGRect rect1 = [SpriteUtilities positionRect:selSprite];
CGRect rect2 = [SpriteUtilities positionRect:EVERY_OTHER_SPRITE];
if (!CGRectIsNull(CGRectIntersection(rect1, rect2))) {
//handle collision
}
The thing is... I didn't find a NSMutableArray method to retrieve the sprite object.
Thank you for your help.
Ok... after a few more reading I got into this:
CCSprite *toCollide;
for (int i = 0; i < [movableSprites count]; i++){
toCollide = [movableSprites objectAtIndex:i];
...
Thanks anyway!! Hope it helps somebody else!
I am having an issue in Kobold2d-Cocos2d regarding the layering of CCSprite objects.
All of my code works fine, except that a certain tile (a CCSprite), held in an array, is supposed to always be on top. The code has an array of references to CCSprites (Tile) and goes along all the tiles swapping them with each other. So element 0 and 1 switch (in the array and on screen using a moveTo), then the new element 1 and 2 switch, then the new element 2 and 3 switch etc...
The idea is the Tile at the start of the chain leapfrogs to the front of the line!
I always want that first tile to stay on top, but it isn't. It only does sometimes (when it's above the other Tile it's switching places with on the screen, implying it was added later)
Here's the CCScene code in question:
//reference first CCSprite in array -works
Tile *firstTile = [tileArray objectAtIndex:(int)[[[selTracker oldSelectionArray] objectAtIndex:0]element]];
//How much time should be spend leapfrogging each two tiles broken up over 1 second.
float intervalTime = .75/(float)[[selTracker oldSelectionArray] count];
//Will use this to count each tile set we leapfrog
float currentPass = 0;
//TODO: destroy this wrapper class that holds number, use NSNumber. Fine for now.
SimpCoord *lastCord;
//Make moving sprite higher than all others. DOESN'T WORK?
[self reorderChild:firstTile z:100];
//Loop through all the tiles that were selected
for (SimpCoord *coord in [selTracker oldSelectionArray])
{
if (lastCord)
{
//Queue each tile to leapfrog with our moving tile
if ([self respondsToSelector:#selector(switchTilesFuncWrapper:)])
{
NSArray *argArray = [NSArray arrayWithObjects:
[NSNumber numberWithInt:[lastCord element]],
[NSNumber numberWithInt:[coord element]],
[NSNumber numberWithFloat:(intervalTime)], nil];
[self performSelector:#selector(switchTilesFuncWrapper:) withObject:argArray afterDelay:((currentPass) * intervalTime)];
}
currentPass++;
}
lastCord = coord;
}
`
That calls the following code by the way that actually swaps the two Tiles (I excluded the function wrapper middleman I needed for multiple arguments):
(In case it makes it easier to understand, rather than use a 2d array to hold all my tiles I just only draw 10 per line, hence the tileCoordsByElement method - but that shouldn't be important)
//
// Switch two tiles on the screen and in the holder array
// onlySwitchArray pass in true to only swap tiles in organization array
// but provide no animation.
- (void) switchTiles:(NSNumber*)elePosVal secPos:(NSNumber*)elePos2Val timeToSwitch:(NSNumber*)time
{
float switchTime = [time floatValue];
int elePos = [elePosVal intValue];
int elePos2 = [elePos2Val intValue];
Tile *tmpTile = [tileArray objectAtIndex:elePos];
Tile *tmpTile2 = [tileArray objectAtIndex:elePos2];
//Move actual tiles on screen
//Move Tile is elePos (1) to elePos2
int curCol = 0;
int curRow = 0;
[self tileCoordsByElement:elePos2 x:&curRow y:&curCol];
CCSequence *tmpTile1_Seq = [CCSequence actions:
[CCMoveTo actionWithDuration:switchTime position:ccp((curRow-1)*tmpTile.width + tmpTile.width/2,
(curCol-1)*tmpTile.height + tmpTile.height/2)], nil];
[tmpTile runAction:[CCRepeat actionWithAction:tmpTile1_Seq times:1]];
//Move Tile that is elePos2 to elePos(1)
[self tileCoordsByElement:elePos x:&curRow y:&curCol];
CCSequence *tmpTile1_Seq2 = [CCSequence actions:
[CCMoveTo actionWithDuration:switchTime position:ccp((curRow-1)*tmpTile.width + tmpTile.width/2,
(curCol-1)*tmpTile.height + tmpTile.height/2)], nil];
[tmpTile2 runAction:[CCRepeat actionWithAction:tmpTile1_Seq2 times:1]];
//Swap tiles in array second
[tileArray replaceObjectAtIndex:elePos withObject:tmpTile2];
[tileArray replaceObjectAtIndex:elePos2 withObject:tmpTile];
}
Alright.
I'm aware some things I'm doing aren't exactly efficient and if it's not relevant I don't really want to focus to heavily on them. This is just a learning exercise for me - I just honestly don't understand why the origional Tile won't stay on top.
I've tried every resource or example I possibly can find for answers (sample included code, tutorials online, terrible book I bought, random somewhat related stackoverflow articles) and I'm getting nothing :\
In case it matters this is how I origionally added my sprites to the scene:
//Set up A CCSpriteBatchNode to load in pList/pngs of images
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"zAtl_BasicImages_64.plist"];
nodeBasicImages = [CCSpriteBatchNode batchNodeWithFile:#"zAtl_BasicImages_64.png" capacity:100];
//Initialize array used to track tiles in scene
tileArray = [[NSMutableArray alloc] init];
for (int i = 0; i<100; i++)
{
Tile *tmpTile = [[Tile alloc] init];
[tileArray addObject:tmpTile];
[self reorderChild:tmpTile z:-1];
}
Note: I checked and the zOrder on both Tiles is correct on the line before the MoveTo animation begins.
I added my sprites not to my layer, but to an image node because I was using a Sprite Atlas. So I was trying to access sprites that weren't even there. - I'm a new user so going to have to wait 8 hours until I can close. Peace. Why it didn't throw an error I'll never know.
How To Have The Same Sprite In Multiple Locations Cocos2d Please Help
I have searched all over and cannot find answer
Just create multiple Sprites (CCSprite instances). They can all use the same texture (bitmap-file).
CCSprite * mySprite1;
CCSprite * mySprite2;
CCSprite * mySprite3;
// create several sprites from the same bitmap file
mySprite1 = [CCSprite spriteWithFile:#"spriteBitmap.png"];
mySprite2 = [CCSprite spriteWithFile:#"spriteBitmap.png"];
mySprite3 = [CCSprite spriteWithFile:#"spriteBitmap.png"];
mySprite1.position = ccp(100, 100);
mySprite2.position = ccp(200, 200);
mySprite3.position = ccp(300, 300);
You can not add the same CCSprite as a child to multiple CCNodes but you can make Cocos2D render the same CCSprite multiple times.
To achieve this you need to create a subclass of CCNode that will store the reference to your CCSprite and draw it in its -draw method applying required transformations.
For example
-(void)draw
{
[super draw];
CGPoint initialPosition = [_node position];
float initialScale = [_node scale];
[_node setScale:self.scale];
[_node setPosition:self.position];
[_node visit];
[_node setPosition:initialPosition];
[_node setScale:initialScale];
}
You may have to to use glScissor if you need picture-in-picture appearance.
Then you just need to addChild an instance of this class for every time you want an additional copy of your original CCSprite rendered.
Put a method on a for loop.
Inside the method create the CCSprite and modify it.
This is best suited for static sprites, since I don't know how you would access these outside of the method.
I've got to sprites, essentially a nucleus (parent) and an electron (child). I'm trying to find a way to have the electron orbit the nucleus. I've found a few posts here and there on moving anchor points, but that is apparently related to the texture of the sprite, not the sprite itself.
This is my current init method for my parent sprite:
self = [super init];
if (self) {
CCSprite *orbitAnchor = [CCSprite new];
[self addChild:orbitAnchor];
orbitAnchor.position = ccp(32,32);
CCSprite *orbiter = [CCSprite spriteWithFile:#"line.png" rect:CGRectMake(0, 0, 8, 8)];
[orbitAnchor addChild:orbiter];
orbiter.position = ccp(40,40);
CCAction *orbitAction = [CCRepeatForever actionWithAction:[CCRotateTo actionWithDuration:1 angle:720]];
[orbitAnchor runAction:orbitAction];
[self initAnimations];
}
return self;
Those numbers are all totally arbitrary though - I just stuck them in there and got what looked best. I'm sure there's a more programatic way to do what I want.
Basically, I'm looking for a way to set the child's axis point at the center of the parent, and then have it rotate around that point. It seems like a relatively simple thing to do using CCRotate and such, but I think I'm missing what to search for in order to move the anchor point of the child. Any suggestions/other posts?
Thanks
You have [CCSprite new] which is an unusual use, probably not supported. Unless the orbit anchor node should display a texture, you can just use a CCNode as anchor.
Technically you're doing everything correct from what I can see. You might want to try without the rotate actions and instead change the direction manually in a scheduled update method.
CCNode *orbitAnchor = [CCNode node];
[self addChild:orbitAnchor z:0 tag:1];
orbitAnchor.position = ccp(32,32);
CCSprite *orbiter = [CCSprite spriteWithFile:#"line.png" rect:CGRectMake(0, 0, 8, 8)];
[orbitAnchor addChild:orbiter z:0 tag:2];
orbiter.position = ccp(40,40);
[self scheduleUpdate];
Update method:
-(void) update:(ccTime)delta
{
CCNode* orbitAnchor = [self getChildByTag:1];
orbitAnchor.direction += 5;
}
From the image filename it looks like you're trying to draw a line from the orbitAnchor to the orbiter. You can do that with ccDrawLine:
-(void) draw
{
CCNode* orbitAnchor = [self getChildByTag:1];
CCNode* orbiter = [self getChildByTag:2];
ccDrawLine(orbitAnchor.position, orbiter.position);
}
Anchor points. Automatically, objects are placed based on the center of an object right? with anchor points you can move that around, so if you rotate the object it will rotate around the anchorpoint. http://www.qcmat.com/understanding-anchorpoint-in-cocos2d/