[原创]swift+spritekit中文教程第三篇
拖了好久的第三篇终于开始了…… 添加敌人为了简便起见,我们将用相同的飞机作为敌人,但是方向和主角飞机相反,从上往下飞(这里解释一下,因为之前使用yScale翻转,结果导致碰撞检测时出现了很诡异的bug,暂时无解,所以我用系统内置的预览工具,将spaceship这张图片进行了上下翻转,然后另存为一个资源,具体如下图。如果有人使用scale并解决问题,可以告知一声,不胜感激)。 var enemyTime:NSTimeInterval = 1 var lastEnemy:NSTimeInterval = 0 在此之前呢,我们先把update函数清理一下。将创建子弹的代码放置到单独的函数中,同时添加创建敌人的函数: func createBullet(){ let bullet = SKShapeNode(rectOfSize: CGSizeMake(10,10)) bullet.position = CGPointMake(plane.position.x,plane.position.y + 50) bullet.strokeColor = UIColor.clearColor() bullet.fillColor = UIColor.greenColor() addChild(bullet) bullet.runAction(SKAction.sequence([SKAction.moveByX(0,y: size.height,duration: 2),SKAction.removeFromParent()])) } func createEnemy(){ let enemy = SKSpriteNode(texture: enemyTexture) enemy.setScale(0.5) enemy.position = CGPointMake(plane.position.x,size.height) addChild(enemy) enemy.runAction(SKAction.sequence([SKAction.moveByX(0,y: -size.height,duration: 4),SKAction.removeFromParent()])) } update(){ //添加到update函数中 if currentTime >= lastBullet + bulletTime{ createBullet() lastBullet = currentTime } if currentTime >= lastEnemy + enemyTime{ createEnemy() lastEnemy = currentTime } } 简洁了很多吧~! 优化敌人首先,敌人出现的时间间隔随机一些: if currentTime >= lastEnemy + enemyTime{ createEnemy() lastEnemy = currentTime enemyTime = NSTimeInterval(arc4random() % 20 + 5) / 10 //一个神奇的经过反复测试得出的还不错的随机时间间隔 } 下一步就是将初始位置随机一些,在createEnemy函数中进行修改: func createEnemy(){ let enemy = SKSpriteNode(texture: enemyTexture) enemy.setScale(0.5) var randomX = CGFloat(arc4random()) % size.width enemy.position = CGPointMake(randomX,SKAction.removeFromParent()])) } 用随机数对宽度取模,即可轻松搞定~ 添加物理首先添加三个不明觉厉的后面会用到的东西 let PlayerCategory:UInt32 = 1<<1 let BulletCategory:UInt32 = 1<<2 let EnemyCategory:UInt32 = 1<<3 这个其实是碰撞标记,这篇博客里简单提到了,其实就是把需要互相碰撞的物体进行一个归类,设定和检测彼此的碰撞,并且发送碰撞消息。目前用到的标记有三个:我方飞机、子弹、敌方飞机。 先给子弹添加物理效果: bullet.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(10,10)) bullet.physicsBody?.categoryBitMask = BulletCategory bullet.physicsBody?.collisionBitMask = 0 bullet.physicsBody?.contactTestBitMask = EnemyCategory 分别是创建物理盒,所属标记,碰撞标记,碰撞通知标记。碰撞消息的产生不受碰撞标记设置的影响,碰撞标记只关系到是否模拟碰撞效果。物理盒大小我们可以自己设定,如果使用了纹理,也可以用纹理的size属性进行设置,就比如接下来的敌人物理盒创建。 enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemyTexture.size()) enemy.physicsBody?.categoryBitMask = EnemyCategory enemy.physicsBody?.collisionBitMask = 0 enemy.physicsBody?.contactTestBitMask = BulletCategory 这五行添加到addChild之前即可。 physicsWorld.contactDelegate = self physicsWorld.gravity = CGVectorMake(0,0) 表示碰撞检测代理为当前世界盒,并且重力为0,保证任何物体不会向下掉落。 func didBeginContact(contact: SKPhysicsContact) { if contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask == BulletCategory | EnemyCategory{ print("enemy die") contact.bodyA.node?.removeFromParent() contact.bodyB.node?.removeFromParent() } } 用来在碰撞发生时进行操作,首先进行判断,碰撞涉及的两个标记,是否是子弹和敌人标记。如果是,就杀死一个敌人,移除相关的子弹和击中的敌人。跑起来看看吧,已经比较完整了~ 全部代码如下: import SpriteKit let PlayerCategory:UInt32 = 1<<1 let BulletCategory:UInt32 = 1<<2 let EnemyCategory:UInt32 = 1<<3 class GameScene: SKScene,SKPhysicsContactDelegate { let planeTexture = SKTexture(imageNamed: "Spaceship") let enemyTexture = SKTexture(imageNamed: "Enemy") var plane:SKSpriteNode! var bulletTime:NSTimeInterval = 0.2//子弹发射间隔 var lastBullet:NSTimeInterval = 0//上次发射的时间点 var toucheGap = CGPoint(x: 0,y: 0) var enemyTime:NSTimeInterval = 1 var lastEnemy:NSTimeInterval = 0 override func didMoveToView(view: SKView) { /* Setup your scene here */ physicsWorld.contactDelegate = self physicsWorld.gravity = CGVectorMake(0,0) plane = SKSpriteNode(texture: planeTexture) plane.position = CGPointMake(size.width * 0.5,size.height * 0.5) plane.setScale(0.5) plane.name = "plane" addChild(plane) } override func touchesBegan(touches: Set<NSObject>,withEvent event: UIEvent) { /* Called when a touch begins */ let location:CGPoint! = (touches.first as! UITouch).locationInNode(self) toucheGap = CGPoint(x: location.x - plane.position.x,y: location.y - plane.position.y) } override func touchesMoved(touches: Set<NSObject>,withEvent event: UIEvent) { let location:CGPoint! = (touches.first as! UITouch).locationInNode(self) let xDir = clamp(location.x - toucheGap.x,min: 0,max: size.width) let yDir = clamp(location.y - toucheGap.y,max: size.height) plane.position = CGPoint(x: xDir,y: yDir) } override func touchesEnded(touches: Set<NSObject>,withEvent event: UIEvent) { } func didBeginContact(contact: SKPhysicsContact) { if contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask == BulletCategory | EnemyCategory{ print("enemy die") contact.bodyA.node?.removeFromParent() contact.bodyB.node?.removeFromParent() } } override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ if currentTime >= lastBullet + bulletTime{ createBullet() lastBullet = currentTime } if currentTime >= lastEnemy + enemyTime{ createEnemy() lastEnemy = currentTime enemyTime = NSTimeInterval(arc4random() % 20 + 5) / 10 } } func createBullet(){ let bullet = SKShapeNode(rectOfSize: CGSizeMake(10,10)) bullet.position = CGPointMake(plane.position.x,plane.position.y + 50) bullet.strokeColor = UIColor.clearColor() bullet.fillColor = UIColor.greenColor() bullet.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(10,10)) bullet.physicsBody?.categoryBitMask = BulletCategory bullet.physicsBody?.collisionBitMask = 0 bullet.physicsBody?.contactTestBitMask = EnemyCategory addChild(bullet) bullet.runAction(SKAction.sequence([SKAction.moveByX(0,SKAction.removeFromParent()])) } func createEnemy(){ let enemy = SKSpriteNode(texture: enemyTexture) enemy.setScale(0.5) var randomX = CGFloat(arc4random()) % size.width enemy.position = CGPointMake(randomX,size.height) enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size) enemy.physicsBody?.categoryBitMask = EnemyCategory enemy.physicsBody?.collisionBitMask = 0 enemy.physicsBody?.contactTestBitMask = BulletCategory addChild(enemy) enemy.runAction(SKAction.sequence([SKAction.moveByX(0,SKAction.removeFromParent()])) } func clamp(x: CGFloat,min: CGFloat,max: CGFloat) -> CGFloat{ if x <= min{ return min }else if x >= max{ return max }else{ return x } } } 下一篇 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- visual Studio之如何快速的进行注释
- AJAX调试技术 IE篇
- objective-c – 如何使用关闭按钮关闭UIActionSheet并避免崩
- sqlite关于The database disk image is malformed问题的解决
- flex中表格第一列固定
- 依赖注入 – 使用Roboguice 2.0b3和Robolectric尝试使用Rob
- XML文件导入、导出到 DataSet
- reactjs – 从地图返回的React对象传播(ES6)
- objective-c – 使用__attribute __((nonnull(2)))声明方法
- c# – 将float转换为二进制表示形式(使用MemoryStream?)