Create NSArray with float value in a range of -1.0 +1.0 from C Array in identical format - nsarray

Ok, maybe I'm tired but have some trouble when try to passing "float value" from an C array style to NSarray across NSNumber and obtain identical data.
What I would like achieve is pass this value in other class for plotting audio Waveform.
assuming:
//needed range from -1.0 to 1.0
monoFloatDataLeft[i] = (float)left / 32768.0;
monoFloatDataRight[i] = (float)right / 32768.0;
ArraySx = &monoFloatDataLeft[i];
ArrayDx = &monoFloatDataRight[i];
NSLog(#"right %f\n",ArrayDx);
[self floatSx:*(ArraySx) floatDx:*(ArrayDx)];
Output: right -0.000061
Now in function...
-(void)floatSx: (float)left floatDx: (float) right{
NSLog (#"Left in function %f\n", left);
NSLog (#"right in function %f\n", right);
NSArray *cannelLeftArray = [NSArray arrayWithObjects:[NSNumber numberWithFloat:left], nil];
NSLog (#"cannelLeftArray %#\n", canaleSinistroArray);
NSArray *channelRightArray = [NSArray arrayWithObjects:[NSNumber numberWithFloat:right], nil];
NSLog (#"channelRightArray %#\n", canaleDestroArray);
}
Output:
Left in function -0.000061
right in function -0.000153
cannelLeftArray("-0.0001525879")
channelRightArray("-6.103516e-05")
Ok, what i need is populate the array with the same float value style like left and right in function...
Hope enough clear.
Thanks in advance

Related

Sprite not drawing/appearing on screen, Cocos2d

I'v got trouble getting my sprite to appear on screen using my current method. I got multiple sprites on the screen already, but I'v added this new one in a different manner as I'm going to manipulate it later on (handling different interactions and such). But I don't see why it doesn't appear on the screen when I run the program. I'v tried changing the z order without luck, but that might be because the sprite wasn't added in the init method like the others so the z order doesn't affect it in comparison to the background and such created in the init method. Anyways, got any clue for why it won't draw on screen?
- (void) addMonster {
CCSprite * monster = [CCSprite spriteWithImageNamed:#"Ghost.png"];
// Determine where to spawn the monster along the Y axis
CGSize viewSize = [CCDirector sharedDirector].viewSize;
int minY = monster.contentSize.height / 2;
int maxY = viewSize.height - monster.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
// Create the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster.position = ccp(viewSize.width + monster.contentSize.width/2, actualY);
[self addChild:monster];
// Determine speed of the monster
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
// Create the actions
CCActionMoveTo * actionMove = [CCActionMoveTo actionWithDuration:actualDuration
position:ccp(-monster.contentSize.width/2, actualY)];
CCActionCallBlock * actionMoveDone = [CCActionCallBlock actionWithBlock:^(CCNode *node) {
[monster removeFromParentAndCleanup:YES];
}];
[monster runAction:[CCActionSequence actions:actionMove, actionMoveDone, nil]];
}
//The call back function
-(void)gameLogic:(CCTime)dt {
[self addMonster];
}
- (id)init{
// Apple recommend assigning self with supers return value
self = [super init];
if (!self) return(nil);
if( (self = [super init]) ) {
self.userInteractionEnabled = YES;
//How often a new ghost gets produced
[self schedule:#selector(gameLogic:) interval:1.0];
//And some more code none relevant to this keeps going...
I am having the same problem.
The sprites i add do appear, but when i leave the scene and come back, they won't appear. As far as i know sprites needs to be added in the init method. When you add them at a later stage (in my case) they appear only once.
I am still looking for a solution to add the sprites at a later stage than the init method and appears more than once.
Maybe this answer helps you finding a solution.

cocos2d flappy bird demo

I am working with the flappy bird demo trying different things just to get to "know each other".
Going through the demo, I've managed to change the direction of the game to vertical scroll moving upwards.
Having reversed the CGFloat to negative values makes my obstacles move upward but once they are out of bounds they do not re-spawn.
If I change the values for a downward scroll they re-spawn as per the update method.
Can someone explain to me what I'm doing wrong with the x to y conversion? Why is the bottom recognized and the top of my screen not?
Thanks in advance
#import "MainScene.h"
static const CGFloat scrollSpeed = -280.f; //upwards
static const CGFloat firstObstaclePosition = -568.f;
static const CGFloat distanceBetweenObstacles = 80;
#implementation MainScene {
CCSprite *_hero;
CCPhysicsNode *_physicsNode;
NSMutableArray *_obstacles;
}
- (void)spawnNewObstacle {
CCNode *previousObstacle = [_obstacles lastObject];
CGFloat previousObstacleYPosition = previousObstacle.position.y;
if (!previousObstacle) {
// this is the first obstacle
previousObstacleYPosition = firstObstaclePosition;
}
CCNode *obstacle = [CCBReader load:#"Obstacle"];
obstacle.position = ccp(0, previousObstacleYPosition + distanceBetweenObstacles);
[_physicsNode addChild:obstacle];
[_obstacles addObject:obstacle];
}
- (void)update:(CCTime)delta {
_hero.position = ccp(_hero.position.x, _hero.position.y + delta * scrollSpeed);//move on Y axis
_physicsNode.position = ccp(_physicsNode.position.x, _physicsNode.position.y - (scrollSpeed *delta));//scroll in Y axis
//spawn more
NSMutableArray *offScreenObstacles = nil;
for (CCNode *obstacle in _obstacles) {
CGPoint obstacleWorldPosition = [_physicsNode convertToWorldSpace:obstacle.position];
CGPoint obstacleScreenPosition = [self convertToNodeSpace:obstacleWorldPosition];
if (obstacleScreenPosition.y < -obstacle.contentSize.height) {
if (!offScreenObstacles) {
offScreenObstacles = [NSMutableArray array];
}
[offScreenObstacles addObject:obstacle];
}
}
for (CCNode *obstacleToRemove in offScreenObstacles) {
[obstacleToRemove removeFromParent];
[_obstacles removeObject:obstacleToRemove];
// for each removed obstacle, add a new one
[self spawnNewObstacle];
}
}
- (void)didLoadFromCCB {
self.userInteractionEnabled = TRUE;
_obstacles = [NSMutableArray array];
[self spawnNewObstacle];
[self spawnNewObstacle];
[self spawnNewObstacle];
}
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
}
#end
I've attached the _physicsNode screenshot from SB.
It looks like your obstacles will be spawning fine if they are a short, constant height, and the distance between them value is large enough. It may be better to incorporate the height of the obstacles to get a more meaningful value of the distance variable. Just a thought.
The line -
obstacle.position = ccp(0, previousObstacleYPosition + distanceBetweenObstacles);
Could be -
obstacle.position = ccp(0, previousObstacleYPosition + distanceBetweenObstacles + previousObstacle.contentSize.height);
As for the problem of the vertical scrolling working downwards and not upwards I believe it is due to this line:
if (obstacleScreenPosition.y < -obstacle.contentSize.height) {
Since this line is responsible for determining when an obstacle is off the screen it has an effect on the spawning of the next obstacle. It makes sense why this line works for downwards scrolling but needs to be changed for upwards scrolling.
Try:
if (obstacleScreenPosition.y > (_physicsNode.contentSize.height + obstacle.contentSize.height)) {
You may or may not need the size of the obstacle depending on where it is anchored.
I hope this works, Good luck.

Convert rotation angle in world space to local space cocos2d

Is there a simple way (ie an api) that converts an angle of rotation in world space to local space of a CCNode? I know the angle of rotation a node needs to have on the screen, but the node is nested deeply in node hierarchy and I would like to set its angle so that it matches what I want. If there's no api, what CC api calls should I make? Something like this:
CCNode * myLocalNode;
float myLocalAngle = CCAngleConvertFromWorldToNode(myLocalNode,myWorldAngle);
myLocalNode -> setRotation(myLocalAngle);
I think the best way to do is to get two reference points, one representing the origin and the other representing the rotation vector. Convert these 2 points to node space, measure the vector between them (subtraction) and convert that to an angle. Here are 2 methods that should be a category of CCNode (note: I refer to self), one to world and the other to node.
-(float) convertRotationToWorldSpace:(float)rotation
{
CGPoint rot = ccpForAngle(-CC_DEGREES_TO_RADIANS(rotation));
CGPoint worldPt = [self convertToWorldSpace:rot];
CGPoint worldOriginPt = [self convertToWorldSpace:CGPointZero];
CGPoint worldVec = ccpSub(worldPt, worldOriginPt);
return -CC_RADIANS_TO_DEGREES(ccpToAngle(worldVec));
}
-(float) convertRotationToNodeSpace:(float)rotation
{
CGPoint rot = ccpForAngle(-CC_DEGREES_TO_RADIANS(rotation));
CGPoint nodePt = [self convertToNodeSpace:rot];
CGPoint nodeOriginPt = [self convertToNodeSpace:CGPointZero];
CGPoint nodeVec = ccpSub(nodePt, nodeOriginPt);
return -CC_RADIANS_TO_DEGREES(ccpToAngle(nodeVec));
}

Converting Objective C NSRange to C++ code?

I was going through the raynderwilch tutorials for Vrope and I have almost ported all the code in that tutorial to C++ but I have stuck to this function where I am stuck how will I port this function to cocos2d-x c++ ?
I have never been in to objective C much so couldnt do it need ur help
-(VRope *)cutRopeInStick:(VStick *)stick newBodyA:(b2Body*)newBodyA newBodyB:(b2Body*)newBodyB {
// 1-First, find out where in your array the rope will be cut
int nPoint = [vSticks indexOfObject:stick];
// Instead of making everything again you'll just use the arrays of
// sticks, points and sprites you already have and split them
// 2-This is the range that defines the new rope
NSRange newRopeRange = (NSRange){nPoint, numPoints-nPoint-1};
// 3-Keep the sticks in a new array
NSArray *newRopeSticks = [vSticks subarrayWithRange:newRopeRange];
// 4-and remove from this object's array
[vSticks removeObjectsInRange:newRopeRange];
// 5-Same for the sprites
NSArray *newRopeSprites = [ropeSprites subarrayWithRange:newRopeRange];
[ropeSprites removeObjectsInRange:newRopeRange];
// 6-Number of points is always the number of sticks + 1
newRopeRange.length += 1;
NSArray *newRopePoints = [vPoints subarrayWithRange:newRopeRange];
[vPoints removeObjectsInRange:newRopeRange];
// 7-The removeObjectsInRange above removed the last point of
// this rope that now belongs to the new rope. You need to clone
// that VPoint and add it to this rope, otherwise you'll have a
// wrong number of points in this rope
VPoint *pointOfBreak = [newRopePoints objectAtIndex:0];
VPoint *newPoint = [[VPoint alloc] init];
[newPoint setPos:pointOfBreak.x y:pointOfBreak.y];
[vPoints addObject:newPoint];
// 7-And last: fix the last VStick of this rope to point to this new point
// instead of the old point that now belongs to the new rope
VStick *lastStick = [vSticks lastObject];
[lastStick setPointB:newPoint];
[newPoint release];
// 8-This will determine how long the rope is now and how long the new rope will be
float32 cutRatio = (float32)nPoint / (numPoints - 1);
// 9-Fix my number of points
numPoints = nPoint + 1;
// Position in Box2d world where the new bodies will initially be
b2Vec2 newBodiesPosition = b2Vec2(pointOfBreak.x / PTM_RATIO, pointOfBreak.y / PTM_RATIO);
// Get a reference to the world to create the new joint
b2World *world = newBodyA->GetWorld();
// 10-Re-create the joint used in this VRope since bRopeJoint does not allow
// to re-define the attached bodies
b2RopeJointDef jd;
jd.bodyA = joint->GetBodyA();
jd.bodyB = newBodyB;
jd.localAnchorA = joint->GetLocalAnchorA();
jd.localAnchorB = b2Vec2(0, 0);
jd.maxLength = joint->GetMaxLength() * cutRatio;
newBodyB->SetTransform(newBodiesPosition, 0.0);
b2RopeJoint *newJoint1 = (b2RopeJoint *)world->CreateJoint(&jd); //create joint
// 11-Create the new rope joint
jd.bodyA = newBodyA;
jd.bodyB = joint->GetBodyB();
jd.localAnchorA = b2Vec2(0, 0);
jd.localAnchorB = joint->GetLocalAnchorB();
jd.maxLength = joint->GetMaxLength() * (1 - cutRatio);
newBodyA->SetTransform(newBodiesPosition, 0.0);
b2RopeJoint *newJoint2 = (b2RopeJoint *)world->CreateJoint(&jd); //create joint
// 12-Destroy the old joint and update to the new one
world->DestroyJoint(joint);
joint = newJoint1;
// 13-Finally, create the new VRope
VRope *newRope = [[VRope alloc] initWithRopeJoint:newJoint2
spriteSheet:spriteSheet
points:newRopePoints
sticks:newRopeSticks
sprites:newRopeSprites];
return [newRope autorelease];
}
Box2d part is the same only that NSRange please help me in converting it to use in cocos2d-x
What will be the alternative to NSRange and NSArray in this situation?
Since NSRange is just a plain C structure, you can simply define it in C++ as well:
typedef struct {
unsigned long location;
unsigned long length;
} NSRange;
As H2CO3 says NSRange is a C-struct and can be defined easily.
For an NSArray you are probably best off using something like a std::vector< VStick >.
You can create a new array similarly to the above NSArray as follows:
std::vector< VStick > newRopeSticks;
newRopeSticks.reserve( range.length );
std::copy( vSticks.begin() + range.Location, vSticks.begin() + range.Location + range.length, std::back_inserter( newRopeSticks ) );
(I may have that slightly wrong thanks to faulty memory but the concept should, basically, work fine)
In answer to your comment its not the right way, no. An index is not an iterator. An iterator can be dereferenced to give the object you are interested in for one.
You are better off calling erase with an iterator range as follows:
vSticks.erase( vSticks.begin() + range.Location, vSticks.begin() + range.Location + range.Length );
This will be far more efficient as each removal of an element from a vector causes the elements above it to be copied down one (as its essentially a dynamically created array). By eraseing a range, as above, it will remove all the elements in the range then copy down all the objects above. This has the advantage of doing the copy down only once instead of for each erase.
I don't know any solution to NSRange, but definitely NSArray can be replaced using CCArray in cocos2d-x.

How to pinch/zoom on a cocos2d (Kobold2D) CCLayer

I have been trying to implement a standard pinch/zoom on a CCLayer in cocos2d (using the Kobold2D gesture recognisers) but with only partial success.
Below is my code which does make pinch/zoom work, so long as the pinch point doesn't move. However if I zoom in over one point on the layer and then lift off and move my fingers to zoom in further over another point, there is an instantaneous jump of the layer. It jumps to where the layer would have been if I'd been zooming in over the second point from the start, instead of simply zooming smoothly from where it was.
Can you see what I'm doing wrong or have I missed an existing simple pinch/zoom algorithm that does this job for CCLayers?
NB: I've left the default (YES) value for ignoreAnchorInPosition. Also, at the start self.scalePrePinch = 1.0f
-(void) update:(ccTime)delta
{
KKInput* input = [KKInput sharedInput];
if (input.gesturePinchBegan) {
CGSize scr = [[CCDirector sharedDirector] screenSize];
CGPoint pinchLocation = [self convertToNodeSpace:input.gesturePinchLocation];
CGPoint anchor = ccp(pinchLocation.x/scr.width, pinchLocation.y/scr.height);
CGFloat newScale = input.gesturePinchScale * self.scalePrePinch;
self.anchorPoint = ccp(self.anchorPoint.x + self.scale / newScale * (anchor.x - self.anchorPoint.x),
self.anchorPoint.y + self.scale / newScale * (anchor.y - self.anchorPoint.y));
self.scale = newScale;
}
else
self.scalePrePinch = self.scale;
}