让我们快速开始吧
在实现触摸处理之前,我们先来创建一个基本的Sprite Kit工程,并在scene中显示出一些sprite(动物)和背景。
至于怎么创建工程这里就不再重复讲述了,如确实有问题建议回到
SpriteKit快速入门。
将工程命名为DragDrop
,devices
选择iPhone
,跟
SpriteKit快速入门
一样,我们希望这个程序只支持横屏显示(landscape)。所以在Project Navigator
中选中DragDrop
工程,
然后选择DragDrop target
,在弹出的画面中,只需要勾选上Landscape Left
和Landscape Right
。
在SpriteKit快速入门
我们通过修改-viewDidLoad:
为-viewDidAppear:
来解决屏幕尺寸问题,现在我们采用另一种方法,将-viewDidLoad:
修改为-viewDidLayoutSubviews
。
接着来这里下载本文需要用到的图片资源。下载并解压之后,将所有的文件拖到工程中,
其中把Copy items into destination group’s folder (if needed)
勾选上,然后单击Finish。
突然发现好像一只没有强调这个操作,特意附上一截图。
现在让我们开始coding吧,首先在MyScene.h
添加两个声明:
后面会用到上面属性存放背景图片和当前被选中的精灵,还有不要忘记那个静态全局变量,后面会用来用作点击标记的。
现在我们开始修改-initWithSize:
的代码:
加载背景图片,并将该node的anchor设置为图片的左下角(0, 0),在SpriteKit中设置node的位置,实际上是设置它的anchor,
默认情况下,node的anchor被设置为node的正中间。
加载小动物,为了好的布局,其中各个node根据屏幕的长度来定位,另外还将这些node的名字设置为kAnimalNodeName。
最后将创建好的node加载到_background
中。
编译运行,可以看见可爱的小动物已经显示在屏幕上了。
触摸的方式选中Sprite
先修改-touchesBegan:
,然后添加-selectNodeForTouch
、degToRad
。
通过scene(self)获得touchLocation位置对应的node。
获取匹配的node后,检查与上次的node是否相同,如果相同的话,在这里直接就返回了。如果是一个新的node或一个未被选中的node,则
出现抖动动画。不过动画启动前需要移除当前已经选中node上的所有running actions,并在这个node上运行一个action,这样做是为了确保
当前只有一个node在做动画,其他node恢复到原样。
判断选中的node知否可以进行动画,如果选中的node可以做动画处理,那么就创建一个sequence action。
触摸的方式移动Sprite和Layer
开始coding前,我们先整理一下思路,通过-touchesBegan:
获取选中node的坐标,-touchesMoved:
获取移动后的坐标,从中计算出
移动的距离,如果选中的动物,则动物移动相应的距离,如果没选中动物,则移动整个Layer。
跟-touchesBegan:withEvent:
一样,先获得touch,然后将它的位置转换为scene中的相应位置。为了计算出移动的距离,需要上一次触摸的位置。
通过当前位置减去上一次的位置就可以计算出需要移动的距离了。最后调用-panForTransaltion:
方法,并将移动距离传入即可。
-boundLayerPos:
,为了保证layer不会移动到背景图外面,在这里传入一个需要移动到的位置,然后该方法会对位置做适当的判断处理,
以确保不会移动太远。
-panForTranslation:
,首先判断_selectNode
是否为动物,如果是,则根据传入的值将node移动到新的位置,若是background layer,
则调用-boundLayerPos:
将它移动到新的位置。
编译运行,大功告成,小动物和背景都可以移动。
SpriteKit使用手势
你可能会问,SpriteKit是否支持手势?答案是肯定的。SpriteKit肯定支持手势。
通过手势识别,我们可以不用写大量的代码来识别不同的手势(如tap,double tap,swipe或pan),
只需要创建一个手势识别对象并将其添加到view中,即可进行手势识别。当有手势发生,会有一个回调。
下面就来看看如何在Sprite Kit中使用手势识别。
首先我们需要注释触摸处理方法:-touchesBegan:withEvent:
和-touchesMoved:withEvent:
。
当scene第一次显示出来时会调用这个方法。在上面的方法中创建了一个pan手势识别器,并用当前的scene来对其做初始化,
另外还传入一个callback:-handlePanFrom:
。接着把这个手势识别器添加到scene中的view里面。
注意:
可能你会问为什么要在这里添加识别器,而不是在scene的init方法中。SKScene
有一个view属性,保存着SKView
该view用来显示scene,不过只有scene显示到屏幕中时这个属性才会被初始化,所以在init方法被调用时该属性是nil。
此处的-didMoveToView:
类似于UIKit中的-viewDidAppear:
,当scene显示出来时,-didMoveToView:
会被调用。
接着,将下面的代码添加到MyScene.m
添加如下代码:
当手势开始、改变(例如用户持续drag),以及结束时,上面这个callback函数都会被调用。该方法会进入不同的case,以处理不同的情况。
当手势开始时,将坐标转变为node坐标系(不要奢望有更便捷的方法),然后就进行node点击判断。
当手势改变时,需要计算出手势的移动量,注意的是平移(pan)之后,将移动设置为0,否则移动量会继续更加。
当手势结束时,UIPanGestureRecognizer可以为我们提供一个移动的速度,这样看起来有一个摇动的效果。
所以,在这里包含的代码用来计算基于速度移动的一个point,然后运行一个moveTo action。
OK!编译运行,现在可以通过手势移动精灵了。
代码下载