Is it possible to make a rope in Sprite Kit with SKPhysicsJoints? The simple answer: sure! you just have to make a lot of small single SKPhysicsBodies and connect them with SKPhysicsJointPins. As you can see in the little demo video we also added bigger pieces below the rope to simulate a whole suspension bridge. To make a rope with single parts connected with pinned joints you don’t even need so much jointed elements. Just let the sprite overlap a bit the physics body to make it look very real.
We also added an element which breaks the joints chain when the collision of the SKPhysicsBody is true.
So here comes the code. The methods are separated into two parts. First part is the ground of the bridge. It iterates through n given times to create and pin little SKPhysicsBodies. Also the „breaking“ element is made into this loop. And last but not least the left and right anchors are set to tie the whole bridge up. The second method creates the rope elements an add it also to this anchors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
// // WWSuspensionBrigde.m // PoBo // // Created by zinne on 29.11.13. // Copyright (c) 2013 waveworks. All rights reserved. // #import "WWSuspensionBrigde.h" @implementation WWSuspensionBrigde +(void)add:(CGPoint)leftStartPosition countJointElements:(int)countJointElements breakableItem:(int)breakableItem game:(SKScene*)game bridgeId:(int)bridgeId { int itemJointWidth = 25; breakableItem = breakableItem - 1; //Left Physics Anchor SKSpriteNode * leftAnchor = [SKSpriteNode spriteNodeWithImageNamed:@"dummypixel_transparent.png"]; leftAnchor.position = leftStartPosition; leftAnchor.size = CGSizeMake(1, 1); leftAnchor.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: leftAnchor.size]; leftAnchor.physicsBody.affectedByGravity = false; leftAnchor.physicsBody.mass = 99999999999; leftAnchor.name = @"suspensionBridgeAnchorLeft"; [game addChild:leftAnchor]; //Left Sprite Anchor SKSpriteNode * leftSpriteAnchor = [SKSpriteNode spriteNodeWithImageNamed:@"suspensionbridge_anchor_left.png"]; leftSpriteAnchor.position = CGPointMake(leftStartPosition.x - 10, leftStartPosition.y + 37); leftSpriteAnchor.size = CGSizeMake(20, 70); leftSpriteAnchor.zPosition = 6; leftSpriteAnchor.name = @"suspensionBridgeBarLeft"; [game addChild:leftSpriteAnchor]; //add BridgeElements for (int i=0; i<countJointElements; i++) { NSString* itemName; NSString* itemFile; if (i == breakableItem) { itemName = [NSString stringWithFormat:@"%d_breakableSuspensionBridgeItem", bridgeId]; itemFile = @"suspensionbridge_broken_item.png"; } else { itemName = [NSString stringWithFormat:@"%d_item_%d", bridgeId, i]; int rndNumber =arc4random() % 2; switch (rndNumber) { case 0: itemFile = @"suspensionbridge_item.png"; break; case 1: itemFile = @"suspensionbridge_item2.png"; } } SKSpriteNode * item = [SKSpriteNode spriteNodeWithImageNamed:itemFile]; item.name = itemName; item.position = CGPointMake(leftStartPosition.x + (i*itemJointWidth) + itemJointWidth/2, leftStartPosition.y); item.size = CGSizeMake(itemJointWidth, 5); item.zPosition = 6; item.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: item.size]; if (i == breakableItem) { item.size = CGSizeMake(48/1.7, 143/2); item.anchorPoint = CGPointMake(0.48 , 0.98); } [game addChild:item]; //Add Joint to the element before SKPhysicsBody* bodyA; if (i == 0) { bodyA = leftAnchor.physicsBody; } else { bodyA = [game childNodeWithName:[NSString stringWithFormat:@"%d_item_%d", bridgeId, i-1]].physicsBody; } if (i == breakableItem + 1) { bodyA = [game childNodeWithName:[NSString stringWithFormat:@"%d_breakableSuspensionBridgeItem", bridgeId]].physicsBody; } SKPhysicsJointPin* joint = [SKPhysicsJointPin jointWithBodyA:bodyA bodyB:item.physicsBody anchor:CGPointMake((item.position.x - item.size.width/2) + 5, item.position.y)]; [game.physicsWorld addJoint:joint]; } //Right Physics Anchor SKSpriteNode * rightAnchor = [SKSpriteNode spriteNodeWithImageNamed:@"dummypixel_transparent.png"]; rightAnchor.position = CGPointMake((leftStartPosition.x + (countJointElements*itemJointWidth)), leftStartPosition.y); rightAnchor.size = CGSizeMake(1, 1); rightAnchor.zPosition = 6; rightAnchor.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: rightAnchor.size]; rightAnchor.physicsBody.affectedByGravity = false; rightAnchor.physicsBody.mass = 99999999999; rightAnchor.name = @"suspensionBridgeAnchorRight"; [game addChild:rightAnchor]; //Right Sprite Anchor SKSpriteNode * rightSpriteAnchor = [SKSpriteNode spriteNodeWithImageNamed:@"suspensionbridge_anchor_right.png"]; rightSpriteAnchor.position = CGPointMake((leftStartPosition.x + (countJointElements*itemJointWidth)) + 7, leftStartPosition.y + 37); rightSpriteAnchor.size = CGSizeMake(20, 70); rightSpriteAnchor.zPosition = 6; rightSpriteAnchor.name = @"suspensionBridgeBarRight"; [game addChild:rightSpriteAnchor]; //Add the Last Joint SKPhysicsJointPin* jointLast = [SKPhysicsJointPin jointWithBodyA:[game childNodeWithName:[NSString stringWithFormat:@"%d_item_%d", bridgeId, countJointElements - 1]].physicsBody bodyB:rightAnchor.physicsBody anchor:rightAnchor.position]; [game.physicsWorld addJoint:jointLast]; [self addRopeJointItems:leftStartPosition countJointElements:countJointElements game:game bridgeId:bridgeId]; } +(void) addRopeJointItems:(CGPoint)leftStartPosition countJointElements:(int)countJointElements game:(SKScene*)game bridgeId:(int)bridgeId { int itemJointWidth = 25; //Left Physics Anchor SKSpriteNode * leftAnchor = [SKSpriteNode spriteNodeWithImageNamed:@"dummypixel_transparent.png"]; leftAnchor.position = CGPointMake(leftStartPosition.x, leftStartPosition.y); leftAnchor.size = CGSizeMake(1, 1); leftAnchor.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: leftAnchor.size]; leftAnchor.physicsBody.affectedByGravity = false; leftAnchor.physicsBody.mass = 99999999999; leftAnchor.name = @"suspensionBridgeRopeAnchorLeft"; [game addChild:leftAnchor]; //add RopeElements for (int i=0; i<countJointElements; i++) { SKSpriteNode * item = [SKSpriteNode spriteNodeWithImageNamed:@"suspensionrope.png"]; item.name = [NSString stringWithFormat:@"%d_ropeitem_%d", bridgeId, i]; item.position = CGPointMake(leftStartPosition.x + (i*itemJointWidth) + itemJointWidth/2, leftStartPosition.y+60); item.size = CGSizeMake(itemJointWidth + 5, 5); item.zPosition = 6; item.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: item.size]; item.physicsBody.categoryBitMask = kNilOptions; [game addChild:item]; //Add Joint to the element before SKPhysicsBody* bodyA; if (i == 0) { bodyA = leftAnchor.physicsBody; } else { bodyA = [game childNodeWithName:[NSString stringWithFormat:@"%d_ropeitem_%d", bridgeId, i-1]].physicsBody; } SKPhysicsJointPin* joint = [SKPhysicsJointPin jointWithBodyA:bodyA bodyB:item.physicsBody anchor:CGPointMake((item.position.x - item.size.width/2) + 5, item.position.y)]; [game.physicsWorld addJoint:joint]; } //Right Physics Anchor SKSpriteNode * rightAnchor = [SKSpriteNode spriteNodeWithImageNamed:@"dummypixel_transparent.png"]; rightAnchor.position = CGPointMake((leftStartPosition.x + (countJointElements*itemJointWidth)), leftStartPosition.y+60); rightAnchor.size = CGSizeMake(1, 1); rightAnchor.zPosition = 6; rightAnchor.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: rightAnchor.size]; rightAnchor.physicsBody.affectedByGravity = false; rightAnchor.physicsBody.mass = 99999999999; rightAnchor.physicsBody.categoryBitMask = kNilOptions; rightAnchor.name = @"suspensionBridgeRopeAnchorRight"; [game addChild:rightAnchor]; //Add the Last Joint SKPhysicsJointPin* jointLast = [SKPhysicsJointPin jointWithBodyA:[game childNodeWithName:[NSString stringWithFormat:@"%d_ropeitem_%d", bridgeId, countJointElements - 1]].physicsBody bodyB:rightAnchor.physicsBody anchor:rightAnchor.position]; [game.physicsWorld addJoint:jointLast]; } @end |
is it possible for you guys to make this one with swift , I am trying to make an Bow with Arrow with this suspension effect, I am searching for clue , this one is the closest one I could find .