Get image in CCAnimation Cocos2d-x - ios

n init method am starting one CCAnimation. its fine. at touch ended method am stoping the animation. at the time of stop i need to get the current image of animate.
Player = CCSprite::create("AngleSelector1.png");
Player->setPosition( ccp(size.width / 2, size.height/2) );
this->addChild(Player);
//Animation
CCAnimation *animate = CCAnimation::create();
for (int i = 1; i <=10; i++)
{
char frameName[128] = {0};
sprintf(frameName, "AngleSelector%d.png", i);
animate->addSpriteFrameWithFileName(frameName) ;
}
animate->setDelayPerUnit(0.35f); // This animation contains 3 frames, will continuous 2.8 seconds.
animate->setRestoreOriginalFrame(true); // Return to the 1st frame after the 3rd frame is played.
CCAnimate *animaction = CCAnimate::create(animate);
CCRepeatForever *rt = CCRepeatForever::create(animaction);
Player->runAction(rt);
this->setTouchEnabled(true);
void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
Player->stopAllActions();
}

i solved using following code. image index will return your current display frame
CCTexture2D* tex = Player->getTexture();
int imageIndex = 0;
for (int i=0; i< animate->getFrames()->count(); i++) {
CCAnimationFrame *frame = (CCAnimationFrame*)animate->getFrames()->objectAtIndex(i);
CCTexture2D *tex2 = frame->getSpriteFrame()->getTexture();
if (tex->isEqual(tex2)) {
imageIndex = i;
break;
}
}

Related

skshapenode adding two nodes?

