2017-04-14 57 views
0

我製作了一個遊戲,其基本思想是玩家精靈必須根據分配給敵人的字母與敵方精靈發生碰撞或避免掉落的敵方精靈。問題是,當我的玩家與一個精靈進行接觸時,周圍的敵人會大幅跳躍前進。這使得遊戲太難玩了,因爲沒有足夠的時間讓玩家擺脫即將來臨的敵方精靈。這發生在設備和模擬器上。SpriteKit敵方精靈在與玩家接觸後跳過

要看我的意思,看看這個簡短的視頻。 013:https://www.dropbox.com/s/8pp66baxc9uhy26/SimulatorScreenSnapz002.mov?dl=0

這裏是我的球員和敵人接觸代碼:

class GameplaySceneClass: SKScene, SKPhysicsContactDelegate { 

private var player:Player? 

private var center = CGFloat() 

private var canMove = false, moveLeft = false 

private var itemController = ItemController() 

private var scoreLabel: SKLabelNode? 

private var wordLabel: SKLabelNode? 

private var score = 0 

private var theWord = "" 

private var vowelPressed = false 

let correct = SoundSFX("correct.wav") 

let wrong = SoundSFX("nomatch.wav") 

let explosion = SoundSFX("explosion.wav") 

var arrayOfStrings: [String]? 

var theCheckedWord = "" 

var currentCount = 0 

var itemsArray = [String]() 

var partialExists = false 

var characterScore = 0 

var onePointLetters = [12, 14, 18, 19, 20] 

var twoPointLetters = [4, 7] 

var threePointLetters = [2, 3, 13, 16] 

var fourPointLetters = [6, 8, 22, 23, 25] 

var fivePointLetters = [11] 

var eightPointLetters = [10, 24] 

var tenPointLetters = [17, 26] 

var letter = 0 

var scoreArray = [Int]() 

var matchingTerms = [String]() 

var gravity:CGFloat = -0.35 

var result = CGSize() 

let synth = AVSpeechSynthesizer() 
var myUtterance = AVSpeechUtterance(string:"") 



override func didMove(to view: SKView) { 

    SoundEngine.shared.backgroundMusicVolume = 1.0 

    SoundEngine.shared.playBackgroundMusic("Jungle Audio-1.m4a", loop: true) 

    initializeGame() 



} 

override func update(_ currentTime: TimeInterval) { 
    managePlayer() 
} 


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

    for touch in touches { 

     let location = touch.location (in: self) 


     if atPoint(location).name == "LetterA" { 

      print ("Letter A pressed") 
      vowelPressed = true 
      theWord = theWord + "A" 
      wordLabel?.text = theWord 
      if theWord.characters.count >= 3 { 
       checkWord() 

      } 
      vowelPressed = false 

     } 

     else if atPoint(location).name == "LetterE" { 

     print ("Letter E pressed") 
      vowelPressed = true 
      theWord = theWord + "E" 
      wordLabel?.text = theWord 
      if theWord.characters.count >= 3 { 
       checkWord() 

      } 
      vowelPressed = false 

    } 

     else if atPoint(location).name == "LetterI" { 

      print ("Letter I pressed") 
      vowelPressed = true 
      theWord = theWord + "I" 
      wordLabel?.text = theWord 
      if theWord.characters.count >= 3 { 
       checkWord() 

      } 

      vowelPressed = false 


     } 

     else if atPoint(location).name == "LetterO" { 

      print ("Letter O pressed") 
      vowelPressed = true 
      theWord = theWord + "O" 
      wordLabel?.text = theWord 
      if theWord.characters.count >= 3 { 
      checkWord() 

      } 

      vowelPressed = false 

     } 

     else if atPoint(location).name == "LetterU" { 

      print ("Letter U pressed") 
      vowelPressed = true 
      theWord = theWord + "U" 
      wordLabel?.text = theWord 
      if theWord.characters.count >= 3 { 
       checkWord() 

      } 

      vowelPressed = false 


     } 

     else if atPoint(location).name == "Pause" { 

      showPauseAlert() 


     } 



     else if atPoint(location).name == "delete" { 

      theWord = "" 
      theCheckedWord = "" 
      wordLabel?.text = theWord 

     } 





     else { 


     if location.x > center && !vowelPressed { 

      moveLeft = false 
     } 

     else if location.x < center && !vowelPressed { 

      moveLeft = true 
     } 



    canMove = true 

     } 
    } 
} 

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

