Cocos2D v3 Calculate the distance after collision - cocos2d-iphone

Is it possible to calculate distance at which the body will fly off in method
-(BOOL)ccPhysicsCollisionBegin:typeA:typeB
I need the exact point, where the body would end up after collision. In other words, will it fly off towards boundary or not; whether the force is strong enough to push it to the boundary or not.
Any ideas? Thanks!
UPDATE:
Found some code. I was told, it's exactly what I want. But I'm not familiar with 'pure' Chipmunk. So, I can't use it anyway yet. The code needs to be inserted in draw method.
// We need a copy of the body and shape to simulate them forwards without doing a full step.
// For performance sake, let's just copy them onto the stack using the C-API.
cpBody body = *(cage.body.body);
cpPolyShape shape = *((cpPolyShape *)cage.shape.shape);
shape.shape.body = &body;
cpVect gravity = space.gravity;
// Check ahead up to 300 frames for a collision.
for(int i=0; i<300; i++){
// Manually update the position and velocity of the body
cpBodyUpdatePosition(&body, FIXED_TIMESTEP);
cpBodyUpdateVelocity(&body, gravity, 1.0f, FIXED_TIMESTEP);
// Perform a shape query to see if the cage hit anything.
if(cpSpaceShapeQuery(space.space, (cpShape *)&shape, NULL, NULL)){
// If it did, draw the box's outline.
cpVect verts[4];
for(int i=0; i<4; i++){
verts[i] = cpBodyLocal2World(&body, cpPolyShapeGetVert((cpShape *)&shape, i));
}
[self drawPolyWithVerts:verts count:4 fillColor:ccc4f(0, 0, 0, 0) borderWidth:1.0 borderColor:ccc4f(0, 0, 0, 1)];
break;
} else if(i%3==0){
// Otherwise, just draw a dot every 10 frames along the path.
[self drawDot:body.p radius:5.0 color:ccc4f(0, 0, 0, 0.5)];
}
}
[super draw];
[self clear];

Related

Slow down sprite's movement

In my scene class I've overridden the update function and I call scheduleUpdate() in the onEnter() method as suggested here. So in the update function I call the update of my layer class which should update my sprites:
void View::update(float dt)
{
world->Step(dt, 10, 10);
for(b2Body *b = world->GetBodyList(); b; b=b->GetNext())
{
if(b->GetUserData() != NULL && b->GetType() != b2_kinematicBody))
{
cocos2d::CCSprite *data = (cocos2d::CCSprite*)b->GetUserData();
data->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
data->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));
}
}
}
At the moment, the only movement is falling down because of gravity. However, the character moves so fast. It almost instantaneously hits the floor. Is there a way to slow this down?
When I used this tutorial for objective c, the ball was falling down much slower.
Did you correctly set the mass of your character? Try to reduce it. Also I recommend you to use a small wrapper which makes life with box2d and cocos2d-x much easier.
Found the problem. I set the position of my sprite to the center of my screen, but I set the position of the body to the bottom. So in the first frame the sprite immediately appeared on the bottom side.
So if anyone has the same problem: check the position of your body. Not just the sprite's position.

Cocos2dx : Deleting kinematic bodies once they are off screen

I am trying to build a platform game. In my game, random platforms appear and move from right part of the screen to the left part .
Using :
b2Vec2 impulse = b2Vec2(-5, 0);
platformBody->SetLinearVelocity(impulse);
But when I see my stats, the number of call / countRef (First line of the Stats) is always increasing as the new platforms move from right to the left. I want to know how can I remove the existing platforms once they have moved passed the left screen (off screen). All my platforms are b2_kinematic bodies (Box2D).
EDIT ANSWER :
I managed to solve it through the following :
for(std::vector::size_type i = 0; i != m_platforms.size(); i++)
{
if (m_platforms[i]->GetPosition().x < 0.0f && m_platforms[i]->GetType() == b2_kinematicBody)
{
CCSprite *sprite = (CCSprite *) m_platforms[i]->GetUserData();
sprite->removeFromParentAndCleanup(true);
world->DestroyBody(m_platforms[i]);
}
}
You could check whether or not your bodies are out of screen on the main loop, and destroy them if so. Something like.-
if (platformBody->GetPosition().x < SCREEN_X_LIMIT) {
world->DestroyBody(platformBody);
// Also, remove attached sprite if exists
}

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.

opengl array of pool balls

i am drawing an array of pool balls in opengl using c++
the problem i am facing is the array draws in a straight line.
when i use gltranslate the balls still only translate along the line when i edit the z and y axis
what i want to do is set the balls up in a triangle shape like the breaking of a pool match
how do i use the array code to set the balls up like this?
any help would be much appreciated
balls[7];
for (int x = ball-start; x<ball-end;x++)
{
glTranslatef(0,0,0.5);
glColor3f(1,0,0);
ball[x].drawball();
}
assuming:
struct Ball {
double x,y,z;
void drawball(void);
/* ... */
} ball[7];
try:
for(int i=0; i<7 ;i++)
{
glPushMatrix();
glTranslated(ball[i].x,ball[i].y,ball[i].z);
glColor3f(1,0,0);
ball[i].drawball();
glPopMatrix();
}
details probably vary, but hopefully you get the idea.
Do something like this:
// first of all, include the x,y position (assuming 2D, since pool) in the Ball object:
class Ball
{
//...
private:
float xpos, ypos;
//...
};
Then when you construct the array of balls, rather than just making 8 balls, you're going to want to allocate the memory on the heap so that it will last throughout your entire game. So do this:
Ball *ball= new Ball*[8];
ball[0] = new Ball(x0,y0);
ball[1] = new Ball(x1,y1);
ball[2] = new Ball(x2,y2);
ball[3] = new Ball(x3,y3);
// ...
Make sure that when your game is over, you clean up after yourself.
for (int i = 0; i < 8; i++)
delete ball[i];
delete [] ball;
Then in your Ball::draw() do something like this:
Ball::draw()
{
glColor3f(/*yellow*/); // Set the color to yellow
glTranslatef(-xpos, -ypos, 0); // Move to the position of the ball
// Draw the ball
glTranslatef(xpos, ypos, 0); // Move back to the default position
}
All you have to do is come up with the correct (x0,y0),(x1,y1),(x2,y2)... to form a triangle! Does this make sense/answer your question?

