How to fix some physics bodies behavior, when some bodies go off the physics edges? - swift

I am working with a game, which has a physics world. I create physics box around the whole scene for prevent the sprites go off the screen. But the issue is, when i add too many bodies to the scene, some of them go off this physics box.
This is the physics box around the scene:
homeArea.size = CGSizeMake(self.frame.size.width, self.frame.size.height)
homeArea.position = CGPointMake(self.frame.size.width / 2.0, self.frame.size.height / 2.0)
homeLayer.addChild(homeArea)
homeArea.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(-homeArea.frame.width / 2.0, -homeArea.frame.height / 2.0, homeArea.frame.size.width, homeArea.frame.size.height))
This is these too many bodies:
func addSprites() {
for i in 0...20 {
for j in 0...20 {
let shape = SKShapeNode(rect: CGRectMake(-5.0, -5.0, 10.0, 10.0))
shape.fillColor = SKColor.redColor()
shape.position = CGPointMake(self.frame.size.width - (shape.frame.size.width * CGFloat(i)), 0.0 + (shape.frame.size.height * CGFloat(j)))
shape.physicsBody = SKPhysicsBody(rectangleOfSize: shape.frame.size)
shape.physicsBody?.dynamic = true
addChild(shape)
}
}
}
And i create a cannon shooting to these bodies. There i want to create something like splash from cannon's bullet. I shoot to this wall from sprites, and notice from nodes count, that because of my bullet, some sprites go off the screen. I added the method usesPreciseCollisionDetection. But it's all the same.

Related

Shooting balls from a rotating cannon

I'm making a SpriteKit game. I have six cannons that I've made rotate back and fourth. I want to shoot cannonballs from each cannon that sync with the rotation of each cannon. I want a duration of one second between each cannonball.
So basically: A cannon that is in constant rotation is shooting cannonballs in the same direction as the rotation.
For the cannons i'm using an extension:
extension CGFloat {
func degreesToRadians() -> CGFloat {
return self * CGFloat.pi / 180
}
}
I'm gonna put the code for just one cannon, since I should be able to figure out how to adjust one of the cannonball movements to the others. Here is one:
func createCannons() {
let cannonLeftBottom = SKSpriteNode(imageNamed: "Cannon")
cannonLeftBottom.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cannonLeftBottom.position = CGPoint(x: -325, y: -420)
cannonLeftBottom.zPosition = 4
cannonLeftBottom.setScale(0.4)
cannonLeftBottom.zRotation = CGFloat(65).degreesToRadians()
let rotateLB = SKAction.rotate(byAngle:
CGFloat(-65).degreesToRadians(), duration: 2)
let rotateBackLB = SKAction.rotate(byAngle:
CGFloat(65).degreesToRadians(), duration: 2)
let repeatRotationLB =
SKAction.repeatForever(SKAction.sequence([rotateLB,rotateBackLB]))
cannonLeftBottom.run(repeatRotationLB)
self.addChild(cannonLeftBottom)
}
Here is my function for the cannonball:
func createBalls() {
let cannonBallLB = SKSpriteNode(imageNamed: "Ball")
cannonBallLB.name = "CannonBall"
cannonBallLB.position = CGPoint(x: -325, y: -420)
cannonBallLB.physicsBody = SKPhysicsBody(circleOfRadius:
cannonBallLB.size.height / 2)
cannonBallLB.physicsBody?.affectedByGravity = false
cannonBallLB.zPosition = 3
cannonBallLB.setScale(0.1)
self.addChild(cannonBallLB)
}
THX!
You need to convert from Polar Coordinates to Rectangular Coordinates.
You do this by using sin and cos
E.G.
let speed = 100 //This would mean move 100 points per second
let force = CGVector(dx:cos(cannon.zRotation) * speed,dy:sin(cannon.zRotation) * speed)
cannonBall.applyForce(force)
Note: Now unless they changed this, force used to be in units of points, if they fixed it to units of meters, then you need to divide your speed by 150, since 150 points = 1 meter in Spritekit

How to have endless scrolling ground at an angle with Swift and Spritekit?

I am trying to implement an endless scrolling ground with Swift and Spritekit. I managed to get the scrolling ground to work if the ground is a flat surface. But I want the ground to be on a decline like it is going down a hill. How can I do this? Here is the code I currently have:
func createGround() {
for i in 0...2 {
let grounds = SKSpriteNode(color: UIColor.white, size: CGSize(width: 600, height: 200))
grounds.name = "Ground"
grounds.anchorPoint = CGPoint(x: 0.5,y: 0.5)
grounds.position = CGPoint(x: CGFloat(i) * grounds.size.width, y: -300)
self.addChild(grounds)
}
}
func moveGround() {
self.enumerateChildNodes(withName: "Ground", using: ({
(node, error) in
node.position.x -= 6
node.position.y += 1
if node.position.x < -((self.scene?.size.width)!) {
node.position.x += (self.scene?.size.width)! * 3
node.position.y =
-400
}
}))
}
This creates the ground and scrolls them through the screen at an angle, but the ground nodes do not line up with each other. I imagine I will need some trigonometric function to make them line up? Here is what is currently looks like:
The white rectangles are my ground nodes. The grey is just a placeholder ground node which is not moving and I plan on deleting once I get the scrolling ground working.

