How to move a sprite at a certain angle with a joystick - cocos2d-iphone

Hi I have finally made a working joystick in cocos2d. I am able to rotate a sprite to the exact angle that the joystick thumb, or cap, is 'pointing'. However, I am unable to move the sprite in that same direction. Is there an easy way to move the sprite with the way I have the rotating code set up? Also is there a way to keep it moving if your thumb is still pressed, but not moving the joystick?. PS this code is all within the TouchesMoved method. PPS. the cap is the thumb, the pad is the joystick background, and the Sprite2 is the sprite that I want to move. (95, 95) is the center of the pad sprite.
if(capSprite.position.x>=padSprite.position.x){
id a3 = [CCFlipX actionWithFlipX:NO];
[sprite2 runAction:a3];
}
if(capSprite.position.x<=padSprite.position.x){
id a4 = [CCFlipX actionWithFlipX:YES];
[sprite2 runAction:a4];
}
CGPoint pos1 = ccp(95, 95);
CGPoint pos2 = ccp(capSprite.position.x, capSprite.position.y);
int offX = pos2.x-pos1.x;
int offY = pos2.y-pos1.y;
float angleRadians = atanf((float)offY/(float)offX);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float theAngle = -1 * angleDegrees;
sprite2.rotation = theAngle;

I'm not familiar with cocos2d but I had a quick look at the documentation and this sample might be of use to you:
if keys[key.UP]:
self.target.acceleration = (200 * rotation_x, 200 * rotation_y)
I had written a long explanation answering your second question but I believe this "self.target.acceleration" solves that too. You can read more at the cocos2d API documentation.

What I generally do is get the angle, convert it to a CGPoint with ccpForAngle(float) and then multiply the CGPoint by a value:
float angle = whatever;
CGPoint anglePoint = ccpForAngle(angle);
// You will need to play with the mult value
angle = ccpMult(angle, 2.5);
// This also works with box2D or probably Chipmunk.
sprite.position = angle;

Related

Cocos2D Make Camera Follow Sprite Not Working Properly

I am using the following code to make the camera follow my character as he falls down the screen:
[self runAction:[CCFollow actionWithTarget:charSprite worldBoundary:[levelLoader gameWorldSize]/*CGRectMake(0,0,320,3000)*/]];
What happens is this: the code runs as you would expect, and follows the character as he falls from the top of the screen. However: when he reaches the middle of the screen the camera stops following him.
I have tried both the code above as well as replacing the [levelLoader gameWorldSize] with the commented out CGRectMake(0,0,320,3000) - both yield the same results. As a last resort I tried to use some code I found on www.raywenderlich.com that has worked for me before (see below) (it worked on the x-axis in another game I wrote), but the same problem occurred.
-(void)setViewpointCenter:(CGPoint) position
{
CGSize winSize = [[CCDirector sharedDirector] winSize];
CGRect worldRect = [levelLoader gameWorldSize];
int x = MAX(position.x, worldRect.origin.x + winSize.width / 2);
int y = MAX(position.y, worldRect.origin.y + winSize.height / 2);
x = MIN(x, (worldRect.origin.x + worldRect.size.width) - winSize.width / 2);
y = MIN(y, (worldRect.origin.y + worldRect.size.height) - winSize.height/2);
CGPoint actualPosition = ccp(x, y);
CGPoint centerOfView = ccp(winSize.width/2, winSize.height/2);
CGPoint viewPoint = ccpSub(centerOfView, actualPosition);
self.position = viewPoint;
}
My world is created in Portrait mode using LevelHelper.
Any help would be greatly appreciated!
CCFollow follows the node within the world boundary, minus half the screen width/height. If your sprite starts falling at y = 320 then CCFollow will follow it until y = 160.
You can either position the sprite to your world boundary's top (y = 3000) or make the world boundary negative (y = -3000). Either way, when the sprite reaches the world boundary, scrolling will stop half a screen width/height before the world boundary.

How to rotate the physics or dynamic body along an arc path in cocos2d(box2D)

