Swift SpriteKit写一个简单的打飞碟小游戏(一)

时间:2024-04-09 20:02:01

 公司要凉凉,百无聊赖之际,码一个小游戏聊以慰藉。看效果:

Swift SpriteKit写一个简单的打飞碟小游戏(一)

这里用的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属性,控制着每个控件的图层,开始没设置这个属性,导致飞碟一会儿有一会儿无,原来是藏在了背景图的下面,

Swift SpriteKit写一个简单的打飞碟小游戏(一)从文档可以看出值越大显示的效果就离观看者越近,zPosition默认值是0.0,也就是大家平级,一旦设置了大小,控件也就有了高低之分。运行看效果:

Swift SpriteKit写一个简单的打飞碟小游戏(一)

第二步,让它们动起来

首先处理背景图,背景图动起来就是让三张图片循环滚动,不断改变图片在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")
    }

看下效果如何:

Swift SpriteKit写一个简单的打飞碟小游戏(一)

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()
    }

手指到哪,飞机就自动飞到下方:

Swift SpriteKit写一个简单的打飞碟小游戏(一)

飞碟移动道理也是一样的,让飞碟往下落,在addBarriers()方法中添加下面的代码:

    //意思是在8.0秒内从当前位置移动到y=0的位置,就是最底部
    barrier.run(SKAction.moveTo(y: 0, duration: 8.0)) {
            barrier.removeAllActions()
            barrier.removeFromParent()
        }

Swift SpriteKit写一个简单的打飞碟小游戏(一)

额.....忘记添加热狗子弹了。先理一下子弹发射的流程: 创建--发射--消失--创建--发射--消失......这么一个循环的过程,所以先来完成循环中的完整事件:

    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一样,不然后面俩家伙碰不到。

Swift SpriteKit写一个简单的打飞碟小游戏(一)

 

源码下载:https://github.com/caimengnan/OpenFire.git