How to keep a 30˚ distance between two lines anchored at a point
To keep your two lines separated by exactly 30°, you can use an SKPhysicsJointFixed
, which is just what it sounds like: it pins two physicsBodies
together in a fixed position. Since you already have them positioned the way you want, just add this code where you have the other SKPhysicsJoints
to hold them that way:
let fixArms = SKPhysicsJointFixed.joint(withBodyA: armLeft.physicsBody!, bodyB: armRight.physicsBody!, anchor: CGPoint.zero)
self.physicsWorld.add(fixArms)
Result:
How To Enforce A Pendulum Path
Here's an example of how to implement an SKPhysicsJointPin:
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
CGPoint location = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
// Create the pendulum's pivot
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:size];
sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];
sprite.physicsBody.dynamic = NO;
sprite.position = location;
sprite.size = CGSizeMake(8, 8);
[self addChild:sprite];
location = CGPointMake(self.frame.size.width/2-100, self.frame.size.height/2);
size = CGSizeMake(50, 200);
// Create the pendulum's bob
SKSpriteNode *sprite2 = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:size];
sprite2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];
sprite2.physicsBody.dynamic = YES;
sprite2.physicsBody.affectedByGravity = YES;
sprite2.physicsBody.linearDamping = 0;
sprite2.physicsBody.mass = 0.1;
sprite2.size = CGSizeMake(32, 32);
sprite2.position = location;
[self addChild:sprite2];
CGPoint point = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
// Create a joint that connects the pivot and the bob
SKPhysicsJointPin *pinJoint = [SKPhysicsJointPin jointWithBodyA:sprite.physicsBody
bodyB:sprite2.physicsBody anchor:point];
// Add the joint to the world
[self.physicsWorld addJoint:pinJoint];
}
return self;
}
SpriteKit stop spinning wheel in a defined angle
Kinematics makes my head hurt, but here you go. I made it to where you can input the amount of rotations and the wheel will rotate that many times as its slowing down to the angle you specify. The other function and extension are there to keep the code relatively clean/readable. So if you just want one giant mess function go ahead and modify it.
• Make sure the node's angularDampening = 0.0
• Make sure the node has a circular physicsbody
// Stops a spinning SpriteNode at a specified angle within a certain amount of rotations
//NOTE: Node must have a circular physicsbody
// Damping should be from 0.0 to 1.0
func decelerate(node: SKSpriteNode, toAngle: CGFloat, rotations: Int) {
if node.physicsBody == nil { print("Node doesn't have a physicsbody"); return } //Avoid crash incase node's physicsbody is nil
var cw:CGFloat { if node.physicsBody!.angularVelocity < CGFloat(0.0) { return -1.0} else { return 1.0} } //Clockwise - using int to reduce if statments with booleans
let m = node.physicsBody!.mass // Mass
let r = CGFloat.squareRoot(node.physicsBody!.area / CGFloat.pi)() // Radius
let i = 0.5 * m * r.squared // Intertia
let wi = node.physicsBody!.angularVelocity // Initial Angular Velocity
let wf:CGFloat = 0 // Final Angular Velocity
let ti = CGFloat.unitCircle(node.zRotation) // Initial Theta
var tf = CGFloat.unitCircle(toAngle) // Final Theta
//Correction constant based on rate of rotation since there seems to be a delay between when the action is calcuated and when it is run
//Without the correction the node stops a little off from its desired stop angle
tf -= 0.00773889 * wi //Might need to change constn
let dt = deltaTheta(ti, tf, Int(cw), rotations)
let a = -cw * 0.5 * wi.squared / abs(dt) // Angular Acceleration - cw used to determine direction
print("A:\(a)")
let time:Double = Double(abs((wf-wi) / a)) // Time needed to stop
let torque:CGFloat = i * a // Torque needed to stop
node.run(SKAction.applyTorque(torque, duration: time))
}
func deltaTheta(_ ti:CGFloat, _ tf:CGFloat, _ clockwise: Int, _ rotations: Int) -> CGFloat {
let extra = CGFloat(rotations)*2*CGFloat.pi
if clockwise == -1 {
if tf>ti { return tf-ti-2*CGFloat.pi-extra }else{ return tf-ti-extra }
}else{
if tf>ti { return tf-ti+extra }else{ return tf+2*CGFloat.pi+extra-ti }
}
}
}
extension CGFloat {
public var squared:CGFloat { return self * self }
public static func unitCircle(_ value: CGFloat) -> CGFloat {
if value < 0 { return 2 * CGFloat.pi + value }
else{ return value }
}
}
Move sprite based upon rotation
moveByX/Y moves your sprite based on the screen coordinates, not the position of your ship, so moving will always be based on the x or y axis. You need to incorporate some trig functions (sin and cos) on your moveby to get it to move in the path you want:
let movespriteLeft = SKAction.moveByX(-100 * sin(ANGLE), y: -100 * -cos(ANGLE), duration: 1)
let movespriteRight = SKAction.moveByX(100 * sin(ANGLE), y: 100 * -cos(ANGLE), duration: 1)
Where ANGLE is in a randian value from 0 to 2PI
You may have to play around with sin and cos a bit depending on your coordinate system
Crash in msvcp90d.dll when retrieving an iterator from a boost::tokenizer
There is a bug in Visual C++ with std::ostringstream
when _HAS_ITERATOR_DEBUGGING
is disabled.
If I recall correctly, the std::string
copy constructor copies iterators. You can get around this by using the std::string
conversion constructor taking a char*
instead.
If you change
std::string mystr(input.str());
to
std::string mystr(input.str().c_str());
then no exception is thrown.
Related Topics
How to Reproduce This Xcode Blue Drag Line
Rotate an Object in Its Direction of Motion
Swift Package Manager - Uikit Dependency
Print() to Console Log with Color
Bold Part of String in Uitextview Swift
Apply Vertical Alpha Gradient to Uitableview
Method' Is Ambiguous for Type Lookup in This Context, Error in Alamofire
Warning: Initialization of 'Unsafebufferpointer<T>' Results in a Dangling Buffer Pointer
Working with C Strings in Swift, Or: How to Convert Unsafepointer<Cchar> to Cstring
Turn Off Xcode's Unused Variable Warnings While Typing
How to Display Realm Results in Swiftui List
Can't Use Storyboard Custom Instantiated Window Controller
Trying to Stream Audio from Microphone to Another Phone via Multipeer Connectivity
Bool Being Seen as Int When Using Anyobject
Swiftui: How to Implement a Custom Init With @Binding Variables