公司要凉凉,百无聊赖之际,码一个小游戏聊以慰藉。看效果:
这里用的iOS7 才出的一个框架SpriteKit,主要用于纹理渲染、添加特效和物理引擎等。
思路及步骤:
1、添加背景图、发射器、子弹和飞碟
2、让它们动起来
3、添加物理效果
4、添加爆炸效果
第一步很简单,找三张宇宙图、一张思聪热狗图、一张飞碟图在Sketch里面切一下就ok了。具体代码写在GameScene里面:
import SpriteKit import GameplayKit class GameScene: SKScene { //发射器 let shipNode: SKSpriteNode = SKSpriteNode(imageNamed: "sicongwang") //添加三个地面变量 var floor1 = SKSpriteNode(imageNamed: "universal_01") var floor2 = SKSpriteNode(imageNamed: "universal_02") var floor3 = SKSpriteNode(imageNamed: "universal_03") var floors:NSMutableArray = NSMutableArray(capacity: 3) override func didMove(to view: SKView) { addPlane() setBackground() addBarriers() } //MARK:添加飞机 func addPlane() { //添加飞机 shipNode.position = CGPoint(x: self.frame.midX, y: 50) shipNode.anchorPoint = CGPoint(x: 0.5, y: 0.5) shipNode.zPosition = 1.0 self.addChild(shipNode) } //MARK:添加背景图 func setBackground() { floors.add(floor1) floors.add(floor2) floors.add(floor3) for i in 0..<floors.count { let floor:SKSpriteNode = floors[i] as! SKSpriteNode floor.position = CGPoint(x: 0, y: CGFloat(i) * self.frame.height) floor.anchorPoint = CGPoint.zero floor.size = self.frame.size } self.addChild(floor1) self.addChild(floor2) self.addChild(floor3) } //MARK:添加飞碟 func addBarriers() { let barrier = SKSpriteNode(imageNamed: "UFO") barrier.name = "barrier" barrier.position = CGPoint(x: self.frame.midX, y: self.frame.size.height - 80) barrier.zPosition = 1.0 self.addChild(barrier) } override func update(_ currentTime: TimeInterval) { // Called before each frame is rendered } }
注意position和anchorPoint的使用,位置坐标系跟平时的iOS 开发有些不一样,还有一个就是zPosition属性,控制着每个控件的图层,开始没设置这个属性,导致飞碟一会儿有一会儿无,原来是藏在了背景图的下面,
从文档可以看出值越大显示的效果就离观看者越近,zPosition默认值是0.0,也就是大家平级,一旦设置了大小,控件也就有了高低之分。运行看效果:
第二步,让它们动起来
首先处理背景图,背景图动起来就是让三张图片循环滚动,不断改变图片在y方向的值,如果图片出了屏幕下方,重新给它找个地方安置。
//MARK:向下滚动1单位 func moveScene() { //floor move floor1.position = CGPoint(x: 0, y: floor1.position.y - 1) floor2.position = CGPoint(x: 0, y: floor2.position.y - 1) floor3.position = CGPoint(x: 0, y: floor3.position.y - 1) //check floor let height_pad = self.frame.size.height if floor1.position.y < -height_pad { floor1.position.y = floor3.position.y + height_pad } if floor2.position.y < -height_pad { floor2.position.y = floor1.position.y + height_pad } if floor3.position.y < -height_pad { floor3.position.y = floor2.position.y + height_pad } }
写一个定时的事件,让它们有滚动的动力:
//MARK:背景滚动,每0.02秒向下滚动1单位 func move() { let moveAct = SKAction.wait(forDuration: 0.02) let generateAct = SKAction.run { self.moveScene() } run(SKAction.repeatForever(SKAction.sequence([moveAct,generateAct])), withKey: "move") }
看下效果如何:
gif展示的有卡顿,模拟器运行起来还是挺顺畅的。
接下来就是飞机动起来啦,运动方式有两种,一种是手指划到哪飞机就飞哪;另一种是飞机一直在底部飞,但是根据手指划动位置的x值来调整自己左右飞行。这里我用的后面这种方法。
//MARK:飞机操作---开始触摸 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { //获取当前点击点的坐标 let touches = touches as NSSet let touch = touches.anyObject() as AnyObject let locationPoint = touch.location(in:self) //将飞机移动到点击点,为了让移动速度保持一个相对稳定的值,规定飞机从中间飞到边上的时间为duration = 0.5秒,其余距离以此为参考来计算时间 //创建移动事件 let newDuration = Double(abs(shipNode.position.x - locationPoint.x)/self.frame.midX) * duration let targetPoint = CGPoint(x: locationPoint.x, y: shipNode.position.y) let shipMove = SKAction.move(to: targetPoint, duration: newDuration) shipNode.run(shipMove) } //MARK:飞机操作---结束触摸 override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { shipNode.removeAllActions() }
手指到哪,飞机就自动飞到下方:
飞碟移动道理也是一样的,让飞碟往下落,在addBarriers()方法中添加下面的代码:
//意思是在8.0秒内从当前位置移动到y=0的位置,就是最底部 barrier.run(SKAction.moveTo(y: 0, duration: 8.0)) { barrier.removeAllActions() barrier.removeFromParent() }
额.....忘记添加热狗子弹了。先理一下子弹发射的流程: 创建--发射--消失--创建--发射--消失......这么一个循环的过程,所以先来完成循环中的完整事件:
func createBullet() { //创建子弹 let bullet = SKSpriteNode(imageNamed: "hotdog") bullet.position = self.shipNode.position bullet.name = "bullet" bullet.zPosition = 1.0 self.addChild(bullet) //发射子弹 let fireAction = SKAction.move(to: CGPoint(x: self.shipNode.position.x, y: self.frame.size.height), duration: 1.5) //子弹离开屏幕消失 let endAction = SKAction.run { bullet.removeFromParent() } //动作组合 let fireSequence = SKAction.sequence([fireAction,endAction]) bullet.run(fireSequence) }
每隔多少秒发射一颗子弹,来一个循环事件:
func shootBullet() { //每隔0.7秒发射一次 let waitAction = SKAction.wait(forDuration: 0.7) //创建一个子弹 let createBulletAction = SKAction.run { self.createBullet() } run(SKAction.repeatForever(SKAction.sequence([createBulletAction,waitAction]))) }
注意子弹的zPosition的值要跟飞碟的zPosition一样,不然后面俩家伙碰不到。