Быстрое программирование.Возможная проблема с SKPhysicscontact - PullRequest
0 голосов
/ 11 декабря 2018

Я работаю над проектом / игрой, и я застрял в добавлении новых врагов в игру и их программировании.Так выглядел мой код до того, как я начал меняться, и имел только один тип «чужеродных».Я хочу создать два новых типа, один из которых вы теряете 5 баллов от попадания, а другой 10. В коде сейчас есть только один из трех, и он дает +5 баллов.Как бы вы, ребята, добавили два новых?Я думаю, что я обдумываю это, и именно поэтому я запутался.

import SpriteKit
import GameplayKit
import CoreMotion

class GameScene: SKScene, SKPhysicsContactDelegate {

    var starfield:SKEmitterNode!
    var player:SKSpriteNode!

    var scoreLabel:SKLabelNode!
    var score:Int = 0 {
        didSet {
            scoreLabel.text = "Score: \(score)"
        }
    }

    var gameTimer:Timer!

    var possibleAliens = ["alien"]
    //This is the "alien you earn +5 point from shooting. Im trying to get 2 new aliens to the scene, one that you lose -5 points from shooting and one you lose -10 on.
    //I have tried to rewrite the codes to the two new, but they still earn +5 points from shooting all 3 types. What would you guys do and how?

    let alienCategory:UInt32 = 0x1 << 1
    let photonTorpedoCategory:UInt32 = 0x1 << 0


    let motionManger = CMMotionManager()
    var xAcceleration:CGFloat = 0

    override func didMove(to view: SKView) {

        starfield = SKEmitterNode(fileNamed: "Starfield")
        starfield.position = CGPoint(x: 0, y: 1472)
        starfield.advanceSimulationTime(10)
        self.addChild(starfield)

        starfield.zPosition = -1

        player = SKSpriteNode(imageNamed: "shuttle")

        player.position = CGPoint(x: self.frame.size.width / 2, y: player.size.height / 2 + 20)

        self.addChild(player)

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

        scoreLabel = SKLabelNode(text: "Score: 0")
        scoreLabel.position = CGPoint(x: 100, y: self.frame.size.height - 60)
        scoreLabel.fontName = "AmericanTypewriter-Bold"
        scoreLabel.fontSize = 36
        scoreLabel.fontColor = UIColor.white
        score = 0

        self.addChild(scoreLabel)


        gameTimer = Timer.scheduledTimer(timeInterval: 0.75, target: self, selector: #selector(addAlien), userInfo: nil, repeats: true)


        motionManger.accelerometerUpdateInterval = 0.2
        motionManger.startAccelerometerUpdates(to: OperationQueue.current!) { (data:CMAccelerometerData?, error:Error?) in
            if let accelerometerData = data {
                let acceleration = accelerometerData.acceleration
                self.xAcceleration = CGFloat(acceleration.x) * 0.75 + self.xAcceleration * 0.25
            }
        }
    }

    func addAlien () {
        possibleAliens = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: possibleAliens) as! [String]

        let alien = SKSpriteNode(imageNamed: possibleAliens[0])

        let randomAlienPosition = GKRandomDistribution(lowestValue: 0, highestValue: 414)
        let position = CGFloat(randomAlienPosition.nextInt())

        alien.position = CGPoint(x: position, y: self.frame.size.height + alien.size.height)

        alien.physicsBody = SKPhysicsBody(rectangleOf: alien.size)
        alien.physicsBody?.isDynamic = true

        alien.physicsBody?.categoryBitMask = alienCategory
        alien.physicsBody?.contactTestBitMask = photonTorpedoCategory
        alien.physicsBody?.collisionBitMask = 0

        self.addChild(alien)

        let animationDuration:TimeInterval = 6

        var actionArray = [SKAction]()

        actionArray.append(SKAction.move(to: CGPoint(x: position, y: -alien.size.height), duration: animationDuration))
        actionArray.append(SKAction.removeFromParent())

        alien.run(SKAction.sequence(actionArray))
    }

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

    func fireTorpedo() {
        self.run(SKAction.playSoundFileNamed("torpedo.mp3", waitForCompletion: false))

        let torpedoNode = SKSpriteNode(imageNamed: "torpedo")
        torpedoNode.position = player.position
        torpedoNode.position.y += 5

        torpedoNode.physicsBody = SKPhysicsBody(circleOfRadius: torpedoNode.size.width / 2)
        torpedoNode.physicsBody?.isDynamic = true

        torpedoNode.physicsBody?.categoryBitMask = photonTorpedoCategory
        torpedoNode.physicsBody?.contactTestBitMask = alienCategory
        torpedoNode.physicsBody?.collisionBitMask = 0
        torpedoNode.physicsBody?.usesPreciseCollisionDetection = true

        self.addChild(torpedoNode)

        let animationDuration:TimeInterval = 0.3

        var actionArray = [SKAction]()

        actionArray.append(SKAction.move(to: CGPoint(x: player.position.x, y: self.frame.size.height + 10), duration: animationDuration))
        actionArray.append(SKAction.removeFromParent())

        torpedoNode.run(SKAction.sequence(actionArray))
    }

