Bullet Firing In Direction Of Tap - swift

So far, my app has a big ball in the middle and a small ball in the middle also. I would like to be able to tap anywhere on the screen and the small ball shoots in that direction. I've heard people say about creating vectors but I can't seem to get these working in swift 3. I am a beginner so sorry about a stupid question!
Here is my code:
var mainBall = SKSpriteNode(imageNamed: "Ball")
override func didMove(to view: SKView) {
mainBall.size = CGSize(width: 300, height: 300)
mainBall.position = CGPoint(x: frame.width / 2, y: frame.height / 2)
self.addChild(mainBall)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: self)
print(position.x)
print(position.y)
}
for touch in (touches) {
touch.location(in: self)
let smallBall = SKSpriteNode(imageNamed: "Ball")
smallBall.position = mainBall.position
smallBall.size = CGSize(width: 100, height: 100)
smallBall.physicsBody = SKPhysicsBody(circleOfRadius: smallBall.size.width / 2)
smallBall.physicsBody?.affectedByGravity = false
self.addChild(smallBall)
}
}

You can use actions to animate SKSprideNodes:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
let newPosition = touch.location(in: self)
...
//assuming self.smallBall exists and is visible already:
[self.smallBall runAction:[SKAction moveTo:newPosition duration:1.0]];
}

Related

How to drag around a SKSpriteNode using Pin Joints

I want to be able to pick up a SKSpriteNode and in effect "dangle" it with my finger. I've been experimenting with SKPhysicsJointPin but it doesn't seem to be delivering the desired result.
Here's the code I'm using:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
if !BeingMoved {
BeingMoved = true
TempDragNode.name = "TempDragNode"
TempDragNode.size = CGSize(width: 44, height: 44)
TempDragNode.physicsBody = SKPhysicsBody(circleOfRadius: 44)
TempDragNode.physicsBody?.affectedByGravity = false
addChild(TempDragNode)
TempDragNode.physicsBody?.allowsRotation = false
let PositionX = CGPoint(x: TempDragNode.position.x, y: TempDragNode.position.y+(TempDragNode.frame.height/2))
let PinJoint = SKPhysicsJointPin.joint(withBodyA: (childNode(withName: "Nutty")?.physicsBody)!, bodyB: TempDragNode.physicsBody!, anchor: PositionX)
scene?.physicsWorld.add(PinJoint)
}
TempDragNode.position = location
}
}

How to move sprite relative to its original position with touch in spritekit

I looking to move a sprite relative to the player's touch. I am familiar with the moveTo SKActions, however I am wondering how to implement sprite movement where the sprite moves along with the user's touch movement.
For example, I have a sprite in the centre of the screen. If I apply a touch at the bottom of the screen and move my finger up , the sprite will move up from the centre(it's original position).
Thanks!
Try this :
import SpriteKit
class GameScene: SKScene {
var node = SKSpriteNode()
var nodePosition = CGPoint()
var startTouch = CGPoint()
override func didMove(to view: SKView) {
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
// node set up
node = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
node.position = CGPoint.zero
self.addChild(node)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self){
startTouch = location
nodePosition = node.position
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self){
node.run(SKAction.move(to: CGPoint(x: nodePosition.x + location.x - startTouch.x, y: nodePosition.y + location.y - startTouch.y), duration: 0.1))
}
}
}

Making my game object bounce forever?

So I am trying to make a ping pong game and I am able to get the ball moving and bouncing but the ball slows down. Whats the code to keep the balls velocity at a constant? Here's what I got:
var ball = SKSpriteNode()
var enemy = SKSpriteNode()
var main = SKSpriteNode()
override func didMove(to view: SKView) {
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width)
ball = self.childNode(withName: "ball") as! SKSpriteNode
enemy = self.childNode(withName: "enemy") as! SKSpriteNode
main = self.childNode(withName: "main") as! SKSpriteNode
ball.physicsBody?.applyImpulse(CGVector(dx: 20, dy: 20))
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 1.0))
}
}
My physics settings are set to the following:
physics definition
Thanks in advance!

