I'm trying to have the "player" sprite move slowly toward touches on the screen. The code that I have now moves the sprite immediately to where the touch happens on the screen. Here is my current code. Thanks!
//
// GameScene.swift
// testing
//
// Created by Matthew Jahnes on 7/3/18.
// Copyright © 2018 Matthew Jahnes. All rights reserved.
//
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var player = SKSpriteNode()
override func didMove(to view: SKView) {
self.anchorPoint = CGPoint(x:0.5, y:0.5)
player = SKSpriteNode(color: UIColor.red, size: CGSize(width: 90, height:90))
player.position = CGPoint(x:0, y:0)
self.addChild(player)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
player.position.x = location.x
player.position.y = location.y
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
You need to
Create an action for moving the player to the destination point.
Stop the previous move action if exists
Run the new move action
Here's the code
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let destination = touch.location(in: self)
let move = SKAction.move(to: destination, duration: 2)
player.removeAction(forKey: "move")
player.run(move, withKey: "move")
}
Related
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))
}
}
}
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!
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]];
}
I am currently creating a 2D game in which I have a cannon staying at the bottom of the screen that fires projectiles to some targets in the upper part of the screen. The user can rotate the cannon in order to aim for the targets. I want the projectile to be fired to the location that the canon faces. I have no idea how to do that and I need your help... Heres my code ->
import SpriteKit
class GameScene: SKScene {
var canon = SKSpriteNode()
var projectile = SKSpriteNode()
var touching = false
var locked = false
var location = CGPoint()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
projectile.position = canon.position
projectile.color = UIColor.whiteColor()
projectile.size = CGSize(width: 50, height: 50)
projectile.physicsBody?.affectedByGravity = false
projectile.physicsBody?.linearDamping = 1
projectile.physicsBody?.dynamic = true
addChild(projectile)
canon.zPosition = 2
canon = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 200))
canon.position = CGPoint(x: self.size.width/2.0, y: 10)
addChild(canon)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
touching = true
let touch = touches.first as UITouch!
location = touch.locationInView(self.view)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
rotateCanon(location.x)
projectile.zRotation = canon.zRotation
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
touching = false
}
func rotateCanon(locationx:CGFloat) {
if locationx <= frame.width/5 && touching {
print(1)
canon.runAction(SKAction.rotateByAngle(0.01, duration: 0.1))
}
if locationx > frame.width/5 && touching {
print(2)
canon.runAction(SKAction.rotateByAngle(-0.01, duration: 0.1))
}
}
}`
Thanks a lot if you can help that would be awesome :D
Please help. I am a beginner on Swift. I've added sprites for player and left/right buttons. But how can I add an action for every button and apply these actions to the player?
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var player: SKSpriteNode!
var leftMove: SKSpriteNode!
var rightMove: SKSpriteNode!
override func didMoveToView(view: SKView) {
player = SKSpriteNode (imageNamed: "player")
player.position = CGPoint(x:127, y:125)
addChild(player)
leftMove = SKSpriteNode (imageNamed: "leftMove")
leftMove.position = CGPoint(x:80, y:35)
leftMove.size = CGSize (width: 55, height: 55)
addChild(leftMove)
rightMove = SKSpriteNode (imageNamed: "rightMove")
rightMove.position = CGPoint(x:160, y:35)
rightMove.size = CGSize (width: 55, height: 55)
addChild(rightMove)
physicsWorld.contactDelegate = self
}
Give the buttons a unique name like:
leftMove.name = "Left"
rightMove.name = "Right"
Implement the logic in touchesBegan:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "Left") {
// Implement your logic for left button touch here:
player.position = CGPoint(x:player.position.x-1, y:player.position.y)
} else if (node.name == "Right") {
// Implement your logic for right button touch here:
player.position = CGPoint(x:player.position.x+1, y:player.position.y)
}
}
}
Welcome to StackOverflow. My recommendation is that for each button that you would like to have actions on, that you subclass SKSpriteNode for those objects. This way you can leverage the touchesBegan:, touchesMoved: and touchesEnded: functions for each of these objects individually. For example:
As promised, here is a more robust version of a subclassed SKSpriteNode. Also, I tested it in one of my projects and I can attest to it working correctly:
import Foundation
import SpriteKit
class SubclassedSKSpriteNode: SKSpriteNode {
init() {
let texture = SKTexture(imageNamed: "whateverImage.png")
super.init(texture: texture, color: UIColor.clearColor(), size: texture.size())
userInteractionEnabled = true
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = (touches.first! ).locationInNode(scene!)
position = scene!.convertPoint(location, toNode: parent!)
print("touchesBegan: \(location)")
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = (touches.first! ).locationInNode(scene!)
position = scene!.convertPoint(location, toNode: parent!)
print("touchesMoved: \(location)")
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = (touches.first! ).locationInNode(scene!)
position = scene!.convertPoint(location, toNode: parent!)
print("touchesEnded: \(location)")
}
}
Also, to add this button to your SKScene (or any other SKNode):
let button = SubclassedSKSpriteNode()
button.position = CGPointMake(420, 300)
addChild(button)
HTH!