Why does Cocos2d-x not show the sprite the first time? - c++

What is the problem? It does not show the sprite the first time.
playerSprite = Sprite::create("ip.png");
playerSprite->setPosition(Vec2(visibleSize.width/2,visibleSize.height));
//this->addChild(playerSprite,1);
auto body = PhysicsBody::createCircle
(playerSprite->getContentSize().width / 2.5);
body->setContactTestBitmask(true);
body->setDynamic(true);
playerSprite->setPhysicsBody(body);
this->addChild(playerSprite,0);

Try Using Another Z-Order of your Sprite. this->addChild(playerSprite,TRY_WITH_SOME_LARGE_VALUE);`
AND see if the result are Same.

Since you questions is not much defined, answer might be incorrect.
First of all, make sure that image is placed correctly and there is no typos in image name.
playerSprite position is in the middle of the top. to center it:
->setPosition(Point(visibleSize.widht * 0.5, visibleSize.height * 0.5));
If this == Scene you can do it like this.
->setPosition(Point(this->getContentSize().width * 0.5, this->getContentSize().height * 0.5));
Also when adding Sprite make sure there is no other Sprite above by setting zOrder to a bigger number
this->addChild(playerSprite, 100);

Related

Box2D with SFML object are ovverlapping and going over each other after colliding

I am using Box2D and SFML to create a simple game. However, my object (ball) does not completely lands after it hits the ground. It seems that 50% of the ball has passed through my border, which looks really awkward. Below are some pictures for illustration.
Ball Before:
Ball After hitting the border at the ground:
As you can see, 50% of the ball has dissapeared (most probably due to offsets or what). Anyone know how to fix it?
Below are my code for the object creation:
circ_ = sf::CircleShape(radius);
circ_.setOrigin(sf::Vector2f(size.x/2,size.y/2));
circ_.setFillColor(sf::Color(255, 255, 255, 255));
circ_.setOutlineThickness(1);
circ_.setOutlineColor(sf::Color::Black);
bodyDef_.position = b2Vec2(position.x/PIXEL_PER_METER, position.y/PIXEL_PER_METER);
bodyDef_.type = b2_staticBody;
bodyFixtureDef_.density = 1.0f;
bodyFixtureDef_.friction = 0.3f;
bodyFixtureDef_.restitution = 0.8f;
Where on my SFML code, I have created the Box2D object using:
Ball basketBall(world, basketBallSize, basketBallPos, 0.0, basketBallRadius, false);
Where radius = 32.
Anybody could help me with this? Thanks.
Box2d uses the center of a circle/polygon shape as position while SFML uses the top left corner of the sprite/shape as position, so you need to take that into account when translating between SFML and Box2d positions. Also keep in mind Box2d uses meters instead of pixles and radians instead of degrees.
Just do like that:
#include <cmath> // for M_PI define
Sprite.setPosition(sf::Vector2f(b2BallBody->GetPosition().x * PIXEL_PER_METER - Sprite.getGlobalBounds().width * 0.5f,
b2BallBody->GetPosition().y * PIXEL_PER_METER - Sprite.getGlobalBounds().height * 0.5f));
Sprite.setRotation(b2BallBody->GetAngle() * (float)(180.0 / M_PI));

Displaying part of the sprite

Here is my problem. The goal is to make a scale, that fills out while the char collects the food.
I got 2 sprites: the scale without the filling and the filling itself. So my question is simple: how to draw a part of the filling sprite depending on the number of "apples" eaten? =)
I solved a similar problem for a loading bar some time ago, using glScissor. Basically I extended CCSprite with a float indicating the filled portion, and overrode visit method like this.-
- (void) visit {
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, (loadingPercent / 100) * self.contentSize.width * CC_CONTENT_SCALE_FACTOR(), self.contentSize.height * 4);
[super visit];
glDisable(GL_SCISSOR_TEST);
}
Hope it helps.

Parent coordinate given a CCNode local coordinate

Is there any cocos2d function that returns the parent coordinate given a node local coordinate? It must be quite a common use case, but I've not found any native cocos2d function. Is there any?
I guess it's something like this. NOTE, I haven't tested this one. ;)
-(CGPoint) nodeToParent: (CGPoint) localPoint
{
CGFloat phi = -self.rotation * B2_pi / 180;
return ccpAdd(self.position, ccpRotateByAngle(localPoint, ccp(0, 0), phi));
}
As m.ding said ... parent->ConvertToNodeSpace() .....
Here's explanation for you so you know when to do what ?
convertToWorldSpace(const CCPoint& nodePoint) converts on-node coords to SCREEN coordinates.
Lets we have layerA with anchor point and position (0,0) attached to screen and have a sprite on this layer at point (100, 100).
What will be SCREEN coords of sprite? - (100, 100)
Lets we moved layerA to point (- 50, - 20). What will be SCREEN coords of sprite? - (100 - 50, 100 - 20), i.e. (50, 80) - that's what convertToWorldSpace returns to us if we call layerA->convertToWorldSpace(ccp(100, 100)).
As for convertToWorldSpaceAR - will return the position relatevely to anchor point: so if our scene - root layer has AP (0.5f, 0.5f) - default, convertToWorldSpaceAR should return position relatively to screen center. I have used convertToNodeSpace
convertToNodeSpace(const CCPoint& worldPoint) - converts SCREEN coords to NODE's local. I.e. if for our example with moved layer call:
layerA->convertToNodeSpace(ccp(50, 80)) - that should return (100, 100) - our sprite on-node coords.
convertToNodeSpaceAR - the same logic as for convertToWorldSpaceAR
assume your parent node is
CCSprite* parent;
you can use:
parent->convertToNodeSpace();
I guess that
-(CGPoint) convertToWorldSpace:(CGPoint)pt
could do the trick, take a look here.
It looks like you are on the right track. [node position] should give the position of the node in the parent's coordinate space, so if you have a local point that is offset from the [node position] then you need to do add the offset like you have done. I'm not sure the ccpRotateByAngle is the right method to do that but you'll just have to test it and find out!

Cocos2D+Box2D: Stack bodies that doesn´t fall?

EDIT 2: Problem solved! I can´t promise it will work with different settings, but by putting my block´s body density to 0, the stack of blocks did not fall when new blocks are added.
I´m sorry about the poor title of the question, I´ll explain my problem closer here:
So, I´ve used Box2D and cocos2D to setup a simple project where two boxes stacks on top of each other (I´m planning to expand to 8-10 boxes). Right now, using a friction of 10.0f on each box, the box at the top still moves around a little. If I would add more boxes, the "tower" would fall and I don´t want that.
I want the boxes to use the gravity to move down, but I never ever want them to change there start x-value.
So, how could I prevent my tower of boxes to fall over or prevent my boxes from moving in x-direction?
EDIT: Posting some code
This code creates on of the boxes, the other one just have a different sprite file.
CCSprite *block = [CCSprite spriteWithFile:#"red.png"];
block.position = ccp(200,380);
[self addChild:block];
//Body definition
b2BodyDef blockDef;
blockDef.type = b2_dynamicBody;
blockDef.position.Set(200/PTM_RATIO, 200/PTM_RATIO);
blockDef.userData = block;
b2Body *blockBody = _world->CreateBody(&blockDef);
//Create the shape
b2PolygonShape blockShape;
blockShape.SetAsBox(block.contentSize.width/PTM_RATIO/2, block.contentSize.height/PTM_RATIO/2);
//Fixture defintion
b2FixtureDef blockFixtureDef;
blockFixtureDef.shape = &blockShape;
blockFixtureDef.restitution = 0.0f;
blockFixtureDef.density = 10.0f;
blockFixtureDef.friction = 10.0f;
_redBlockFixture = blockBody->CreateFixture(&blockFixtureDef);
Nothing fancy.
Regards.
You could setup a 2 (1 pixel wide) walls in box2D to the left and right of the block. Here's some sample code for the left wall. To create the right wall, just copy and past the code and change the variable names and the position of the BodyDef.
// Constant you'll need to define
float wallHeight;
// Create wall body
b2BodyDef wallBodyDef;
wallBodyDef.type = b2_dynamicBody;
wallBodyDef.position.Set(200 - block.contentSize.width/PTM_RATIO/2, 0);
b2Body *wallBody = _world->CreateBody(&wallBodyDef);
// Create wall shape
b2PolygonShape wallShape;
wallShape.SetAsBox(1, wallHeight);
// Create shape definition and add to body
b2FixtureDef wallShapeDef;
wallShapeDef.shape = &wallShape;
wallShapeDef.density = 100.0f;
wallShapeDef.friction = 0.0f;
wallShapeDef.restitution = 0.0f;
b2Fixture *wallFixture = wallBody->CreateFixture(&wallShapeDef);
I solved this problem by adjusting the restitution (bounce) of the static surface upon which the blocks are stacked. For example, if the floor has a restitution of .2, a stack of five blocks will look like they are compressing into each other, and eventually topple:
Set the restitution of the floor to 0, and the blocks stay stacked the way you would expect:

How to draw line in topmost z-oder

I want to draw line connect two sprites, but i can not do that in this case:
//add Map Background
map = [CCTMXTiledMap tiledMapWithTMXFile:#"orthogonal-test-zorder.tmx"];
[self addChild:map z:1 tag:kTagTileMap];
//overite draw function
- (void)draw {
glColor4f(0.8, 1.0, 0.76, 1.0);
glEnable(GL_LINE_SMOOTH);
ccDrawLine( ccp(0, 0), ccp(150, 150) );
}
the line is not shown on screen, if i remove map background , it's shown.
I don't know Cocos2D so this is just wild guessing, but the z parameter of [self addChild:map z:1 tag:kTagTileMap]; seems to be a z offset. Since 1 would be in front of 0 (the likely default), your map would render in front of your line. Try [self addChild:map z:-1 tag:kTagTileMap];
I've encounted same problem 2 days ago.
My solution is to make a seperate MyLineLayer which only draw the line. Then you can set the z-index of the CCLayer to the top.
I think that using an enveloped MyLineLayer would be better than make the z-index of the tile map smaller.