我们创建了忍者精灵和怪兽精灵了, 但是我们的忍者精灵还差一些东西,那就是飞镖, 哈哈, 如果我们将忍者精灵的飞镖添加上去应该会很有趣.那么我们怎么去添加飞镖呢. 我的打算是这样的,当我么点击屏幕的时候.忍者的手里就会发射一个飞镖,飞镖就会飞出去. 飞出去的方向就是忍者的坐标与我们点击的屏幕的坐标之间的向量方向, 至于什么是向量,大家高中都学过的,实在不知道的话就当做是直线方向吧! 图片就大概是下面这个样子
为了计算这个方向, 我们需要写一些计算方法, 这些方法Sprite Kit里面是没有的,所以就只有靠我们自己丰衣足食啦.那么我们在GameScene.swift里面的最顶部添加以下代码:
func +(left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y)
}
func -(left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x - right.x, y: left.y - right.y)
}
func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x * scalar, y: point.y * scalar)
}
func /(point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x / scalar, y: point.y / scalar)
}
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
return CGFloat(sqrtf(Float(a)))
}
#endif
extension CGPoint {
func length() -> CGFloat {
return sqrt(x*x + y*y)
}
func normalized() -> CGPoint {
return self / length()
}
}
你可能对这种方法的写法比较奇怪, 如果感觉比较困惑. 可以百度”Swift operator overload”, 然后我们在文件的添加以下方法
override func touchesEnded(touches: Set<NSObject> , withEvent event: UIEvent) {
if let touch = touches.first as? UITouch {
runAction(SKAction.playSoundFileNamed("pew-pew-lei.caf", waitForCompletion: false))
let touchLocation = touch.locationInNode(self)
let projectile = SKSpriteNode(imageNamed: "projectile")
projectile.position = player.position
projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody?.dynamic = true
projectile.physicsBody?.categoryBitMask = PhysicsCategory.Projectile
projectile.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
projectile.physicsBody?.collisionBitMask = PhysicsCategory.None
projectile.physicsBody?.usesPreciseCollisionDetection = true
let offset = touchLocation - projectile.position
if (offset.x < 0) { return }
addChild(projectile)
let direction = offset.normalized()
let shootAmount = direction * 1000
let realDest = shootAmount + projectile.position
let actionMove = SKAction.moveTo(realDest, duration: 2.0)
let actionMoveDone = SKAction.removeFromParent()
projectile.runAction(SKAction.sequence([actionMove, actionMoveDone]))
}
}
这段代码略显复杂,我们一步一步来说
- Sprite Kit包含一个由带有locationInNode(:)和previousLocationInNode(:)方法的UITouch集合,通过SKNode的坐标系统,这些方法可以让你找到点击时的具体坐标;
- 我们在场景中创建了一些飞镖,但是这些飞镖有一些条件限制,比如我们不能让这些飞镖往后飞.
- 然后将飞镖的当前位置与我们点击屏幕的位置坐标进行计算获取飞镖的移动方向;如果X坐标为0,就意味着我们的飞镖需要向后射击,当然,这种情况是不允许存在的.忍者当然不能从后面射击,所以直接return就好了.
- 综合以上几点,我们就可以将飞镖添加到场景里面了
- 通过normalized()方法.我们将偏移转化成单位向量,这样的话,不管我们的飞镖移动的距离多远,方向都是一致的,因为(1*length = length) ; 数学向量知识,不懂百度)
- 最后,创建moveTo(_:,duration:)和removeFromParent()方法;
运行之后看到的效果如下