Reputation: 8012
I have a circular disc sprite that always rotates around its center, spinning like a wheel. I want to re-orient it in 3d space and keep its rotation. I've tried messing with the grid property, skewX/Y, the camera, everything I can find, but I can't figure out how to produce this effect with rotation.
Upvotes: 2
Views: 2950
Reputation: 8012
HachiEthan's answer is good, and allows you to set the perspective with skewX/skewY while maintaining rotation. However, I think that it is easier to work with the camera for setting perspective. In that case, you can achieve the effect by wrapping your rotating sprite in a parent node.
For example:
CCNode *node3D;
CCSprite *sprite;
node3D = [CCNode node];
sprite = [CCSprite spriteWithFile:@"HugeDisc_Red.png"];
//[[node3D camera] setCenterX:15 centerY:45 centerZ:40]; // You can use the camera
[node3D setSkewX:25]; // Skew also works if you prefer it
[node3D setRotation:145]; // Skew + rotation looks pretty convincing
[node3D setPosition:ccp(middleX+105, middleY-110)];
[node3D setIgnoreAnchorPointForPosition:NO];
[node3D setAnchorPoint:ccp(0.5f,0.5f)];
[sprite setPosition:ccp(node3D.contentSize.width/2, node3D.contentSize.height/2)];
[sprite runAction:rotate];
[node3D addChild:sprite];
Ultimately, it comes down to a matter of preference. Do you want to make a custom sprite object for this? Do you prefer camera, or skew? Depending on your needs, one of these should fit your needs.
Upvotes: 2
Reputation: 5703
A couple routes:
Figure out the maths to get the correct skew value for the rotation value. (I don't know off of the top of my head, sorry, although you can probably reverse engineer it from option-2)
You could sub-class CCSprite
, override CCNode
's - (CGAffineTransform)nodeToParentTransform
method and have to apply the skew first, THEN rotation, in order to get your desired effect. This spares you figuring out the proper skew calculation at the expense of a fairly kludgy sprite subclass.
From CCNode.h
you can learn its current order of operations:
/* Order in transformations with grid disabled
-# The node will be translated (position)
-# The node will be rotated (rotation)
-# The node will be skewed (skewX, skewY)
-# The node will be scaled (scale, scaleX, scaleY)
-# The node will be moved according to the camera values (camera)
... etc. */
Here's a hacked together version of that method with skew first: (lacks optimizations found in original method in CCNode.m
)
- (CGAffineTransform)nodeToParentTransform
{
if ( isTransformDirty_ ) {
// Translate values
float x = position_.x;
float y = position_.y;
if ( ignoreAnchorPointForPosition_ ) {
x += anchorPointInPoints_.x;
y += anchorPointInPoints_.y;
}
transform_ = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)),
tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f,
x, y );
// Rotation values
float c = 1, s = 0;
if( rotation_ ) {
float radians = -CC_DEGREES_TO_RADIANS(rotation_);
c = cosf(radians);
s = sinf(radians);
}
CGAffineTransform rotMatrix = CGAffineTransformMake( c * scaleX_, s * scaleX_,
-s * scaleY_, c * scaleY_,
0.0f, 0.0f );
transform_ = CGAffineTransformConcat(rotMatrix, transform_);
// adjust anchor point
if( ! CGPointEqualToPoint(anchorPointInPoints_, CGPointZero) )
transform_ = CGAffineTransformTranslate(transform_, -anchorPointInPoints_.x, -anchorPointInPoints_.y);
isTransformDirty_ = NO;
}
return transform_;
}
Upvotes: 2