如何在一个不同类的循环中生成一个SKnode - swift

时间:2016-05-06 03:55:13

标签: swift sprite-kit nodes subclass

我正在创建一个射击游戏,我正在尝试创建一个射击方法,但我当前的方法只在点击时生成一个子弹。我将我的子弹定义为SKnode子类,并在我的gameScene.swift中使用touches start方法调用它。这是

的方式
class Bullet1: SKNode {

var Bullet1:SKSpriteNode = SKSpriteNode()
var Bullet1Animaton:SKAction?

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

override init () {

    super.init()
}
func createBullet1s (){
    let wait:SKAction = SKAction.waitForDuration( CFTimeInterval(0.25))
    let block:SKAction = SKAction.runBlock(createBullet1)
    let seq2:SKAction = SKAction.sequence( [block, wait])
    SKAction.repeatActionForever(seq2)
    self.runAction(seq2, withKey:"droneAction")

}
func createBullet1() {

    Bullet1 = SKSpriteNode(imageNamed: "bullet.png")
    Bullet1.xScale = 0.5
    Bullet1.yScale = 0.5
    Bullet1.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet1.size)
    Bullet1.physicsBody?.categoryBitMask = PhysicsCategory.bullet1
    Bullet1.physicsBody?.contactTestBitMask = PhysicsCategory.enemy1 
    Bullet1.physicsBody?.affectedByGravity = false
    Bullet1.physicsBody?.dynamic = true
    self.addChild(Bullet1)
    self.name = "Bullet1"
}

}
class GameScene: SKScene, SKPhysicsContactDelegate {

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

override func touchesBegan(touches: Set<UITouch>, withEvent 
event:UIEvent?) {
    for touch in touches {

    let location = touch.locationInNode(self)
    let node = nodeAtPoint(location)

        if (CGRectContainsPoint(joystick.frame, location)) {
            stickActive = true
            fireWeapon = true
        }else{
            stickActive = false
        }

if stickActive == true && fireWeapon == true{  if fireWeapon == false 
{}

let bulletAction = SKAction.runBlock({
let v = CGVector(dx: location.x - self.joystickBase.position.x, dy: 
location.y - self.joystickBase.position.y)
let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
let deg = angle * CGFloat(180 / M_PI)
print(deg + 180) // prints degree in debugging
self.hero.zRotation = angle - 1.57079633 //rotates with angle of joy 
stic

let bullet1:Bullet1 = Bullet1()
bullet1.createBullet1()

bullet1.position = CGPoint (x: self.hero.position.x , y: 
self.hero.position.y) // Bullet spawn @ anchor point
let xDist:CGFloat = sin(angle - 1.5709633) * 35 //bullet spawn location
let yDist:CGFloat = cos(angle - 1.5709633) * 35 //bullet spawn location

bullet1.position = CGPointMake( self.hero.position.x - xDist, 
self.hero.position.y + yDist) //spawning bullet @ defined location

let xDistMove:CGFloat = sin(angle - 1.5709633) * 700 //Bullet max x 
distance
let yDistMove:CGFloat = cos(angle - 1.5709633) * 700 //Bullet max y 
distance

let bulletMovementY = SKAction.moveToY(self.hero.position.y + 
yDistMove, duration: 1) //Bullet y speed
let bulletMovementX = SKAction.moveToX(self.hero.position.x - 
xDistMove, duration: 1) //Bullet x speed

bullet1.runAction(bulletMovementY)
bullet1.runAction(bulletMovementX)

self.addChild(bullet1)
})
let wait = SKAction.waitForDuration(0.25)
let completeSequence = SKAction.sequence([bulletAction, wait])
let repeatShootingActionForever =
SKAction.repeatActionForever(completeSequence)
self.runAction(repeatShootingActionForever, withKey: "BulletAction")
        }

override func touchesMoved(touches: Set<UITouch>, withEvent event: 
UIEvent?) {

for touch in touches {
let location = touch.locationInNode(self
if (stickActive == true) {

let v = CGVector(dx: location.x - joystickBase.position.x, dy: 
location.y - joystickBase.position.y)
let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
let deg = angle * CGFloat(180 / M_PI)
let length: CGFloat = joystickBase.frame.size.height / 2                   
print(deg + 180) // prints degree in debugging

joystick.position = location

hero.zRotation = angle - 1.57079633 //rotates with angle of joy stick

if (CGRectContainsPoint(joystickBase.frame, location)) {
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: 
UIEvent?) {

    for touch in touches {

    let location = touch.locationInNode(self)

if stickActive == true && fireWeapon == true{  if fireWeapon == false 
{}

let v = CGVector(dx: location.x - joystickBase.position.x, dy: 
location.y - joystickBase.position.y)
let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
let deg = angle * CGFloat(180 / M_PI)//converts radains to degrees and 
generates a degree when touchesmove == true
let length: CGFloat = joystickBase.frame.size.height / 2 //sets maximum 
distance for joystick ball
print(deg + 180) // prints degree in debugging

joystick.position = location

self.hero.zRotation = angle - 1.57079633 //rotates with   
angle of joy stick
let xDist:CGFloat = sin(angle - 1.5709633) * 35 //bullet spawn location
let yDist:CGFloat = cos(angle - 1.5709633) * 35 //bullet spawn location

bullet1.position = CGPointMake( self.hero.position.x - xDist, 
self.hero.position.y + yDist) //spawning bullet @ defined location

let xDistMove:CGFloat = sin(angle - 1.5709633) * 700 //Bullet max x     
distance
let yDistMove:CGFloat = cos(angle - 1.5709633) * 700 //Bullet max y 
distance

let bulletMovementY = SKAction.moveToY(self.hero.position.y +   
yDistMove, duration: 1) //Bullet y speed
let bulletMovemenX = SKAction.moveToX(self.hero.position.x - xDistMove, 
duration: 1) //Bullet x speed

            bullet1.runAction(bulletMovementY)
            bullet1.runAction(bulletMovemenX)
}}

你可以看到我需要在触摸开始时调用我的子弹方法,因为子弹生成位置与操纵杆协调。当我按照我在createBullet1s方法中尝试的操纵杆按下操纵杆时,当前方法仅在点击时生成1个子弹而不是每0.25秒创建一个新子弹。如果有人能帮助我,我将非常感激!谢谢

1 个答案:

答案 0 :(得分:1)

如果必须为每个项目符号计算新的值,那么这样的事情就是我猜的方法(在每个节点名称之前添加self.):

if stickActive == true && fireWeapon == true{  if fireWeapon == false      
{}
let shootingAction = SKAction.runBlock({
    let v = CGVector(dx: location.x - joystickBase.position.x, dy: 
    location.y - joystickBase.position.y)
    let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
    let deg = angle * CGFloat(180 / M_PI)//converts radains to degrees and  
        generates a degree when touchesmove == true 
        print(deg + 180) 
        let bullet1:Bullet1 = Bullet1()
        self.bullet1.createBullet1s()

        self.bullet1.position = CGPoint (x: self.hero.position.x , y: self.hero.position.y) 
        let xDist:CGFloat = sin(angle - 1.5709633) * 35 
        let yDist:CGFloat = cos(angle - 1.5709633) * 35 
        self.bullet1.position = CGPointMake(self.hero.position.x - xDist,self.hero.position.y + yDist) 

        let xDistMove:CGFloat = sin(angle - 1.5709633) * 700 
        let yDistMove:CGFloat = cos(angle - 1.5709633) * 700 

        let bulletMovementY = SKAction.moveToY(self.hero.position.y + yDistMove, 
        duration: 1) 
        let bulletMovemenX = SKAction.moveToX(self.hero.position.x - xDistMove,   
        duration: 1) 
        let wait:SKAction = SKAction.waitForDuration(CFTimeInterval(0.25))

        self.addChild(self.bullet1)

        let groupMovement = SKAction.group([bulletMovementY,bulletMovementX])
        let removeNode = SKAction.removeFromParent()
        let sequenceMovementWithWait = SKAction.sequence([wait,groupMovement,removeNode])
        self.hero.runAction(sequenceMovementWithWait)
        self.hero.zRotation = angle - 1.57079633 
    })

let repeatShootingActionForever = SKAction.repeatActionForever(shootingAction)
self.runAction(repeatShootingActionForever, withKey: "BulletAction"))

如果每个项目的值可以保持不变,那么这样就足够了:

        let bulletAction = SKAction.runBlock({
        self.addChild(self.bullet1)
        let groupAction = SKAction([bulletMovementY,bulletMovementX])
        let removeNode = SKAction.removeFromParent()
        let finalSequenceWithWait = SKAction.sequence([wait,groupAction,removeNode])
        self.bullet1.runAction(finalSequenceWithWait)
        })
        let repeatBulletActionForever = SKAction.repeatActionForever(bulletAction)
        self.runAction(repeatBulletActionForever, withKey: "BulletAction")

对于我在TouchesEnded中所说的两种方式:

self.removeActionForKey("BulletAction")

编辑:

好的..你有一个SKNode子类,你可以将子弹(SpriteNodes)添加到SKNode。顺便说一下 - 它很复杂,因为你给了SpriteNodes和SKNode相同的名字。但是,子弹(SpriteNodes)会添加到SKNode中,而SKNode会添加到GameScene中。现在我们在gamescene中“生成”和“删除”这个SKNode,但是我们只将SpriteNodes添加到SKNode中,我们不会在那里删除它们。

你想在GameScene中同时看到多个子弹吗?如果你一次只需要1个子弹可见(但重复)我会说可能有助于从你的SKNode中删除Bullet(SpriteNode),就像我们在GameScene中那样。

想象一下:

- GameScene creates a SKNode. (your class Bullet1)
- SKNode creates Child SpriteNode
- GameScene removes the SKNode.
- GameScene creates another SKNode. (again your class Bullet1)
- SKNode wants to create Child SpriteNode
-> Error: SpriteNode already exists.

所以我们需要编辑你的课程。

//class Bullet1
func createBullet1() {
if Bullet1.parent == nil{
    Bullet1 = SKSpriteNode(imageNamed: "bullet.png")
    Bullet1.xScale = 0.5
    Bullet1.yScale = 0.5
    Bullet1.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet1.size)
    Bullet1.physicsBody?.categoryBitMask = PhysicsCategory.bullet1
    Bullet1.physicsBody?.contactTestBitMask = PhysicsCategory.enemy1 
    Bullet1.physicsBody?.affectedByGravity = false
    Bullet1.physicsBody?.dynamic = true
    self.addChild(Bullet1)
    self.name = "Bullet1"
    }
else{
    Bullet1.removeFromParent()
}
}

哦,我们需要等待0.25秒才能添加新的SKNode,以便动画完成。在你的GameScene编辑这部分:

let repeatShootingActionForever = SKAction.repeatActionForever(shootingAction)
self.runAction(repeatShootingActionForever, withKey: "BulletAction"))

到此:

let wait = SKAction.waitForDuration(0.25)
let runShootingAction = SKAction.runBlock(shootingAction)
let completeSequence = SKAction.sequence([wait,runShootingAction])
let repeatShootingActionForever = SKAction.repeatActionForever(completeSequence)
self.runAction(repeatShootingActionForever, withKey: "BulletAction"))

我打赌有更好的解决方案,我也不是Swift的专家。你必须测试..对不起。

另一个编辑: 你没有告诉子弹应该有哪个zRotation。

试试这个(你有bulletAction = SKAction.runBlock):

let bulletAction = SKAction.runBlock({
let v = CGVector(dx: location.x - self.joystickBase.position.x, dy: location.y - self.joystickBase.position.y)
let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
let deg = angle * CGFloat(180 / M_PI)//converts radains to degrees and generates a degree when touchesmove == true
print(deg + 180) // prints degree in debugging
let bullet1:Bullet1 = Bullet1()

bullet1.position = CGPoint (x: self.hero.position.x , y: self.hero.position.y) // Bullet spawn @ anchor point
bullet1.zRotation = angle - 1.57079633 //rotates with angle of joy stick
let xDist:CGFloat = sin(angle - 1.5709633) * 35 //bullet spawn location
let yDist:CGFloat = cos(angle - 1.5709633) * 35 //bullet spawn location

bullet1.position = CGPointMake( self.hero.position.x - xDist, self.hero.position.y + yDist) //spawning bullet @ defined location

bullet1.createBullet1()    

let xDistMove:CGFloat = sin(angle - 1.5709633) * 700 //Bullet max x distance
let yDistMove:CGFloat = cos(angle - 1.5709633) * 700 //Bullet max y distance

let bulletMovementY = SKAction.moveToY(self.hero.position.y+yDistMove, duration: 1) //Bullet y speed
let bulletMovemenX = SKAction.moveToX(self.hero.position.x -xDistMove, duration: 1) //Bullet x speed
let wait:SKAction = SKAction.waitForDuration( CFTimeInterval(0.25))
// let bulletFire = SKAction.sequence([wait,bulletMovemenX, bulletMovementY])
self.addChild(bullet1)

bullet1.runAction(wait)
bullet1.runAction(bulletMovementY)
bullet1.runAction(bulletMovemenX)

self.hero.zRotation = angle - 1.57079633 //rotates with angle of joy stick
})

上次修改: 我在你的更新方法中看不到bullet1.zRotation所以我想你只想要英雄来改变zRotation。

但是,如果zRotation仅在touchesBegan而不在touchesMoved中更改,我会说您应该使angle成为可在两种方法中更改的全局变量。也许这会有所帮助,因为英雄根据angle(我认为)的价值得到他的zRotation。

  1. angle设为全局变量并添加一个变量,告诉您触摸是否被移动:

    class GameScene: SKScene, SKPhysicsContactDelegate{
        var angle = CGFloat() // It should be a CGFloat, right?
        var touchesMovedOn = false
    
  2. touchesBegan编辑此部分:

    let bulletAction = SKAction.runBlock({
    let v = CGVector(dx: location.x - self.joystickBase.position.x, dy: location.y - self.joystickBase.position.y)
    let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
    let deg = angle * CGFloat(180 / M_PI)
    print(deg + 180) // prints degree in debugging
    self.hero.zRotation = angle - 1.57079633 //rotates with angle of joystic
    
  3. 到此:

        let bulletAction = SKAction.runBlock({
        let v = CGVector(dx: location.x - self.joystickBase.position.x, dy: location.y - self.joystickBase.position.y)
        if touchesMovedOn == false{
            angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
        }
        let deg = angle * CGFloat(180 / M_PI)
        print(deg + 180) // prints degree in debugging
        self.hero.zRotation = angle - 1.57079633 //rotates with angle of joystic
    
    1. touchesMoved编辑此部分:

      let v = CGVector(dx: location.x - joystickBase.position.x, dy: location.y - joystickBase.position.y)
      let angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
      let deg = angle * CGFloat(180 / M_PI)//converts radains to degrees and generates a degree when touchesmove == true
      let length: CGFloat = joystickBase.frame.size.height / 2 //sets Maximum distance for joystick ball
      print(deg + 180) // prints degree in Debugging to this:
      
    2. 到此:

          touchesMovedOn = true
          let v = CGVector(dx: location.x - joystickBase.position.x, dy: location.y - joystickBase.position.y)
          angle = atan2(v.dy, v.dx) //where angle is defined "in radians"
          let deg = angle * CGFloat(180 / M_PI)//converts radains to degrees and generates a degree when touchesmove == true
          let length: CGFloat = joystickBase.frame.size.height / 2 //sets Maximum distance for joystick ball
          print(deg + 180) // prints degree in Debugging to this:
      
      1. touchesEnded

        中添加此行
        touchesMovedOn = false
        
      2. 如果这没有帮助我真的需要项目,因为我必须自己测试问题所在。所以我希望它现在有效。好运 !正如我所说,我确信有更好的解决方案,所以在未来你应该注意使代码更好。 ; - )