公司要凉凉,百无聊赖之际,码一个小游戏聊以慰藉。看效果:
这里用的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一样,不然后面俩家伙碰不到。