質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.72%

現在表示しているSceneを最初から再読み込みする際にノードが正しく動作しない。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 200

前提・実現したいこと

Swift SpriteKit でFlappyBirdの様なゲームを作成しています。

しかし"やり直す"ボタンを押すことで現在表示しているScene再読み込みすることで
画面を最初から表示する機能を実装中に以下のエラーメッセージが発生しました。
最初に起動した際には正しく動作しています。

発生している問題・エラーメッセージ

おそらくdidMove内のif文の中身を実行するタイミングで SIGABRTエラーが出て
クラッシュしています。

該当のソースコード

import SpriteKit
import GameplayKit
import Foundation

let bard = SKSpriteNode(imageNamed: "bard")
let stop = SKSpriteNode(imageNamed: "stop")
let scorel = SKLabelNode(fontNamed: "Helvetica Neue")

struct category {
static let Wall: UInt32 = 1
static let player: UInt32 = 2
static let frame: UInt32 = 3
static let score: UInt32 = 4
}

var timer = Timer()
var label = UILabel()
var flag = true
var stopCount = 0
var score = 0
var scoreFlag = true

class GameScene: SKScene,SKPhysicsContactDelegate{

override func didMove(to view: SKView) {
print("1")

if flag == true {
print("2")
//床のアニメーション
timer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(self.yukaAnime) , userInfo: nil, repeats: true )
//壁のアニメーション
timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(self.wall), userInfo: nil, repeats: true)
//最初の床アニメーション
yukaAnime1()
//最初の壁アニメーション
wall()

//スコア
scorel.text = "score \(score)"
scorel.position = CGPoint(x: -200, y:500)
scorel.fontSize = 30
scorel.zPosition = 10
addChild(scorel)

self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -10.0)

//鳥
bard.position = CGPoint(x: -230, y: 200)
bard.size = CGSize(width: bard.size.width * 0.25, height: bard.size.height * 0.25)
bard.physicsBody = SKPhysicsBody(rectangleOf: bard.size )
bard.physicsBody?.categoryBitMask = category.player
bard.physicsBody?.collisionBitMask = category.Wall
bard.physicsBody?.contactTestBitMask = category.Wall
bard.physicsBody?.isDynamic = true
self.addChild(bard)

self.physicsWorld.contactDelegate = self

//一時停止
stop.position = CGPoint(x: 280, y: 550)
stop.zPosition = 10
stop.name = "stop"
stop.size = CGSize(width: 80, height: 80)
self.addChild(stop)
}
}
func scoreCount() {
if scoreFlag == true {
score = score + 100
}
scorel.text = "score \(score)"
print("\(score)")
}

func didBegin(_ contact: SKPhysicsContact) {
let firstBody: SKPhysicsBody = contact.bodyA
let secondBody: SKPhysicsBody = contact.bodyB

if ((firstBody.categoryBitMask == category.Wall) && (secondBody.categoryBitMask == category.player)) ||
((firstBody.categoryBitMask == category.player) && (secondBody.categoryBitMask == category.Wall)){
flag = false
gameover()
reset()
scoreFlag = false
}
if ((firstBody.categoryBitMask == category.score) && (secondBody.categoryBitMask == category.player)) ||
((firstBody.categoryBitMask == category.player) && (secondBody.categoryBitMask == category.score)) {
scoreCount()
}
}
func gameover(){
let label = SKLabelNode(fontNamed: "Helvetica Neue")
label.fontSize = 100
label.position = CGPoint(x: 0, y: 0)
label.zPosition = 5
label.text = "gameover"
addChild(label)
}
func reset(){

let reset = SKLabelNode(fontNamed: "Helvetica Neue")
reset.fontSize = 40
reset.position = CGPoint(x: 0, y: -100)
reset.zPosition = 5
reset.text = "やり直す"
reset.name = "reset"
flag = true
addChild(reset)
}

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

for touch : AnyObject in touches {
let location = touch.location(in: self)
let touchedNode = self.atPoint(location)

if let name = touchedNode.name {

if name == "stop" && stopCount % 2 == 0 {
self.isPaused = true
stopCount += 1
bard.color = UIColor.white
} else if name == "stop" && stopCount % 2 == 1{
self.isPaused = false
stopCount += 1
} else if name == "reset" {

let result = GameScene(fileNamed: "GameScene")
result?.scaleMode = .aspectFill
self.view?.presentScene(result)
}
}
}
}

