Swift 像著名的蛇游戏一样移动玩家

Swift 像著名的蛇游戏一样移动玩家,swift,Swift,我正在做一个游戏,我想玩家应该避免球出现在屏幕上。球将从任何角度射入,当球员与另一个球接触时,比赛结束。我唯一的问题是球员的移动。我希望它能像著名的蛇类游戏一样移动,而不会像蛇一样让玩家留下痕迹。所以,我希望玩家以恒定的速度在某个方向移动,当玩家触摸屏幕左侧时,玩家向左移动,当玩家触摸右侧时,玩家向右移动。但是当球员触到任何一边时,球员不应该像90度那样移动,应该轻轻地移动到任何一边。因此,如果玩家想要移动90度,他/她必须将手指在屏幕上停留更长时间 在这段视频中,您可以看到我希望播放机如何移动

我正在做一个游戏,我想玩家应该避免球出现在屏幕上。球将从任何角度射入,当球员与另一个球接触时,比赛结束。我唯一的问题是球员的移动。我希望它能像著名的蛇类游戏一样移动,而不会像蛇一样让玩家留下痕迹。所以,我希望玩家以恒定的速度在某个方向移动,当玩家触摸屏幕左侧时,玩家向左移动,当玩家触摸右侧时,玩家向右移动。但是当球员触到任何一边时,球员不应该像90度那样移动,应该轻轻地移动到任何一边。因此,如果玩家想要移动90度,他/她必须将手指在屏幕上停留更长时间

在这段视频中,您可以看到我希望播放机如何移动。尽管你可以忽略玩家留下的痕迹

这是我的密码:

随机类将随机生成球:

import Foundation
import CoreGraphics

public extension CGFloat {

public static func randomBetweenNumbers(firstNum: CGFloat, secondNum: 
CGFloat) -> CGFloat {

    return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - 
secondNum) + firstNum

}

}
玩家等级:

import SpriteKit

struct ColliderType {

static let Player: UInt32 = 1
static let Score: UInt32 = 2
static let Enemy: UInt32 = 3

}

class Player: SKSpriteNode {

func initialize() {
    self.name = "Player"
    self.zPosition = 1
    self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.height / 
2)
    self.physicsBody?.affectedByGravity = false
    self.physicsBody?.categoryBitMask = ColliderType.Player
    self.physicsBody?.collisionBitMask = ColliderType.Enemy
    self.physicsBody?.contactTestBitMask = ColliderType.Score | 
ColliderType.Enemy
}

}
这是GamePlaySecene类:

import SpriteKit

class GameplayScene: SKScene, SKPhysicsContactDelegate {

var player = Player()

var ball = SKSpriteNode()

var ballIsTouched = false

var scoreLabel = SKLabelNode()
var score = 0

var counter = Timer()

override func didMove(to view: SKView) {
    initialize()
}

override func update(_ currentTime: TimeInterval) {

}

override func touchesBegan(_ touches: Set<UITouch>, with event: 
UIEvent?) {


    for touch in touches {

        let location = touch.location(in: self)

        if atPoint(location).name == "Retry" {
            self.removeAllActions()
            self.removeAllChildren()
            initialize()
        }

        if atPoint(location).name == "Quit" {
            let mainmenu = MainMenuScene(fileNamed: "MainMenuScene")
            mainmenu!.scaleMode = .aspectFill
            self.view?.presentScene(mainmenu!, transition: 
SKTransition.fade(withDuration: TimeInterval(1)))
        }

    }

}

func didBegin(_ contact: SKPhysicsContact) {

    var firstBody = SKPhysicsBody()
    var secondBody = SKPhysicsBody()

    if contact.bodyA.node?.name == "Player" {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Score" {
        incrementCoinScore()
        secondBody.node?.removeFromParent()
    }

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Enemy" {
        playerDied()
        firstBody.node?.removeFromParent()
    }

}

func initialize() {

    score = 0

    physicsWorld.contactDelegate = self

    createPlayer()
    createBackground()
    spawnEnemy1()
    spawnEnemy2()
    spawnEnemy3()
    spawnEnemy4()
    createLabel()

    counter = Timer.scheduledTimer(timeInterval: TimeInterval(1), 
target: self, selector: "incrementScore", userInfo: nil, repeats: true)
}

