Trying to move / drag SKSpriteNode in y axis - ios

I'm trying to create a small game ,and in there there is a pipe , and i want to move that pipe along with the y axis , i want to do thins for finger swipe , i tried to do this with touches began but its doesn't looks smooth , so i tried to use uipangesture , but in not familiar with the sprite integration ,
can someone help me to achive this
class GameScene: SKScene,SKPhysicsContactDelegate {
var pipeTextureUp:SKTexture!
var pipeTextureDown:SKTexture!
var pipeUp:SKSpriteNode!
var pipeDown:SKSpriteNode!
var circleTouch: UITouch?
var verticalPipeGap:Double = 60.0
var moveStatus: Bool!
override func didMoveToView(view: SKView) {
/* Setup your scene here */
backgroundColor = SKColor.whiteColor()
//set the gravity
self.physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
self.physicsWorld.contactDelegate = self
//first create the pipe in a random location
pipeTextureUp = SKTexture(imageNamed: "PipeUp")
pipeTextureUp.filteringMode = .Nearest
pipeTextureDown = SKTexture(imageNamed: "PipeDown")
pipeTextureDown.filteringMode = .Nearest
pipeUp = SKSpriteNode(texture: pipeTextureUp)
pipeUp.setScale(2.0)
pipeUp.name = "pipeUp"
pipeUp.position = CGPoint(x: size.width * 0.9, y: 0.0)
pipeDown = SKSpriteNode(texture: pipeTextureDown)
pipeDown.setScale(2.0)
pipeDown.name = "pipeDown"
pipeDown.position = CGPoint(x: Double(size.width) * 0.9 , y: Double(pipeDown.size.height) + verticalPipeGap)
//addChild(pipeDown)
addChild(pipeUp)
}
func didBeginContact(contact: SKPhysicsContact) {
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
print("touches started")
moveStatus = true
circleTouch = touch
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
print(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
//let fingerPoint = CGPoint(x: size.width * 0.9, y: 0.3)
let actionUpMove:SKAction = SKAction.moveToY(positionInScene.y, duration: 1.0)
pipeUp.runAction(actionUpMove)
pipeUp.position.y = positionInScene.y
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
//let fingerPoint = CGPoint(x: size.width * 0.9, y: 0.3)
circleTouch = nil
}
}
}
}

If you want to intercept your swiping along Y coordinate you could put this code in didMoveToView:
let swipeUp:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(GameScene.swipedUp(_:)))
swipeUp.direction = .Up
swipeUp.cancelsTouchesInView = true
swipeUp.delaysTouchesBegan = true
view.addGestureRecognizer(swipeUp)
let swipeDown:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(GameScene.swipedDown(_:)))
swipeDown.direction = .Down
swipeDown.cancelsTouchesInView = true
swipeDown.delaysTouchesBegan = true
view.addGestureRecognizer(swipeDown)
Then your methods are:
func swipedUp(sender:UISwipeGestureRecognizer){
print("swiped up")
}
func swipedDown(sender:UISwipeGestureRecognizer){
print("swiped down")
}

UPDATE : apparently this is what i had to do ,
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
handleTouch(touches.first!, name: name)
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
handleTouch(touches.first!, name: name)
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
handleTouch(touches.first!, name: name)
}
}
}
func handleTouch(touch: UITouch , name : String) {
let location = touch.locationInNode(self) // get the current point
let node = self.nodeAtPoint(location) //get the current node based on the touched location
let previousLocation = touch.previousLocationInNode(self) //get the previous location in node
let diff = location.y - previousLocation.y; //get the different of location
let newPosition = CGPointMake(node.position.x, node.position.y + diff);
var newPipeDownPosition :CGPoint;
if (name == "pipeDown" )
{
newPipeDownPosition = CGPointMake(self.pipeUp.position.x, self.pipeUp.position.y + diff);
pipeDown.position.y = newPosition.y
pipeUp.position.y = newPipeDownPosition.y
}else{
newPipeDownPosition = CGPointMake(self.pipeDown.position.x, self.pipeDown.position.y + diff);
pipeUp.position.y = newPosition.y
pipeDown.position.y = newPipeDownPosition.y
}
}
now the pipe moves according to top and down direction

