这篇文章的游戏使用SpriteKit和Swift语言来完成。
SpriteKit是苹果自己的游戏引擎,更能贴合iOS系统底层的API,不过架构和实现上都是模仿了Cocos2D。所以使用上其实差别不大,不过SpriteKit更轻量级一些。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
var skView : SKView = self.view as SKView
if !skView.scene {
//DEBUG
skView.showsFPS = true
skView.showsNodeCount = true
var scene : SKScene = GameScene.sceneWithSize(skView.bounds.size)
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}func setupMedia() {
var error : NSError?
let backgroundMusicURL : NSURL = NSBundle.mainBundle().URLForResource(BG_MUSIC_NAME, withExtension: "caf")
backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: backgroundMusicURL , error: &error)
if error {
println("load background music error : \(error)")
} else {
backgroundMusicPlayer!.numberOfLoops = -1
backgroundMusicPlayer!.prepareToPlay()
backgroundMusicPlayer!.play()
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupMedia()
}class GameOverScene : SKScene {
convenience init(size: CGSize, won: Bool) {
self.init(size: size)
self.backgroundColor = SKColor(red:1.0, green:1.0, blue:1.0, alpha:1.0)
self.setupMsgLabel(isWon :won)
self.directorAction()
}
func setupMsgLabel(isWon won: Bool) {
var msg: String = won ? "Yow Won!" : "You Lose :["
var msgLabel = SKLabelNode(fontNamed: "Chalkduster")
msgLabel.text = msg
msgLabel.fontSize = 40
msgLabel.fontColor = SKColor.blackColor()
msgLabel.position = CGPointMake(self.size.width/2, self.size.height/2)
self.addChild(msgLabel)
}
func directorAction() {
var actions: AnyObject[] = [ SKAction.waitForDuration(3.0), SKAction.runBlock({
var reveal = SKTransition.flipHorizontalWithDuration(0.5)
var gameScene = GameScene(size: self.size)
self.view.presentScene(gameScene, transition: reveal)
}) ]
var sequence = SKAction.sequence(actions)
self.runAction(sequence)
}
} var player: SKSpriteNode! //英雄精灵
var lastSpawnTimeInterval: NSTimeInterval! //记录上次时间和更新时间
var lastUpdateTimeInterval: NSTimeInterval!
var monstersDestroyed: Int! //记录被消灭的怪兽数量 init(size: CGSize) {
super.init(size: size)
self.backgroundColor = SKColor(red: 1.0, green:1.0, blue:1.0, alpha:1.0)
player = SKSpriteNode(imageNamed: "player")
player.position = CGPointMake(self.player.size.width/2, self.frame.size.height/2)
self.addChild(player)
monstersDestroyed = 0
lastSpawnTimeInterval = 0
lastUpdateTimeInterval = 0
gameLevel.nextLevel()
//physics
self.physicsWorld.gravity = CGVectorMake(0, 0)
self.physicsWorld.contactDelegate = self
}func addMonster() {
var monster = SKSpriteNode(imageNamed: "monster")
//location
var minY = monster.size.height/2
var maxY = self.frame.size.height - monster.size.height/2
var rangeY = maxY - minY
var actualY = arc4random() % rangeY + minY
monster.position = CGPointMake(self.frame.size.width + monster.size.width/2, actualY)
self.addChild(monster)
//physics
monster.physicsBody = SKPhysicsBody(rectangleOfSize: monster.size)
monster.physicsBody.dynamic = true
monster.physicsBody.categoryBitMask = monsterCategory
monster.physicsBody.contactTestBitMask = projectileCategory
monster.physicsBody.collisionBitMask = 0
//speed
var minDuration = 2.0
var maxDuration = 4.0
var rangeDuration = maxDuration - minDuration
var actualDuration = arc4random() % rangeDuration + minDuration
var actionMove = SKAction.moveTo(CGPointMake(-monster.size.width/2, actualY), duration: actualDuration)
var actionMoveDone = SKAction.removeFromParent()
var loseAction = SKAction.runBlock({
var reveal = SKTransition.flipHorizontalWithDuration(0.5)
var gameOverScene = GameOverScene(size: self.size, won: false)
self.view.presentScene(gameOverScene, transition: reveal)
})
monster.runAction(SKAction.sequence([actionMove, loseAction, actionMoveDone]))
}
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
// get touch
var touch = touches.anyObject() as UITouch
var location = touch.locationInNode(self)
//bullet action
self.addProjectile(location: location)
}
func addProjectile(#location: CGPoint) {
var projectile = SKSpriteNode(imageNamed:"projectile")
projectile.position = player.position
//physics
projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody.dynamic = true
projectile.physicsBody.categoryBitMask = projectileCategory
projectile.physicsBody.contactTestBitMask = monsterCategory
projectile.physicsBody.collisionBitMask = 0
projectile.physicsBody.usesPreciseCollisionDetection = true
var offset = niSub(location, projectile.position)
if offset.x < 0 {return}
self.addChild(projectile)
// direct unit vector
var direction = niNormalize(offset)
//to screen's edge
var shootAmount = niMult(direction, 1000)
//now loc
var realDest = niAdd(shootAmount, projectile.position)
//action
var velocity = 480.0/1.0
var realMoveDuration = Double(self.size.width) / velocity
var actionMove = SKAction.moveTo(realDest, duration: realMoveDuration)
var actionMoveDone = SKAction.removeFromParent()
var sequence = SKAction.sequence([actionMove, actionMoveDone])
projectile.runAction(sequence)
self.runAction(SKAction.playSoundFileNamed("pew-pew-lei.caf", waitForCompletion: false))
}// overload
@infix func %(lhs: UInt32, rhs: Float) -> Float {
return Float(lhs) % Float(rhs)
}
@infix func %(lhs: UInt32, rhs: Double) -> Double {
return Double(lhs) % Double(rhs)
}
let niAdd = {(a: CGPoint, b: CGPoint) -> CGPoint in CGPointMake(a.x + b.x, a.y + b.y)}
let niSub = {(a: CGPoint, b: CGPoint) -> CGPoint in CGPointMake(a.x - b.x, a.y - b.y)}
let niMult = {(a: CGPoint, b: Float) -> CGPoint in CGPointMake(a.x * b, a.y * b)}
let niLength = {(a: CGPoint) -> CGFloat in CGFloat(sqrt(Double(a.x * a.x + a.y * a.y)))}// unit vector
let niNormalize = {(a : CGPoint) -> CGPoint in
var length = niLength(a)
return CGPointMake(a.x / length, a.y / length)
}
override func update(currentTime: NSTimeInterval) {
var timeSinceLast: CFTimeInterval = currentTime - lastSpawnTimeInterval
lastUpdateTimeInterval = currentTime
if timeSinceLast > 1 {
timeSinceLast = Double(gameLevel.toRaw()) / 60.0
lastUpdateTimeInterval = currentTime
}
self.updateWithTimeSinceLastUpdate(timeSinceLast: timeSinceLast)
}
func updateWithTimeSinceLastUpdate(#timeSinceLast: CFTimeInterval) {
lastSpawnTimeInterval = lastSpawnTimeInterval + timeSinceLast
if lastSpawnTimeInterval > 1 {
lastSpawnTimeInterval = 0
self.addMonster()
}
} func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody!
var secondBody: SKPhysicsBody!
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask & projectileCategory) != 0 && (secondBody.categoryBitMask & monsterCategory) != 0 {
self.didCollide(projectile: firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode)
}
} func didCollide(#projectile: SKSpriteNode, monster: SKSpriteNode) {
projectile.removeFromParent()
monster.removeFromParent()
monstersDestroyed = monstersDestroyed + 1
if monstersDestroyed > 30 {
var reveal = SKTransition.flipHorizontalWithDuration(0.5)
var gameOverScene = GameOverScene(size: self.size, won: true)
self.view.presentScene(gameOverScene, transition: reveal)
}
}使用Swift和SpriteKit写一个忍者游戏,布布扣,bubuko.com
原文地址:http://blog.csdn.net/cocoarannie/article/details/37371081