Sprite Kit SKPhysicsJoint
Я пытаюсь поэкспериментировать с совместной системой Sprite Kit. До сих пор мне было трудно сделать хотя бы одну нить "веревка"/"веревка". Конечная цель - создать что-то вроде баскетбольной сетки, в которой будет 1 левая веревка (вертикальная), 1 правая веревка (вертикальная) и как минимум 2 веревки между соединяющими левую и правую веревку (по горизонтали) - всего 4 веревки, Затем выясните, как сделать так, чтобы 2 горизонтальные веревки не сталкивались с объектом (пушечным ядром?), Когда он проходит через них. Кто-нибудь знает, как сделать что-то подобное? Я пробовал это в течение 2 недель, и у меня болят глаза и пальцы.
1 ответ
Вы можете соединить несколько физических тел вместе с предельными соединениями, чтобы создать структуру, похожую на веревку, на которую влияют столкновения с другими телами. Мой код довольно грязный, но вот класс Scene для проекта набора спрайтов. У него есть баскетбольная сетка, и когда вы нажимаете на экран, он порождает мяч.
со скриншотом здесь https://dl.dropboxusercontent.com/s/flixgbhfk2yysr8/screenshot.jpg?dl=0
РЕДАКТИРОВАТЬ: извините за это, код сейчас в obj-C
РЕДАКТИРОВАТЬ: вставьте эти методы в ваш подкласс SKScene:
-(void)addBasketAtPos:(CGPoint)pos WithSize:(CGSize)size HoopThickness:(CGFloat)hoopThickness RopeThickness:(CGFloat)ropeThickness GapSize:(CGFloat)gapSize {
int nSect=ceil(size.height/(ropeThickness*4));
SKSpriteNode *hoop=[SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(size.width+hoopThickness, hoopThickness)];
hoop.position=pos;
//[self addChild:hoop];
SKNode *lHoopEdge=[SKNode node];
lHoopEdge.position=CGPointMake(pos.x-size.width/2, pos.y);
lHoopEdge.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:hoopThickness/2];
lHoopEdge.physicsBody.dynamic=false;
lHoopEdge.physicsBody.restitution=0.9;
[self addChild:lHoopEdge];
SKNode *rHoopEdge=[SKNode node];
rHoopEdge.position=CGPointMake(pos.x+size.width/2, pos.y);
rHoopEdge.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:hoopThickness/2];
rHoopEdge.physicsBody.dynamic=false;
rHoopEdge.physicsBody.restitution=0.9;
[self addChild:rHoopEdge];
NSMutableArray *rope1=[self makeRopeAtPos:lHoopEdge.position node:lHoopEdge num: nSect gap:size.height/nSect width:ropeThickness];
NSMutableArray *rope2=[self makeRopeAtPos:rHoopEdge.position node:lHoopEdge num: nSect gap:size.height/nSect width:ropeThickness];
CGFloat insetStep=(size.width-gapSize)/2/nSect;
for (int i=0;i<rope1.count;++i) {
SKNode *a=[rope1 objectAtIndex:i];
SKNode *b=[rope2 objectAtIndex:i];
a.position=CGPointMake(a.position.x+i*insetStep, a.position.y);
b.position=CGPointMake(b.position.x-i*insetStep, b.position.y);
}
for (int i=0;i<rope1.count;++i) {
/*
SKNode *n1=[rope1 objectAtIndex:i];
SKNode *n2=[rope2 objectAtIndex:i];
SKPhysicsJointLimit* joint=[self joinBodyA:n1.physicsBody bodyB:n2.physicsBody ropeThickness:ropeThickness];
[self.physicsWorld addJoint:joint];
*/
if (i>0) {
[self.physicsWorld addJoint:[self joinBodyA:((SKNode*)[rope1 objectAtIndex:i]).physicsBody
bodyB:((SKNode*)[rope2 objectAtIndex:i-1]).physicsBody
ropeThickness:ropeThickness]];
[self.physicsWorld addJoint:[self joinBodyA:((SKNode*)[rope2 objectAtIndex:i]).physicsBody
bodyB:((SKNode*)[rope1 objectAtIndex:i-1]).physicsBody
ropeThickness:ropeThickness]];
}
if (i==rope1.count-1) {
[self.physicsWorld addJoint:[self joinBodyA:((SKNode*)[rope1 objectAtIndex:i]).physicsBody
bodyB:((SKNode*)[rope2 objectAtIndex:i]).physicsBody
ropeThickness:ropeThickness]];
}
}
[self addChild:hoop];
}
-(NSMutableArray*)makeRopeAtPos:(CGPoint)p node:(SKNode*)node num:(int)num gap:(CGFloat)gap width:(CGFloat)width {
NSMutableArray *array=[[NSMutableArray alloc] init];
SKNode *last=node;
CGPoint pos=p;
CGPoint anchor=pos;
for (int i=0; i<num; ++i) {
pos=CGPointMake(pos.x, pos.y-gap);
last=[self makeRopeSegAtPos:pos prev:last anchor:anchor first:(i==0) width:width];
anchor=pos;
[array addObject:last];
}
return array;
}
-(SKNode*)makeRopeSegAtPos:(CGPoint)pos prev:(SKNode*)prev anchor:(CGPoint)anchor first:(BOOL)first width:(CGFloat)width {
//SKNode *r=[SKNode node];
SKSpriteNode *r=[SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(anchor.y-pos.y, width)];
r.position=pos;
r.anchorPoint=CGPointMake(0, 0.5);
if (first) {
//r.size=CGSizeMake(10, 20);
r.constraints=@[[SKConstraint orientToPoint:anchor inNode:self offset:nil]];
}else {
r.constraints=@[[SKConstraint orientToNode:prev offset:nil]];
}
r.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:width];
r.physicsBody.allowsRotation=NO;
//r.physicsBody.density=0.2;
r.physicsBody.linearDamping=0.8;
[self addChild:r];
SKPhysicsJointLimit *j=[SKPhysicsJointLimit jointWithBodyA:r.physicsBody bodyB:prev.physicsBody anchorA:r.position anchorB:anchor];
[self.physicsWorld addJoint:j];
return r;
}
-(SKPhysicsJoint*)joinBodyA:(SKPhysicsBody*)bodyA bodyB:(SKPhysicsBody*)bodyB ropeThickness:(CGFloat)ropeThickness {
SKPhysicsJointLimit *j=[SKPhysicsJointLimit jointWithBodyA:bodyA bodyB:bodyB anchorA:bodyA.node.position anchorB:bodyB.node.position];
SKSpriteNode *rope=[SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(j.maxLength, ropeThickness)];
rope.anchorPoint=CGPointMake(0, 0.5);
rope.constraints=@[[SKConstraint distance:[SKRange rangeWithUpperLimit:1] toNode:bodyA.node],[SKConstraint orientToNode:bodyB.node offset:nil]];
SKAction *keepLength=[SKAction repeatActionForever:[SKAction sequence:@[[SKAction waitForDuration:1/60],[SKAction runBlock:^{
rope.size=CGSizeMake(sqrtf(powf(bodyA.node.position.x-bodyB.node.position.x, 2)+powf(bodyA.node.position.y-bodyB.node.position.y, 2)), rope.size.height);
}]]]];
[rope runAction:keepLength];
[self addChild:rope];
return j;
}
использование
[self addBasketAtPos: CGPointMake(self.size.width/2, self.size.height*0.7)
WithSize: CGSizeMake(100, 100)
HoopThickness: 10
RopeThickness: 5
GapSize: 80
];
добавить корзину
см. новый скриншот здесь: https://dl.dropboxusercontent.com/s/xe07ri70rgpxp47/screenshot%202.jpg?dl=0