Related

How to drag and flick a node in SpriteKit while gravity is present?

With my current code, the node is extremely laggy, and moves or teleports in random directions for some reason when its flicked. How can i fix this, and also can someone explain why it is teleporting and moving to random places in the scene.
Also, is there anyway to allow the node to be moved only when it is dragged from its position, rather than being at the gesturerecognizer's coordinates at all times?
override func didMove(to view: SKView) {
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.pan(_:)))
view.addGestureRecognizer(gestureRecognizer)
circleNode.physicsBody = SKPhysicsBody(circleOfRadius: 20)
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.addChild(circleNode)
}
#objc func pan(_ recognizer: UIPanGestureRecognizer) {
if recognizer.state == .changed {
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
var location = recognizer.location(in: self.view!)
location = self.convertPoint(fromView: location)
circleNode.position = location
}
if recognizer.state == .ended {
self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
let transformerX = 1024/self.view!.frame.size.width
let transformerY = 768/self.view!.frame.size.height
let velocity = recognizer.velocity(in: self.view)
circleNode.physicsBody?.applyForce(CGVector(dx: velocity.x * transformerX, dy: velocity.y * transformerY))
}
}
Here is some code I was playing around with. I'm able to drag and flick a spear (spear Image) and also "pop" a pig head. This is the whole GameScene.Remove the code you don't need. :)
import SpriteKit
import CoreMotion
class GameScene: SKScene, SKPhysicsContactDelegate {
enum CollisionTypes: UInt32{
case spear = 1
case wall = 2
case head = 4
}
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
//Add contact delegate
physicsWorld.contactDelegate = self
self.backgroundColor = .white
self.addChild(spearNode)
self.addChild(headNode)
}
lazy var spearNode: SKSpriteNode = {
let node = SKSpriteNode(imageNamed: "spear2")
node.name = "Spear"
node.physicsBody = SKPhysicsBody(texture: node.texture!,
size: CGSize(width: node.frame.width , height: node.frame.height))
node.position = CGPoint(x:self.frame.midX , y:self.frame.midY)
node.physicsBody?.affectedByGravity = true
node.physicsBody?.allowsRotation = false
node.size = CGSize(width: node.frame.width , height: node.frame.height )
node.physicsBody?.categoryBitMask = CollisionTypes.spear.rawValue
node.physicsBody?.contactTestBitMask = CollisionTypes.head.rawValue
node.physicsBody?.collisionBitMask = CollisionTypes.head.rawValue
return node
}()
lazy var headNode: SKSpriteNode = {
let node = SKSpriteNode(imageNamed: "Pig")
node.name = "Pig"
node.physicsBody = SKPhysicsBody(texture: node.texture!,
size: CGSize(width: node.frame.width , height: node.frame.height))
node.position = CGPoint(x:self.frame.midX , y:self.frame.maxY - 100)
node.physicsBody?.affectedByGravity = true
node.physicsBody?.allowsRotation = false
node.size = CGSize(width: node.frame.width / 2 , height: node.frame.height / 2 )
node.physicsBody?.categoryBitMask = CollisionTypes.head.rawValue
return node
}()
func didBegin(_ contact: SKPhysicsContact){
guard let nodeA = contact.bodyA.node else {return}
guard let nodeB = contact.bodyB.node else {return}
print("Contacted")
if nodeA.name == "Pig" && nodeB.name == "Spear"{
nodeA.removeFromParent()
}
if nodeA.name == "Spear" && nodeB.name == "Pig"{
nodeB.removeFromParent()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in:self)
if spearNode.frame.contains(location) {
touchPoint = location
touching = true
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in: self)
touchPoint = location
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func update(_ currentTime: TimeInterval) {
physicsWorld.gravity = CGVector(dx:0, dy: -9.8)
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-spearNode.position.x, dy: touchPoint.y-spearNode.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
spearNode.physicsBody!.velocity=velocity
}
}
}
Why not simply impart a force to the object based upon the swipe gesture rather than turning off gravity, manually moving the object, and then turning on gravity again when the swipe is over?

How to move single SKspritenode from array

I have an array of sprites and I move it when click on it, the problem is that it is moving all the sprites and I want it to move a single element, how can I do this? thank you in advance
This is my code:
var containerPieces: [ContainerPieces] = []
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
let rsCurrent = self.atPoint(location)
for nodo in containerPieces {
let rsBody = nodo.block.physicsBody
if rsBody == rsCurrent.physicsBody {
if nodo.block.frame.contains(location) {
nodo.block.position = location
nodo.block.run(blinkAnimation(), withKey:"wiggle")
isFingerOnPaddle = true
}
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if isFingerOnPaddle {
let touch = touches.first
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
for nodo in containerPieces{
var paddleX = nodo.block.position.x + (touchLocation.x - previousLocation.x)
var paddleY = nodo.block.position.y + (touchLocation.y - previousLocation.y)
paddleX = max(paddleX, nodo.block.size.width/2)
paddleX = min(paddleX, size.width - nodo.block.size.width/2)
paddleY = max(paddleY, nodo.block.size.width/2)
paddleY = min(paddleY, size.width - nodo.block.size.width/2)
nodo.block.position = CGPoint(x: paddleX, y: paddleY)
}
}
}

use two sprite objects at the same time with single touch?

Currently, I can only use one at a time, and not make the two paddles (one on each side of the screen) act independently when different finger movements are used with each one. Here is the class. Any ideas?
let BallCategoryName = "ball"
let GameMessageName = "gameMessage"
let BallCategory : UInt32 = 0x1 << 0
let LeftCategory : UInt32 = 0x1 << 1
let BlockCategory : UInt32 = 0x1 << 2
let PaddleCategory : UInt32 = 0x1 << 3
let BorderCategory : UInt32 = 0x1 << 4
class GameScene: SKScene, SKPhysicsContactDelegate {
var isFingerOnPaddleL = false
var isFingerOnPaddleR = false
override func didMove(to view: SKView) {
super.didMove(to: view)
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
physicsWorld.contactDelegate = self
let ball = childNode(withName: BallCategoryName) as! SKSpriteNode
ball.physicsBody!.applyImpulse(CGVector(dx: 2.0, dy: -2.0))
let paddleL = childNode(withName: "paddleL") as! SKSpriteNode
//let paddleR = childNode(withName: "paddleR") as! SKSpriteNode
let leftRect = CGRect(x: frame.origin.x, y: frame.origin.y, width: 1, height: frame.size.height)
let left = SKNode()
left.physicsBody = SKPhysicsBody(edgeLoopFrom: leftRect)
addChild(left)
left.physicsBody!.categoryBitMask = LeftCategory
ball.physicsBody!.categoryBitMask = BallCategory
paddleL.physicsBody!.categoryBitMask = PaddleCategory
borderBody.categoryBitMask = BorderCategory
ball.physicsBody!.contactTestBitMask = LeftCategory
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if let body = physicsWorld.body(at: touchLocation) {
if body.node!.name == "paddleL" {
print("Began touch on paddleL")
isFingerOnPaddleL = true
}
else if body.node!.name == "paddleR" {
print("Began touch on paddleR")
isFingerOnPaddleR = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// 1
if isFingerOnPaddleL {
// 2
let touch = touches.first
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
// 3
let paddle = childNode(withName: "paddleL") as! SKSpriteNode
// 4
var paddleY = paddle.position.y + (touchLocation.y - previousLocation.y)
// 5
paddleY = max(paddle.size.height/2, paddleY)
paddleY = min(size.height - paddle.size.height/2, paddleY)
// 6
paddle.position = CGPoint(x: paddle.position.x, y: paddleY)
}
else if isFingerOnPaddleR {
// 2
let touch = touches.first
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
// 3
let paddle = childNode(withName: "paddleR") as! SKSpriteNode
// 4
var paddleY = paddle.position.y + (touchLocation.y - previousLocation.y)
// 5
paddleY = max(paddle.size.height/2, paddleY)
paddleY = min(size.height - paddle.size.height/2, paddleY)
// 6
paddle.position = CGPoint(x: paddle.position.x, y: paddleY)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if (isFingerOnPaddleL == true) {
isFingerOnPaddleL = false
}
else if (isFingerOnPaddleR == true) {
isFingerOnPaddleR = false
}
}
func didBegin(_ contact: SKPhysicsContact) {
// 1
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
// 2
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 3
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == LeftCategory {
print("Hit left. First contact has been made.")
}
}
}
You can process the paddles independently by tracking each touch throughout its lifecycle (began/moved/ended). First, define a dictionary with the touch object as the key and the node's name as the value
var touchTracker:[UITouch:String] = [:]
then in touchesBegan, store the name of paddle(s) touched by the user
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let touchLocation = touch.location(in: self)
let node = atPoint(touchLocation)
if let name = node.name {
if name == "paddleL" {
print("Began touch on paddleL")
touchTracker[touch] = name
}
else if name == "paddleR" {
print("Began touch on paddleR")
touchTracker[touch] = name
}
}
}
}
In touchesMoved, use the touch object to retrieve the node's name from the dictionary, and use the name to access the appropriate paddle.
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let touchLocation = touch.location(in: self)
if let name = touchTracker[touch] {
if let paddle = childNode(withName: name) as? SKSpriteNode {
// Move a paddle
paddle.position = CGPoint(x:paddle.position.x, y:touchLocation.y)
}
}
}
}
Lastly, remove the touch/name from the dictionary when a touch ends.
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
if touchTracker[touch] != nil {
touchTracker.removeValue(forKey: touch)
}
}
}

