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

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

ただいまの
回答率

88.04%

モグラたたきゲームで出現するモグラの数をランダムにしたい

受付中

回答 1

投稿

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

score 1

プログラミング初心者です。SpriteKitでゲームを作っております。
モグラたたきゲームでタイマーのメソッドを使用し3種類のモグラをランダムに出現させていますが、現在、全ての穴からモグラが一斉に出てくる状態になっています。この出現するモグラの数をランダムにしたいです。どなたかご教示いただきたく、よろしくお願いいたします。

該当のソースコード

import UIKit
import SpriteKit
import GameplayKit
import AVFoundation

class GameScene: SKScene,SKPhysicsContactDelegate {

///モグラの位置
var enemyPoint = [[150,250],[250,600],[200,800],[500,400],[550,150],[650,700],[550,950],[300,1100]]

///モグラを入れる配列
var enemy01Array:[SKSpriteNode] = []
var enemy02Array:[SKSpriteNode] = []
var enemy03Array:[SKSpriteNode] = []

//タイマー
var enemyTimer = Timer()

override func didMove(to view: SKView) {

//もぐらの穴
for i in 0...7{
let hole = SKSpriteNode(imageNamed:"hole.png")
hole.position = CGPoint(x:enemyPoint[i][0],y:enemyPoint[i][1])
self.addChild(hole)
}

//タイマーの設定
enemyTimer = Timer.scheduledTimer(
timeInterval: 3.5,
target:self,
selector:#selector(GameScene.randomLoop),
userInfo:nil,repeats:true)
}

//モグラをランダムに表示
@objc func randomLoop(){

for i in 0...7{
let random = Int(arc4random_uniform(20))

let enemy01 = SKSpriteNode(imageNamed: "enemy01.png")
enemy01.position = CGPoint(x:enemyPoint[i][0],y:enemyPoint[i][1])
enemy01.zPosition = 1

let enemy02 = SKSpriteNode(imageNamed: "enemy02.png")
enemy02.position = CGPoint(x:enemyPoint[i][0],y:enemyPoint[i][1])
enemy02.zPosition = 1

let enemy03 = SKSpriteNode(imageNamed: "enemy03.png")
enemy03.position = CGPoint(x:enemyPoint[i][0],y:enemyPoint[i][1])
enemy02.zPosition = 1

enemy01Array.append(enemy01)
enemy02Array.append(enemy02)
enemy03Array.append(enemy03)
enemy01.name = "enemy01"
enemy02.name = "enemy02"
enemy03.name = "enemy03"

if(random>0 && random<13){
self.addChild(enemy01)

}else if(random>=13 && random<18){
self.addChild(enemy02)

}else{
self.addChild(enemy03)
}

let action1 = SKAction.wait(forDuration: 0.8,withRange:2.0)
let action2 = SKAction.hide()
let action3 = SKAction.wait(forDuration: 0.5,withRange:2.0)
let action4 = SKAction.unhide()
let actionS = SKAction.sequence([action1,action2,action3,action4])

enemy01.run(actionS)
enemy02.run(actionS)
enemy03.run(actionS)

//Nodeが追加され続けてしまっていたタイマー追加までに消える
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0){
let Node1 = self.childNode(withName: "enemy01")
let Node2 = self.childNode(withName: "enemy02")
let Node3 = self.childNode(withName: "enemy03")
Node1?.removeFromParent()
Node2?.removeFromParent()
Node3?.removeFromParent()
}
}
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch:AnyObject = touches.first{
let location = touch.location(in:self)
let touchNode = self.atPoint(location)

if let name = touchNode.name {
if name == "enemy01" {

let enemy01 = SKSpriteNode(imageNamed:"enemy01")
enemy01.position = touchNode.position
self.addChild(enemy01)

//モグラを1回転するアクション
let action1 = SKAction.rotate(byAngle: 6.28, duration: 0.2)
let action2 = SKAction.moveTo(y: touchNode.position.y + 150,duration: 0.2)
let actionG = SKAction.group([action1,action2])
let action3 = SKAction.removeFromParent()
let actionS = SKAction.sequence([actionG,action3])
enemy01.run(actionS)
touchNode.position.y = -100

}else if let name = touchNode.name {
if name == "enemy02" {

let enemy02 = SKSpriteNode(imageNamed:"enemy02")
enemy02.position = touchNode.position
self.addChild(enemy02)

//モグラを1回転するアクション
let action1 = SKAction.rotate(byAngle: 6.28, duration: 0.3)
let action2 = SKAction.moveTo(y: touchNode.position.y + 150,duration: 0.3)
let actionG = SKAction.group([action1,action2])
let action3 = SKAction.removeFromParent()
let actionS = SKAction.sequence([actionG,action3])
enemy02.run(actionS)
touchNode.position.y = -100

}else if let name = touchNode.name {
if name == "enemy03" {

let enemy03 = SKSpriteNode(imageNamed:"enemy03")
enemy03.xScale = 0.6
enemy03.yScale = 0.6
enemy03.position = touchNode.position
self.addChild(enemy03)

//モグラを1回転するアクション
let action1 = SKAction.rotate(byAngle: 6.28, duration: 0.3)
let action2 = SKAction.moveTo(y: touchNode.position.y + 150,duration: 0.3)
let actionG = SKAction.group([action1,action2])
let action3 = SKAction.removeFromParent()
let actionS = SKAction.sequence([actionG,action3])
enemy03.run(actionS)
touchNode.position.y = -100
}
}
}
}
}
}