func createPlayer() {
    player = Player(imageNamed: "Player")
    player.initialize()
    player.position = CGPoint(x: 0, y: 0)
    self.addChild(player)
}

func createBackground() {
    let bg = SKSpriteNode(imageNamed: "BG")
    bg.name = "BG"
    bg.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    bg.position = CGPoint(x: 0, y: 0)
    self.addChild(bg)
}

func createEnemy1() {
    let ball = SKSpriteNode(imageNamed: "Orange")
    ball.name = "Enemy"
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball.zPosition = 1
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 
2)
    ball.physicsBody?.categoryBitMask = ColliderType.Enemy
    ball.physicsBody?.affectedByGravity = false
    ball.physicsBody?.isDynamic = false

    ball.position.y = self.size.height + 100
    ball.position.x = CGFloat.randomBetweenNumbers(firstNum: -345, 
secondNum: 345)

    self.addChild(ball)

    let destination = self.frame.height * 2
    let move = SKAction.moveTo(y: -destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveEnemy1")
}

func spawnEnemy1() {

    let spawn = SKAction.run({ () -> Void in
        self.createEnemy1()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(1))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnEnemy1")
}

func createEnemy2() {
    let ball = SKSpriteNode(imageNamed: "Green")
    ball.name = "Enemy"
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball.zPosition = 1
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 
 2)
    ball.physicsBody?.categoryBitMask = ColliderType.Enemy
    ball.physicsBody?.affectedByGravity = false
    ball.physicsBody?.isDynamic = false

    ball.position.y = -self.size.height + 100
    ball.position.x = CGFloat.randomBetweenNumbers(firstNum: -345, 
secondNum: 345)

    self.addChild(ball)

    let destination = self.frame.height * 2
    let move = SKAction.moveTo(y: destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveEnemy2")
}

func spawnEnemy2() {

    let spawn = SKAction.run({ () -> Void in
        self.createEnemy2()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(1))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnEnemy2")
}

func createEnemy3() {
    let ball = SKSpriteNode(imageNamed: "Blue")
    ball.name = "Enemy"
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball.zPosition = 1
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 
2)
    ball.physicsBody?.categoryBitMask = ColliderType.Enemy
    ball.physicsBody?.affectedByGravity = false
    ball.physicsBody?.isDynamic = false

    ball.position.x = -self.size.width + 200
    ball.position.y = CGFloat.randomBetweenNumbers(firstNum: -637, 
secondNum: 637)

    self.addChild(ball)

    let destination = self.frame.height * 2
    let move = SKAction.moveTo(x: destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveEnemy3")
}

func spawnEnemy3() {

    let spawn = SKAction.run({ () -> Void in
        self.createEnemy3()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(1))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnEnemy3")
}

func createEnemy4() {
    let ball = SKSpriteNode(imageNamed: "Yellow")
    ball.name = "Enemy"
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball.zPosition = 1
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height / 
2)
    ball.physicsBody?.categoryBitMask = ColliderType.Enemy
    ball.physicsBody?.affectedByGravity = false
    ball.physicsBody?.isDynamic = false

    ball.position.x = self.size.width + 200
    ball.position.y = CGFloat.randomBetweenNumbers(firstNum: -637, 
secondNum: 637)

    self.addChild(ball)

    let destination = self.frame.height * 2
    let move = SKAction.moveTo(x: -destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveEnemy4")
}

func spawnEnemy4() {

    let spawn = SKAction.run({ () -> Void in
        self.createEnemy4()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(1))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnEnemy4")
}


func createLabel() {
    scoreLabel.zPosition = 3
    scoreLabel.position = CGPoint(x: -320, y: 600)
    scoreLabel.fontName = "Verdana"
    scoreLabel.fontSize = 70
    scoreLabel.text = "0"
    self.addChild(scoreLabel)
}

func incrementScore() {
    score += 1
    scoreLabel.text = String(score)
}

func incrementCoinScore() {
    score += 5
}

func playerDied() {

    counter.invalidate()

    let highscore = GameManager.instance.getHighscore()

    if highscore < score {
        GameManager.instance.setHighscore(highscore: score)
    }

    let retry = SKSpriteNode(imageNamed: "Retry")
    let quit = SKSpriteNode(imageNamed: "Quit")

    retry.name = "Retry"
    retry.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    retry.position = CGPoint(x: -150, y: -50)
    retry.zPosition = 2
    retry.setScale(0)

    quit.name = "Quit"
    quit.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    quit.position = CGPoint(x: 150, y: -50)
    quit.zPosition = 2
    quit.setScale(0)

    let scaleUp = SKAction.scale(to: 1, duration: TimeInterval(0.5))

    retry.run(scaleUp)
    quit.run(scaleUp)

    self.addChild(retry)
    self.addChild(quit)

}

}

我不得不把你的问题读了好几遍才明白你在说什么。但是,自从我玩achtung die curve的时候,它终于成功了。下面是一个你想要的工作示例。复制粘贴检查

如果有什么你不完全理解的,尽管问

class Player: SKSpriteNode {

    let playerSpeed = 3
    let turnRate:CGFloat = 0.03
    var isAlive = true

    // this is the initializer for the class. when you make an instance
    // of your class, this function will be called. and this is were you setup your player.
    init() {

    //create a texture for your player
    let texture = SKTexture(imageNamed: "player")
    //setup other stuff you already have in your own code.
    // when you create an instance in your createPlayer function do like this
   // let player = Player()
   // player.position = CGPoint(x: 0, y: 0)
   //self.addChild(player)

  // note that you do not need to call the init manually.

    // since your player class is an subclass of SKSpriteNode you have to call super.init().
    // This is the initializer of your superclass (SKSpriteNode), 
    // I would suggest you read more about subclassing and this will make sens. 
        super.init(texture: texture, color: UIColor.clear, size:texture.size())
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    func turnLeft(){

        // add to the current rotation by a factor of turnRate
        self.run(SKAction.rotate(byAngle: turnRate, duration: 0))

    }

    func turnRight(){

        // subtract from the current rotation by a factor of turnRate
        self.run(SKAction.rotate(byAngle: -turnRate, duration: 0))

    }

    func move(){

        // this gives us a position in the scene space that is 3 points(or what ever value playerSpeed is) 
        // infront of the player. basicly we convert (x:0, y:3) from the player coordinates. to the scene coordinate.
        // Even when the player rotates in the scene. the (x:0, y:3) is allways the same in the player coordinate.
        let newPosition = convert(CGPoint(x:0, y:playerSpeed), to: scene!)
        self.position = newPosition

    }


}

class GameScene: SKScene {

    let player = Player()

    var shouldTurnLeft = false
    var shouldTurnRight = false

    override func didMove(to view: SKView) {


        addChild(player)


    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        let touchLocation = touches.first?.location(in: self)

        if (touchLocation?.x)! > 0{

            shouldTurnRight = true
        }
        else if (touchLocation?.x)! < 0{

            shouldTurnLeft = true

        }

    }


    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        shouldTurnLeft = false
        shouldTurnRight = false
    }


    override func update(_ currentTime: TimeInterval) {

        // if the player is alive. move the player every frame
   if player.isAlive{
        player.move()

        if shouldTurnLeft {
            player.turnLeft()
        }
        if shouldTurnRight{
            player.turnRight()
        }
   }




        // Called before each frame is rendered
    }
}

谢谢不过我有一个问题。当我添加代码时,我的createPlayer函数出现了一个错误。更准确地说,在player=playerImageName:player行中。Swift希望我将imageNamed更改为coder,当我这样做时,我在同一行中遇到另一个问题,即无法将string类型的值转换为预期的参数类型NSCoder。你知道怎么解决吗?是的,你的代码与我答案中的代码不太兼容。我的意思是,如果你将我的代码复制到一个新的空项目中,它会按照你所描述的方式工作。然后评估它是如何工作的,然后定制适合您的代码的概念。但这就是您当前代码的问题:当您在createPlayer函数中创建player类的实例时。您尝试提供图像作为参数。player=playerImageName:player。在您的player类中,您不接受init函数中的任何参数。老实说,我以前从没见过他。只是标准的init。我将更新我的答案,让你对它的外观有更多的了解:如果你仍然有问题。将您的代码发布在这里,我会实时显示/解释:谢谢,完全做到了!!: