Is there a way to use velocity to make a sprite follow your finger? I want a sprite to follow my finger but I don't want it to be drag and drop. I want it to be able to interact with other sprite with the delegate properties.
For example: I want a ball to reset when it hits a wall.
I have the code set up to reset the ball. When the ball hits the wall, it doesn't reset. I put in a print statement to see if its registering the collisions. When the ball hits the wall, it prints the statement.
Thats a problem with how I'm making the ball move, right?
Or could there be an error with my code.
Code:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ball = SKSpriteNode()
var danger1 = SKSpriteNode()
var danger2 = SKSpriteNode()
var goal = SKSpriteNode()
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
ball = self.childNode(withName: "ball") as! SKSpriteNode
danger1 = self.childNode(withName: "danger1") as! SKSpriteNode
danger2 = self.childNode(withName: "danger2") as! SKSpriteNode
goal = self.childNode(withName: "goal") as! SKSpriteNode
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 0
danger1.physicsBody = SKPhysicsBody(rectangleOf: danger1.size)
danger1.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
danger1.physicsBody?.isDynamic = false
danger2.physicsBody = SKPhysicsBody(rectangleOf: danger2.size)
danger2.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
danger2.physicsBody?.isDynamic = false
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2)
ball.physicsBody?.categoryBitMask = PhysicsCategories.ballCategory
ball.physicsBody?.contactTestBitMask = PhysicsCategories.dangerCategory | PhysicsCategories.goalCategory
ball.physicsBody?.collisionBitMask = PhysicsCategories.none
ball.physicsBody?.isDynamic = true
ball.physicsBody!.affectedByGravity = false
goal.physicsBody = SKPhysicsBody(rectangleOf: goal.size)
goal.physicsBody?.categoryBitMask = PhysicsCategories.goalCategory
goal.physicsBody?.isDynamic = false
setupPhysics()
startGame()
}
func setupPhysics() {
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
physicsWorld.contactDelegate = self
}
func startGame() {
ball.position = CGPoint(x: 0, y: 550)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
ball.position.x = location.x
ball.position.y = location.y
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.dangerCategory {
print("Contact")
} else if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.goalCategory {
print("goal contact")
}
}
}
As you mentioned, you should use velocity instead of position.
You have to apply the difference of the positions. In order to make it a bit smoother, you should also apply weight to your velocity.
This has not been tested and looks more like pseudo code, but that's what you should do basically.
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let destination = touch.location(in: self)
let position = ball.position
let direction = destination - position // the vector of the difference
let weight = 0.95 // 0.0 to 1.0
ball.velocity = CGVector(direction * weight) // multiply the vector by the weight
}
}
You should do this in a loop that runs every frame and use a flag to see if there's a finger touching the screen, because it doesn't apply velocity when you touch the screen but don't move your finger.
Related
I'm using SpriteKit for iOS app with Swift.
I made a small SKShapeNode("ball") and a big circle path("room"), and I want a SKShapeNode to stay within the circle.
Here is my code:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var isFingerOnBall = false
var ball: SKShapeNode!
var room: SKShapeNode!
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 == "ball" {
isFingerOnBall = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if isFingerOnBall {
ball.position = touchLocation
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
isFingerOnBall = false
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
let radius:CGFloat = 60
// BALL
ball = SKShapeNode(circleOfRadius: radius)
ball.name = "ball"
ball.fillColor = .red
ball.strokeColor = .clear
ball.position = CGPoint(x: 0, y: 150)
ball.physicsBody = SKPhysicsBody(circleOfRadius: radius)
ball.physicsBody?.isDynamic = true
scene?.addChild(ball)
// ROOM
room = SKShapeNode(circleOfRadius: radius * 5)
room.name = "room"
room.strokeColor = .white
room.lineWidth = 10
room.position = CGPoint(x: 0, y: 0)
room.physicsBody = SKPhysicsBody(edgeLoopFrom: room.path!)
room.physicsBody?.isDynamic = false
scene?.addChild(room)
}
}
I expected the room's SKPhysicsBody would limit the ball go out beyond the path,
OK image
but when my finger drags the ball out of the circle(room), it goes out too.
No good image
Thanks in advance.
There is a few ways to do this although the simplest I can think of is to replace you didMove(to view: SKView) method with this:
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
// BALL
let ball = SKShapeNode(circleOfRadius: 10)
ball.fillColor = .yellow
ball.strokeColor = .yellow
ball.lineWidth = 5
ball.physicsBody = SKPhysicsBody(circleOfRadius: 10)
ball.physicsBody?.isDynamic = true
ball.physicsBody?.affectedByGravity = true
ball.physicsBody?.categoryBitMask = 1
ball.physicsBody?.collisionBitMask = 2
ball.physicsBody?.contactTestBitMask = 0
addChild(ball)
// ROOM
let room = SKShapeNode(circleOfRadius: 200)
room.fillColor = .clear
room.strokeColor = .red
room.lineWidth = 5
room.physicsBody = SKPhysicsBody(edgeLoopFrom: room.path!)
room.physicsBody?.isDynamic = false
room.physicsBody?.affectedByGravity = false
room.physicsBody?.categoryBitMask = 2
room.physicsBody?.collisionBitMask = 0
room.physicsBody?.contactTestBitMask = 0
addChild(room)
}
Basically you just need to set the PhysicsBody CategoryBitMask and Collision Bit mask. Also don't assign a solid physics body notice the use of the "edgeFromLoop" to make the rooms physic body.
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if isFingerOnBall {
let roomRadius: CGFloat = 200
let hyp = sqrt(touchLocation.x * touchLocation.x + touchLocation.y * touchLocation.y)
if abs(hyp) > roomRadius {
ball.position = ball.position
} else {
ball.position = touchLocation
}
}
}
Here you are getting the hypotenuse of the new touch point and checking to see that its greater then the radius of the room. If it is then the position of the ball remains the same, if not then update the ball position as normal.
Hope this helps and enjoy
I am trying to make a sprite follow my finger using velocity so it doesn't phase through other sprite nodes, or push them around. I just want the sprite node, aka the ball, to simply hit the other sprite node and either bounce off or just simply hit it and sit there until its moved again.
At the moment I am using location based movement:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
ball.position.x = location.x
ball.position.y = location.y
print("x: \(ball.position.x), y: \(ball.position.y)")
}
}
how can I make it so it doesn't move around other sprite nodes and actually reacts with categoryBitMask elements?
I'm new to this whole thing. Hopefully you understand :)
REST OF MY CODE:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ball = SKSpriteNode()
var danger1 = SKSpriteNode()
var danger2 = SKSpriteNode()
var goal = SKSpriteNode()
override func didMove(to view: SKView) {
ball = self.childNode(withName: "ball") as! SKSpriteNode
danger1 = self.childNode(withName: "danger1") as! SKSpriteNode
danger2 = self.childNode(withName: "danger2") as! SKSpriteNode
goal = self.childNode(withName: "goal") as! SKSpriteNode
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 0
danger1.physicsBody = SKPhysicsBody()
danger1.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
danger2.physicsBody = SKPhysicsBody()
danger2.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
ball.physicsBody = SKPhysicsBody()
ball.physicsBody?.categoryBitMask = PhysicsCategories.ballCategory
ball.physicsBody?.contactTestBitMask = PhysicsCategories.dangerCategory
ball.physicsBody?.collisionBitMask = PhysicsCategories.none
goal.physicsBody = SKPhysicsBody(circleOfRadius: goal.size.width/2)
goal.physicsBody?.categoryBitMask = PhysicsCategories.goalCategory
danger1.physicsBody?.isDynamic = true
ball.physicsBody?.isDynamic = true
goal.physicsBody?.isDynamic = true
danger2.physicsBody?.isDynamic = true
danger2.physicsBody!.affectedByGravity = false
danger1.physicsBody!.affectedByGravity = false
goal.physicsBody!.affectedByGravity = false
ball.physicsBody!.affectedByGravity = false
setupPhysics()
}
func setupPhysics() {
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
physicsWorld.contactDelegate = self
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
ball.position.x = location.x
ball.position.y = location.y
print("x: \(ball.position.x), y: \(ball.position.y)")
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.dangerCategory {
ball.position = CGPoint(x: 0, y: 550)
} else if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.goalCategory {
print("Goal!")
}
}
}
Try commenting out this line:
ball.physicsBody?.collisionBitMask = PhysicsCategories.none
which prevents the ball from colliding with anything, i.e. it is unaffected by collisions with any object. Note - this does NOT mean that other objects are unaffected by collision with the ball. collision are 2-way - given 2 node A and B, you have to define if A collides with B and if B collides with A. This isn;t necessary for contact - it's enough to define that A contacts B. If it's actually b that moves into A, didBegin() will still get called. you don't have to define that B contact A also.
You haven't appeared to set the collisionBitMask on any other physics body, which means those will collide with everything.
this explains why the ball moves through the wall - because it isn't colliding with it, although every other object should get pushed around by the ball.
Try putting a:
print("Contact")
as the first line of your didBegin() to see if any contacts are being registered.
If you want to drag sprites with your finger then making them bounce off (collide with) other sprites can be tricky, because dragging implies that you want to set their position manually and bouncing off implies that your want the sprites to be moved by the Sprite-Kit engine and the 2 are not really compatible.
It's probably worth pointing our that 'collisions' are sprites bouncing off each other and are handled by the SK engine. The collisionBitMask controls what objects bounce off each other.
'Contacts' are just a way to get notified when 2 objects touch. They are controlled by the contactTestBitMask.
Both contact and collisions rely on the categoryBitMAsk
My step-by-step guide for collisions and contacts:
https://stackoverflow.com/a/51041474/1430420
And a guide to collision and contactTest bit masks:
https://stackoverflow.com/a/40596890/1430420
Manipulating bit masks to turn individual collision and contacts off and on. https://stackoverflow.com/a/46495864/1430420
I am building a spritekit game and have just started the project. I have a circle on the screen which starts in the center, and when i drag my finger from the circle outward, it will show a dotted line/bezierpath connected to the ball which will help the user see where it is aiming the ball. When the user lifts their finger, the ball will shoot in the opposite direction of the aim line. (Think a game like soccer stars or pool). The issue is that the maneuver works the first time when everything starts in the middle: I drag my finger and the ball shoots in opposite direction then stops. But when I try it again, the position of the aiming line says it is the same as the ball (It should be), but then it shows up like an inch away from the ball on the screen. I feel like this may be an issue that the scene(s) behind the objects may not be the same size? But I'm confused because I think I'm only using one scene.
GameViewController viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
scene.size = view.bounds.size
//scene.anchorPoint = CGPoint(x: 0.0, y: 0.0)
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
GameScene Code (Doubt you need all of it but whatever):
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ball = SKShapeNode(circleOfRadius: 35)
var touchingBall = false
var aimLine = SKShapeNode()
var startAimPoint = CGPoint()
var endAimPoint = CGPoint()
let damping:CGFloat = 0.94
override func didMove(to view: SKView) {
ball.fillColor = SKColor.orange
ball.name = "ball"
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
var physicsBody = SKPhysicsBody(circleOfRadius: 35)
ball.physicsBody = physicsBody
ball.physicsBody?.affectedByGravity = false
ball.physicsBody?.friction = 10.0
ball.position = CGPoint(x: frame.midX, y: frame.midY)
self.addChild(ball)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("TOUCHES BEGAN.")
for touch in touches {
print("TB: \(touchingBall)")
let location = touch.location(in: self)
let node : SKNode = self.atPoint(location)
if node.name == "ball" {
// touched inside node
if ball.physicsBody!.angularVelocity <= 0.0{
touchingBall = true
startAimPoint = ball.position
print(touchingBall)
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("TOCUHES MOVED.")
for touch in touches {
let location = touch.location(in: self)
if touchingBall{
endAimPoint = location
assignAimLine(start: startAimPoint, end: endAimPoint)
print("Moving touched ball")
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touches ended. \(touchingBall)")
if touchingBall == true{
ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x - startAimPoint.x) * 3, dy: -(endAimPoint.y - startAimPoint.y) * 3))
}
touchingBall = false
aimLine.removeFromParent()
print(touchingBall)
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touches cancelled. \(touchingBall)")
if touchingBall == true{
ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x - startAimPoint.x) * 3, dy: -(endAimPoint.y - startAimPoint.y) * 3))
}
touchingBall = false
aimLine.removeFromParent()
print(touchingBall)
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
print(ball.physicsBody!.velocity)
let dx2 = ball.physicsBody!.velocity.dx * damping
let dy2 = ball.physicsBody!.velocity.dy * damping
ball.physicsBody!.velocity = CGVector(dx: dx2, dy: dy2)
}
func assignAimLine(start: CGPoint, end: CGPoint){
aimLine.removeFromParent()
var bezierPath = UIBezierPath()
bezierPath.move(to: start)
bezierPath.addLine(to: shortenedEnd(startPoint: start, endPoint: end))
var pattern : [CGFloat] = [10.0, 10.0]
let dashed = SKShapeNode(path: bezierPath.cgPath.copy(dashingWithPhase: 2, lengths: pattern))
aimLine = dashed
aimLine.position = ball.position
aimLine.zPosition = 0
self.addChild(aimLine)
}
func hypotenuse(bp: UIBezierPath) -> Double{
var a2 = bp.cgPath.boundingBox.height * bp.cgPath.boundingBox.height
var b2 = bp.cgPath.boundingBox.width * bp.cgPath.boundingBox.width
return Double(sqrt(a2 + b2))
}
func hypotenuse(startP: CGPoint, endP: CGPoint) -> Double{
var bezierPath = UIBezierPath()
bezierPath.move(to: startP)
bezierPath.addLine(to: endP)
return hypotenuse(bp: bezierPath)
}
func shortenedEnd(startPoint: CGPoint, endPoint: CGPoint) -> CGPoint{
var endTemp = endPoint
//while hypotenuse(startP: startPoint, endP: endTemp) > 150{
endTemp = CGPoint(x: endTemp.x / 1.01, y: endTemp.y / 1.01)
//}
return endTemp
}
func addTestPoint(loc: CGPoint, color: UIColor){
var temp = SKShapeNode(circleOfRadius: 45)
temp.fillColor = color
temp.position = loc
self.addChild(temp)
}
}
I tried printing the frame size for the scene and it says 400 something x 700 something (I am testing on iPhone 6 Plus), and it says the UIScreen is same size so i don't know what issue is. Overall, I just need the aiming line to be on the center of the circle more than just the first time I try the maneuver. Thanks.
Like I mentioned in the comments, your problem was how you were laying out your paths. The code below makes the path relative to the ball instead of absolute to the scene. I also fixed the issue with creating new shapes every time.
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ball = SKShapeNode(circleOfRadius: 35)
var touchingBall = false
var aimLine = SKShapeNode()
var endAimPoint = CGPoint()
override func didMove(to view: SKView) {
ball.fillColor = SKColor.orange
ball.name = "ball"
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
ball.position = CGPoint(x: frame.midX, y: frame.midY)
let physicsBody = SKPhysicsBody(circleOfRadius: 35)
physicsBody.affectedByGravity = false
physicsBody.friction = 10.0
physicsBody.linearDamping = 0.94
ball.physicsBody = physicsBody
self.addChild(ball)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("TOUCHES BEGAN.")
for touch in touches {
print("TB: \(touchingBall)")
let location = touch.location(in: self)
let node : SKNode = self.atPoint(location)
if node.name == "ball" {
// touched inside node
if ball.physicsBody!.angularVelocity <= 0.0{
touchingBall = true
aimLine.path = nil
self.addChild(aimLine)
print(touchingBall)
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("TOCUHES MOVED.")
for touch in touches {
let location = touch.location(in: self)
if touchingBall{
endAimPoint = self.convert(location, to: ball)
assignAimLine(end: endAimPoint)
print("Moving touched ball")
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touches ended. \(touchingBall)")
if touchingBall == true{
ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x) * 3, dy: -(endAimPoint.y) * 3))
}
touchingBall = false
aimLine.removeFromParent()
print(touchingBall)
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touches cancelled. \(touchingBall)")
if touchingBall == true{
ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x) * 3, dy: -(endAimPoint.y) * 3))
}
touchingBall = false
aimLine.removeFromParent()
print(touchingBall)
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
print(ball.physicsBody!.velocity)
//let dx2 = ball.physicsBody!.velocity.dx * damping
//let dy2 = ball.physicsBody!.velocity.dy * damping
//ball.physicsBody!.velocity = CGVector(dx: dx2, dy: dy2)
}
func assignAimLine(end: CGPoint){
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint.zero)
bezierPath.addLine(to: end)
let pattern : [CGFloat] = [10.0, 10.0]
aimLine.position = ball.position
aimLine.path = bezierPath.cgPath.copy(dashingWithPhase: 2, lengths: pattern)
aimLine.zPosition = 0
}
func addTestPoint(loc: CGPoint, color: UIColor){
var temp = SKShapeNode(circleOfRadius: 45)
temp.fillColor = color
temp.position = loc
self.addChild(temp)
}
}
I have a simple game where meteors are spawned and the player must dodge these meteors. I am trying to detect if the player (rocketship) has collided with the meteor (enemy) with PhysicsBody. However, nothing happens when they collide. The console should print "Crash detected"
Here's my code:
import SpriteKit
import GameplayKit
import UIKit
class GameScene: SKScene, SKPhysicsContactDelegate{
let player = SKSpriteNode(imageNamed: "spaceship")
let stars = SKSpriteNode(imageNamed: "stars")
let meteor = SKSpriteNode(imageNamed: "meteor")
override func didMove(to view: SKView) {
print(frame.size.width)
print(frame.size.height)
stars.position = CGPoint(x:0, y:0)
stars.zPosition = 1
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
player.position = CGPoint(x:0, y:-320)
player.zPosition = 4
player.physicsBody = SKPhysicsBody()
player.physicsBody?.affectedByGravity = false
player.physicsBody?.isDynamic = false
player.physicsBody?.categoryBitMask = 0
player.physicsBody?.collisionBitMask = 1
player.physicsBody?.contactTestBitMask = 1
self.addChild(player)
self.addChild(stars)
addMeteor()
}
func addMeteor() {
meteor.physicsBody = SKPhysicsBody(circleOfRadius: meteor.size.width / 2)
meteor.physicsBody?.affectedByGravity = false
meteor.setScale(0.50)
meteor.position = CGPoint(x:Int(arc4random()%300),y:Int(arc4random()%600))
//meteor.position = CGPoint(x:0 , y:0)
meteor.zPosition = 4
meteor.physicsBody?.categoryBitMask = 1
meteor.physicsBody?.collisionBitMask = 0
self.addChild(meteor)
}
func fireBullet() {
let bullet = SKSpriteNode(imageNamed: "bullet")
bullet.position = player.position
bullet.setScale(0.5)
bullet.zPosition = 3
self.addChild(bullet)
let moveBullet = SKAction.moveTo(y: self.size.height + bullet.size.height, duration: 1)
let deleteBullet = SKAction.removeFromParent()
let bulletSequence = SKAction.sequence([moveBullet, deleteBullet])
bullet.run(bulletSequence)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
fireBullet()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches {
let pointOfTouch = touch.location(in: self)
let previousPointOfTouch = touch.previousLocation(in: self)
let amountDragged = pointOfTouch.x - previousPointOfTouch.x
player.position.x += amountDragged
}
}
func didBegin(_ contact: SKPhysicsContact) {
print("Crash detected")
}
override func update(_ currentTime: TimeInterval) {
meteor.position.y -= 6
if meteor.position.y < player.position.y - 300{
meteor.removeFromParent()
addMeteor()
}
}
}
The program should detect collision and then execute the didBegin function (which prints "Crash detected" to the console). However, when I run the program, the console doesn't have anything printed to it. Anybody know what im doing wrong? Thanks!
in didMove method add this line of code physicsWorld.contactDelegate = self. you set playerCateoryBitmask to 0. that means nothing can hit the player. use player.physicsBody?.categoryBitMask = 2 and also set your meteor a contactTestBitMask like so: meteor.physicsBody?.contactTestBitMask
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!