func didBegin(_ contact: SKPhysicsContact) { 

    if !gamePaused { 

    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 == "Tile" { 


     letter = secondBody.node?.userData?.value(forKey:"key") as! Int 
     print ("The value of letter is \(letter)") 
     var letterCode = String(describing: letter) 
     var letterValue = Int(letterCode) 
     var finalLetterValue = letterValue!+64 
     var ASCIICode = Character(UnicodeScalar(finalLetterValue)!) 
     var letterString = String(describing:ASCIICode) 
     theWord = theWord + letterString 
     print (theWord) 

     if onePointLetters.contains(letter) { 

      characterScore += 1 



     } 

     else if twoPointLetters.contains(letter) { 

      characterScore += 2 


     } 

     else if threePointLetters.contains(letter) { 

      characterScore += 3 


     } 

     else if fourPointLetters.contains(letter) { 

      characterScore += 4 
         } 

     else if fivePointLetters.contains(letter) { 

      characterScore += 5 


     } 


     else if eightPointLetters.contains(letter) { 

      characterScore += 8 

     } 

     else if tenPointLetters.contains(letter) { 

      characterScore += 10 

     } 

     wordLabel?.text = theWord 
     theCheckedWord = theWord.lowercased() 
     print ("The checked word is \(theCheckedWord)") 


     checkWord() 

     secondBody.node?.removeFromParent() 

    } 


    if firstBody.node?.name == "Player" && secondBody.node?.name == "Bomb" { 

     explosion.play() 
     firstBody.node?.removeFromParent() 
     secondBody.node?.removeFromParent() 
     theWord = "" 
     score = 0 
     scoreLabel?.text = String(score) 
     var delayTimer = SKAction.wait(forDuration:1) 
     run (delayTimer) 
     restartGame() 

    } 


} 

} 



private func initializeGame() { 





    do { 
     // This solution assumes you've got the file in your bundle 
     if let path = Bundle.main.path(forResource: "en", ofType: "txt"){ 
      let data = try String(contentsOfFile:path, encoding: String.Encoding.utf8) 
      arrayOfStrings = data.components(separatedBy: "\n") 

     } 
    } catch let err as NSError { 
     // do something with Error 
     print(err) 
    } 

    physicsWorld.contactDelegate = self 
    physicsWorld.gravity = CGVector(dx:0,dy:gravity) 





    player = childNode(withName: "Player") as? Player! 
    player?.initializePlayer() 
    player?.position = CGPoint(x:0, y: -420) 
    scoreLabel = childNode(withName: "ScoreLabel") as? SKLabelNode! 
    scoreLabel?.text = String(score) 
    wordLabel = childNode(withName:"WordLabel") as? SKLabelNode! 
    wordLabel?.text = "" 
    center = self.frame.size.width/self.frame.size.height 



    var spawnBlocks = SKAction.repeatForever(SKAction.sequence([SKAction.wait(forDuration:1),SKAction.run(spawnItems)])) 



    var removeBlocks = SKAction.repeatForever(SKAction.sequence([SKAction.wait(forDuration:1),SKAction.run(removeItems)])) 


    if gamePaused == true { 

     self.scene?.isPaused = true 

    } 

    self.run(spawnBlocks) 


    self.run(removeBlocks) 


} 

private func checkWord() { 

    theCheckedWord = theWord.lowercased() 


    if (arrayOfStrings?.contains(theCheckedWord))! { 

     print ("Yes! \(theCheckedWord) is a word") 





     correct.play() 
     print ("The current value of score is \(score)") 
     score += characterScore 
     print ("Current gravity setting is \(gravity)") 
     scoreLabel?.text = String(score) 
     characterScore = 0 

     matchingTerms = (arrayOfStrings?.filter({$0.hasPrefix(theCheckedWord) 

     }))! 


     if matchingTerms.count == 1 { 


      characterScore = 0 
      print ("Current gravity setting is \(gravity)") 
      theWord = "" 
      theCheckedWord = "" 
      wordLabel?.text = "" 


     } 

    } 



    else if !(arrayOfStrings?.contains(theCheckedWord))! { 



     matchingTerms = (arrayOfStrings?.filter({$0.hasPrefix(theCheckedWord) 

     }))! 



     if matchingTerms.count == 0 { 

      wrong.play() 

      characterScore = 0 

      if score >= 5 { 

       score -= 5 

      } 



      theWord = "" 
      theCheckedWord = "" 
      wordLabel?.text = "" 

     } 
    } 



} 

這裏是我的敵人代碼:

import SpriteKit 

struct ColliderType { 

static let PLAYER: UInt32 = 0 
static let TILE_AND_BOMB: UInt32 = 1; 

} 


public var bounds = UIScreen.main.bounds 
public var width = bounds.size.width 
public var height = bounds.size.height 


