Swift - 跳跃吃苹果游戏开发(SpriteKit游戏开发)
(本文代码已升级至Swift3)
1,样例说明
(1)屏幕从右到左不断地生成苹果飞过来(苹果高度随机)
(2)点击屏幕可以让熊猫跳跃
(3)熊猫碰到苹果,苹果消失
2,运行效果
3,样例代码
苹果工厂类 AppleFactory.swift
import SpriteKit class AppleFactory:SKNode{ //定义苹果纹理 let appleTexture = SKTexture(imageNamed: "apple") //游戏场景的宽度 var sceneWidth :CGFloat = 0.0 //定义苹果数组 var arrApple = [SKSpriteNode]() //定时器 var timer = Timer() func onInit(_ width:CGFloat) { self.sceneWidth = width //启动的定时器 timer = Timer.scheduledTimer( timeInterval: 0.2, target: self, selector: #selector(AppleFactory.createApple), userInfo: nil, repeats: true) } //创建苹果类 func createApple(){ //通过随机数来随机生成苹果 //算法是,随机生成0-9的数,当随机数大于8的时候声称苹果 //也就是说,有1/10的几率生成苹果 //这样游戏场景中的苹果就不会整整齐齐以相同间隔出现了 let random = arc4random() % 10 if random > 8 { //生成苹果 let apple = SKSpriteNode(texture: appleTexture) //设置物理体 apple.physicsBody = SKPhysicsBody(rectangleOf: apple.size) //弹性设为0 apple.physicsBody?.restitution = 0 //物理体标识 apple.physicsBody?.categoryBitMask = BitMaskType.apple //不受物理效果影响 apple.physicsBody?.isDynamic = false //设置中心点 apple.anchorPoint = CGPoint(x: 0, y: 0) //z轴深度 apple.zPosition = 40 //设定位置 let theY = CGFloat(arc4random()%200 + 200) apple.position = CGPoint(x: sceneWidth+apple.frame.width , y: theY) //加入数组 arrApple.append(apple) //加入场景 self.addChild(apple) } } //苹果移动方法 func move(_ speed:CGFloat){ for apple in arrApple { apple.position.x -= speed } //移出屏幕外时移除苹果 if arrApple.count > 0 && arrApple[0].position.x < -20{ arrApple[0].removeFromParent() arrApple.remove(at: 0) } } //重置方法 func reSet(){ //移除所有子对象 self.removeAllChildren() //清空苹果数组 arrApple.removeAll(keepingCapacity: false) } }
熊猫类 Panda.swift
import SpriteKit class Panda: SKSpriteNode { //定义纹理 let pandaTexture = SKTexture(imageNamed: "panda") init() { //执行父类的构造方法 super.init(texture:pandaTexture,color:SKColor.white,size:pandaTexture.size()) //设置中心点 self.anchorPoint = CGPoint(x: 0, y: 0) self.physicsBody = SKPhysicsBody(rectangleOf:pandaTexture.size()) self.physicsBody?.isDynamic = true self.physicsBody?.allowsRotation = false //弹性 self.physicsBody?.restitution = 0 self.physicsBody?.categoryBitMask = BitMaskType.panda self.physicsBody?.contactTestBitMask = BitMaskType.scene|BitMaskType.apple self.physicsBody?.collisionBitMask = BitMaskType.scene } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } //跳 func jump (){ //施加一个向上的力,让小人跳起来 self.physicsBody?.velocity = CGVector(dx: 0, dy: 700) } }
碰撞标识类 - BitMaskType.swift
class BitMaskType { class var panda:UInt32{ return 1<<0 } class var apple:UInt32{ return 1<<1 } class var scene:UInt32{ return 1<<2 } }
主场景 - GameScene.swift
import SpriteKit class GameScene: SKScene,SKPhysicsContactDelegate { lazy var appleFactory = AppleFactory() lazy var panda = Panda() //移动速度 var moveSpeed:CGFloat = 15 //吃到的苹果数 var appleNum = 0 override func didMove(to view: SKView) { //物理世界代理 self.physicsWorld.contactDelegate = self //重力设置 self.physicsWorld.gravity = CGVector(dx: 0, dy: -5) //设置物理体 self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame) //设置种类标示 self.physicsBody?.categoryBitMask = BitMaskType.scene //是否响应物理效果 self.physicsBody?.isDynamic = false //场景的背景颜色 let skyColor = SKColor(red:113/255,green:197/255,blue:207/255,alpha:1) self.backgroundColor = skyColor //给小人定一个初始位置 panda.position = CGPoint(x: 200, y: 400) //将小人显示在场景中 self.addChild(panda) //苹果工厂 appleFactory.onInit(self.frame.width) self.addChild( appleFactory ) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { panda.jump() } override func update(_ currentTime: TimeInterval) { appleFactory.move(moveSpeed) } //碰撞检测方法 func didBegin(_ contact: SKPhysicsContact) { //熊猫和苹果碰撞 if (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (BitMaskType.apple | BitMaskType.panda){ //苹果计数加1 self.appleNum += 1 //如果碰撞体A是苹果,隐藏碰撞体A,反之隐藏碰撞体B //(因为苹果出了屏幕都会被移除,所以这里隐藏就可以了) if contact.bodyA.categoryBitMask == BitMaskType.apple { contact.bodyA.node?.isHidden = true }else{ contact.bodyB.node?.isHidden = true } } } }
源码下载:EatApple.zip
碰撞标识类为什么要设为UInt32?而且左位移运算新手也不好理解~~
游戏场景的宽度不是狂赌~~
假如程序开始开始生成100个苹果,然后点击屏幕将100个移除。。。 请问怎么才能移除干净,释放内存。