iOS傳感器:使用陀螺儀完成一個小球撞壁的小游戲

上一次借著實現(xiàn)一個隨屏幕旋轉(zhuǎn)的小玩意,了解了iPhone內(nèi)置的加速計。今天咱們繼續(xù)搞點好玩的東東。按照計劃這次要看看陀螺儀了。

最終咱們會完成一個小球撞壁的小游戲,一個超級賤的利用陀螺儀的APP。小球可以感受到重力,從而能夠隨著手機的運動來一起運動。為了增加一點點趣味性,對小球的運動范圍做了限制。當(dāng)小球碰到屏幕的邊緣的時候,會進行反彈,相反方向運動。咱們一起來看看實現(xiàn)后的實況錄像:

今天的代碼比起上次的加速計稍微多了一點點,所以就提供了源碼供大家批評。同時由于這部分Swfit和Objective-C略微有不太一樣的地方,所以源碼提供了兩版。

其實不管是加速計還是今天的陀螺儀,都是用到了上次說的iOS當(dāng)中的那個核心運動框架CoreMotion。

1. 陀螺儀介紹

陀螺儀主要是用來測量沿著某個特定的坐標(biāo)軸旋轉(zhuǎn)速度的。在使用中,陀螺儀始終指向一個固定的方向,當(dāng)運動物體的運動方向偏離預(yù)定方向時,陀螺儀就可以感受出來。

在手機上,僅用加速度計沒辦法測量或重構(gòu)出完整的3D動作,測不到轉(zhuǎn)動的動作的,加速計只能檢測軸向的線性動作。但陀螺儀則可以對轉(zhuǎn)動、偏轉(zhuǎn)的動作做很好的測量,這樣就可以精確分析判斷出使用者的實際動作。而后根據(jù)動作,可以對手機做相應(yīng)的操作。

1.1 陀螺儀的應(yīng)用場景

各位童鞋相比都玩過Wii,那個體感手柄肯定就用到了陀螺儀。玩家通過揮動運動手柄,來控制游戲。例如乒乓球、網(wǎng)球、賽車等等。有一些酷炫的APP會通過小幅度的傾斜,偏轉(zhuǎn)手機,實現(xiàn)彩蛋功能,例如放大縮小之類的。或者把手機屏幕翻轉(zhuǎn),就可以拒接電話或者靜音啥的。 拍照類的APP也會通過陀螺儀把拍照時候手的抖動反饋交給圖像處理器,以便抓到更清晰穩(wěn)定的圖片。

還有一些是最近剛剛看到的好賤好賤的APP。例如Send Me To Heaven,游戲的玩法超級簡單,只需向天空拋擲手機,扔得越高,分?jǐn)?shù)也就越高。

Throw Me App 另外一個賤不拉幾的APP。這是一個相機APP,使用時打開APP并將手機拋向空中,當(dāng)手機在空中時,使用陀螺儀和加速計探測手機是否達到了最高點,且攝像頭是否向下。隨后,該應(yīng)用將激活攝像頭快門進行拍照。

1.2 陀螺儀在iOS中的使用

iPhone、iPad、iWatch都有內(nèi)置的陀螺儀,也都可以讓開發(fā)者進行調(diào)用。同樣,用一張圖展現(xiàn)一下:

2. 陀螺儀的使用

2.1 使用步驟

陀螺儀同樣也是通過CoreMotion這個框架來管理的,所以和加速計一樣,四個標(biāo)準(zhǔn)步驟:

初始化CMMotionManager管理對象;

調(diào)用管理對象的對象方法獲取數(shù)據(jù);

處理數(shù)據(jù);

當(dāng)不需要使用的時候,停止獲取數(shù)據(jù)。

2.2 陀螺儀數(shù)據(jù)獲取的兩種方法

CoreMotion中有2種獲取數(shù)據(jù)方式,一種叫做PUSH的方式,一種叫做PULL的方式。顧名思義,PUSH就是被動的獲取。設(shè)定完了之后,線程定時把獲取到的數(shù)據(jù)推送回來。可想而知,對于資源的消耗是會稍微大一點的。 PULL,就是要去索取。拉一下才會獲取到數(shù)據(jù)。不要不給。上一次加速計咱們給出的代碼是OC的,今天咱們就用Swift的。