@objc func wall(){
let wallpair = SKNode()

let topWall = SKSpriteNode(imageNamed: "wall")
let btmWall = SKSpriteNode(imageNamed: "wall")
let score = SKSpriteNode(imageNamed: "score")

let random = Int.random(in: -400...400)

topWall.position = CGPoint(x: 360, y: random + 600)
btmWall.position = CGPoint(x: 360, y: random + -600)
score.position = CGPoint(x: 360, y: random)
score.zPosition = -2

topWall.size = CGSize(width: topWall.size.width * 0.5, height: topWall.size.height * 0.5)
btmWall.setScale(0.5)
score.setScale(0.5)

let action = SKAction.moveTo(x: -2000, duration: 7)
let actionDone = SKAction.removeFromParent()
wallpair.run(SKAction.sequence([action, actionDone]))

topWall.physicsBody = SKPhysicsBody(rectangleOf: topWall.size )
topWall.physicsBody?.categoryBitMask = category.Wall
topWall.physicsBody?.collisionBitMask = category.player
topWall.physicsBody?.contactTestBitMask = category.player
topWall.physicsBody?.isDynamic = false
topWall.physicsBody?.affectedByGravity = false

btmWall.physicsBody = SKPhysicsBody(rectangleOf: btmWall.size )
btmWall.physicsBody?.categoryBitMask = category.Wall
btmWall.physicsBody?.collisionBitMask = category.player
btmWall.physicsBody?.contactTestBitMask = category.player
btmWall.physicsBody?.isDynamic = false
btmWall.physicsBody?.affectedByGravity = false

score.physicsBody = SKPhysicsBody(rectangleOf: score.size)
score.physicsBody?.categoryBitMask = category.score
score.physicsBody?.collisionBitMask = category.player
score.physicsBody?.contactTestBitMask = category.player
score.physicsBody?.isDynamic = false
score.physicsBody?.affectedByGravity = false

wallpair.addChild(score)
wallpair.addChild(topWall)
wallpair.addChild(btmWall)

self.addChild(wallpair)

}

func yukaAnime1(){
let yuka = SKSpriteNode(imageNamed: "yuka")
yuka.position = CGPoint(x: 300, y: -640)
yuka.size = CGSize(width: yuka.size.width * 0.2, height: yuka.size.height * 0.2)
let action = SKAction.moveTo(x: -2000, duration: 7)
let actionDone = SKAction.removeFromParent()
yuka.zPosition = 1
yuka.run(SKAction.sequence([action, actionDone]))
addChild(yuka)
}

@objc func yukaAnime(){
let yuka = SKSpriteNode(imageNamed: "yuka")
yuka.position = CGPoint(x: 300, y: -640)
yuka.size = CGSize(width: yuka.size.width * 0.2, height: yuka.size.height * 0.2)

yuka.physicsBody = SKPhysicsBody(rectangleOf: yuka.size)
yuka.physicsBody?.categoryBitMask = category.frame
yuka.physicsBody?.collisionBitMask = category.frame
yuka.physicsBody?.contactTestBitMask = category.player
yuka.physicsBody?.isDynamic = false
yuka.physicsBody?.affectedByGravity = false

let action = SKAction.moveTo(x: -2000, duration: 15)
let actionDone = SKAction.removeFromParent()
yuka.zPosition = 1
yuka.run(SKAction.sequence([action, actionDone]))

addChild(yuka)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touch")
if flag == true {
bard.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
bard.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 130))
}else if flag == false {
bard.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
bard.physicsBody?.applyImpulse(CGVector(dx: 0, dy: -50))
}
}
}

試したこと

didMove内のif文の外にノードを配置してみたら、再読み込みした際に
そのノードだけ表示することはできました。(右下のnode数からみて、画面外にはみ出ている可能性や
zPositionの設定で重なっているなどの可能性はなさそうです。)

なのでおそらくif文の中に原因がある様なのですが手掛かりが掴めません。

didMove内のtimer2つを消してみて再読み込みしてみると
一応クラッシュはしませんでしたが、鳥のサイズや重力関係がおかしくなってしまいます。

補足情報(FW/ツールのバージョンなど)

まだ初心者で読みにくいと思いますが、回答して頂けると幸いです

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

ごめんなさい。自己解決致しました

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.72%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る