    func didBegin(_ contact: SKPhysicsContact) {
        var firstBody:SKPhysicsBody
        var secondBody:SKPhysicsBody

        if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
            firstBody = contact.bodyA
            secondBody = contact.bodyB
        }else{
            firstBody = contact.bodyB
            secondBody = contact.bodyA
        }

        if (firstBody.categoryBitMask & photonTorpedoCategory) != 0 && (secondBody.categoryBitMask & alienCategory) != 0 {
           torpedoDidCollideWithAlien(torpedoNode: firstBody.node as! SKSpriteNode, alienNode: secondBody.node as! SKSpriteNode)
        }

    }

    func torpedoDidCollideWithAlien (torpedoNode:SKSpriteNode, alienNode:SKSpriteNode) {

        let explosion = SKEmitterNode(fileNamed: "Explosion")!
        explosion.position = alienNode.position
        self.addChild(explosion)

        self.run(SKAction.playSoundFileNamed("explosion.mp3", waitForCompletion: false))

        torpedoNode.removeFromParent()
        alienNode.removeFromParent()

        self.run(SKAction.wait(forDuration: 2)) { 
            explosion.removeFromParent()
        }

        score += 5
    }

    override func didSimulatePhysics() {
        player.position.x += xAcceleration * 50

        if player.position.x < -20 {
            player.position = CGPoint(x: self.size.width + 20, y: player.position.y)
        }else if player.position.x > self.size.width + 20 {
            player.position = CGPoint(x: -20, y: player.position.y)
        }
    }

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

1 Ответ

0 голосов
/ 11 декабря 2018

Я бы не советовал следовать этому ответу, если ваша игра станет более сложной.Обычно я бы сказал, что инопланетяне помещаются в подклассы, инициализированные с их собственными битовыми масками категорий и другими свойствами, но чтобы избежать слишком частого изменения вашего кода, я просто изменил метод addAlien() и didBeginContact.У каждого пришельца есть своя категория BitMask и textureName.

let alienCategories:[UInt32] = [(0x1 << 1),(0x1 << 2),(0x1 << 3)]
let alienTextureNames:[String] = ["alien1","alien2","alien3"]

Это сделает случайного Чужого, используя значения в коллекциях выше

func addAlien () {

    //Random index between 0 and 2 changing the texture and category bitmask
    let index = Int.random(in: 0...2)
    let textureName = alienTextureNames[index]
    let alien = SKSpriteNode(imageNamed: textureName)

    //Use Int.random() if you don't want a CGFLoat
    let xPos = CGFloat.random(in: 0...414)
    let yPos = frame.size.height + alien.size.height
    alien.position = CGPoint(x: xPos, y: yPos)

    alien.physicsBody = SKPhysicsBody(rectangleOf: alien.size)
    alien.physicsBody?.isDynamic = true

    alien.physicsBody?.categoryBitMask = alienCategories[index]
    alien.physicsBody?.contactTestBitMask = photonTorpedoCategory
    alien.physicsBody?.collisionBitMask = 0

    self.addChild(alien)

    let moveAction = SKAction.moveTo(y: -alien.size.height, duration: 6)
    alien.run(moveAction, completion: { alien.removeFromParent() })

}

func didBegin(_ contact: SKPhysicsContact) {
    var firstBody:SKPhysicsBody
    var secondBody:SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    }else{
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if firstBody.categoryBitMask == photonTorpedoCategory && secondBody.categoryBitMask == alienCategories[0] {
        torpedoDidCollideWithAlien(torpedoNode: firstBody.node as! SKSpriteNode, alienNode: secondBody.node as! SKSpriteNode)
        score += 5

    }else if firstBody.categoryBitMask == photonTorpedoCategory && secondBody.categoryBitMask == alienCategories[1] {
        torpedoDidCollideWithAlien(torpedoNode: firstBody.node as! SKSpriteNode, alienNode: secondBody.node as! SKSpriteNode)
        score -= 5

    }else if firstBody.categoryBitMask == photonTorpedoCategory && secondBody.categoryBitMask == alienCategories[2] {
        torpedoDidCollideWithAlien(torpedoNode: firstBody.node as! SKSpriteNode, alienNode: secondBody.node as! SKSpriteNode)
        score -= 10

    }
}

Измените строку torpedoNode.physicsBody?.contactTestBitMask = alienCategory в методе fireTorpedo на alien.physicsBody?.contactTestBitMask = (alienCategories[0] | alienCategories[1] | alienCategories[2])

...