How do I allow MULTIPLE images to be moved using touch in SpriteKit?

so I am making this game in Swift and I have included the code of what I have done on the 'GameScene.swift' file.
I have 4 different objects that will need to be recreated at run time after every 0.2 seconds (don't even know how to do that :/), however using the code I currently have, if I try to move the 'coin20', 'coin100', or 'coin50' image, they don't move, only 'coin10' gets moved to their location and is far too sensitive so it just moves around like crazy whilst the other images are static.
I hope this question is specific enough since my past questions weren't well received by answerers, if not please let me know how to improve, i'm just a beginner in programming.
Thank you
Code:
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var coin10 = SKSpriteNode(imageNamed: "10S.png")
var coin100 = SKSpriteNode(imageNamed: "100S.png")
var coin50 = SKSpriteNode(imageNamed: "50S.png")
var coin20 = SKSpriteNode(imageNamed: "20S.png")
var wall1 = SKSpriteNode(imageNamed: "Wall1.png")
var wall2 = SKSpriteNode(imageNamed: "Wall2.png")
var bar = SKSpriteNode(imageNamed: "Bar.png")
var scorelabel = SKLabelNode()
var score = 0
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
enum ColliderType:UInt32 {
case coin = 1
case wall = 2
}
override func didMoveToView(view: SKView) {
/* Setup your scene here */
//Adding coin10
coin10.position = CGPointMake(self.size.width / 2, self.size.height / 5)
coin10.physicsBody = SKPhysicsBody(circleOfRadius: coin10.size.width/2)
coin10.physicsBody!.affectedByGravity = false
coin10.physicsBody!.categoryBitMask = ColliderType.coin.rawValue
coin10.physicsBody!.contactTestBitMask = ColliderType.wall.rawValue
coin10.physicsBody!.collisionBitMask = ColliderType.wall.rawValue
coin10.physicsBody!.dynamic = true
self.addChild(coin10)
//Adding coin100
coin100.position = CGPointMake(self.size.width / 1.7, self.size.height / 5.1)
coin100.physicsBody = SKPhysicsBody(circleOfRadius: coin100.size.width/2)
coin100.physicsBody!.affectedByGravity = false
coin100.physicsBody!.categoryBitMask = ColliderType.coin.rawValue
coin100.physicsBody!.contactTestBitMask = ColliderType.wall.rawValue
coin100.physicsBody!.collisionBitMask = ColliderType.wall.rawValue
coin100.physicsBody!.dynamic = true
self.addChild(coin100)
//Adding coin50
coin50.position = CGPointMake(self.size.width / 2.2, self.size.height / 4.9)
coin50.physicsBody = SKPhysicsBody(circleOfRadius: coin50.size.width/2)
coin50.physicsBody!.affectedByGravity = false
coin50.physicsBody!.categoryBitMask = ColliderType.coin.rawValue
coin50.physicsBody!.contactTestBitMask = ColliderType.wall.rawValue
coin50.physicsBody!.collisionBitMask = ColliderType.wall.rawValue
coin50.physicsBody!.dynamic = true
self.addChild(coin50)
//Adding coin20
coin20.position = CGPointMake(self.size.width / 2.4, self.size.height / 5)
coin20.physicsBody = SKPhysicsBody(circleOfRadius: coin20.size.width/2)
coin20.physicsBody!.affectedByGravity = false
coin20.physicsBody!.categoryBitMask = ColliderType.coin.rawValue
coin20.physicsBody!.contactTestBitMask = ColliderType.wall.rawValue
coin20.physicsBody!.collisionBitMask = ColliderType.wall.rawValue
coin50.physicsBody!.dynamic = true
self.addChild(coin20)
//Adding wall1
wall1.position = CGPointMake(self.size.width / 1.72, self.size.height / 1.07)
wall1.physicsBody = SKPhysicsBody(rectangleOfSize: wall1.frame.size )
wall1.physicsBody!.affectedByGravity = false
wall1.physicsBody!.categoryBitMask = ColliderType.wall.rawValue
wall1.physicsBody!.contactTestBitMask = ColliderType.coin.rawValue
wall1.physicsBody!.collisionBitMask = ColliderType.coin.rawValue
wall1.physicsBody!.dynamic = false
self.addChild(wall1)
//Adding wall2
wall2.position = CGPointMake(self.size.width / 2.5, self.size.height / 1.07)
wall2.physicsBody = SKPhysicsBody(rectangleOfSize: wall2.frame.size )
wall2.physicsBody!.affectedByGravity = false
wall2.physicsBody!.categoryBitMask = ColliderType.wall.rawValue
wall2.physicsBody!.contactTestBitMask = ColliderType.coin.rawValue
wall2.physicsBody!.collisionBitMask = ColliderType.coin.rawValue
wall2.physicsBody!.dynamic = false
self.addChild(wall2)
//Adding bar
bar.position = CGPointMake(self.size.width / 2, self.size.height / 1)
bar.physicsBody = SKPhysicsBody(rectangleOfSize: wall2.frame.size)
bar.physicsBody!.affectedByGravity = false
bar.physicsBody!.categoryBitMask = ColliderType.wall.rawValue
bar.physicsBody!.contactTestBitMask = ColliderType.coin.rawValue
bar.physicsBody!.collisionBitMask = ColliderType.coin.rawValue
bar.physicsBody!.dynamic = false
self.addChild(bar)
//Adding physics world properties
self.physicsWorld.contactDelegate = self
var scenebody = SKPhysicsBody(edgeLoopFromRect: self.frame)
scenebody.friction = 0
self.physicsBody = scenebody
self.physicsWorld.gravity = CGVectorMake(0, -0.3)
//Scoreboard
scorelabel = SKLabelNode(text: "0")
scorelabel.position.y = (self.size.height/2)
scorelabel.position.x = (self.size.height/2.3)
addChild(scorelabel)
}
func didBeginContact(contact: SKPhysicsContact) {
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
let touch = touches.first as! UITouch
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if coin10.containsPoint(location){
touchPoint = location
touching = true
}
else if coin100.containsPoint(location){
touchPoint = location
touching = true
}
else if coin20.containsPoint(location){
touchPoint = location
touching = true
}
else if coin50.containsPoint(location){
touchPoint = location
touching = true
}
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if coin10.containsPoint(location){
touchPoint = location
}
else if coin100.containsPoint(location){
touchPoint = location
}
else if coin50.containsPoint(location){
touchPoint = location
}
else if coin20.containsPoint(location){
touchPoint = location
}
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
touching = false
}
override func update(currentTime: CFTimeInterval) {
if touching {
let dt: CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-coin10.position.x, dy: touchPoint.y-coin10.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
coin10.physicsBody!.velocity = velocity
}
}
}
First, add this instance variable
var touchedCoin:SKSpriteNode?
Then, in touchesBegan, set touchedCoin to the coin that was touched:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if coin10.containsPoint(location) {
touchPoint = location
touching = true
touchedCoin = coin10
}
else if coin100.containsPoint(location){
touchPoint = location
touching = true
touchedCoin = coin100
}
else if coin20.containsPoint(location){
touchPoint = location
touching = true
touchedCoin = coin20
}
else if coin50.containsPoint(location){
touchPoint = location
touching = true
touchedCoin = coin50
}
}
}
Lastly, move the coin that was touched
override func update(currentTime: CFTimeInterval) {
if touching {
let dt: CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-touchedCoin!.position.x, dy: touchPoint.y-touchedCoin!.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
touchedCoin!.physicsBody!.velocity = velocity
}
}

