Simple code below creates a ball (on touch) and set physics body to make it fall and bounce. I set the bounds to match the frame, wanting the ball to remain 100% within the screen. However when running the code, the ball will move off the screen out of view left and right. How can I keep the sprite within the bounds of the screen?
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
if let touch = touches.first {
let location = touch.locationInNode(self)
let ball = SKShapeNode(circleOfRadius: 20)
ball.physicsBody = SKPhysicsBody(circleOfRadius: 20)
ball.physicsBody!.restitution = 0.4
ball.position = location
addChild(ball)
}
}
}
Related
I want to make an SKSpritenode expand only in one direction, in this case only upwards.
override func didMoveToView(view: SKView) {
var rightlegs = SKSpriteNode()
rightlegs.size = CGSize(width: 10, height: 50)
rightlegs.color = SKColor.yellowColor()
rightlegs.position = CGPointMake(self.frame.width / 2 + 20, self.frame.height / 2 - 40)
self.addChild(rightlegs)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
So.. When i press the screen I want the height to expand; however, not from both direction. How do I solve this problem? Thank for your time:)
You can do it by changing the anchorPoint property of the sprite to CGPoint(x:0.5, y:0.0) (this will bottom-align sprite's texture) and scaling the sprite's height using yScale property, like this:
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
let rightlegs = SKSpriteNode(color: .yellowColor(), size: CGSize(width: 10, height: 50))
override func didMoveToView(view: SKView) {
rightlegs.anchorPoint.y = 0.0
rightlegs.position = CGPointMake(self.frame.width / 2 + 20, self.frame.height / 2 - 40)
self.addChild(rightlegs)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Without animation
rightlegs.yScale += 0.2
}
}
Or you can make it animated using some of the SKAction scaling methods:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
//With animation
rightlegs.runAction(SKAction.scaleYTo(rightlegs.yScale + 0.2, duration: 0.2))
}
About anchorPoint from docs:
Defines the point in the sprite that corresponds to the node’s
position.
You specify the value for this property in the unit coordinate space.
The default value is (0.5,0.5), which means that the sprite is
centered on its position.
Basically what anchorPoint does is that it defines how texture will be drawn relative to node's position and affects on rotation and scaling of a node...
A good explanation about how anchor point works and what it does can be found in Apple's Working with Sprites section of documentation.
I need help with the movement in Swift. I have a SKSpriteNode and I need help with touch and drag movement left or right to move and the SKSpriteNode. But only the left and right. When I click on the other side than the x position of the picture is to just run over smoothly. Could anyone help how to do it? Thanks.
import SpriteKit
class PlayScene: SKScene {
let rocket = SKSpriteNode(imageNamed: "rocket")
override func didMoveToView(view: SKView) {
rocket.position = CGPoint(x: self.frame.width/2, y: self.frame.height * 0.8)
self.addChild(rocket)
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
rocket.position = CGPoint(x: location.x, y: self.frame.height * 0.8)
}
}
In this, the rocket animates for 1 second to the location of the touch and then moves with the touch if the user moves their finger.
class GameScene: SKScene {
let rocket = SKSpriteNode(imageNamed: "rocket")
override func didMoveToView(view: SKView) {
rocket.position = CGPoint(x: self.frame.width/2, y: self.frame.height * 0.8)
self.addChild(rocket)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
rocket.position = location
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let moveAction = SKAction.moveTo(location, duration: 1/*Or as long as you want it to move*/)
rocket.runAction(moveAction)
}
}
}
Hope this helps.
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
let sprite = SKSpriteNode(imageNamed:"Beach Ball-100")
self.addChild(sprite)
sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = location
sprite.color = UIColor.redColor()
sprite.physicsBody = SKPhysicsBody(edgeLoopFromRect:self.frame)
sprite.physicsBody?.affectedByGravity = true
var action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)
}
}
}
The code above is present in my scene class. When I run it, the ball object is not falling as expected since the gravity property is set to true. Please explain what I am doing wrong.
The Physicsbody is wrong. You need the frame of the sprite and not of the world:
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.frame.size)
Add SKPhysicsContactDelegate:
class GameScene: SKScene, SKPhysicsContactDelegate
Define your physicsWorld in didMoveToView or in touchesBegan(like you did in example)
physicsWorld.gravity = CGVectorMake(0, -1.0)
physicsWorld.contactDelegate = self
Give your node proper SKPhysicsBody size
sprite.physicsBody = SKPhysicsBody(circleOfRadius: frame.size.width / 2)
I have a simple scene which adds a bouncing ball to the scene once a user touches in an area. The goal will be to bounce the balls off pins in order to 'score' in a certain area.
I'm just at the very beginning of coding the app, but I can't as yet find a way to create a limit for the amount of balls a user can generate. At the moment, they can generate any number of balls and over-saturate the scene, leading to a drop in FPS and a very easy game!
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let ball = SKSpriteNode(imageNamed:"ball")
ball.xScale = 0.2
ball.yScale = 0.2
ball.position = location
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 2.0)
ball.physicsBody!.dynamic = true
ball.physicsBody!.friction = 0
ball.physicsBody!.restitution = 0.8
ball.name = "ball"
self.addChild(ball)
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
I know I need to ask the scene how many ball nodes are in the scene and then remove a ball once it reached a limit but everything I seem to try results in errors.
there are a ton of ways to do this, but this is probably the easiest.
NOTE: unless you remove balls from the scene at some point, you're going to hit a ten ball limit and get stuck.
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
// ball limit
let limit = 10
// setup counter
var i = 0
// loop through the ball nodes added to the scene
self.enumerateChildNodesWithName("ball", usingBlock: {
_, _ in // we dont need to use these variables right now
i += 1 // increment the counter
})
// if we haven't hit our limit, add a ball (YOUR CODE HERE)
if i <= limit {
let ball = SKSpriteNode(imageNamed:"ball")
ball.xScale = 0.2
ball.yScale = 0.2
ball.position = location
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 2.0)
ball.physicsBody!.dynamic = true
ball.physicsBody!.friction = 0
ball.physicsBody!.restitution = 0.8
ball.name = "ball"
self.addChild(ball)
}
}
}
every time I add the following code:
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
the physics body for my "ball" item stops moving. It worked before adding the previous line.
here is all my code:
class GameScene: SKScene {
// creaTE nODE/Sprite
let ball = SKSpriteNode(imageNamed: "ball.png")
override func didMoveToView(view: SKView) {
// set up scene here
self.backgroundColor = SKColor.whiteColor()
//add physics to scene
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
//create cg piont for sprite
ball.position = CGPointMake(size.width / 2, size.height / 2)
//give it some real life physics!
ball.physicsBody = SKPhysicsBody(circleOfRadius: size.height / 2)
addChild(ball)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
This line is causing the problem:
ball.physicsBody = SKPhysicsBody(circleOfRadius: size.height / 2)
You need to use
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 2)
The physicsBody being created in the previous line was the size of the scene, hence it did not have space to move!
You can check the physicsBody being created by setting the showsPhysics property to YES in the SKView. Check here for more details.