WatchKit开发的博客

同步新浪微博:@WatchKit开发

[WatchKit开发]用帧动画做AppleWatch小游戏

     WatchKit已经发布了2天,先行者们已经进行了探索并发表了总览性的文章去帮助引导开发者。然而这一般本的WatchKit明确的显示了:1.AppleWatch设备不负责计算功能,而仅负责图像渲染;2.不支持iOS的传统CoreAnimation等动画形式。这两点对于希望在AppleWatch上开发小游戏的开发者几乎是断了其念头。但是对于我这个新入行的人来说,必须有坚持的精神(没钱又任性)才能更快速的前进,因此尝试了用已有手段去实现一个超mini小游戏。

      对WatchKit已经有所了解的话,会明白上述两个麻烦是可以解决的。对第一个问题,可以借助WatchKit Extension在iPhone上运算然后传输结果给Watch,但是这会造成延时。对于第二个问题,Apple提供的第一个CodeSample使用了帧动画,但这可能造成存储空间的浪费。但也许这些副作用对于小如AppleWatch的设备体验来说也是可以接受的,那么我们还是开始实践吧!

     我计划做一个这样的小游戏:屏幕左边是玩家,屏幕右边会出现怪物并往左移动,而我们要做的就是点击屏幕下方按钮控制玩家进行上下移动的切换来实现躲避怪物。

     首先建立一个testGame项目,并添加一个WatchApp的target
下一步的时候我们先选择Swift语言,生成了可以开发WatchKit的工程。

然后展开testGameWatchApp可以找到Inteface.storyboard


    大神们昨天的文章已经提到现在用代码是不能创建界面元素的。那么我们就在Inteface.storyboard里先拖几个图像上去试试,先拖了1个Image到MainInterfaceControllerScene上然后设定尺寸为背景大小作为背景图,然后我们再拖第2个Image叠上去想作为玩家,结果却自动变成了这样:


哎呀呀原来现在的Layout都是自动的,设置不了位置了啊- -!此路不通!

好吧,看了一下能用的UI对象,新的Group元素是可以设置背景图而且可以嵌套的,就像我们用Html做排版那样!

我们将图片帧的资源文件做好放到testGameWatchApp下,player0.png代表玩家在上方,player1.png代表玩家在下方;monster00.png~monster04.png代表怪物在上方的动作序列帧,monster10.png~monster14.png代表怪物在上方的动作序列帧。



我们再拖了1个Group做背景,2个Group嵌入其中分别代表玩家和怪物。背景Group的设置简化如下:


玩家的Group:


接下来是怪物的:


大家现在应该可以明白,我的思路就是每个Group代表不同的对象运动范围,通过小图片元素配透明底图,切换图片序列实现在不同位置的移动效果。

好了再加一个button,目前只有button等几个元素可以实现点击事件的处理。


除了背景图,在InterfaceController里全部建立IBOutlet。

   @IBOutletweakvar player: WKInterfaceGroup!

    @IBOutletweakvar monster: WKInterfaceGroup!

    @IBOutletweakvar btn: WKInterfaceButton!

添加控制变量的声明

    var pos:UInt32!=0//0表示玩家在上 1表示在下

    var i:UInt8=0//怪物的当前帧序列号

    var rand:UInt32!=arc4random() % 2//怪物出来的位置-0表示上 1表示在下

    let max:UInt8=4//撞到玩家的位置(常量)

然后写初始化函数里的代码,我们需要做一个定时器,每0.2秒通过执行自定义的update()函数更新怪物的位置并执行相关检测

    override init(context: AnyObject?) {

        super.init(context: context)

        var timer=NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: "update", userInfo: nil, repeats: true)

    }

update函数的代码

func update(){

 //检测位置

        ifi==max {

            ifpos==rand {

                NSLog("You die!")

            }

        }

        //更新怪物图像

        monster.setBackgroundImageNamed("monster\(rand)\(i).png")

        i++

        

        //未撞上,重置

        ifi>max {

            i=0

            rand=arc4random() % 2

        }

    }

将dodge按钮的SendAction拖到Controller里命名为dodge

@IBActionfunc dodge() {

        ifpos==0 {

         pos=1

        } else {

         pos=0   

        }

        //改变玩家的位置图像

        player.setBackgroundImageNamed("player\(pos).png")

    }

好了,现在运行!效果已出来,按dodge按钮可以上下移动躲避怪物,撞到后会在控制台打印“You died!”


模拟器上实测,按钮按下后动画效果有近1秒的延迟,这是因为图片是从iPhone传过来的。我们可以添加图片缓存来加速

我们先测试缓存玩家的2张图片,将图片的target membership设置一下:


然后在init函数里补充代码,

    let img0:UIImage=UIImage(named: "player0.png")!

    WKInterfaceDevice.currentDevice().addCachedImage(img0, name: "player0")

    let img1:UIImage=UIImage(named: "player1.png")!

    WKInterfaceDevice.currentDevice().addCachedImage(img1, name: "player1")

修改玩家的图像加载代码,再次运行,响应延迟降低为半秒。怪物图片的缓存这里就略过了。

我们再补充玩家死亡事件,添加新的interfacecontroller,并设置identifier



修改NSLog("You die!"为:

 //NSLog("You die!")

   self.presentControllerWithName("over", context:nil)

基本思路就介绍到这里,证明AppleWatch目前也是可以做点超简单小游戏的。若要做出更精美的效果,应该需要用到更多绘制图像的API,以后有机会再细述吧。