As I am newbie to cocoa2d I am struggling alot to rotate the physics or dynamic body along an arc path.
The way I tried is as follows:
#define COS_ANIMATOR(position, timeCount, speed, waveMagnitude) ((cosf(timeCount * speed) * waveMagnitude) + position)
#define SIN_ANIMATOR(position, timeCount, speed, waveMagnitude) ((sinf(timeCount * speed) * waveMagnitude) + position)
CCSpriteBatchNode *pipe_parent = [CCSpriteBatchNode batchNodeWithFile:#"pipe.png" capacity:100];
CCTexture2D *pipeSpriteTexture_ = [pipe_parent texture];
PhysicsSprite *pipeSprite = [PhysicsSprite spriteWithTexture:pipeSpriteTexture_ rect:CGRectMake(0 ,0 ,55,122)];
//pipe = [CCSprite spriteWithFile:#"pipe.png"
// rect:CGRectMake(0, 0, 55, 122)];
[self addChild:pipeSprite];
// pipe.position = ccp(s.width/2 , 420.0);
b2BodyDef myBodyDef;
myBodyDef.type = b2_staticBody; //this will be a dynamic body
myBodyDef.position.Set(((s.width/2) - 90)/PTM_RATIO, 420.0/PTM_RATIO); //set the starting position
myBodyDef.angle = 0; //set the starting angle
b2Body* staticBody = world->CreateBody(&myBodyDef);
b2PolygonShape boxShape;
boxShape.SetAsBox(1,1);
b2FixtureDef boxFixtureDef;
boxFixtureDef.shape = &boxShape;
boxFixtureDef.density = 1;
boxFixtureDef.userData = pipeSprite;
boxFixtureDef.filter.groupIndex = -1;
staticBody->CreateFixture(&boxFixtureDef);
[pipeSprite setPhysicsBody:staticBody];
-(void) draw
{
//
// IMPORTANT:
// This is only for debug purposes
// It is recommend to disable it
//
[super draw];
const CGPoint newSpritePosition = ccp(COS_ANIMATOR(150, mTimeCounter, 0.05,50), SIN_ANIMATOR(400, mTimeCounter, -0.05, 50));
pipeSprite.position = newSpritePosition;
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
world->DrawDebugData();
kmGLPopMatrix();
}
on following this approach my sprite rotating in circular motion instead of rotating in an arc path.
Please give your ideas or suggestions.
Thanks all
I'm not entirely sure what it is you are looking to accomplish when you talk about rotating in an arc path. I only see you setting a position, not a rotation, so are you just wanting to set a position, or a rotation, or both? Your position code looks like you are trying to achieve a circular (or elliptical) path because you are using the sine and cosine in the x,y position.
If you're looking to move a sprite along a sine curve, I did that today and it took a bit of trial and error. I had some variables for the amplitude and period, and from there I traced out a nice sine curve movement in the sprite's update: method.
CGPoint initialPosition; // set this to the sprite's initial position
float amplitude; // in points
float period; // in points
float y, x = initialPosition.x;
-(void) update:(ccTime)dt
{
x += dt * 100; // speed of movement across the screen. Picked by trial and error.
y = initalPosition.y + amplitude * sinf((x - initialPosition.x)/period);
sprite.position = ccp(x,y);
sprite.rotation = cosf((x - initialPosition.x)/period); // optional if you want to rotate along the path as well
}
Don't know if this is anything you are looking for but it might give you some ideas.

Make an object follow the camera in OpenGL

I'm making a racecar game in OpenGL (just a small project) and I'm having problems trying to make my car follow the camera view.
It wasn't hard to make it follow the camera as the camera moves forward and/or backward, but as I rotate the camera (look right or left) the car remais still. I mean, it still moves forward and backward but it's not in front of the camera (it's on the side).
Here is my code (the part where I try to implement it):
void updateCam() {
gluLookAt(posX,posY + 0.025 * std::abs(sin(headPosAux*PI/180)),posZ,
posX + sin(roty*PI/180),posY + 0.025 * std::abs(sin(headPosAux*PI/180)) + cos(rotx*PI/180),posZ -cos(roty*PI/180),
0.0,1.0,0.0);
listenerPos[0] = posX;
listenerPos[1] = posY;
listenerPos[2] = posZ;
source0Pos[0] = posX;
source0Pos[1] = posY;
source0Pos[2] = posZ;
GLfloat distD;
distD = posZ - 3.3;
//makes the car "follow" the camera
modelPOR.Translate(posX,posY,distD);
}
I think the problem is that you change the center location in gluLookAt and not in the modelPOR.Translate
the 3 middle parameters of gluLookAt set the center of the view, so the car should be at the exact same position but you modify the center without modifying the car's position.
gluLookAt(posX,posY + 0.025 * std::abs(sin(headPosAux*PI/180)),posZ,
// center x
posX + sin(roty*PI/180),
// center y
posY + 0.025 * std::abs(sin(headPosAux*PI/180)) + cos(rotx*PI/180),
// center z
posZ -cos(roty*PI/180),
0.0,1.0,0.0);
you should probably translate the car by those same values. then it will be centered.
another problem that seems to be in that code is that you rotate the camera and not the car, so the car probably will not stay pointing in the same direction as the camera. (is that desired or do you do it elswhere?)
but are you really sure you want to make the car follow the camera? it would probably be better the other way around.

Can I make CCFollow follow more naturally?

I want to build a platform game with cocos2d/Box2D. I use CCFollow to follow the player sprite but CCFollow constantly puts it in the center of the screen. I want CCFollow to follow more naturally, like a human turning a camcorder with an acceptable lag, a small overshoot ...etc.
Here is a method of mine that didn't work: I attached (via a distance joint) a small physics body to the player that doesn't collide with anything, represented by a transparent sprite. I CCFollow'ed the transparent sprite. I was hoping this ghost body would act like a balloon attached to the player, hence a smooth shift in view. The problem is distance joint breaks with too heavy - too light objects. The balloon moves around randomly, and of course, it pulls the player back a little no matter how light it is.
What is a better way of following a moving sprite smoothly?
Try add this to CCActions in cocos2d libs.
-(void) step:(ccTime) dt
{
#define CLAMP(x,y,z) MIN(MAX(x,y),z)
CGPoint pos;
if(boundarySet)
{
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(boundaryFullyCovered) return;
CGPoint tempPos = ccpSub(halfScreenSize, followedNode_.position);
pos = ccp(CLAMP(tempPos.x,leftBoundary,rightBoundary), CLAMP(tempPos.y,bottomBoundary,topBoundary));
}
else {
// pos = ccpSub( halfScreenSize, followedNode_.position );
CCNode *n = (CCNode*)target_;
float s = n.scale;
pos = ccpSub( halfScreenSize, followedNode_.position );
pos.x *= s;
pos.y *= s;
}
CGPoint moveVect;
CGPoint oldPos = [target_ position];
double dist = ccpDistance(pos, oldPos);
if (dist > 1){
moveVect = ccpMult(ccpSub(pos,oldPos),0.05); //0.05 is the smooth constant.
oldPos = ccpAdd(oldPos, moveVect);
[target_ setPosition:oldPos];
}
#undef CLAMP
}
i get this from cocos2d forums.
Perhaps this http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:actions_ease can help you get an "acceleration" effect with CCFollow.

box2d collision with curves

Hi all
im working on an ipad app using cocos2d objective c and box2d. my question is in relation to box2d and collisions with curves. basically i have circles within a larger circle arena. the smaller circles collide with each other fine but i want to know how to make them collide with the edges of the larger arena circle correctly so that they dont leave the arena and bounce back in. any ideas on how to approach this problem would be great
cheers
ok i got it working but im not sure if its the correct way to do it
int sides = 50;
float x_coordPREV=([Arena contentSize].width/2)*cos(0.0);
float y_coordPREV=([Arena contentSize].width/2)*sin(0.0);
x_coordPREV += Arena.position.x;
y_coordPREV += Arena.position.y;
b2BodyDef arenaBodyDef;
arenaBodyDef.position.Set(0,0);
b2Body *arenaBody = _world->CreateBody(&arenaBodyDef);
b2PolygonShape arenaBox;
b2FixtureDef arenaShapeDef;
arenaShapeDef.shape = &arenaBox;
for(float angle=0.0f;angle<(2*M_PI);angle+=(2*M_PI)/sides){
float x_coord=([Arena contentSize].width/2-10)*cos(angle);
float y_coord=([Arena contentSize].width/2-10)*sin(angle);
x_coord += Arena.position.x;
y_coord += Arena.position.y;
arenaBox.SetAsEdge(b2Vec2(x_coordPREV/PTM_RATIO,y_coordPREV/PTM_RATIO),b2Vec2( x_coord/PTM_RATIO,y_coord/PTM_RATIO ));
arenaBody->CreateFixture(&arenaShapeDef);
x_coordPREV = x_coord;
y_coordPREV = y_coord;
}
this creates a circle out of 50 sides and appears to be doing what i want. if anyone has a better way please let me know
ty
not sur eif this i what you are looking for but i saw this on a forum:
b2BodyDef edgedef;
edgedef.position.Set(0.f,10.f);
b2Body* edge = world->CreateBody(&edgedef);
b2Vec2 vertices[2];
vertices[0].Set(0.0f, 0.0f);
vertices[1].Set(10.0f, 0.0f);
int32 count = 2;
b2PolygonShape polygon;
polygon.Set(vertices, count);
b2FixtureDef edgefixtureDef;
edgefixtureDef.shape = &polygon;
edge->CreateFixture(&edgefixtureDef);
you could see how you could add more points by sending a larger array