添加子弹
为了节省时间,这里用Shape代替。
在load中,创建一个shape精灵:
var 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()]))
序列中两个动作,一个是竖向位移场景高度那么长的距离,正值向上负值向下,保证子弹至少能打到屏幕以外才会消失,第二个动作则是将其从场景里移除,同时也就被销毁了。
再来一发!
只有一发不太爽!将子弹的所有逻辑,从load中搬移到update中,这样每帧都会执行……突突突好密集,吓尿了。
下面增加一个发射间隔。我们留意到update函数里有一个参数,会传递系统时间,这个怎么能利用一下呢?
定义两个类成员变量在isTouched属性下面:
var bulletTime:NSTimeInterval = 0.2//子弹发射间隔
var lastBullet:NSTimeInterval = 0//上次发射的时间点
然后在update中添加if条件
if(currentTime >= lastBullet + bulletTime){
//创建子弹....
lastBullet = currentTime
}
若当前时间大于上次发射时间+发射间隔,那么发射一次,然后更新上次发射时间为当前时间
so,跑一下吧,效果还不错~
改进操作
因为飞机比较小,在手机端很难安逸的点击到,改进办法是只要点击屏幕,飞机就会沿着你手指移动方向移动,下面我们实现这个功能。
首先在类变量里添加一个变量:var toucheGap = CGPoint(x: 0, y: 0)
,然后将touchesBegan/touchesMoved/touchesEnded修改为:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
let location:CGPoint! = touches.first?.locationInNode(self)
toucheGap = CGPoint(x: location.x - plane.position.x, y: location.y - plane.position.y)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location:CGPoint! = touches.first?.locationInNode(self)
plane.position = CGPoint(x: location.x - toucheGap.x, y: location.y - toucheGap.y)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
点击的时候,记录下手指和飞机的距离,然后手指移动的时候,将位移坐标等量应用到飞机的位移上。这下操作起来舒服多了!
限定边界
可是现在飞机能飞到屏幕外了,这个怎么破!
飞的时候限制一下边界就行啦~
首先我们写一个限定范围的函数,方便以后用。(之后可以开发你自己的math库)
func clamp(x: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat{
if x <= min{
return min
}else if x >= max{
return max
}else{
return x
}
}
之后我们在GameViewController中,将场景大小改为let scene = GameScene(size: CGSizeMake(750, 1334))
因为iPhone5和6、6+都是相同的分辨率比例,所以经过自适应后能完美适配这三种屏幕。
然后将touchesMoved作如下修改:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location:CGPoint! = touches.first?.locationInNode(self)
let xDir = clamp(location.x - toucheGap.x, min: 0, max: size.width)
let yDir = clamp(location.y - toucheGap.y, min: 0, max: size.height)
plane.position = CGPoint(x: xDir, y: yDir)
}
在每次设置飞机坐标的时候,预先判断是否超出了屏幕边界,如果超过边界,clamp函数会返回边界位置。现在把游戏运行起来,就发现飞机已经飞不出去了~
下面贴出GameScene类全部代码:
class GameScene: SKScene, SKPhysicsContactDelegate {
let planeTexture = SKTexture(imageNamed: "Spaceship")
var plane:SKSpriteNode!
var isTouched = false
var bulletTime:NSTimeInterval = 0.2//子弹发射间隔
var lastBullet:NSTimeInterval = 0//上次发射的时间点
var toucheGap = CGPoint(x: 0, y: 0)
override func didMoveToView(view: SKView) {
/* Setup your scene here */
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<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
let location:CGPoint! = touches.first?.locationInNode(self)
toucheGap = CGPoint(x: location.x - plane.position.x, y: location.y - plane.position.y)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location:CGPoint! = touches.first?.locationInNode(self)
let xDir = clamp(location.x - toucheGap.x, min: 0, max: size.width)
let yDir = clamp(location.y - toucheGap.y, min: 0, max: size.height)
plane.position = CGPoint(x: xDir, y: yDir)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
func didBeginContact(contact: SKPhysicsContact) {
}
func didEndContact(contact: SKPhysicsContact) {
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if currentTime >= lastBullet + bulletTime{
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()]))
lastBullet = currentTime
}
}
func clamp(x: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat{
if x <= min{
return min
}else if x >= max{
return max
}else{
return x
}
}
}