2.2.1 PULL的方式

privatefunc?useGyroPull()?{

//判斷陀螺儀可不可用

ifmanager.isGyroAvailable?{

//設(shè)置陀螺儀多久采樣一次

manager.gyroUpdateInterval?=0.1

//開始更新,后臺線程開始運行。這是Pull方式。

manager.startGyroUpdates()

}

//獲取并處理陀螺儀數(shù)據(jù)。這里我們就只是簡單的做了打印。

print("X?=?\(manager.gyroData?.rotationRate.x????0)","Y?=?\(manager.gyroData?.rotationRate.y????0)","Z?=?\(manager.gyroData?.rotationRate.z????0)")

}

2.2.2 PUSH的方式

privatefunc?useGyroPush()?{

//判斷陀螺儀可不可用

ifmanager.isGyroAvailable?{

//設(shè)置陀螺儀多久采樣一次

manager.gyroUpdateInterval?=0.1

//Push方式獲取和處理數(shù)據(jù),這里我們一樣只是做了簡單的打印。把采樣的工作放在了主線程中。?????????????????????manager.startGyroUpdates(to:?OperationQueue.main,?withHandler:?{?(gyroData,?error)?in

print("X?=?\(self.manager.gyroData?.rotationRate.x????0)","Y?=?\(self.manager.gyroData?.rotationRate.y????0)","Z?=?\(self.manager.gyroData?.rotationRate.z????0)")

})

}else{

print("陀螺儀不可用")

}

}

3. 開始我們的小游戲

3.1 思維導(dǎo)圖

3.2 實現(xiàn)

3.2.1 以X軸邊界值處理及碰壁后速度處理為例

//????????????對球在X軸碰壁進行處理

ifcurrentPoint.x?=?bounds.size.width?-?imageWidth?/2{

currentPoint.x?=?bounds.size.width?-?imageWidth?/2

ballXVelocity?=?-ballXVelocity?*0.8

}

3.2.2 開啟陀螺儀并更新

manager.deviceMotionUpdateInterval?=1/60

//注意一下,在Swift沒有了NSOperation。被OperationQueue取代了。

manager.startDeviceMotionUpdates(to:?OperationQueue.main)?{?(motion,?error)in

self.ballView!.accelleration?=?(motion?.gravity)!

//開啟主隊列異步線程,更新球的位置。

DispatchQueue.main.async?{

self.ballView!.updateLocation(multiplier:5000)

}

3.2.3 更新小球的位置

func?updateLocation(multiplier?:?Double)?{

if(lastUpdateTime?!=?nil)?{

let?updatePeriod?:?Double?=Date.init().timeIntervalSince(lastUpdateTime!)

ballXVelocity?=?ballXVelocity?+?accelleration.x?*?updatePeriod

ballYVelocity?=?ballYVelocity?+?accelleration.y?*?updatePeriod

let?coefficient?=?updatePeriod?*?multiplier

currentPoint?=?CGPoint(x:?currentPoint.x?+?(CGFloat)(ballXVelocity?*?coefficient),?y:?currentPoint.y?-?(CGFloat)(ballYVelocity?*?coefficient))

}

lastUpdateTime?=Date()

}

3.3 關(guān)于Swift中重寫set/get

其實寫到這里的時候才突然想起來,咱們從來沒有說過Swift怎么重寫Set/Get方法。而且貌似也沒有分享過iOS開發(fā)中多線程的東東。下個系列非典型技術(shù)宅就可以寫寫多線程相關(guān)的玩意兒吧,如果多線程這部分不太明白的話,對不住對不住對不住,馬上補上。

在swift中其實重寫set不太常見,但這都是OC留下來的臭毛病,就非要重新咋辦?請自行搜索,就不提供鏈接到*書了。

這個不是重點,咱們在寫小球的時候用到的是didSet這個方法。這是啥吶?這是swift當(dāng)中的觀察者,用來監(jiān)視屬性除了初始化之外的屬性變化。

didSet:在屬性值改變后觸發(fā),didSet可以帶一個oldName的參數(shù),表示舊的屬性,不帶的話默認(rèn)命名為oldValue。

willSet:在屬性值改變前觸發(fā),可以帶一個newName的參數(shù),沒有的話,該參數(shù)默認(rèn)命名為newValue。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容