moving paddles only pushing the puck, not hitting it

I am trying to move the paddle, if it hits the puck, the puck should move away. But the puck only move, more like the paddle is only pushing it.
Declaring paddle:
p1.fillColor = SKColor.blackColor()
p1.name = p1Name
p1.physicsBody = SKPhysicsBody(circleOfRadius: 30)
p1.physicsBody.restitution = 1.0
p1.physicsBody.angularDamping = 0.0
p1.physicsBody.allowsRotation = false
p1.physicsBody.dynamic = true
p1.physicsBody.categoryBitMask = p1Category
p1.physicsBody.collisionBitMask = wallCategory | pCategory
p1.physicsBody.contactTestBitMask = pCategory
p1.position = CGPointMake(self.frame.width/2, self.frame.height/4)
self.addChild(p1)
Delcaring puck:
puck.fillColor = SKColor.redColor()
puck.name = pName
puck.physicsBody = SKPhysicsBody(circleOfRadius: 25)
puck.physicsBody.restitution = 0.8
puck.physicsBody.angularDamping = 0.5
puck.physicsBody.linearDamping = 0.5
puck.physicsBody.allowsRotation = false
puck.physicsBody.usesPreciseCollisionDetection = true
puck.physicsBody.friction = 0.0
puck.physicsBody.dynamic = true
puck.physicsBody.categoryBitMask = pCategory
puck.physicsBody.collisionBitMask = wallCategory | p1Category
puck.physicsBody.contactTestBitMask = p1Category
puck.position = CGPointMake(self.frame.width/2, self.frame.height/2)
self.addChild(puck)
How i move the paddle:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let body: SKPhysicsBody = self.nodeAtPoint(location).physicsBody
if (body.node.name == self.p1Name) {
self.fingerOnP1 = true
self.p1.physicsBody.collisionBitMask = wallCategory
}
}
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousLocation = touch.previousLocationInNode(self)
let body = self.nodeAtPoint(location).physicsBody
if (body != nil && body.node != nil) {
if (body.node.name == self.p1Name && self.fingerOnP1 == true) {
let paddle = self.childNodeWithName(p1Name) as SKShapeNode
var paddleX: Int = Int(paddle.position.x) + Int(location.x - previousLocation.x)
let _x: Int = Int(paddle.frame.width/2)
paddleX = max(paddleX, _x)
paddleX = min(paddleX, Int(self.size.width)-_x)
var paddleY: Int = Int(paddle.position.y) + Int(location.y - previousLocation.y)
let _y: Int = Int(paddle.frame.height/2)
paddleY = max(paddleY, _y)
paddleY = min(paddleY, Int(self.size.height)-_y)
paddle.position = CGPointMake(CGFloat(paddleX), CGFloat(paddleY))
}
}
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
var onP1 = false
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if (self.nodeAtPoint(location) == p1) {
onP1 = true
}
}
if (onP1 == true) {
self.fingerOnP1 == false
self.p1.physicsBody.collisionBitMask = wallCategory | pCategory
}
}
I guess the problem is I'm not applying any force to the paddle, I'm just moving the paddle, too. How would I apply force while moving it?
I thought of apply impulse to the puck after contact, but i have no idea how to move it a proper angle or make it move at a proper speed.
func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody!
var secondBody: SKPhysicsBody!
if (contact.bodyA.categoryBitMask > contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA
secondBody = contact.bodyB
}
else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if (firstBody.categoryBitMask == p1Category && secondBody.categoryBitMask == pCategory) {
if (self.fingerOnP1) {
NSLog("hit", nil)
secondBody.applyImpulse(CGVectorMake(20, 0))
}
}
}

Resources