Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'skew' into develop

  • Loading branch information...
commit fa02b8ac43d48919127e6bca7398f3efa96ed95b 2 parents 1f45d9f + bb75a47
@ricardoquesada ricardoquesada authored
View
24 cocos2d/CCActionInterval.h
@@ -176,6 +176,30 @@ then running it again in Reverse mode.
-(id) initWithDuration: (ccTime)duration position:(CGPoint)deltaPosition;
@end
+/** Skews a CCNode object to given angles by modifying it's skewX and skewY attributes */
+@interface CCSkewTo : CCActionInterval <NSCopying>
+{
+ float skewX;
+ float skewY;
+ float startSkewX;
+ float startSkewY;
+ float endSkewX;
+ float endSkewY;
+ float deltaX;
+ float deltaY;
+}
+/** creates the action */
++(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy;
+/** initializes the action */
+-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy;
+@end
+
+/** Skews a CCNode object by skewX and skewY degrees */
+@interface CCSkewBy : CCSkewTo <NSCopying>
+{
+}
+@end
+
/** Moves a CCNode object simulating a parabolic jump movement by modifying it's position attribute.
*/
@interface CCJumpBy : CCActionInterval <NSCopying>
View
103 cocos2d/CCActionInterval.m
@@ -613,6 +613,109 @@ -(CCActionInterval*) reverse
}
@end
+
+//
+// SkewTo
+//
+#pragma mark -
+#pragma mark SkewTo
+
+@implementation CCSkewTo
++(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy
+{
+ return [[[self alloc] initWithDuration: t skewX:sx skewY:sy] autorelease];
+}
+
+-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy
+{
+ if( (self=[super initWithDuration:t]) ) {
+ endSkewX = sx;
+ endSkewY = sy;
+ }
+ return self;
+}
+
+-(id) copyWithZone: (NSZone*) zone
+{
+ CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] skewX:endSkewX skewY:endSkewY];
+ return copy;
+}
+
+-(void) startWithTarget:(CCNode *)aTarget
+{
+ [super startWithTarget:aTarget];
+
+ startSkewX = [target_ skewX];
+
+ if (startSkewX > 0)
+ startSkewX = fmodf(startSkewX, 180.0f);
+ else
+ startSkewX = fmodf(startSkewX, -180.0f);
+
+ deltaX = endSkewX - startSkewX;
+
+ if ( deltaX > 180 ) {
+ deltaX -= 360;
+ }
+ if ( deltaX < -180 ) {
+ deltaX += 360;
+ }
+
+ startSkewY = [target_ skewY];
+
+ if (startSkewY > 0)
+ startSkewY = fmodf(startSkewY, 360.0f);
+ else
+ startSkewY = fmodf(startSkewY, -360.0f);
+
+ deltaY = endSkewY - startSkewY;
+
+ if ( deltaY > 180 ) {
+ deltaY -= 360;
+ }
+ if ( deltaY < -180 ) {
+ deltaY += 360;
+ }
+}
+
+-(void) update: (ccTime) t
+{
+ [target_ setSkewX: (startSkewX + deltaX * t ) ];
+ [target_ setSkewY: (startSkewY + deltaY * t ) ];
+}
+
+@end
+
+//
+// CCSkewBy
+//
+@implementation CCSkewBy
+
+-(id) initWithDuration:(ccTime)t skewX:(float)deltaSkewX skewY:(float)deltaSkewY
+{
+ if( (self=[super initWithDuration:t skewX:deltaSkewX skewY:deltaSkewY]) ) {
+ skewX = deltaSkewX;
+ skewY = deltaSkewY;
+ }
+ return self;
+}
+
+-(void) startWithTarget:(CCNode *)aTarget
+{
+ [super startWithTarget:aTarget];
+ deltaX = skewX;
+ deltaY = skewY;
+ endSkewX = startSkewX + deltaX;
+ endSkewY = startSkewY + deltaY;
+}
+
+-(CCActionInterval*) reverse
+{
+ return [[self class] actionWithDuration:duration_ skewX:-skewX skewY:-skewY];
+}
+@end
+
+
//
// JumpBy
//
View
17 cocos2d/CCNode.h
@@ -105,6 +105,9 @@ enum {
// position of the node
CGPoint position_;
CGPoint positionInPixels_;
+
+ // skew angles
+ float skewX_, skewY_;
// is visible
BOOL visible_;
@@ -174,6 +177,20 @@ enum {
@since v0.8
*/
@property (nonatomic,readwrite) float vertexZ;
+
+/** The X skew angle of the node in degrees.
+ This angle describes the shear distortion in the X direction.
+ Thus, it is the angle between the Y axis and the left edge of the shape
+ The default skewX angle is 0. Positive values distort the node in a CW direction.
+ */
+@property(nonatomic,readwrite,assign) float skewX;
+
+/** The Y skew angle of the node in degrees.
+ This angle describes the shear distortion in the Y direction.
+ Thus, it is the angle between the X axis and the bottom edge of the shape
+ The default skewY angle is 0. Positive values distort the node in a CCW direction.
+ */
+@property(nonatomic,readwrite,assign) float skewY;
/** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. */
@property(nonatomic,readwrite,assign) float rotation;
/** The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. */
View
38 cocos2d/CCNode.m
@@ -73,12 +73,32 @@ @implementation CCNode
#pragma mark CCNode - Transform related properties
@synthesize rotation = rotation_, scaleX = scaleX_, scaleY = scaleY_;
+@synthesize skewX = skewX_, skewY = skewY_;
@synthesize position = position_, positionInPixels = positionInPixels_;
@synthesize anchorPoint = anchorPoint_, anchorPointInPixels = anchorPointInPixels_;
@synthesize contentSize = contentSize_, contentSizeInPixels = contentSizeInPixels_;
@synthesize isRelativeAnchorPoint = isRelativeAnchorPoint_;
// getters synthesized, setters explicit
+
+-(void) setSkewX:(float)newSkewX
+{
+ skewX_ = newSkewX;
+ isTransformDirty_ = isInverseDirty_ = YES;
+#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
+ isTransformGLDirty_ = YES;
+#endif
+}
+
+-(void) setSkewY:(float)newSkewY
+{
+ skewY_ = newSkewY;
+ isTransformDirty_ = isInverseDirty_ = YES;
+#if CC_NODE_TRANSFORM_USING_AFFINE_MATRIX
+ isTransformGLDirty_ = YES;
+#endif
+}
+
-(void) setRotation: (float)newRotation
{
rotation_ = newRotation;
@@ -237,6 +257,7 @@ -(id) init
isRunning_ = NO;
+ skewX_ = skewY_ = 0.0f;
rotation_ = 0.0f;
scaleX_ = scaleY_ = 1.0f;
positionInPixels_ = position_ = CGPointZero;
@@ -615,6 +636,12 @@ -(void) transform
if (rotation_ != 0.0f )
glRotatef( -rotation_, 0.0f, 0.0f, 1.0f );
+ // skew
+ if ( (skewX_ != 0.0f) || (skewY_ != 0.0f) ) {
+ GLfloat m[6] = { 1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_), tanf(CC_DEGREES_TO_RADIANS(skewX_), 1.0f, 0.0f, 0.0f };
+ glMultMatrixf(m);
+ }
+
// scale
if (scaleX_ != 1.0f || scaleY_ != 1.0f)
glScalef( scaleX_, scaleY_, 1.0f );
@@ -757,19 +784,26 @@ - (CGAffineTransform)nodeToParentTransform
if ( !isRelativeAnchorPoint_ && !CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) )
transform_ = CGAffineTransformTranslate(transform_, anchorPointInPixels_.x, anchorPointInPixels_.y);
-
+
if( ! CGPointEqualToPoint(positionInPixels_, CGPointZero) )
transform_ = CGAffineTransformTranslate(transform_, positionInPixels_.x, positionInPixels_.y);
if( rotation_ != 0 )
transform_ = CGAffineTransformRotate(transform_, -CC_DEGREES_TO_RADIANS(rotation_));
+ if( skewX_ != 0 || skewY_ != 0 ) {
+ // create a skewed coordinate system
+ CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(skewY_)), tanf(CC_DEGREES_TO_RADIANS(skewX_)), 1.0f, 0.0f, 0.0f);
+ // apply the skew to the transform
+ transform_ = CGAffineTransformConcat(skew, transform_);
+ }
+
if( ! (scaleX_ == 1 && scaleY_ == 1) )
transform_ = CGAffineTransformScale(transform_, scaleX_, scaleY_);
if( ! CGPointEqualToPoint(anchorPointInPixels_, CGPointZero) )
transform_ = CGAffineTransformTranslate(transform_, -anchorPointInPixels_.x, -anchorPointInPixels_.y);
-
+
isTransformDirty_ = NO;
}
View
4 cocos2d/CCSprite.h
@@ -52,9 +52,11 @@ typedef enum {
CC_HONOR_PARENT_TRANSFORM_ROTATE = 1 << 1,
//! Scale with it's parent
CC_HONOR_PARENT_TRANSFORM_SCALE = 1 << 2,
+ //! Skew with it's parent
+ CC_HONOR_PARENT_TRANSFORM_SKEW = 1 << 3,
//! All possible transformation enabled. Default value.
- CC_HONOR_PARENT_TRANSFORM_ALL = CC_HONOR_PARENT_TRANSFORM_TRANSLATE | CC_HONOR_PARENT_TRANSFORM_ROTATE | CC_HONOR_PARENT_TRANSFORM_SCALE,
+ CC_HONOR_PARENT_TRANSFORM_ALL = CC_HONOR_PARENT_TRANSFORM_TRANSLATE | CC_HONOR_PARENT_TRANSFORM_ROTATE | CC_HONOR_PARENT_TRANSFORM_SCALE | CC_HONOR_PARENT_TRANSFORM_SKEW,
} ccHonorParentTransform;
View
42 cocos2d/CCSprite.m
@@ -50,6 +50,7 @@
CGPoint pos; // position x and y
CGPoint scale; // scale x and y
float rotation;
+ CGPoint skew; // skew x and y
CGPoint ap; // anchor point in pixels
BOOL visible;
};
@@ -473,8 +474,24 @@ -(void)updateTransform
float c = cosf(radians);
float s = sinf(radians);
- matrix = CGAffineTransformMake( c * scaleX_, s * scaleX_,
- -s * scaleY_, c * scaleY_,
+ float matrixB = s * scaleX_;
+ if ( skewY_ != 0 )
+ {
+ // only apply skew if it is non-zero, to avoid
+ // cancelling the rotation component
+ matrixB *= tanf(CC_DEGREES_TO_RADIANS(skewY_));
+ }
+
+ float matrixC = -s * scaleY_;
+ if ( skewX_ != 0 )
+ {
+ // only apply skew if it is non-zero to avoid
+ // cancelling the rotation component
+ matrixC *= tanf(CC_DEGREES_TO_RADIANS(skewX_));
+ }
+
+ matrix = CGAffineTransformMake( c * scaleX_, matrixB,
+ matrixC, c * scaleY_,
positionInPixels_.x, positionInPixels_.y);
matrix = CGAffineTransformTranslate(matrix, -anchorPointInPixels_.x, -anchorPointInPixels_.y);
@@ -503,11 +520,16 @@ -(void)updateTransform
}
CGAffineTransform newMatrix = CGAffineTransformIdentity;
- // 2nd: Translate, Rotate, Scale
+ // 2nd: Translate, Skew, Rotate, Scale
if( prevHonor & CC_HONOR_PARENT_TRANSFORM_TRANSLATE )
newMatrix = CGAffineTransformTranslate(newMatrix, tv.pos.x, tv.pos.y);
if( prevHonor & CC_HONOR_PARENT_TRANSFORM_ROTATE )
newMatrix = CGAffineTransformRotate(newMatrix, -CC_DEGREES_TO_RADIANS(tv.rotation));
+ if ( prevHonor & CC_HONOR_PARENT_TRANSFORM_SKEW ) {
+ CGAffineTransform skew = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(tv.skew.y)), tanf(CC_DEGREES_TO_RADIANS(tv.skew.x)), 1.0f, 0.0f, 0.0f);
+ // apply the skew to the transform
+ newMatrix = CGAffineTransformConcat(skew, newMatrix);
+ }
if( prevHonor & CC_HONOR_PARENT_TRANSFORM_SCALE ) {
newMatrix = CGAffineTransformScale(newMatrix, tv.scale.x, tv.scale.y);
}
@@ -570,6 +592,8 @@ -(void) getTransformValues:(struct transformValues_*) tv
tv->scale.x = scaleX_;
tv->scale.y = scaleY_;
tv->rotation = rotation_;
+ tv->skew.x = skewX_;
+ tv->skew.y = skewY_;
tv->ap = anchorPointInPixels_;
tv->visible = visible_;
}
@@ -728,6 +752,18 @@ -(void)setRotation:(float)rot
SET_DIRTY_RECURSIVELY();
}
+-(void)setSkewX:(float)sx
+{
+ [super setSkewX:sx];
+ SET_DIRTY_RECURSIVELY();
+}
+
+-(void)setSkewY:(float)sy
+{
+ [super setSkewY:sy];
+ SET_DIRTY_RECURSIVELY();
+}
+
-(void)setScaleX:(float) sx
{
[super setScaleX:sx];
View
9 tests/ActionsTest.h
@@ -40,6 +40,7 @@
-(void) restartCallback:(id) sender;
@end
+
@interface ActionManual : ActionDemo
{}
@end
@@ -56,6 +57,14 @@
{}
@end
+@interface ActionSkew : ActionDemo
+{}
+@end
+
+@interface ActionSkewRotateScale : ActionDemo
+{}
+@end
+
@interface ActionJump : ActionDemo
{}
@end
View
77 tests/ActionsTest.m
@@ -18,6 +18,8 @@
@"ActionMove",
@"ActionRotate",
@"ActionScale",
+ @"ActionSkew",
+ @"ActionSkewRotateScale",
@"ActionJump",
@"ActionBezier",
@"ActionBlink",
@@ -311,6 +313,81 @@ -(NSString *) title
@end
+@implementation ActionSkew
+-(void) onEnter
+{
+ [super onEnter];
+
+ [self centerSprites:3];
+
+ id actionTo = [CCSkewTo actionWithDuration:2 skewX:37.2f skewY:-37.2f];
+ id actionToBack = [CCSkewTo actionWithDuration:2 skewX:0 skewY:0];
+ id actionBy = [CCSkewBy actionWithDuration:2 skewX:0.0f skewY:-90.0f];
+ id actionBy2 = [CCSkewBy actionWithDuration:2 skewX:45.0f skewY:45.0f];
+ id actionByBack = [actionBy reverse];
+
+ [tamara runAction:[CCSequence actions:actionTo, actionToBack, nil]];
+ [grossini runAction: [CCSequence actions:actionBy, actionByBack, nil]];
+
+ [kathia runAction: [CCSequence actions:actionBy2, [actionBy2 reverse], nil]];
+}
+-(NSString *) title
+{
+ return @"SkewTo / SkewBy";
+}
+
+@end
+
+@implementation ActionSkewRotateScale
+-(void) onEnter
+{
+ [super onEnter];
+
+ [tamara removeFromParentAndCleanup:YES];
+ [grossini removeFromParentAndCleanup:YES];
+ [kathia removeFromParentAndCleanup:YES];
+
+ CGSize boxSize = CGSizeMake(100.0f, 100.0f);
+
+ CCColorLayer *box = [CCColorLayer layerWithColor:ccc4(255,255,0,255)];
+ box.anchorPoint = ccp(0,0);
+ box.position = ccp(190,110);
+ box.contentSize = boxSize;
+
+ static CGFloat markerside = 10.0f;
+ CCColorLayer *uL = [CCColorLayer layerWithColor:ccc4(255,0,0,255)];
+ [box addChild:uL];
+ uL.contentSize = CGSizeMake(markerside, markerside);
+ uL.position = ccp(0.f, boxSize.height-markerside);
+ uL.anchorPoint = ccp(0,0);
+
+ CCColorLayer *uR = [CCColorLayer layerWithColor:ccc4(0,0,255,255)];
+ [box addChild:uR];
+ uR.contentSize = CGSizeMake(markerside, markerside);
+ uR.position = ccp(boxSize.width-markerside, boxSize.height-markerside);
+ uR.anchorPoint = ccp(0,0);
+ [self addChild:box];
+
+ id actionTo = [CCSkewTo actionWithDuration:2 skewX:0.f skewY:2.f];
+ id rotateTo = [CCRotateTo actionWithDuration:2 angle:61.0f];
+ id actionScaleTo = [CCScaleTo actionWithDuration:2 scaleX:-0.44f scaleY:0.47f];
+
+ id actionScaleToBack = [CCScaleTo actionWithDuration:2 scaleX:1.0f scaleY:1.0f];
+ id rotateToBack = [CCRotateTo actionWithDuration:2 angle:0];
+ id actionToBack = [CCSkewTo actionWithDuration:2 skewX:0 skewY:0];
+
+ [box runAction:[CCSequence actions:actionTo, actionToBack, nil]];
+ [box runAction:[CCSequence actions:rotateTo, rotateToBack, nil]];
+ [box runAction:[CCSequence actions:actionScaleTo, actionScaleToBack, nil]];
+}
+-(NSString *) title
+{
+ return @"Skew + Rotate + Scale";
+}
+
+@end
+
+
@implementation ActionJump
-(void) onEnter
{
Please sign in to comment.
Something went wrong with that request. Please try again.