class ItemController { 



private var minX = CGFloat(-(width/2)), maxX = CGFloat(width/2) 

private var vowelNumbers = [1, 5, 9, 15, 21] 

func spawnItems() -> SKSpriteNode { 
    let item: SKSpriteNode? 

    if Int(randomBetweenNumbers(firstNum: 0, secondNum: 10)) > 7 { 
     item = SKSpriteNode(imageNamed: "Bomb") 
     item!.name = "Bomb" 
     item!.setScale(0.6) 
     item!.physicsBody = SKPhysicsBody(circleOfRadius:   item!.size.height/2) 
     print ("The value of width is \(width)") 

    } else { 
     var num = Int(randomBetweenNumbers(firstNum: 1, secondNum: 26)) 

     if vowelNumbers.contains(num) { 

      num = num + 1 
     } 

     item = SKSpriteNode(imageNamed: "Tile \(num)") 
     item?.userData = NSMutableDictionary() 
     item!.name = "Tile" 
     item!.userData!.setValue(num, forKey:"key") 
     item!.zRotation = 0 
     item!.setScale(0.9) 
     item!.physicsBody = SKPhysicsBody(circleOfRadius: item!.size.height/2) 
     if gamePaused == true { 

      item!.isPaused = true 

     } 

     else { 

      item!.isPaused = false 

     } 
    } 

    item!.physicsBody?.categoryBitMask = ColliderType.TILE_AND_BOMB; 
    item!.physicsBody?.isDynamic = true 

    item!.zPosition = 3 
    item!.anchorPoint = CGPoint(x: 0.5, y: 0.5) 

    item!.position.x = randomBetweenNumbers(firstNum: minX, secondNum: maxX) 
    item!.position.y = 600 

    return item! 
} 



func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat { 
    return CGFloat(arc4random())/CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum); 
} 

} 
您可以在00:06和00看到滯後

這裏是我的播放器代碼:

import SpriteKit 

class Player: SKSpriteNode { 

private var minX = CGFloat(-300), maxX = CGFloat(300) 

func initializePlayer() { 

    name = "Player" 

    physicsBody = SKPhysicsBody(circleOfRadius: size.height/2) 
    physicsBody?.affectedByGravity = false 
    physicsBody?.isDynamic = false 
    physicsBody?.categoryBitMask = ColliderType.PLAYER 
    physicsBody?.contactTestBitMask = ColliderType.TILE_AND_BOMB 


    } 

func move(left:Bool){ 

    if left { 
    position.x -= 15 

     if position.x < minX { 

      position.x = minX 
     } 

    } 
    else { 

    position.x += 15 

     if position.x > maxX { 

      position.x = maxX 
     } 


    } 

    } 

} 
+0

這是否也發生在設備上? – BadgerBadger

+0

「arrayOfStrings」中有多少個字符串? – nathan

+0

此外......如果你使用了skspritenode的子類並添加了一個字母屬性或類似的東西,你的checkWords方法和你檢查字母的整個方法可能會更有效率。 – BadgerBadger

回答

0

考慮調用從SKAction方法:

let checkWordsAction = SKAction.run() { 
    [weak self] in 
    self?.checkWord() 
} 
self.run(checkWordsAction) 

這樣一來,如果你的數組太大,代碼將不會中斷,因爲你走它來檢查你的話。

此外,我不確定您在didBegin(contact:)方法結束時的等待操作(當您與炸彈發生碰撞時)要做的事情。如果您在重新開始遊戲之前嘗試等待1秒鐘,請記住按照您的方式調用等待操作不會暫停您的代碼。實際上它只會讓場景閒置1秒鐘,並在後臺重新開始遊戲。如果是這樣的預期效果,這是好的,但你可能使用run(_:completion:)方法,而不是更好,從完成關閉致電restartGame()

let waitAction = SKAction.wait(1) 
self.run(waitAction) { [weak self] in 
    self?.restartGame() 
} 

希望這有助於!

+0

這個問題肯定是你所建議的數組大小。我從簡單的「將你自己的」陣列切換到Lexicontext,它爲20美元提供了一個簡單而即時的解決方案。這裏也可能有免費的解決方案,但Lexicontext對於文字遊戲來說非常容易實現。 – user3140521

0

在didBegin(_聯繫人:SKPhysicsContact),創建兩個物理機構:

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

也許是因爲你創建兩個新物理機構創建滯後。如果你不創建物理實體,但是隻需創建現有的?我沒有測試過,但也許嘗試:

let firstBody: SKPhysicsBody 
let secondBody: SKPhysicsBody 

if contact.bodyA.node?.name == "Player" { 

    firstBody = contact.bodyA 
    secondBody = contact.bodyB 
} 

else { 
    firstBody = contact.bodyB 
    secondBody = contact.bodyA 
} 
+0

哦!這是一個很好的電話!這絕對沒有幫助! – BadgerBadger

相關問題