/FlappyBird.spritebuilder/Source/libs/cocos2d-iphone.backup/UnitTests/CCPhysicsTests.m
https://gitlab.com/lirao/FlappyBird-SpriteBuilder · Objective C · 1110 lines · 767 code · 262 blank · 81 comment · 46 complexity · c061fda80d9133db252fb09c65752e0a MD5 · raw file
- //
- // CCPhysicsTests.m
- // CCPhysicsTests
- //
- // Created by Scott Lembcke on 10/11/13.
- //
- //
- #import <XCTest/XCTest.h>
- #import "cocos2d.h"
- #import "CCPhysics+ObjectiveChipmunk.h"
- #import "CCDirector_Private.h"
- @interface CCScheduler(Test)
- -(CCTimer*)fixedUpdateTimer;
- @end
- @interface CCPhysicsTests : XCTestCase <CCPhysicsCollisionDelegate>
- @end
- @implementation CCPhysicsTests
- static void
- TestBasicSequenceHelper(id self, CCPhysicsNode *physicsNode, CCNode *parent, CCNode *node, CCPhysicsBody *body)
- {
- // Probably not necessary, but doesn't hurt.
- CCScene *scene = [CCScene node];
- [scene addChild:physicsNode];
-
- // Allow the parent to be the physics node.
- if(parent != physicsNode) [physicsNode addChild:parent];
-
- CGPoint position = node.position;
- float rotation = node.rotation;
-
- const float accuracy = 1e-4;
-
- // Sanity check.
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- [parent addChild:node];
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Set the physics body.
- // Node's internal transform is still used since the onEnter hasn't happened.
- node.physicsBody = body;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Force on onEnter to be called.
- // Body's transform is now used instead of the node's.
- [scene onEnter];
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Remove the node and check the position is still correct
- [node removeFromParent];
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Add back to the physics
- [parent addChild:node];
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Force onExit
- [scene onExit];
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Force re-entry to the scene.
- [scene onEnter];
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Try switching the physics body.
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:ccp(1,1)];
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Test setting the body to nil.
- node.physicsBody = nil;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Set back to the original body
- node.physicsBody = body;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Try setting the body when not added to a scene anymore.
- [node removeFromParent];
- node.physicsBody = nil;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Check that setting the position works in this state.
- node.position = position;
- XCTAssertTrue(ccpDistance(node.position, position) < accuracy, @"");
- XCTAssertEqualWithAccuracy(node.rotation, rotation, accuracy, @"");
-
- // Terrible things happen when you don't call this due to Cocos2D global variables.
- [scene onExit];
- }
- -(void)testBasicSequences1
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- CCNode *node = [CCNode node];
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, physicsNode, node, body);
- }
- -(void)testBasicSequences2
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *node = [CCNode node];
- node.position = ccp(100, 100);
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, physicsNode, node, body);
- }
- -(void)testBasicSequences3
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, physicsNode, node, body);
- }
- -(void)testBasicSequences4
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
- node.rotation = 30;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, physicsNode, node, body);
- }
- -(void)testBasicSequences5
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
- node.rotation = 30;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, physicsNode, node, body);
- }
- -(void)testBasicSequences6
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *parent = [CCNode node];
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
- node.rotation = 30;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, parent, node, body);
- }
- -(void)testBasicSequences7
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *parent = [CCNode node];
- parent.position = ccp(20, 60);
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
- node.rotation = 30;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, parent, node, body);
- }
- -(void)testBasicSequences8
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *parent = [CCNode node];
- parent.contentSize = CGSizeMake(25, 35);
- parent.anchorPoint = ccp(0.3, 0.7);
- parent.position = ccp(20, 60);
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
- node.rotation = 30;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, parent, node, body);
- }
- -(void)testBasicSequences9
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *parent = [CCNode node];
- parent.contentSize = CGSizeMake(25, 35);
- parent.anchorPoint = ccp(0.3, 0.7);
- parent.position = ccp(20, 60);
- parent.rotation = -10;
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0.5, 0.5);
- node.position = ccp(100, 100);
- node.rotation = 35;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, parent, node, body);
- }
- -(void)testBasicSequences10
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *parent = [CCNode node];
- parent.contentSize = CGSizeMake(25, 35);
- parent.anchorPoint = ccp(0.3, 0.7);
- parent.position = ccp(20, 60);
- parent.rotation = -15;
- parent.scaleX = 1.5;
- parent.scaleY = 8.0;
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0,0);
- node.position = ccp(100, 100);
- node.rotation = 30;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
-
- TestBasicSequenceHelper(self, physicsNode, parent, node, body);
- }
- -(void)testBasicSequences11
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *parent = [CCNode node];
- parent.contentSize = CGSizeMake(25, 35);
- parent.anchorPoint = ccp(0.3, 0.7);
- parent.position = ccp(20, 60);
- parent.rotation = -15;
- parent.scaleX = 1.5;
- parent.scaleY = 8.0;
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(30, 30);
- node.anchorPoint = ccp(0,0);
- node.position = ccp(100, 100);
- node.rotation = 30;
- node.scaleX = 2.0;
- node.scaleY = 3.0;
-
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- body.type = CCPhysicsBodyTypeStatic;
-
- TestBasicSequenceHelper(self, physicsNode, parent, node, body);
- }
- -(void)testDynamicAnchorPoint
- {
- cpFloat accuracy = 1e-4;
-
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(2, 2);
- node.anchorPoint = ccp(0.5, 0.5);
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node.physicsBody.type = CCPhysicsBodyTypeDynamic;
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- [physicsNode addChild:node];
- [physicsNode onEnter];
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- node.rotation = 90;
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- [physicsNode onExit];
- }
- -(void)testStaticAnchorPoint
- {
- cpFloat accuracy = 1e-4;
-
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- CCNode *node = [CCNode node];
- node.contentSize = CGSizeMake(2, 2);
- node.anchorPoint = ccp(0.5, 0.5);
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node.physicsBody.type = CCPhysicsBodyTypeStatic;
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- [physicsNode addChild:node];
- [physicsNode onEnter];
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- node.rotation = 90;
- XCTAssert(ccpDistance(node.position, CGPointZero) < accuracy, @"");
-
- [physicsNode onExit];
- }
- -(void)testCollisionGroups
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
-
- NSString *noCollide = @"nocollide";
-
- CCNode *node1 = [CCNode node];
- node1.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node1.physicsBody.collisionGroup = noCollide;
- [physicsNode addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node2.physicsBody.collisionGroup = noCollide;
- [physicsNode addChild:node2];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- // Step the physics for a while.
- for(int i=0; i<100; i++){
- [physicsNode fixedUpdate:1.0/60.0];
- }
-
- // Both nodes should be at (0, 0)
- XCTAssertTrue(CGPointEqualToPoint(node1.position, CGPointZero) , @"");
- XCTAssertTrue(CGPointEqualToPoint(node2.position, CGPointZero) , @"");
-
- [physicsNode onExit];
- }
- -(void)testAffectedByGravity
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- physicsNode.gravity = ccp(0, -100);
-
- NSString *noCollide = @"nocollide";
-
- CCNode *node1 = [CCNode node];
- node1.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node1.physicsBody.collisionGroup = noCollide;
- [physicsNode addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node2.physicsBody.collisionGroup = noCollide;
- node2.physicsBody.affectedByGravity = NO;
- [physicsNode addChild:node2];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- // Step the physics for a while.
- for(int i=0; i<100; i++){
- [physicsNode fixedUpdate:1.0/60.0];
- }
-
- // Node1 should move down due to gravity
- XCTAssertTrue(node1.position.y < 0.0, @"");
-
- // Node2 should stay at (0, 0)
- XCTAssertTrue(node2.position.y == 0.0, @"");
-
- [physicsNode onExit];
- }
- -(void)testAllowsRotation
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- [physicsNode onEnter];
-
- {
- // Regular body.
- CCNode *node = [CCNode node];
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- [physicsNode addChild:node];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- XCTAssert(node.physicsBody.body.moment < INFINITY, @"");
- }{
- // Set before adding.
- CCNode *node = [CCNode node];
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node.physicsBody.allowsRotation = NO;
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
-
- [physicsNode addChild:node];
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
-
- XCTAssert(node.physicsBody.body.moment == INFINITY, @"");
- }{
- // Set after adding.
- CCNode *node = [CCNode node];
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- [physicsNode addChild:node];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
- node.physicsBody.allowsRotation = NO;
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
-
- XCTAssert(node.physicsBody.body.moment == INFINITY, @"");
- }{
- // Set and reverted before adding.
- CCNode *node = [CCNode node];
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node.physicsBody.allowsRotation = NO;
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
- node.physicsBody.allowsRotation = YES;
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- [physicsNode addChild:node];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- XCTAssert(node.physicsBody.body.moment < INFINITY, @"");
- }{
- // Set before and reverted after adding.
- CCNode *node = [CCNode node];
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node.physicsBody.allowsRotation = NO;
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
-
- [physicsNode addChild:node];
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
- node.physicsBody.allowsRotation = YES;
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- XCTAssert(node.physicsBody.body.moment < INFINITY, @"");
- }{
- // Set reverted after adding.
- CCNode *node = [CCNode node];
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- [physicsNode addChild:node];
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
- node.physicsBody.allowsRotation = NO;
- XCTAssert(node.physicsBody.allowsRotation == NO, @"");
- node.physicsBody.allowsRotation = YES;
- XCTAssert(node.physicsBody.allowsRotation == YES, @"");
-
- XCTAssert(node.physicsBody.body.moment < INFINITY, @"");
- }
-
- [physicsNode onExit];
- }
- -(void)testBodyType
- {
- CGPoint points[3] = {};
-
- // Regular bodies should default to being dynamic.
- XCTAssertEqual([CCPhysicsBody bodyWithCircleOfRadius:0 andCenter:CGPointZero].type, CCPhysicsBodyTypeDynamic, @"");
- XCTAssertEqual([CCPhysicsBody bodyWithPillFrom:ccp(0, 1) to:ccp(1, 0) cornerRadius:0].type, CCPhysicsBodyTypeDynamic, @"");
- XCTAssertEqual([CCPhysicsBody bodyWithPolygonFromPoints:points count:3 cornerRadius:0].type, CCPhysicsBodyTypeDynamic, @"");
- XCTAssertEqual([CCPhysicsBody bodyWithRect:CGRectZero cornerRadius:0].type, CCPhysicsBodyTypeDynamic, @"");
-
- // Polyline bodies should default to being static bodies.
- XCTAssertEqual([CCPhysicsBody bodyWithPolylineFromRect:CGRectZero cornerRadius:0].type, CCPhysicsBodyTypeStatic, @"");
-
- XCTAssertEqual([CCPhysicsBody bodyWithPolylineFromPoints:points count:3 cornerRadius:0 looped:YES].type, CCPhysicsBodyTypeStatic, @"");
-
- // Test body type setters
- CCPhysicsBody *body = [CCPhysicsBody bodyWithCircleOfRadius:0 andCenter:CGPointZero];
-
- body.type = CCPhysicsBodyTypeStatic;
- XCTAssertEqual(body.type, CCPhysicsBodyTypeStatic, @"");
- XCTAssertEqual(body.body.type, CP_BODY_TYPE_STATIC, @"");
-
- // body.type = CCPhysicsBodyTypeKinematic;
- // XCTAssertEqual(body.type, CCPhysicsBodyTypeKinematic, @"");
- // XCTAssertEqual(body.body.type, CP_BODY_TYPE_KINEMATIC, @"");
-
- body.type = CCPhysicsBodyTypeDynamic;
- XCTAssertEqual(body.type, CCPhysicsBodyTypeDynamic, @"");
- XCTAssertEqual(body.body.type, CP_BODY_TYPE_DYNAMIC, @"");
- }
- -(void)testBreakingJoints
- {
- CCPhysicsNode *physics = [CCPhysicsNode node];
- physics.gravity = ccp(0, -100);
-
- CGRect rect = CGRectMake(0, 0, 50, 50);
- CCPhysicsJoint *joint1, *joint2, *joint3, *joint4;
-
- // These should break.
- {
- CCNode *node1 = [CCNode node];
- node1.position = ccp(100, 200);
-
- CCPhysicsBody *body1 = node1.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
- body1.type = CCPhysicsBodyTypeStatic;
-
- [physics addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.position = ccp(100, 100);
-
- CCPhysicsBody *body2 = node2.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
-
- [physics addChild:node2];
-
- joint1 = [CCPhysicsJoint connectedPivotJointWithBodyA:body1 bodyB:body2 anchorA:ccp(rect.size.width/2.0, -rect.size.height/4.0)];
- joint1.breakingForce = -physics.gravity.y*body2.mass*0.9;
- }{
- CCNode *node1 = [CCNode node];
- node1.position = ccp(200, 200);
-
- CCPhysicsBody *body1 = node1.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
- body1.type = CCPhysicsBodyTypeStatic;
-
- [physics addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.position = ccp(200, 100);
-
- CCPhysicsBody *body2 = node2.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
-
- [physics addChild:node2];
-
- joint2 = [CCPhysicsJoint connectedDistanceJointWithBodyA:body1 bodyB:body2 anchorA:ccp(rect.size.width/2.0, 0.0) anchorB:ccp(rect.size.width/2.0, rect.size.height)];
- joint2.breakingForce = -physics.gravity.y*body2.mass*0.9;
- }
-
- // These shouldn't
- {
- CCNode *node1 = [CCNode node];
- node1.position = ccp(300, 200);
-
- CCPhysicsBody *body1 = node1.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
- body1.type = CCPhysicsBodyTypeStatic;
-
- [physics addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.position = ccp(300, 100);
-
- CCPhysicsBody *body2 = node2.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
-
- [physics addChild:node2];
-
- joint3 = [CCPhysicsJoint connectedPivotJointWithBodyA:body1 bodyB:body2 anchorA:ccp(rect.size.width/2.0, -rect.size.height/4.0)];
- joint3.breakingForce = -physics.gravity.y*body2.mass*1.1;
- }{
- CCNode *node1 = [CCNode node];
- node1.position = ccp(400, 200);
-
- CCPhysicsBody *body1 = node1.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
- body1.type = CCPhysicsBodyTypeStatic;
-
- [physics addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.position = ccp(400, 100);
-
- CCPhysicsBody *body2 = node2.physicsBody = [CCPhysicsBody bodyWithRect:rect cornerRadius:0.0];
-
- [physics addChild:node2];
-
- joint4 = [CCPhysicsJoint connectedDistanceJointWithBodyA:body1 bodyB:body2 anchorA:ccp(rect.size.width/2.0, 0.0) anchorB:ccp(rect.size.width/2.0, rect.size.height)];
- joint4.breakingForce = -physics.gravity.y*body2.mass*1.1;
- }
-
- [physics onEnter];
-
- for(int i=0; i<100; i++){
- [physics fixedUpdate:1.0/60.0];
- }
-
- XCTAssert(!joint1.valid, @"");
- XCTAssert(!joint2.valid, @"");
- XCTAssert(joint3.valid, @"");
- XCTAssert(joint4.valid, @"");
-
- [physics onExit];
- }
- -(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair theStaticOne:(CCNode *)nodeA theDynamicOne:(CCNode *)nodeB
- {
- nodeB.physicsBody.type = CCPhysicsBodyTypeStatic;
-
- // TODO not sure if we should hide the deferred nature or not... Hrm.
- XCTAssertEqual(nodeB.physicsBody.type, CCPhysicsBodyTypeDynamic, @"");
-
- return FALSE;
- }
- -(void)testBodyTypeCollisions
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- physicsNode.collisionDelegate = self;
- physicsNode.gravity = ccp(0, -100);
-
- CCNode *node1 = [CCNode node];
- node1.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node1.physicsBody.type = CCPhysicsBodyTypeStatic;
- node1.physicsBody.collisionType = @"theStaticOne";
- [physicsNode addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.position = ccp(0, 10);
- node2.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node2.physicsBody.type = CCPhysicsBodyTypeDynamic;
- node2.physicsBody.collisionType = @"theDynamicOne";
- [physicsNode addChild:node2];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- // Step the physics for a while.
- for(int i=0; i<100; i++){
- [physicsNode fixedUpdate:1.0/100.0];
- }
-
- XCTAssertEqual(node2.physicsBody.type, CCPhysicsBodyTypeStatic, @"");
-
- [physicsNode onExit];
- }
- -(void)testBodyEachCollisionPair
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- physicsNode.gravity = ccp(0, -100);
-
- CCNode *node1 = [CCNode node];
- node1.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node1.physicsBody.type = CCPhysicsBodyTypeStatic;
- [physicsNode addChild:node1];
-
- CCNode *node2 = [CCNode node];
- node2.position = ccp(0, 10);
- node2.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1.0 andCenter:CGPointZero];
- node2.physicsBody.type = CCPhysicsBodyTypeDynamic;
- [physicsNode addChild:node2];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- // Step the physics for a while.
- for(int i=0; i<100; i++){
- [physicsNode fixedUpdate:1.0/100.0];
- }
-
- __block BOOL check = NO;
-
- [node1.physicsBody eachCollisionPair:^(CCPhysicsCollisionPair *pair) {
- CCPhysicsShape *a, *b; [pair shapeA:&a shapeB:&b];
- check = (
- (a.node == node1 && b.node == node2) ||
- (b.node == node1 && a.node == node2)
- );
- }];
-
- XCTAssert(check, @"The objects should have had a collision pair listed between them.");
-
- [physicsNode onExit];
- }
- //Focusing on Position.
- -(void)testKineticBodyBasic1
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- physicsNode.collisionDelegate = self;
- physicsNode.gravity = ccp(0, 0);
-
- CGPoint node0Pos = ccp(100.0f,0.0f);
-
- CCNode *node0 = [CCNode node];
- node0.position = node0Pos;
- node0.name = @"node0";
- [physicsNode addChild:node0];
-
- CCPhysicsBody * body1 = [CCPhysicsBody bodyWithRect:CGRectMake(0, 0, 60, 20) cornerRadius:0];
-
- CGPoint node1Pos = ccp(-25, 0);
- CCNode *node1 = [CCNode node];
- node1.physicsBody = body1;
- node1.physicsBody.type = CCPhysicsBodyTypeStatic;
- node1.physicsBody.collisionType = @"theStaticOne";
- node1.name = @"node1";
- node1.position = node1Pos;
- node1.contentSize = CGSizeMake(60, 20);
- node1.anchorPoint = ccp(0.5f,0.5f);
- [node0 addChild:node1];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- // Step the physics for a while.
- const int KineticCount = 50;
-
- //Test translation.
- for(int i=0; i<100; i++)
- {
- if(i < KineticCount)
- {
- node0.position = ccp(node0Pos.x + (i + 1), node0Pos.y);
- }
-
- [physicsNode fixedUpdate:1.0/100.0];
-
- if(i >= KineticCount)
- {
- XCTAssertTrue(body1.type != CCPhysicsBodyTypeKinematic,@"Should not be kinetic now.");
- XCTAssertTrue(ccpLength(body1.velocity) == 0.0f ,@"Should not have velocity.");
- }
- else
- {
- XCTAssertTrue(body1.type == CCPhysicsBodyTypeKinematic, @"Should be kinetic now");
- XCTAssertTrue(ccpLength(body1.velocity) > 0.0f ,@"Should have velocity.");
- XCTAssertTrue(body1.absolutePosition.x == (45.0f + (i + 1)), @"should be this value");
- }
- }
-
-
- }
- //Focusing on rotation.
- -(void)testKineticBodyBasic2
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- physicsNode.collisionDelegate = self;
- physicsNode.gravity = ccp(0, 0);
-
- CGPoint node0Pos = ccp(100.0f,0.0f);
-
- CCNode *node0 = [CCNode node];
- node0.position = node0Pos;
- node0.name = @"node0";
- [physicsNode addChild:node0];
-
- CCPhysicsBody * body1 = [CCPhysicsBody bodyWithRect:CGRectMake(0, 0, 60, 20) cornerRadius:0];
-
- CGPoint node1Pos = ccp(-25, 0);
- CCNode *node1 = [CCNode node];
- node1.physicsBody = body1;
- node1.physicsBody.type = CCPhysicsBodyTypeStatic;
- node1.physicsBody.collisionType = @"theStaticOne";
- node1.name = @"node1";
- node1.position = node1Pos;
- node1.contentSize = CGSizeMake(60, 20);
- node1.anchorPoint = ccp(0.5f,0.5f);
- [node0 addChild:node1];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- // Step the physics for a while.
- const int KineticCount = 50;
-
-
- //Test translation.
- for(int i=0; i<100; i++)
- {
- if(i < KineticCount)
- {
- node0.rotation = (i + 1) * 1.0f;
- node1.rotation = (i + 1) * 1.0f;
- }
-
- [physicsNode fixedUpdate:1.0/100.0];
-
- if(i >= KineticCount)
- {
- XCTAssertTrue(body1.type != CCPhysicsBodyTypeKinematic, @"Should not be kinetic now.");
- }
- else
- {
- XCTAssertTrue(body1.type == CCPhysicsBodyTypeKinematic, @"Should be kinetic now");
- XCTAssertEqualWithAccuracy(-CC_RADIANS_TO_DEGREES(body1.absoluteRadians),(i + 1) * 2.0f,0.01f, @"Should be 2x rotation because of parent.");
- }
- }
-
- //TODO on exit
- //TODO if node0->node1->node2->node3 and you detatch node1,that node0 can get unobservered.
-
- }
- //When a node graph that is the child of a physics node is added (onEnter) ensure all the actions
- //it subsuquently posesses are changed to fixed scheduled.
- -(void)testKineticNodeActionsBasic1
- {
- CCPhysicsNode *physicsNode = [CCPhysicsNode node];
- physicsNode.collisionDelegate = self;
- physicsNode.gravity = ccp(0, 0);
-
- CGPoint node0Pos = ccp(0.0f,0.0f);
-
- CCNode *node0 = [CCNode node];
- node0.position = node0Pos;
- node0.name = @"node0";
- node0.scale = 2.0f;
- [node0 runAction:[CCActionMoveBy actionWithDuration:10 position:ccp(100, 0)]];
- [physicsNode addChild:node0];
-
- CCPhysicsBody * body1 = [CCPhysicsBody bodyWithRect:CGRectMake(0, 0, 60, 20) cornerRadius:0];
-
- CGPoint node1Pos = ccp(0, 0);
- CCNode *node1 = [CCNode node];
- node1.physicsBody = body1;
- node1.physicsBody.type = CCPhysicsBodyTypeStatic;
- node1.physicsBody.collisionType = @"theStaticOne";
- node1.name = @"node1";
- node1.position = node1Pos;
- node1.contentSize = CGSizeMake(60, 20);
- node1.anchorPoint = ccp(0.0f,0.0f);
- [node0 addChild:node1];
-
- [node1 runAction:[CCActionMoveBy actionWithDuration:10 position:ccp(100, 0)]];
-
- // Force entering the scene to set up the physics objects.
- [physicsNode onEnter];
-
- CCScheduler * scheduler = [CCDirector sharedDirector].scheduler;
- scheduler.fixedUpdateInterval = 0.1f;
- [scheduler update:0.10f];// first tick
- const float accuracy = 1e-4;
- //test actions are fixed.
- for(int i = 0; i < 100; i++)
- {
- float desired = (float)i * 0.1f * 100.0f/10.0f + (float)i * 0.1f * 200.0f/10.0f;
- //NSLog(@"node1.position.x= %0.2f desired = %0.2f",body1.absolutePosition.x, desired);
- XCTAssertEqualWithAccuracy(body1.absolutePosition.x, desired , accuracy, @"Not in the write position");
- [scheduler update:0.10f];
- }
- }
- //TODO
- //Test : When a node is added to a scene graph, its actions are Fixed if its part of a PhysicsNode.
- -(void)testApplyImpulse
- {
- CCPhysicsNode *physics = [CCPhysicsNode node];
- [physics onEnter];
-
- {
- CCNode *node = [CCNode node];
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- node.physicsBody.velocity = ccp(10, 10);
- [node.physicsBody applyImpulse:ccp(5, 5)];
- XCTAssert(ccpDistance(ccp(11, 11), node.physicsBody.velocity) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.rotation = 90;
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- node.physicsBody.velocity = ccp(10, 10);
- [node.physicsBody applyImpulse:ccp(5, 5)];
- XCTAssert(ccpDistance(ccp(11, 11), node.physicsBody.velocity) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- node.physicsBody.velocity = ccp(10, 10);
- [node.physicsBody applyImpulse:ccp(5, 5) atWorldPoint:node.position];
- XCTAssert(ccpDistance(ccp(11, 11), node.physicsBody.velocity) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- node.physicsBody.velocity = ccp(10, 10);
- [node.physicsBody applyImpulse:ccp(5, 5) atLocalPoint:ccp(0, 0)];
- XCTAssert(ccpDistance(ccp(11, 11), node.physicsBody.velocity) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- node.rotation = 90;
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- node.physicsBody.velocity = ccp(10, 10);
- [node.physicsBody applyImpulse:ccp(5, 0) atLocalPoint:ccp(0, 0)];
- XCTAssert(ccpDistance(ccp(10, 9), node.physicsBody.velocity) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- node.rotation = 180;
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- node.physicsBody.velocity = ccp(10, 10);
- [node.physicsBody applyImpulse:ccp(5, 0) atLocalPoint:ccp(0, 1)];
- XCTAssert(ccpDistance(ccp(9, 10), node.physicsBody.velocity) < 1e-5, @"");
- XCTAssertEqualWithAccuracy(node.physicsBody.angularVelocity, -2, 1e-5, @"");
- }
-
- [physics onExit];
- }
- -(void)testApplyForce
- {
- CCPhysicsNode *physics = [CCPhysicsNode node];
- [physics onEnter];
-
- {
- CCNode *node = [CCNode node];
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- [node.physicsBody applyForce:ccp(5, 5)];
- XCTAssert(ccpDistance(ccp(5, 5), node.physicsBody.force) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.rotation = 90;
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- [node.physicsBody applyForce:ccp(5, 5)];
- XCTAssert(ccpDistance(ccp(5, 5), node.physicsBody.force) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- [node.physicsBody applyForce:ccp(5, 5) atWorldPoint:node.position];
- XCTAssert(ccpDistance(ccp(5, 5), node.physicsBody.force) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- [node.physicsBody applyForce:ccp(5, 5) atLocalPoint:ccp(0, 0)];
- XCTAssert(ccpDistance(ccp(5, 5), node.physicsBody.force) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- node.rotation = 90;
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- [node.physicsBody applyForce:ccp(5, 0) atLocalPoint:ccp(0, 0)];
- XCTAssert(ccpDistance(ccp(0, -5), node.physicsBody.force) < 1e-5, @"");
- }{
- CCNode *node = [CCNode node];
- node.position = ccp(20, 20);
- node.rotation = 180;
- [physics addChild:node];
-
- node.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:1 andCenter:CGPointZero];
- node.physicsBody.mass = 5;
-
- [node.physicsBody applyForce:ccp(5, 0) atLocalPoint:ccp(0, 1)];
- XCTAssert(ccpDistance(ccp(-5, 0), node.physicsBody.force) < 1e-5, @"");
- XCTAssertEqualWithAccuracy(node.physicsBody.torque, -5, 1e-5, @"");
- }
-
- [physics onExit];
- }
- // TODO
- // * Check that body and shape settings are preserved through multiple add/remove cycles and are actually applied to the cpBody.
- // * Check that changing properties before and after adding to an active physics node updates the properties correctly.
- @end