override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}

```使っているツールのバージョンなど補足情報
swift3

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

検索するとこのサイトが出てきたのですが、
[Swiftで作るモグラ叩きゲーム]
http://gevvoi.hatenablog.com/entry/2016/04/04/060000
このあたりを参考にされたのだと思います。
記事中の参考本、
iphoneのゲームアプリをつくろう!
サンプルコードが今回のコードの元だと思います。
配列を2つ作り、穴とモグラの配列。
穴と同じ数もぐらを作って、時間差で表示させています。
全ての穴には、1匹もぐらが入ってる感じです。
アクションループ中に内容は変更出来ないと思うので、
アクションが終わったらもぐらの配列の中身を変更する様にしました。
配列と同じ穴の位置のもぐらを削除して、同じ位置に新しく追加しました。
本のサンプルでは、タイマーはタイムアップを判定するものだったので
外しました。
一度iphoneのゲームアプリをつくろう!サンプルを見てみると良いと思います

import SpriteKit

class GameScene: SKScene {
    // モグラの位置([x,y]のセットで8個所)を作る CGPointへ変更
let mogPoint = [CGPoint(x:150,y:250),CGPoint(x:250,y:600),
        CGPoint(x:200,y:800),CGPoint(x:500,y: 400),
        CGPoint(x:550,y:150),CGPoint(x:650,y: 700),
        CGPoint(x:550.0,y: 950),CGPoint(x:300,y: 1100)]
    // モグラを入れる配列を用意する(タッチしたかを調べるため)
var mogArray:[SKSpriteNode] = []
//var myTimer = Timer()
override func didMove(to view: SKView) {
// モグラの準備をする モグラ穴を作る
//mogPoint穴の位置の要素 8回繰り返す
for i in mogPoint {
let hole = SKSpriteNode(imageNamed: "hole.png")
    hole.position = i // モグラ穴の位置を指定する
    self.addChild(hole)  // モグラを表示する
    }


    // タイマーをスタートする(1.0秒ごとにtimerUpdateを繰り返し実行)
//Timer.scheduledTimer(timeInterval: 1.0, target:self,selector:#selector(timerUpdate),userInfo:nil,repeats:true)
    // 穴の数だけモグラを作る
for i in mogPoint {
let random = Int(arc4random_uniform(3))
    switch random {
        case 0:
    let mog = SKSpriteNode(imageNamed: "enemy01.png")
        mog.position = i // モグラの位置を指定する
        mog.zPosition = 1
        mog.name = "enemy01"
        self.addChild(mog)// モグラを表示する
        mogArray.append(mog)  // モグラを配列に追加する
        case 1:
    let mog1 = SKSpriteNode(imageNamed: "enemy02.png")
        mog1.position = i // モグラの位置を指定する
        mog1.zPosition = 1
        mog1.name = "enemy02"
        self.addChild(mog1)// モグラを表示する
        mogArray.append(mog1)
        default:
    let mog2 = SKSpriteNode(imageNamed: "enemy03.png")
        mog2.position = i // モグラの位置を指定する
        mog2.zPosition = 1
        mog2.name = "enemy03"
        self.addChild(mog2)// モグラを表示する
            mogArray.append(mog2)
            }
        }
    popAction()
    }

// 【モグラが穴から出たり入ったりするアクションをつける】
func popAction(){
for i in mogArray {
i.run(action(pos:i.position), completion: {() -> Void in
if let index = self.mogArray.firstIndex(of:i ) {
    self.changemogura(at:index)
            }
        })
    }
}
    //配列もぐらを変更する。 at:Intはもぐらの配列のインデックス
func changemogura(at:Int){
let random = Int(arc4random_uniform(3))
  //  print("ランダムの数",random)
    switch random {
        case 0:
let mog = SKSpriteNode(imageNamed: "enemy01.png")
    mog.position = mogPoint[at] // モグラの位置を指定する
    mog.zPosition = 1
    mog.name = "enemy01"
    self.addChild(mog)// モグラを表示する
    mogArray[at] = mog  //配列を入れ替える
        case 1:
let mog1 = SKSpriteNode(imageNamed: "enemy02.png")
    mog1.position = mogPoint[at] // モグラの位置を指定する
    mog1.zPosition = 1
    mog1.name = "enemy02"
    self.addChild(mog1)// モグラを表示する
    mogArray[at] = mog1 //配列を入れ替える
    default:
let mog2 = SKSpriteNode(imageNamed: "enemy03.png")
    mog2.position = mogPoint[at] // モグラの位置を指定する
    mog2.zPosition = 1
    mog2.name = "enemy03"
    self.addChild(mog2)// モグラを表示する
    mogArray[at] = mog2
        }

mogArray[at].run(action(pos:mogArray[at].position), completion: {() -> Void in
if let removeindex = self.mogArray.firstIndex(of:self.mogArray[at] ) {
    self.changemogura(at:removeindex)
            }
    })
}

//もぐらアクション
func action(pos:CGPoint)->SKAction {
let action1 = SKAction.moveTo(y: -1000, duration: 0.0)
let action2 = SKAction.wait(forDuration: 2.0, withRange: 4.0)
let action3 = SKAction.moveTo(y: pos.y, duration: 0.0)
let action4 = SKAction.wait(forDuration: 1.0, withRange: 2.0)
let remove = SKAction.removeFromParent()
let actionS = SKAction.sequence([action1, action2, action3, action4, remove])
return SKAction.sequence([actionS])
    }

// タイマーで実行される処理(1.0秒ごとに繰り返し実行)
//@objc func timerUpdate() {
//  }

    // タッチしたときの処理
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch: AnyObject in touches {
            let location = touch.location(in: self)
            // タッチした位置にあるものを調べる
            let touchNode = self.atPoint(location)
            actionS(touch:touchNode)
        }
    }




func actionS(touch:SKNode){
for i in mogArray {    // 配列の要素を繰り返す
    // もし、タッチしたものがモグラだったら、やっつける
if touch == i { // スコアをアップして、表示する
    switch i.name {
    case "enemy01":
        print("01")
    case "enemy02":
        print("02")
    case "enemy03":
        print("03")
    default:print("その他")
    }

let mog = SKSpriteNode(imageNamed: "mog3.png")
    // やられたモグラを作る
    mog.position = touch.position
    // 位置を指定する
                self.addChild(mog)
// やられたモグラを表示させる
// 【モグラに回転しながら上に飛び出して消えるアクションをつける】
// モグラを1回転するアクション
let action1 = SKAction.rotate(byAngle: 6.28, duration: 0.3)
// モグラを上に100移動するアクション
let action2 = SKAction.moveTo(y: touch.position.y + 150, duration: 0.3)
        // action1とaction2を同時に行う
let actionG = SKAction.group([action1, action2])
        // モグラを削除するアクション
let action3 = SKAction.removeFromParent()
        // actionGとaction3を順番に行う
let actionS = SKAction.sequence([actionG, action3])
    // モグラに「回転しながら上に飛び出して消えるアクション」をつける
        mog.run(actionS)
    touch.position.y = -1000
    // モグラを地下(-1000)に移動して消す
            }
        }
    }
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2021/01/30 13:35

    ご連絡遅くなりすみません。ご教示いただきありがとうございます。
    はい、該当の参考書に記載のコードを元にブログの方のソースを参考にさせていただいておりました。
    ただ、意図には合わずこちらで質問した経緯になります。

    ソースコードありがとうございます!
    モグラがランダムな数で表示されることが確認できました。
    すみません、2点伺ってもよろしいでしょうか。
    ・モグラが消える際に一瞬別のモグラがチラつくのですが、このモグラがでないようにすることは可能でしょうか。
    ・以下のソースについて私の環境がswift3で古いせいかcaseの行でエラーが出るようでして、
     書き方はご存知でしょうか。
    ーーーーーーーーーーーーーーーーーーーーーーーー
    if touch == i { // スコアをアップして、表示する
    switch i.name {
    case "enemy01":
    print("01")
    case "enemy02":
    print("02")
    case "enemy03":
    print("03")
    default:print("その他")
    }
    ーーーーーーーーーーーーーーーーーーーーーーーー
    以上、大変恐縮ですが教えていただけますとありがたいです。

    キャンセル

  • 2021/02/01 23:18

    解決したのであれば質問をクローズしてください。

    キャンセル

  • この投稿は削除されました

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

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

関連した質問

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