首先我们需要将在游戏中创建一个初始化方法initGame,我们将原来在didMove方法中的部分代码移至该方法中:
func initGame(){
if gameTimer != nil{
gameTimer.invalidate()
gameTimer = nil
}
gameOver = false
enumerateChildNodes(withName: "enemy"){(enemy,_) in
enemy.removeFromParent()
}
player = SKSpriteNode(imageNamed: "player")
player.position = CGPoint(x: 100, y: frame.size.height/2.0)
player.physicsBody = SKPhysicsBody(texture: player.texture!, size:player.size)
player.physicsBody!.contactTestBitMask = 1
addChild(player)
score = 0
gameTimer = Timer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
}
那么原来的didMove方法就简化为:
override func didMove(to view: SKView) {
backgroundColor = .black
starfield = SKEmitterNode(fileNamed: "Starfield")!
starfield.position = CGPoint(x: frame.size.width, y: frame.size.height/2.0)
starfield.advanceSimulationTime(10)
addChild(starfield)
starfield.zPosition = -1
scoreLabel = SKLabelNode(fontNamed: "Chalkduster")
scoreLabel.position = CGPoint(x: 16, y: 16)
scoreLabel.horizontalAlignmentMode = .left
addChild(scoreLabel)
physicsWorld.gravity = CGVector(dx: 0, dy: 0)
physicsWorld.contactDelegate = self
initGame()
}
我们希望按钮外围有一个边框,这样看起来更像一个按钮,所以总共需要两个SKNode来模拟:一个label加一个shapeNode:
var restart:SKLabelNode!
var border:SKShapeNode!
在刚才的didMove方法中加入初始化restart和border的代码:
restart = SKLabelNode(fontNamed: "Chalkduster")
restart.text = "Restart"
restart.position = CGPoint(x: frame.size.width - 16 - restart.frame.size.width, y: 16)
restart.horizontalAlignmentMode = .right
addChild(restart)
restart.fontColor = .red
border = SKShapeNode(rect: restart.frame + CGFloat(5), cornerRadius: 10.0)
border.lineWidth = 5.0
border.strokeColor = .yellow
addChild(border)
为了更好地处理按钮外部的边框的大小及位置,我特地写了一个+操作符,来根据现有label的frame返回一个包裹边框的CGRect:
func +(left:CGRect,right:CGFloat)->CGRect{
return CGRect(x: left.origin.x - right, y: left.origin.y - right, width: left.size.width + right, height: left.size.height + right)
}
现在运行App可以看到一个类似按钮的Node出现在屏幕右下角,但是我们触摸它的时候没有任何反应,因为我们还没有做出反馈哦 ;)
在touchesBegan方法中加入如下代码:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {return}
let location = touch.location(in: self)
if nodes(at: location).contains(restart){
//在这里我们等会尝试做一些动画效果...
if gameOver {
initGame()
}
}
}
我们可以看到,当玩家触摸restart按钮时,我们判断游戏是否已经结束,如果是的我们重新开始游戏,这就是之前创建initGame发放的意义啊!
现在运行App,在游戏结束时触摸restart按钮时,游戏重新开始了!所以restart按钮的功能已经实现了.但是…它只是看起来像一个按钮,但按下时完全没有视觉反馈,让人很无语,处女座的你们能忍吗(本猫不是处女座都不能忍啊!)
所以让我们利用SpriteKit提供的Action来完成这个视觉鸡肋吧 ;)
我们想要的效果是当玩家按下restart按钮,其边框会发生大小变化并向”下”发生稍许位移,同事border内部增加填充色.restart按钮本身也要有所表现啊!我们会改变文字颜色和文字大小.当然所有这些改变在一个很小的时间间隔后会恢复为原来的状态.
在上面的 “//在这里我们等会尝试做一些动画效果…” 注释位置添加如下代码:
border.fillColor = .red
let mov = SKAction.moveBy(x: -3, y: -3, duration: 0.1)
let scale = SKAction.scale(to: 1.02, duration: 0.1)
let grp = SKAction.group([mov,scale])
let act = SKAction.wait(forDuration: 0.1)
let blk = SKAction.run {[unowned self] in
self.border.fillColor = .clear
self.border.position = CGPoint(x:self.border.position.x + 3,y:self.border.position.y + 3)
self.border.setScale(1.0)
}
border.run(SKAction.sequence([grp,act,blk]))
restart.fontColor = .yellow
restart.fontSize -= 5
let btnBlk = SKAction.run {[unowned self] in
self.restart.fontColor = .red
self.restart.fontSize += 5
}
restart.run(SKAction.sequence([act,btnBlk]))
代码的含义上面已经解释过了,我们允许App来看一下实际的效果吧:
作者:mydo 发表于2017/4/26 19:36:58 原文链接
阅读:109 评论:0 查看评论