All my textures are stretched vertically in Spritekit/Swift

Let's say I have a basketball texture made up of pixel art and it's 21x21. I put it in the game:
ball = SKSpriteNode(imageNamed: "ball")
ball.position.x = CGFloat.random(min: 0 , max: self.frame.width)
ball.position.y = self.frame.height + ball.frame.height * 2
ball.zPosition = 1
ball.size = CGSizeMake(21 , 21)
ball.setScale(10)
ball.texture!.filteringMode = .Nearest
//then all the physics stuff
self.addChild(ball)
but when they spawn, the pixels are stretched vertically, and when the balls roll, it's always stretched vertically-so the problem seems to be rooted somewhere in the engine. What should I try next?
Thanks yall

Swift - sprite kit - make SKPhysicsJointPin have less motion

I'm trying to create a snake with multiple body parts that moves left and right. Im using a pin, but upon the snake stopping, the body keeps moving and doesn't stop. I've messed around with the max and min angles, and the torque, but nothing seems to work. Should I use a different type of joint?
Sorry i cant log into my other account, but heres the code. Basically the second part just wobbles a lot. I wish to add 7-8 parts, but they just keep on wobbling, especially after moving "head". i would like a fluid "swoop" motion when i move the snake.
self.physicsWorld.gravity = CGVectorMake(0, -100)
self.physicsWorld.contactDelegate = self
head.size = CGSize(width: 25,height: 25)
head.physicsBody = SKPhysicsBody(texture: head.texture, size: head.size)
head.position = CGPointMake(100,400)
head.anchorPoint = CGPoint(x: 0.5, y: 1)
head.physicsBody!.dynamic = false
head.zPosition = 3
self.addChild(head)
var p1 = SKSpriteNode(imageNamed: "snakeBodyPart.png")
p1.size = CGSize(width: 25,height: 25)
p1.physicsBody = SKPhysicsBody(texture: p1.texture, size: p1.size)
p1.position = CGPointMake(100,380)
p1.anchorPoint = CGPoint(x: 0.5, y: 1)
p1.physicsBody!.dynamic = true
addChild(p1)
var joint = SKPhysicsJointPin.jointWithBodyA(head.physicsBody, bodyB: p1.physicsBody, anchor: CGPoint(x: CGRectGetMidX(head.frame), y: CGRectGetMinY(head.frame) + 10))
joint.upperAngleLimit = 0.1
joint.rotationSpeed = 0.1
self.physicsWorld.addJoint(joint)

How can I make the player not able to go through certain boundaries? (off-screen)

Hey so I was watching Ray Wenderlich's tutorial on How to Make a Game Like Mega Jump! and tried to create a similar project on my own. So during the tutorial you set the player to be able to go off the screen whenever you tilt the device.
override func didSimulatePhysics() {
player.physicsBody?.velocity = CGVector(dx: xAcceleration * 400.0, dy: player.physicsBody!.velocity.dy)
if player.position.x < -20.0 {
player.position = CGPoint(x: self.size.width + 20.0, y: player.position.y)
} else if (player.position.x > self.size.width + 20.0) {
player.position = CGPoint(x: -20.0, y: player.position.y)
}
return;
}
This is the code I have which makes the player go off the screen. How can I do this but for the player NOT being able to go off the screen? For example if you tilt your device all the way to the right make the player to stay on the right side until you move it the other way! Thank you in advance.
Currently you check if the player is out of screen (more then 20px) and then set his position to the other side, 20px out of the screen.
But you want to stop the player at 0px and your screen width. You can do it like this:
if player.position.x <= 0.0 {
player.position = CGPoint(x: 0.0, y: player.position.y)
} else if (player.position.x >= self.size.width) {
player.position = CGPoint(x: self.size.width, y: player.position.y)
}
This just set's the position of the player to 0.0 if he's moving out to the left, or your screen width, if he's moving out to the right.
The current code "loops around" so moving all the way to the left means you end up on the right.
Just change the coordinates in the if blocks to pin to the edges. Something like this:
if player.position.x < -20.0 {
player.position = CGPoint(x: -20.0, y: player.position.y)
} else if (player.position.x > self.size.width + 20.0) {
player.position = CGPoint(x: self.size.width + 20.0, y: player.position.y)
}
Notice that if the player is beyond the left edge (x < -20) then you just leave the x-position at -20. Similar thing on the right edge.
You'll have to try this out to see how it works with the physics and acceleration but that should be the general idea.