Is object remain fixed when scrolling background in cocos2d

I have one question when infinite background scrolling is done, is the object remain fixed(like doodle in doodle jump, papy in papi jump) or these object really moves.Is only background move or both (background and object )move.plz someone help me.I am searching for this solution for 4/5 days,but can't get the solution.So plz someone help me. And if object does not move how to create such a illusion of object moving.
If you add the object to the same layer as the scrolling background, then it will scroll as the background scrolls.
If your looking for an effect like the hero in doodle jump, you may want to look at having two or more layers in a scene.
Layer 1: Scrolling Background Layer
Layer 2: Sprite layer
SomeScene.m
CCLayer *backgroundLayer = [[CCLayer alloc] init];
CCLayer *spriteLayer= [[CCLayer alloc] init];
[self addChild:backgroundLayer z:0];
[self addChild:spriteLayer z:1];
//Hero stays in one spot regardless of background scrolling.
CCSprite *squidHero = [[CCSprite alloc] initWithFile:#"squid.png"];
[spriteLayer addChild:squidHero];
If you want objects to scroll with the background add it to the background layer:
//Platform moves with background.
CCSprite *bouncePlatform= [[CCSprite alloc] initWithFile:#"bouncePlatform.png"];
[backgroundLayer addChild:bouncePlatform];
Another alternative is to use a CCFollow action. You would code as if the background is static (which it will be) and the player is moving (which it will be), but add a CCFollow action to the player. This essentially moves the camera so that it tracks your player.
You can also modify the classes so that you can get the CCFollow action to follow with an offset (i.e., so the player is not in the middle of the screen) as well as to have a smoothing effect to it, so that when the player moves, the follow action is not jerky. See the below code:
*NOTE I am using cocos2d-x, the c++ port. The methods are similar in cocos2d, and you should be able to modify these to fit the cocos2d syntax. Or search around -- I found these for cocos2d and then ported to c++.
//defines the action to constantly follow the player (in my case, "runner.p_sprite is the sprite pointing to the player)
FollowWithOffset* followAction = FollowWithOffset::create(runner.p_sprite, CCRectZero);
runAction(followAction);
And separately, I have copied the class definition for CCFollow to create my own class, CCFollowWithAction. This also has a smoothing effect (you can look this up more online) so that when the player moves, the actions are not jerky. I modified "initWithTarget," to take into account an offset, and "step," to add a smoothing action. You can see the modifications in the comments below.
bool FollowWithOffset::initWithTarget(CCNode *pFollowedNode, const CCRect& rect/* = CCRectZero*/)
{
CCAssert(pFollowedNode != NULL, "");
pFollowedNode->retain();
m_pobFollowedNode = pFollowedNode;
if (rect.equals(CCRectZero))
{
m_bBoundarySet = false;
}
else
{
m_bBoundarySet = true;
}
m_bBoundaryFullyCovered = false;
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
m_obFullScreenSize = CCPointMake(winSize.width, winSize.height);
//m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);
m_obHalfScreenSize = CCPointMake(m_obFullScreenSize.x/2 + RUNNER_FOLLOW_OFFSET_X,
m_obFullScreenSize.y/2 + RUNNER_FOLLOW_OFFSET_Y);
if (m_bBoundarySet)
{
m_fLeftBoundary = -((rect.origin.x+rect.size.width) - m_obFullScreenSize.x);
m_fRightBoundary = -rect.origin.x ;
m_fTopBoundary = -rect.origin.y;
m_fBottomBoundary = -((rect.origin.y+rect.size.height) - m_obFullScreenSize.y);
if(m_fRightBoundary < m_fLeftBoundary)
{
// screen width is larger than world's boundary width
//set both in the middle of the world
m_fRightBoundary = m_fLeftBoundary = (m_fLeftBoundary + m_fRightBoundary) / 2;
}
if(m_fTopBoundary < m_fBottomBoundary)
{
// screen width is larger than world's boundary width
//set both in the middle of the world
m_fTopBoundary = m_fBottomBoundary = (m_fTopBoundary + m_fBottomBoundary) / 2;
}
if( (m_fTopBoundary == m_fBottomBoundary) && (m_fLeftBoundary == m_fRightBoundary) )
{
m_bBoundaryFullyCovered = true;
}
}
return true;
}
void FollowWithOffset::step(float dt)
{
CC_UNUSED_PARAM(dt);
if(m_bBoundarySet){
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(m_bBoundaryFullyCovered)
return;
CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
m_pTarget->setPosition(ccp(clampf(tempPos.x, m_fLeftBoundary, m_fRightBoundary),
clampf(tempPos.y, m_fBottomBoundary, m_fTopBoundary)));
}
else{
//custom written code to add in support for a smooth ccfollow action
CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
CCPoint moveVect = ccpMult(ccpSub(tempPos,m_pTarget->getPosition()),0.25); //0.25 is the smooth constant.
CCPoint newPos = ccpAdd(m_pTarget->getPosition(), moveVect);
m_pTarget->setPosition(newPos);
}
}