I'm not sure whether there's an issue with the implementation or the way I'm using it.
However, it's presenting over 2,400 nodes when it should be ~ 1,250
-(void)drawWeb {
//get distance of 50 across
int distanceMargin = _background.frame.size.width/50;
NSLog(#"%i", distanceMargin);
__block int xCounter = distanceMargin;
__block int yCounter = 0;
NSArray *alphabet = [[NSArray alloc] initWithObjects:#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z", nil];
for (int i = 0; i < 25; i++) {
for (int j = 0; j < 50; j++) {
webPoint *shape = [webPoint shapeNodeWithCircleOfRadius:1];
shape.position = CGPointMake(xCounter, _background.frame.size.height - yCounter);
shape.fillColor = [UIColor blackColor];
shape.alpha = 1;
shape.webPoint = [NSString stringWithFormat:#"%#%i", alphabet[i], j];
shape.positionX = xCounter;
shape.positionY = yCounter;
shape.name = #"webPoint";
[_background addChild:shape];
xCounter = xCounter + distanceMargin;
}
xCounter = distanceMargin;
yCounter = yCounter + distanceMargin;
}
}
By default when creating SKShapeNode, strokeColor is already set and it requires 1 node + 1 draw call. In your example you are setting fillColor too, which requires additional node and additional draw pass.
SKShapeNode is not performant solution in many cases (it should be used sparingly), and in your case, if you enable debugging labels you will probably see that there are a lot of draw calls required for scene rendering. Debugging labels can be enabled in view controller (showsDrawCount = YES)
Draw calls are directly affecting on performance in SpriteKit applications and you should try to keep that number as low as possible. One way would be using SKSpriteNode and texture atlases.

How to stop white lines on edge of background in sprite kit Xcode?

This is my code for a scrolling background:
for (int i = 0; i < 2; i++) {
bg1 = [SKSpriteNode spriteNodeWithImageNamed:#"nightbackground"];
bg1.anchorPoint = CGPointZero;
bg1.position = CGPointMake(0, 0);
[bg1 setScale:0.5];
[self addChild:bg1];
bg2 = [SKSpriteNode spriteNodeWithImageNamed:#"nightbackground"];
bg2.anchorPoint = CGPointZero;
bg2.position = CGPointMake(bg1.size.width-1, 0);
[bg2 setScale:0.5];
[self addChild:bg2];
}
Now when the new repeated image comes in, you can see where the new image starts, there is a white line. Is their a way of getting rid of it or overlapping the two so you don't see the start of it?
for (int i = 0; i < 2; i++) {
_bg =
[SKSpriteNode spriteNodeWithImageNamed:#"nightbackground"];
_bg.anchorPoint = CGPointMake(0.5, 0.5);
_bg.position = CGPointMake(i * _ground.size.width, 0);
_bg.name = #"bg";
_bg.zPosition = 10;
[self addChild:_bg];
}
I would have tried this solution, you make the anchorpoint the middle of the sprite and use the for-loop-value to place them out. You only need one addchild

how to move sprite with delay in cocos2d?

i have number of sprite in array. now i want to moving that sprite with delay time 0.5.i am use below code at that time all sprite are fall at same time but i want to falling the sprite one by one.i am also use CCDelay method but also not get required result.
for (int j = 1; j < [ary count]; j++)
{
torpedoOne.position = ccp(160,580);
id actionMove = [CCMoveTo actionWithDuration:2.0
position:ccp(30 + (j*25),300)];
id deleay = [CCDelayTime actionWithDuration:1.0];
[torpedoOne runAction:[CCSequence actions:actionMove,deleay,nil]];
[self addChild:torpedoOne];
}
first of all for loop is complete after the action is run so that all sprite has same acion with same time.
how can i run action when each time go in for loop?
i am aslo try COCOS2D: how to animate falling bricks into a grid
you logic is weird. Try
for (int j = 0;j<[ary count]; j++{ // gets all objects in ary : 0 to count-1
torpedoOne = [ary objectAtIndex:j]; // I am assuming this is what you wanted
torpedoOne.position = ccp(160,580);
id actionMove = [CCMoveTo actionWithDuration:2.0
position:ccp(30 + (j*25),300)];
float delayTime = j*0.5f;
torpedoOne.visible = NO;
id show = [CCShow action]; // if you want them invisible prior to start move
id delay = [CCDelayTime actionWithDuration:delayTime];
[torpedoOne runAction:[CCSequence actions:delay,show,actionMove,nil]];
}
also, you should set torpedoOne inside the loop.
After a long time,i got one by one with sprite with animation by particular delay in cocos2d .
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
for (int j = 1; j < [ary count]; j++)
{
dispatch_async(dispatch_get_main_queue(),
^{
torpedoOne.position = ccp(160,580);
id actionMove = [CCMoveTo actionWithDuration:2.0
position:ccp(30 + (j*25),300)];
id deleay = [CCDelayTime actionWithDuration:1.0];
[torpedoOne runAction:[CCSequence actions:actionMove,deleay,nil]];
[self addChild:torpedoOne];
});
[NSThread sleepForTimeInterval:delay];
}
});

'CALayer position contains NaN: [nan nan]' when working with Bouncing Ball Array in C4

So I'm trying to just recreate a bouncing ball app using xcode and C4. What I'm trying to do right now is re-create some of the examples in Dan Shiffmans Nature of Code book in C4.
So far I've managed to create my own class of "Mover" objects that bounce around the screen. That's all working great. The next step was to start "applying some forces" to the movers and play around with that.
I seem to be getting an exception thats crashing the program now that I've added methods to apply force. I put on exception breakpoints and this line in C4Control.m is where it stops:
if(_animationDuration == 0.0f) super.center = center;
Looking into this more, I notice that neither super.center or center properties have a value assigned to them (both of NaN). I'm not sure what's causing this? This seemed to start once I decided to set each Movers initial velocity/accel to 0 and only assign "fores" (C4Vectors for wind and gravity) to create motion in these objects. When I comment out the 2 lines that apply each force, the problem goes away.
This is the implementation of my mover class:
//Init Method
- (id)initWithPoint:(CGPoint)point andCanvasController:(C4CanvasController *)canvasController {
self = [super init];
if (self) {
canvasFrame = CGPointMake(canvasController.canvas.width,
canvasController.canvas.height);
diam = [C4Math randomInt:70];
mass = diam * 0.5f;
CGRect ellipseFrame = CGRectMake(0, 0, diam, diam);
[self ellipse:ellipseFrame];
self.lineWidth = 0.0f;
self.fillColor = [UIColor colorWithRed:[C4Math randomInt:60]/60
green:[C4Math randomInt:100]/100.0f
blue:0.9f
alpha:0.3f];
int foo = arc4random() % (int)([canvasController.canvas height]);
int bar = arc4random() % (int)([canvasController.canvas width]);
self.location = [C4Vector vectorWithX:foo
Y:bar
Z:0.0f];
self.origin = self.location.CGPoint;
self.accel = [C4Vector vectorWithX:0.00f Y:0.0f Z:0.0f];
self.vel = [C4Vector vectorWithX:0.00f Y:0.0f Z:0.0f];
}
return self;
}
//Method to calculate updated mover position
-(void)update{
[self.vel add:self.accel];
[self.location add:self.vel];
self.origin = self.location.CGPoint;
[self.accel multiplyScalar:0];
[self checkBounds];
}
//Checking if mover has reached edge of screen
-(void)checkBounds{
if (self.origin.x > canvasFrame.x - diam){
self.location.x = canvasFrame.x - diam;
self.vel.x *= -1;
}
else if (self.origin.x < 0){
self.vel.x *= -1;
self.location.x = 0;
}
if(self.origin.y > canvasFrame.y - diam){
self.location.y = canvasFrame.y - diam;
self.vel.y *= -1;
}
else if(self.origin.y < 0){
self.vel.y *= -1;
self.location.y = 0;
}
}
//Start C4Timer to run update every 1/60th of a second
- (void) run{
updateTimer = [C4Timer automaticTimerWithInterval:1/60.0f
target:self
method:#"update"
repeats:YES];
}
//Calculate a force to apply to mover
- (void)applyForce:(C4Vector *)force{
[force divideScalar:mass];
[self.accel add:force];
}
In my C4WorkSpace.m file:
#import "C4Workspace.h"
#import "Mover.h"
#implementation C4WorkSpace{
Mover *testMover;
NSMutableArray *moverArray;
}
-(void)setup {
C4Vector *gravity = [C4Vector vectorWithX:0.01f Y:0.0 Z:0.0f];
C4Vector *wind = [C4Vector vectorWithX:0 Y:0.4 Z:0];
moverArray = [[NSMutableArray alloc]init];
//Not using foo/bar variables right now, but usually use them to create CGPoint p
//int foo = arc4random() % (int)([self.canvas height]);
//int bar = arc4random() % (int)([self.canvas width]);
for (int i = 0; i < 500; i++) {
CGPoint p = CGPointMake(0,0);
Mover *m = [[Mover alloc]initWithPoint:p andCanvasController:self];
[moverArray addObject:m];
}
for (Mover *m in moverArray){
[self addShape:m];
[m run];
[m applyForce:gravity];
[m applyForce:wind];
}
}
#end
Sorry for how long this was, any and all help is much appreciated!

Set sprite using background position

I am new to cocos2d so please help me if u can
I have background moving from right to left, and the background contains small windows with 3 rows of windows
_spaceDust1 = [CCSprite spriteWithFile:#"bg_front_spacedust.png"];
_spaceDust2 = [CCSprite spriteWithFile:#"bg_front_spacedust.png"];
CGPoint dustSpeed = ccp(0.1 , 0.1);
CGPoint bgSpeed = ccp(0.05 , 0.05);
[_backgroundNode addChild:_spaceDust1 z:0 parallaxRatio:dustSpeed positionOffset:ccp(0,winSize.height / 2)];
[_backgroundNode addChild:_spaceDust2 z:0 parallaxRatio:dustSpeed positionOffset:ccp(_spaceDust1.contentSize.width , winSize.height / 2)];
Now add enemies wich also move from right to left with same speed
_robbers = [[CCArray alloc] initWithCapacity:kNumAstroids];
for (int i = 0; i < kNumAstroids; ++i) {
CCSprite *asteroid = [CCSprite spriteWithSpriteFrameName:#"robber.png"];
asteroid.visible = NO;
[_batchNode addChild:asteroid];
[_robbers addObject:asteroid];
}
in update method:
double curTime = CACurrentMediaTime();
if (curTime > _nextRunemanSpawn) {
float randSecs = [self randomValueBetween:0.20 andValue:1.0];
_nextRunemanSpawn = randSecs + curTime;
float randY = 80.0;
float randY1 = 185.0;
float randY2 = 293.0;
float randDuration = [self randomValueBetween:5.2 andValue:5.2];
float randDuration1 = [self randomValueBetween:1.0 andValue:1.0];
CCSprite *asteroid = [_robbers objectAtIndex:_nextRobber];
_nextRobber++;
if (_nextRobber >= _robbers.count) {
_nextRobber = 0;
}
//[asteroid stopAllActions];
int winChoice = arc4random() % 3;
if (winChoice == 0) {
asteroid.position = ccp(winSize.width +asteroid.contentSize.width / 2 , randY);
asteroid.visible = YES;
}
else if(winChoice == 1){
asteroid.position = ccp(winSize.width +asteroid.contentSize.width / 2 , randY1);
asteroid.visible = YES;
}else {
asteroid.position = ccp(winSize.width +asteroid.contentSize.width / 2 , randY2);
asteroid.visible = YES;
}
[asteroid runAction:[CCSequence actions:[CCMoveBy actionWithDuration:randDuration position:ccp(-winSize.width-asteroid.contentSize.width, 0)],
[CCCallFuncN actionWithTarget:self selector:#selector(setInvisible:)],nil]];
All is going well but i want to set this enemies in to window and in random position
so how can i set x-argument of enemies so it can be fix in to window of the background?
For some reason I cannot comment so this is written as an answer. What exactly are you trying to do? I am a bit confused. It sounds like you want the X position to be set so that it is in one of 3 random positions, is that correct?

Resources