今回は iOS で加速度センサーの値を取得する方法です。
Cocos Sharp でも CCAccelerometer で加速度センサーの値を取得できますが、
この方法だと、センサーの値が遅延して取得されるという不具合があるので、
ネイティブで取得したセンサーの値をグローバルで参照できるクラスに書込み、
その値を Cocos Sharp 側から参照する方法を採用しています。
センサーの値の取得方法は、プッシュ型とプル型の2種類あります。
・プッシュ型…センサーが値を通知してくれる。
・プル型…センサーの値を自分で取得しに行く。
今回はプッシュ型で値を取得します。
まず、センサーの値を書き込むクラス AccelerometerInfo を作成します。
CocosSharpGameSample.Core プロジェクトの CrossCuttingConcerns に AccelerometerInfo.cs を追加します。
namespace CocosSharpGameSample.Core { public sealed class AccelerometerInfo { private static readonly AccelerometerInfo defaultInstance = new AccelerometerInfo(); private double accelerationX = 0d; private double accelerationY = 0d; private double accelerationZ = 0d; private AccelerometerInfo() { } public static AccelerometerInfo Default { get { return defaultInstance; } } public double AccelerationX { get { return this.accelerationX; } set { this.accelerationX = value; } } public double AccelerationY { get { return this.accelerationY; } set { this.accelerationY = value; } } public double AccelerationZ { get { return this.accelerationZ; } set { this.accelerationZ = value; } } } }
CocosSharpGameSample.iOS プロジェクトの AppDelegate.cs のフィールドに、CMMotionManager を定義します。
また、センサーの値を書き込む際のロックキーを定義します。
// 加速度センサー private CMMotionManager cMMotionManager; // ロックキー private object accelerometerSyncLock = new object();
センサーを有効にし、イベントハンドラ内に値を書き込む処理を追加します。
// 加速度センサーのセットアップ this.cMMotionManager = new CMMotionManager(); // センサーの更新間隔 cMMotionManager.AccelerometerUpdateInterval = 0.1d; // センサー更新時のハンドラの設定 cMMotionManager.StartAccelerometerUpdates(NSOperationQueue.CurrentQueue, (data, error) => { lock (this.accelerometerSyncLock) { // センサーの値を書き込む AccelerometerInfo.Default.AccelerationX = data.Acceleration.X; AccelerometerInfo.Default.AccelerationY = data.Acceleration.Y; AccelerometerInfo.Default.AccelerationZ = data.Acceleration.Z; } });
以上をまとめると AppDelegate.cs は下記のようになります。
using System; using Foundation; using UIKit; using CoreMotion; using CocosSharp; using CocosSharpGameSample.Core; namespace CocosSharpGameSample.iOS { [Register("AppDelegate")] public partial class AppDelegate : UIApplicationDelegate { // 加速度センサー private CMMotionManager cMMotionManager; // ロックキー private object accelerometerSyncLock = new object(); public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // 加速度センサーのセットアップ this.cMMotionManager = new CMMotionManager(); // センサーの更新間隔 cMMotionManager.AccelerometerUpdateInterval = 0.1d; // センサー更新時のハンドラの設定 cMMotionManager.StartAccelerometerUpdates(NSOperationQueue.CurrentQueue, (data, error) => { lock (this.accelerometerSyncLock) { // センサーの値を書き込む AccelerometerInfo.Default.AccelerationX = data.Acceleration.X; AccelerometerInfo.Default.AccelerationY = data.Acceleration.Y; AccelerometerInfo.Default.AccelerationZ = data.Acceleration.Z; } }); // ゲームをを起動する。 var application = new CCApplication(); application.ApplicationDelegate = new SampleGameApplicationDelegate(); application.StartGame(); return true; } // 画面の向きを LandscapeLeft に固定 [Export("application:supportedInterfaceOrientationsForWindow:")] public UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, IntPtr forWindow) { return UIInterfaceOrientationMask.LandscapeLeft; } } }
次に、ゲーム画面内にセンサーの値を表示します。
文字を表示する時には CCLabel を使用します。
CocosSharpGameSample.Core プロジェクトの GameLayer.cs のフィールドに、X,Y,Z軸のセンサーの値を表示する CCLabel を定義します。
private CCLabel accelerationX; private CCLabel accelerationY; private CCLabel accelerationZ;
AddedToScene メソッド内で、ラベルのインスタンスを作成、配置します。
this.accelerationX = new CCLabel(String.Empty, String.Empty, 40f, CCLabelFormat.SystemFont); this.accelerationX.HorizontalAlignment = CCTextAlignment.Left; this.accelerationX.VerticalAlignment = CCVerticalTextAlignment.Top; this.accelerationX.Color = CCColor3B.White; this.accelerationX.PositionX = 250f; this.accelerationX.PositionY = 120f; AddChild(this.accelerationX); this.accelerationY = new CCLabel(String.Empty, String.Empty, 40f, CCLabelFormat.SystemFont); this.accelerationY.HorizontalAlignment = CCTextAlignment.Left; this.accelerationY.VerticalAlignment = CCVerticalTextAlignment.Top; this.accelerationY.Color = CCColor3B.White; this.accelerationY.PositionX = 250f; this.accelerationY.PositionY = 80f; AddChild(this.accelerationY); this.accelerationZ = new CCLabel(String.Empty, String.Empty, 40f, CCLabelFormat.SystemFont); this.accelerationZ.HorizontalAlignment = CCTextAlignment.Left; this.accelerationZ.VerticalAlignment = CCVerticalTextAlignment.Top; this.accelerationZ.Color = CCColor3B.White; this.accelerationZ.PositionX = 250f; this.accelerationZ.PositionY = 40f; AddChild(this.accelerationZ);
ラベルのテキストにセンサーから取得した値を設定するメソッドを定義します。
private void UpdateAccelerationLabels() { this.accelerationX.Text = "X : " + (AccelerometerInfo.Default.AccelerationX >= 0 ? "+" : String.Empty) + AccelerometerInfo.Default.AccelerationX.ToString("0.00000000"); this.accelerationY.Text = "Y : " + (AccelerometerInfo.Default.AccelerationY >= 0 ? "+" : String.Empty) + AccelerometerInfo.Default.AccelerationY.ToString("0.00000000"); this.accelerationZ.Text = "Z : " + (AccelerometerInfo.Default.AccelerationZ >= 0 ? "+" : String.Empty) + AccelerometerInfo.Default.AccelerationZ.ToString("0.00000000"); }
ゲームは1/60秒などの一定時間ごとに「スケジューラ」が呼ばれ続け、
そのタイミングで処理が実行されることで構成されますので、
スケジューラにラベルのテキストを更新するメソッドを登録します。
第2引数は更新頻度です。0.1fだと0.1秒ごとに更新されます。
private void StartScheduling() { this.Schedule(t => this.UpdateAccelerationLabels(), 0.1f); }
AddedToScene メソッド内で、StartScheduling メソッドをコールします。
potected override void AddedToScene() { (省略) this.StartScheduling(); }
以上をまとめると GameLayer.cs は下記のようになります。
using System; using CocosSharp; namespace CocosSharpGameSample.Core { public class GameLayer : LayerBase { private CCLabel accelerationX; private CCLabel accelerationY; private CCLabel accelerationZ; public GameLayer() : base() { } protected override void AddedToScene() { base.AddedToScene(); // ゲーム画面の背景画像を配置 var gameBackground = new CCSprite("/Resources/Images/Background/GameBackground.png", null); gameBackground.Position = new CCPoint(this.ContentSize.Center.X, this.ContentSize.Center.Y); AddChild(gameBackground); // モーションセンサーの値を表示するラベル this.accelerationX = new CCLabel(String.Empty, String.Empty, 40f, CCLabelFormat.SystemFont); this.accelerationX.HorizontalAlignment = CCTextAlignment.Left; this.accelerationX.VerticalAlignment = CCVerticalTextAlignment.Top; this.accelerationX.Color = CCColor3B.White; this.accelerationX.PositionX = 250f; this.accelerationX.PositionY = 120f; AddChild(this.accelerationX); this.accelerationY = new CCLabel(String.Empty, String.Empty, 40f, CCLabelFormat.SystemFont); this.accelerationY.HorizontalAlignment = CCTextAlignment.Left; this.accelerationY.VerticalAlignment = CCVerticalTextAlignment.Top; this.accelerationY.Color = CCColor3B.White; this.accelerationY.PositionX = 250f; this.accelerationY.PositionY = 80f; AddChild(this.accelerationY); this.accelerationZ = new CCLabel(String.Empty, String.Empty, 40f, CCLabelFormat.SystemFont); this.accelerationZ.HorizontalAlignment = CCTextAlignment.Left; this.accelerationZ.VerticalAlignment = CCVerticalTextAlignment.Top; this.accelerationZ.Color = CCColor3B.White; this.accelerationZ.PositionX = 250f; this.accelerationZ.PositionY = 40f; AddChild(this.accelerationZ); this.StartScheduling(); } private void StartScheduling() { this.Schedule(t => this.UpdateAccelerationLabels(), 0.1f); } private void UpdateAccelerationLabels() { this.accelerationX.Text = "X : " + (AccelerometerInfo.Default.AccelerationX >= 0 ? "+" : String.Empty) + AccelerometerInfo.Default.AccelerationX.ToString("0.00000000"); this.accelerationY.Text = "Y : " + (AccelerometerInfo.Default.AccelerationY >= 0 ? "+" : String.Empty) + AccelerometerInfo.Default.AccelerationY.ToString("0.00000000"); this.accelerationZ.Text = "Z : " + (AccelerometerInfo.Default.AccelerationZ >= 0 ? "+" : String.Empty) + AccelerometerInfo.Default.AccelerationZ.ToString("0.00000000"); } } }
これで、ゲーム画面でセンサーの値が更新されるようになりました。
今回はここまでです。