- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直在尝试使用 sprite 套件,为我的想法构建原型(prototype)。我一直在使用 SKPhysicsJointPin 将一串物理体连接在一起,以制作一根绳子(实际上更像是自行车链条,但它已经足够好了)。场景中还有一些球,当我点击它们时,它们会掉落。这导致以下情况:
但是,当我丢更多的球时,链条似乎无法处理它,并“断裂”:
这是一个movie showing the phenomenon
这是怎么回事?该文档从不建议 SKPhysicsJointPin 具有有限的最大强度或弹性或类似物。这是 sprite 套件中的“错误”,还是我使用了错误的方法?
最佳答案
我在绳索模拟中遇到了类似的弹性错误,最终想出了一个解决方法。
这是我的绳索界面:
#import <SpriteKit/SpriteKit.h>
@interface ALRope : NSObject
@property(nonatomic, readonly) NSArray *ropeRings;
@property(nonatomic) int ringCount;
@property(nonatomic) CGFloat ringScale;
@property(nonatomic) CGFloat ringsDistance;
@property(nonatomic) CGFloat jointsFrictionTorque;
@property(nonatomic) CGFloat ringsZPosition;
@property(nonatomic) CGPoint startRingPosition;
@property(nonatomic) CGFloat ringFriction;
@property(nonatomic) CGFloat ringRestitution;
@property(nonatomic) CGFloat ringMass;
@property(nonatomic) BOOL shouldEnableJointsAngleLimits;
@property(nonatomic) CGFloat jointsLowerAngleLimit;
@property(nonatomic) CGFloat jointsUpperAngleLimit;
-(instancetype)initWithRingTexture:(SKTexture *)ringTexture;
-(void)buildRopeWithScene:(SKScene *)scene;
-(void)adjustRingPositions;
-(SKSpriteNode *)startRing;
-(SKSpriteNode *)lastRing;
@end
绳索实现:
#import "ALRope.h"
@implementation ALRope
{
SKTexture *_ringTexture;
NSMutableArray *_ropeRings;
}
static CGFloat const RINGS_DISTANCE_DEFAULT = 0;
static CGFloat const JOINTS_FRICTION_TORQUE_DEFAULT = 0;
static CGFloat const RING_SCALE_DEFAULT = 1;
static int const RING_COUNT_DEFAULT = 30;
static CGFloat const RINGS_Z_POSITION_DEFAULT = 1;
static BOOL const SHOULD_ENABLE_JOINTS_ANGLE_LIMITS_DEFAULT = NO;
static CGFloat const JOINT_LOWER_ANGLE_LIMIT_DEFAULT = -M_PI / 3;
static CGFloat const JOINT_UPPER_ANGLE_LIMIT_DEFAULT = M_PI / 3;
static CGFloat const RING_FRICTION_DEFAULT = 0;
static CGFloat const RING_RESTITUTION_DEFAULT = 0;
static CGFloat const RING_MASS_DEFAULT = -1;
-(instancetype)initWithRingTexture:(SKTexture *)ringTexture
{
if(self = [super init]) {
_ringTexture = ringTexture;
//apply defaults
_startRingPosition = CGPointMake(0, 0);
_ringsDistance = RINGS_DISTANCE_DEFAULT;
_jointsFrictionTorque = JOINTS_FRICTION_TORQUE_DEFAULT;
_ringScale = RING_SCALE_DEFAULT;
_ringCount = RING_COUNT_DEFAULT;
_ringsZPosition = RINGS_Z_POSITION_DEFAULT;
_shouldEnableJointsAngleLimits = SHOULD_ENABLE_JOINTS_ANGLE_LIMITS_DEFAULT;
_jointsLowerAngleLimit = JOINT_LOWER_ANGLE_LIMIT_DEFAULT;
_jointsUpperAngleLimit = JOINT_UPPER_ANGLE_LIMIT_DEFAULT;
_ringFriction = RING_FRICTION_DEFAULT;
_ringRestitution = RING_RESTITUTION_DEFAULT;
_ringMass = RING_MASS_DEFAULT;
}
return self;
}
-(void)buildRopeWithScene:(SKScene *)scene
{
_ropeRings = [NSMutableArray new];
SKSpriteNode *firstRing = [self addRopeRingWithPosition:_startRingPosition underScene:scene];
SKSpriteNode *lastRing = firstRing;
CGPoint position;
for (int i = 1; i < _ringCount; i++) {
position = CGPointMake(lastRing.position.x, lastRing.position.y - lastRing.size.height - _ringsDistance);
lastRing = [self addRopeRingWithPosition:position underScene:scene];
}
[self addJointsWithScene:scene];
}
-(SKSpriteNode *)addRopeRingWithPosition:(CGPoint)position underScene:(SKScene *)scene
{
SKSpriteNode *ring = [SKSpriteNode spriteNodeWithTexture:_ringTexture];
ring.xScale = ring.yScale = _ringScale;
ring.position = position;
ring.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ring.size.height / 2];
ring.physicsBody.allowsRotation = YES;
ring.physicsBody.friction = _ringFriction;
ring.physicsBody.restitution = _ringRestitution;
if(_ringMass > 0) {
ring.physicsBody.mass = _ringMass;
}
[scene addChild:ring];
[_ropeRings addObject:ring];
return ring;
}
-(void)addJointsWithScene:(SKScene *)scene
{
for (int i = 1; i < _ropeRings.count; i++) {
SKSpriteNode *nodeA = [_ropeRings objectAtIndex:i-1];
SKSpriteNode *nodeB = [_ropeRings objectAtIndex:i];
SKPhysicsJointPin *joint = [SKPhysicsJointPin jointWithBodyA:nodeA.physicsBody
bodyB:nodeB.physicsBody
anchor:CGPointMake(nodeA.position.x,
nodeA.position.y - (nodeA.size.height + _ringsDistance) / 2)];
joint.frictionTorque = _jointsFrictionTorque;
joint.shouldEnableLimits = _shouldEnableJointsAngleLimits;
if(_shouldEnableJointsAngleLimits) {
joint.lowerAngleLimit = _jointsLowerAngleLimit;
joint.upperAngleLimit = _jointsUpperAngleLimit;
}
[scene.physicsWorld addJoint:joint];
}
}
//workaround for elastic effect should be called from didSimulatePhysics
-(void)adjustRingPositions
{
//based on zRotations of all rings and the position of start ring adjust the rest of the rings positions starting from top to bottom
for (int i = 1; i < _ropeRings.count; i++) {
SKSpriteNode *nodeA = [_ropeRings objectAtIndex:i-1];
SKSpriteNode *nodeB = [_ropeRings objectAtIndex:i];
CGFloat thetaA = nodeA.zRotation - M_PI / 2,
thetaB = nodeB.zRotation + M_PI / 2,
jointRadius = (_ringsDistance + nodeA.size.height) / 2,
xJoint = jointRadius * cosf(thetaA) + nodeA.position.x,
yJoint = jointRadius * sinf(thetaA) + nodeA.position.y,
theta = thetaB - M_PI,
xB = jointRadius * cosf(theta) + xJoint,
yB = jointRadius * sinf(theta) + yJoint;
nodeB.position = CGPointMake(xB, yB);
}
}
-(SKSpriteNode *)startRing
{
return _ropeRings[0];
}
-(SKSpriteNode *)lastRing
{
return [_ropeRings lastObject];
}
@end
展示如何使用绳子的场景代码:
#import "ALRopeDemoScene.h"
#import "ALRope.h"
@implementation ALRopeDemoScene
{
__weak SKSpriteNode *_branch;
CGPoint _touchLastPosition;
BOOL _branchIsMoving;
ALRope *_rope;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.backgroundColor = [SKColor colorWithRed:0.2 green:0.5 blue:0.6 alpha:1.0];
[self buildScene];
}
return self;
}
-(void) buildScene {
SKSpriteNode *branch = [SKSpriteNode spriteNodeWithImageNamed:@"Branch"];
_branch = branch;
branch.position = CGPointMake(CGRectGetMaxX(self.frame) - branch.size.width / 2,
CGRectGetMidY(self.frame) + 200);
branch.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(2, 10)];
branch.physicsBody.dynamic = NO;
[self addChild:branch];
_rope = [[ALRope alloc] initWithRingTexture:[SKTexture textureWithImageNamed:@"rope_ring"]];
//configure rope params if needed
// _rope.ringCount = ...;//default is 30
// _rope.ringScale = ...;//default is 1
// _rope.ringsDistance = ...;//default is 0
// _rope.jointsFrictionTorque = ...;//default is 0
// _rope.ringsZPosition = ...;//default is 1
// _rope.ringFriction = ...;//default is 0
// _rope.ringRestitution = ...;//default is 0
// _rope.ringMass = ...;//ignored unless mass > 0; default -1
// _rope.shouldEnableJointsAngleLimits = ...;//default is NO
// _rope.jointsLowerAngleLimit = ...;//default is -M_PI/3
// _rope.jointsUpperAngleLimit = ...;//default is M_PI/3
_rope.startRingPosition = CGPointMake(branch.position.x - 100, branch.position.y);//default is (0, 0)
[_rope buildRopeWithScene:self];
//attach rope to branch
SKSpriteNode *startRing = [_rope startRing];
CGPoint jointAnchor = CGPointMake(startRing.position.x, startRing.position.y + startRing.size.height / 2);
SKPhysicsJointPin *joint = [SKPhysicsJointPin jointWithBodyA:branch.physicsBody bodyB:startRing.physicsBody anchor:jointAnchor];
[self.physicsWorld addJoint:joint];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
if(CGRectContainsPoint(_branch.frame, location)) {
_branchIsMoving = YES;
_touchLastPosition = location;
}
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
_branchIsMoving = NO;
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if(_branchIsMoving) {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self],
branchCurrentPosition = _branch.position;
CGFloat dx = location.x - _touchLastPosition.x,
dy = location.y - _touchLastPosition.y;
_branch.position = CGPointMake(branchCurrentPosition.x + dx, branchCurrentPosition.y + dy);
_touchLastPosition = location;
}
}
-(void)didSimulatePhysics
{
//workaround for elastic effect
[_rope adjustRingPositions];
}
@end
注意来自 [scene didSimulatePhysics] 的 [rope adjustRingPositions] 调用。这是弹性错误的实际解决方法。
完整的演示代码是here .希望对您有所帮助!
关于ios - SKPhysics : Made a rope, 为什么会坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24824585/
struct PhysicsCategory { static let None : UInt32 = 0 static let All : UInt32 = U
我正在尝试使用 SpriteKit 中的 SKPhysicsContactDelegate 函数,但它似乎不起作用。我希望一个 Sprite 在击中另一个 Sprite 时执行一个 Action 。我
Apple 的文档在解释如何有效地实现此类方法时含糊不清 + (SKPhysicsBody *)bodyWithBodies:(NSArray *)bodies; //the error that I
如何创建一个凹形的 SKPhysicsBody? 我的猜测是创建一个由多个凸体组成的复合节点。我可以用任何其他方式“粘贴”它们,从而在它们之间创建 SKPhysicsJointFixed 吗? 最佳答
我怎样才能分别从左向右滑动桨叶,让角色跳跃的桨叶停止,而其余的桨叶继续滑动?如何让4个桨以相同的速度慢慢地左右前后移动。请谢谢。 在这段代码中,我试图为所有这些创建一个 SKPhysics 实体,但我
在我被反对票钉在十字架上之前,让我说我已经对此进行了研究,但我仍然不明白为什么我会收到这个错误。 我有一个玩家试图防御的核心,您可以从中射出小激光来防御即将到来的 meteor 。好吧,我已经设置好了
代码如下: import SpriteKit import CoreMotion struct PhysicsCatagory { static let Player :UInt32 = 0
所以我正在创建一个游戏,我只想检测玩家节点和敌人发射的子弹之间的碰撞。所以我已经为每个玩家和子弹设置了正确的参数和 categoryBitMask 和 contactTestBitMask。 通过实现
我一直在尝试使用 sprite 套件,为我的想法构建原型(prototype)。我一直在使用 SKPhysicsJointPin 将一串物理体连接在一起,以制作一根绳子(实际上更像是自行车链条,但它已
尝试在 SpriteKit 中使用径向重力场时遇到问题 我不希望同类对象(由categoryBitMask定义)相互吸引 这是我的做法: struct PhyscisCategory { st
随着 iOS 8 的发布苹果也发布了新的 swift。购买他们还发布了 Sprite 套件的一些更新。其中之一是每像素物理体。我试图找到如何在 xcode beta 中实现这个每像素物理体,并且在搜索
我正在创建一个游戏,对于我的角色,他的腿和躯干有单独的动画,因此它们是具有单独物理体的单独节点。我在将躯干和腿连接在一起时遇到了很多麻烦,但是,将它们连接起来不是问题,让它们保持连接才是问题。在四处走
想要使用 SKPhysics(启用碰撞)拖动 SKSpriteNode(跟随您的手指移动) 2 失败的解决方案: 1) a) 解决方案:改变SKSpriteNode的位置 b) 问题:当用户拖动 sp
我正在尝试为 iPad Pro 12.9 创建物理边界 我是这样做的: override func didMove(to view: SKView) { physicsWorld.co
我是一名优秀的程序员,十分优秀!