App crash when 2 fingers are on the screen, touches began, touches moved

I'm not sure what's happening so i can't really describe it to you properly, I made an app that draws a line with the dragging of the users finger, its a sprite kit Game so i used touchesBegan and touchesMoved, so what happens is if i place a finger on the screen while I'm drawing another line the game crashes. what I'm looking for is a way to ignore the second touch until the first is over.My game Draws a line from the start position of the touch till the end position when the touches end
here is the code in my touches functions
var lineNode = SKShapeNode()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches{
positionOfStartTouch = touch.location(in: self)
lastPoint = touch.location(in: self)
firstPoint = touch.location(in: self)
}
let pathToDraw = CGMutablePath()
print(pathToDraw.isEmpty)
pathToDraw.move(to: CGPoint(x: firstPoint.x, y: firstPoint.y))
if frame.width == 375 {
lineNode.lineWidth = 4
}else if frame.width == 414 {
lineNode.lineWidth = 6
}else if frame.width == 768 {
lineNode.lineWidth = 8
}
lineNode.strokeColor = UIColor.white
lineNode.name = "Line"
lineNode.zPosition = 100000
lineNode.path = pathToDraw
self.addChild(lineNode)
shapeNodes.append(lineNode)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches{
positionInScene = touch.location(in: self)
}
let pathToDraw = lineNode.path as! CGMutablePath
lineNode.removeFromParent()
pathToDraw.move(to: CGPoint(x: firstPoint.x, y: firstPoint.y))
pathToDraw.addLine(to: CGPoint(x: positionInScene.x, y: positionInScene.y))
lineNode.path = pathToDraw
shapeNodes.append(lineNode)
self.addChild(lineNode)
firstPoint = positionInScene
}
The node can only have one parent. You are trying to add lineNode multiple times the the scene. Try this:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches{
positionInScene = touch.location(in: self)
}
let pathToDraw = lineNode.path as! CGMutablePath
lineNode.removeFromParent()
pathToDraw.move(to: CGPoint(x: firstPoint.x, y: firstPoint.y))
pathToDraw.addLine(to: CGPoint(x: positionInScene.x, y: positionInScene.y))
lineNode.path = pathToDraw
if let copy = lineNode.copy() as? SKShapeNode {
shapeNodes.append(copy)
self.addChild(copy)
}
firstPoint = positionInScene
}
Do the same in touchesBegan. Of course I am not going into your logic about what should happen when multiple touches occur. I am just pointing out where is the error and why your app crashes.

Single click needed to run function instead of double click SpriteKit

Im making a flappy bird clone and when the bird dies, the spriteNode with restart button pop ups, but the fist click is stoping animation (if there any) and second click forse the restart() function
heres how i make SpriteNode menu with button:
let menu = SKSpriteNode(texture: self.groundTex)
menu.name = "menu"
menu.position = CGPoint(x: 0, y: 0)
menu.zPosition = 20
let restartButton = SKSpriteNode(texture: self.heroTexture)
restartButton.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
restartButton.zPosition = 40
restartButton.name = "restart"
let moveMenu = SKAction.moveTo(CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2), duration: 1.0)
self.menuNode.addChild(menu)
menuNode.addChild(restartButton)
self.addChild(menuNode)
menu.runAction(SKAction.sequence([
moveMenu,
SKAction.waitForDuration(NSTimeInterval(1.0)),
makeGameEnd
]), withKey: "gameover"
here is how i detect touch:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first
let location = touch?.locationInNode(self)
let node: SKNode = nodeAtPoint(location!)
if node.name == "restart" {
restart()
}
UPDATE
my restart():
func restart() {
let scene = GameScene(size: self.size)
scene.scaleMode = .AspectFill
self.view?.presentScene(scene)
}
You can check for a double tap like this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first
let location = touch?.locationInNode(self)
let node: SKNode = nodeAtPoint(location!)
if touch.tapCount % 2 == 0 {
if node.name == "restart" {
restart()
}
}
}