I am using enableRetinaDisplay in my project and it is working very well except when I use this code.
//+++VRope
//create batchnode to render rope segments
CCSpriteBatchNode *ropeSegmentSprite = [CCSpriteBatchNode batchNodeWithFile:#"rope.png" ];
[game addChild:ropeSegmentSprite];
//Create two cgpoints for start and end point of rope
CGPoint pointA = ccp(73, 330); //Top
CGPoint pointB = ccp(self.position.x +5, self.position.y +30); //Bottom
//create vrope using initWithPoints method
verletRope = [[VRope alloc] initWithPoints:pointA pointB:pointB spriteSheet:ropeSegmentSprite];
Instead of drawing one high-res image of the rope, this code is drawing two rope images. I know that it is the retina display that is causing this because I tested it on an iphone 3gs and the simulator and it works great... until I test it on my iphone 4 then it draws two ropes instead of one. Am I doing something wrong?
I know it's too late but I found this question on the first page when searching google so I'll post this answer for others to find in the future.
In VRope.mm search for
[[[spriteSheet textureAtlas] texture] pixelsHigh]
and replace with
[[[spriteSheet textureAtlas] texture] pixelsHigh]/CC_CONTENT_SCALE_FACTOR()
That's it.
Related
I've looked around quite a bit and haven't been able to find a concise answer to this question. For my Cocos2D game I have integrated the Chipmunk physics engine. On initialization, I setup the boundaries of the 'playing field' by establishing a series of bodies and static shapes as follows:
- (void)initPlayingField {
// Physics parameters
CGSize fieldSize = _model.fieldSize;
CGFloat radius = 2.0;
CGFloat elasticity = 0.3;
CGFloat friction = 1.0;
// Bottom
CGPoint lowerLeft = ccp(0, 0);
CGPoint lowerRight = ccp(fieldSize.width, 0);
[self addStaticBodyToSpace:lowerLeft finish:lowerRight radius:radius elasticity:elasticity friction:friction];
// Left
CGPoint topLeft = ccp(0, fieldSize.height);
[self addStaticBodyToSpace:lowerLeft finish:topLeft radius:radius elasticity:elasticity friction:friction];
// Right
CGPoint topRight = ccp(fieldSize.width, fieldSize.height);
[self addStaticBodyToSpace:lowerRight finish:topRight radius:radius elasticity:elasticity friction:friction];
// Top
[self addStaticBodyToSpace:topLeft finish:topRight radius:radius elasticity:elasticity friction:friction];
}
This setup works, except for one thing-- the positions of the boundaries appear to be off by a significant amount of pixels to the right. After initializing a player, and sending him towards the boundary walls, it does not bounce off the edges of the screen (as I would expect by setting up the bounding box at 0,0), but rather some number of pixels (maybe 30-50) inwards from the edges of the screen. What gives?
I initially thought the issue came from where I was rendering the player sprite, but after running it through the debugger, everything looks good. Are there special protocols to follow when using chipmunk's positions to render sprites? Do I need to multiply everything by some sort of PIXELS_PER_METER? Would it matter if they are in a sprite sheet? A sprite batch node? Here is how I set the sprite position in my view:
Player *player = [[RootModel sharedModel] player];
self.playerSprite.position = player.position;
self.playerSprite.rotation = player.rotation;
And here is how I set the position in my Model:
- (void)update:(CGFloat)dt {
self.position = self.body->p;
self.rotation = self.body->a;
}
(Yes, I know it's redundant to store the position because chipmunk does that inherently.)
Also, bonus question for for those who finished reading the post. How might you move a body at a constant velocity in whatever direction it is facing, only allowing it to turn left or right at any given time, but never slow down?
What's the shape of the physics body? Perhaps you simply forgot to consider making the shape the same size of the sprite. If you only consider the position, then the sprite will be able to move halfway outside the screen at any border because its position is at the center of the sprite.
To move a body at constant velocity, set its velocity while disabling friction (set to 0?) and allowing it to rebound off of collisions with its impact speed (in Box2D that would be restitution = 1, don't know about Chipmunk).
Have you tried debug drawing the collision shapes? Cocos2D 2.1 has my CCPhysicsDebugNode class in it that makes it pretty easy to add. That will let you know if your geometry is lined up with your graphics. How thick are your boundary shapes? Are you possibly adding the sprites to a parent node that might be offsetting them?
Chipmunk doesn't require you to tune it for any real units. You can just use pixels or whatever.
Lastly, #LearnCocos2D has the right idea about the constant velocity. Set friction to 0 and elasticity to 1.0. You will also probably want to check it's velocity every frame and accelerate it back towards it's normal velocity each frame. Colliding with non-static geometry will cause it to lose speed.
EDIT: If the question is badly written have a look at the video (3), same link as in the bottom of this page.
I am trying to draw a very simple bezier curve using ccBezierConfig and Cocos2D. Reading on Wikipedia I tried to understand a bit controls points and found this image:
http://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Bezier_2_big.png/240px-Bezier_2_big.png
If you look on the wikipedia page from which I took the image there is a cool animation. Have a look here.
This is the code I used:
CCSprite *r = [CCSprite spriteWithFile:#"hi.png"];
r.anchorPoint = CGPointMake(0.5f, 0.5f);
r.position = CGPointMake(0.0f, 200.0f);
ccBezierConfig bezier;
bezier.controlPoint_1 = CGPointMake(0.0f, 200.0f);
bezier.controlPoint_1 = CGPointMake(180.0f, 330.0f);
bezier.endPosition = CGPointMake(320.0f,200.0f);
id bezierForward = [CCBezierBy actionWithDuration:1 bezier:bezier];
[r runAction:bezierForward];
[self addChild:r z:0 tag:77];
The app runs on Portrait mode and my speculation matching the control points of 1 and the ones in my code was that:
sprite.position should correspond to P0
bezier.controlPoint_1 should correspond to P0
bezier.controlPoint_2 should correspond to P1
bezier.endPosition should correspond to P2
I did try two approaches. By setting the position of the sprite and by not setting it.
I assumed that position should be the same as controlPoint_1 as in the wikipedia schema 1 there are only three points.
I get an output I don't quiet understand.. I made a little video of it, is a private youtube video:
to see the video click here
OK, the answer is rather simple...
The quadratic Bézier curve is not the one drawn by cocos2d. Instead, check the same wiki page for cubic Bézier curve. That's what you should be looking at.
Initial position is the position of the sprite (P0)
Control points 1 & 2 are P1 & P2, respectively.
End point is the end point.
Nice video, btw, I enjoyed it xD.
Evidence from the CCActionInterval.h file in the cocos2d library:
/** An action that moves the target with a cubic Bezier curve by a certain distance.
*/
#interface CCBezierBy : CCActionInterval <NSCopying>
{
ccBezierConfig config;
CGPoint startPosition;
}
This link should help you construct your cubic Bézier curves visually, instead of tweaking the values and running the app.
I have a CCSprite object of which I need to update the on screen (x,y) position as quickly as possible. It is an augmented reality app so the on screen position needs to appear fixed to a real world location.
Currently, during each update I check the heading and attitude of the device then move the sprite accordingly by determining the new x and y positions
[spriteObject setPosition:ccp(newX, newY)];
Each degree change in heading corresponds to 10 pixels in on screen position, so by setting the position this way the sprite jumps around in intervals of 10 pixels which looks stupid. I'd like to animate it smoothly, maybe by using
[spriteObject runAction:[CCMoveTo actionWithDuration:0.2f position:ccp(newX, newY)]];
but the problem here is that a new position update comes in while the sprite is animating and it sort of screws the whole thing up. Anyone know of a nice solution to this problem? Any help is much appreciated as I've tried numerous failed solutions to this point.
You can try to just animate your sprite movement to the point. I mean, you can several times during one second run animated position correction with duration of 1/numberOfUpdates in one second. Something like
- (void) onEnter
{
[super onEnter];
[self schedule:#selector(updatePositionAnimated) interval:0.2f];
}
- (void) updatePositionAnimated
{
[spriteObject runAction:[CCMoveTo actionWithDuration:0.2f position:ccp(newX, newY)]];
}
I suppose, you will have smooth enough animation in this case
I'm really going crazy trying to figure this out, so any help would be really appreciated. I'm trying to hide most of a sprite and show it gradually. This works fine if I only work with rectangles. For example, I found someone's implementation of the "ClippingNode" class and it worked well, namely, this part of the code:
-(void) visit
{
glPushMatrix();
glEnable(GL_SCISSOR_TEST);
glScissor(clippingRegion.origin.x + positionInPixels_.x, clippingRegion.origin.y + positionInPixels_.y, clippingRegion.size.width, clippingRegion.size.height);
[super visit];
glDisable(GL_SCISSOR_TEST);
glPopMatrix();
}
The problem is I need an irregular shape, not just a rectangle. I was hoping I could stack calls to glScissor and create a shape with many smaller rectangles, but unfortunately glScissor only works once (the last time it was called).
It seems that cocos2d doesn't support OpenGLs stencil buffer (does it?) and even if it did, I find OpenGL so hard to understand, I'd still need someone to explain it to me. If I could set a bezier path on the sprite as a mask (which I think you can do in Quartz), that would be great, but it doesn't seem like that's supported.
Please, if anyone has any bit of wisdom here, that'd be great!
Figured it out. You can call glScissor multiple times, you just also need to draw that scissored shape each time:
-(void) visit
{
NSEnumerator *enumerator;
NSValue *val;
CGRect aRegion;
glPushMatrix();
glEnable(GL_SCISSOR_TEST);
enumerator = [regions objectEnumerator];
while ((val = (NSValue *)[enumerator nextObject])) {
aRegion = [val CGRectValue];
glScissor(aRegion.origin.x, aRegion.origin.y,
aRegion.size.width, aRegion.size.height);
[super visit];
}
glDisable(GL_SCISSOR_TEST);
glPopMatrix();
}
It isn't possible with glScissor, but you could easily achieve this effect using the stencil buffer. Here is the documentation:
http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html
There is also a NeHe tutorial on the stencil buffer, but it is in C++, not Objective C (though it should be easy to translate into whatever application you need):
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=26
EDIT: This is based on the assumption that you want to clip it to some arbitrary shape, for example a star, smiley whatever, instead of just a rectangle.
I'm using cocos2d v0.99.5-beta2 and I have a strange problem only on iPhone 1st gen and iPhone 3g.
When I change iPhone's orientation all my CCSprite are deformed and duplicated.
I already have tested many methods to rotate my scene but I always have the same result.
But I haven't this problem on simulator, iPhone 4 and iPad.
See screenshots
I wonder if it's not a problem linked to the hardware. It looks like as the graphic hardware doesn't support orientation changes. But it's only suppositions.
I hope someone can help me.
Not sure if this will make a difference but are you specifying the content size of the texture or are you letting cocos2d define it? Here I am using a subclass of CCSprite (spuButton):
CCTexture2D *redButtonNormal = [[CCTextureCache sharedTextureCache] addImage:#"RedButtonNormal.png"]; //I don't specify the content size.
spuButton *redButton = [spuButton spuButtonWithTexture:redButtonNormal];
redButton.position = ccp(((size.width / 2) - (redButton.contentSize.width / 2)), ((size.height / 2) + (redButton.contentSize.height / 2)));
[self addChild:redButton];
Hope this helps 8)