toOne v1.1 アップデート Cocos2dにおけるシェイク 前面カメラを用いて動作するセンサー機能など
toOne - コイントス のアップデートを行いました。

今回実装された機能は以下になります。
トス動作に
・シェイク動作
・センサー(前面カメラを使って、デバイスに触らずトスできます。)
を追加しました。
一つ前の記事でお話しした機能の実装です。
センサー動作に関しましては、機構上、暗めの場所だとあんまりちゃんと動作しないかもしれません。
以下は技術的な話となります。
■cocos2dにおけるシェイク動作
cocos2dではiOSデフォルトのシェイク機能が使えないので、加速度センサーを使用してシェイク動作を取得します。
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
const float violence = 1;
static BOOL beenhere;
BOOL shake = FALSE;
if (beenhere) return;
beenhere = TRUE;
if (acceleration.x > violence * 1.5 || acceleration.x < (-1.5* violence))
shake = TRUE;
if (acceleration.y > violence * 2 || acceleration.y < (-2 * violence))
shake = TRUE;
if (acceleration.z > violence * 3 || acceleration.z < (-3 * violence))
shake = TRUE;
if (shake) {
id particleSystem = [CCParticleSystemQuad particleWithFile:@"particle.plist"];
[self addChild: particleSystem];
// Super simple Audio playback for sound effects!
[[SimpleAudioEngine sharedEngine] playEffect:@"Sound.mp3"];
shake = FALSE;
}
beenhere = FALSE;
}
引用:stackoverflow - Cocos2d shake/accelerometer issue
引用元のページでも語られているように、これだけだと動作に問題が出るので、タイマーで禁則を設けるなど多少修正を加えています。
■デバイスに触らず、手をかざして動作するセンサー
前面カメラを使用したAVCaptureSessionにて、取得したcgImageの明るさ差分からセンサー機構を作ります。
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVImageBufferRef buffer;
buffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(buffer, 0);
uint8_t* base;
size_t width, height, bytesPerRow;
base = CVPixelBufferGetBaseAddress(buffer);
width = CVPixelBufferGetWidth(buffer);
height = CVPixelBufferGetHeight(buffer);
bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);
CGColorSpaceRef colorSpace;
CGContextRef cgContext;
colorSpace = CGColorSpaceCreateDeviceRGB();
cgContext = CGBitmapContextCreate(
base, width, height, 8, bytesPerRow, colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
CGImageRef cgImage;
cgImage = CGBitmapContextCreateImage(cgContext);
size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
size_t bytesPerPixel = bitsPerPixel/bitsPerComponent;
CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
CFDataRef bitmapData = CGDataProviderCopyData(provider);
const UInt8* data = CFDataGetBytePtr(bitmapData);
// Calculate the average luminance
float avgLuminance = 0.0;
for(int row = 0; row < height; row++){
for(int col = 0; col < width; col++){
const UInt8* pixel = &data[row*bytesPerRow + col*bytesPerPixel];
avgLuminance += (pixel[0]*0.114) + (pixel[1]*0.587) + (pixel[2]*0.299);
}
}
avgLuminance /= (width*height);
CGImageRelease(cgImage);
CGContextRelease(cgContext);
CFRelease(bitmapData);
CVPixelBufferUnlockBaseAddress(buffer, 0);
}
参考:stackoverflow - iOS- Using RGB camera data to make a rough proximity sensor
基本的には、上記の方法でキャプチャしているデータの明るさを取得することができます。
実際には多少の修正を加えており、2〜3秒間で明るさのサンプルを採った平均値から差分を取得するように実装しています。
あとは他に必要ならば、変数を用いて各スイッチ機構、禁則動作機構などを実装して完成です。
通常、AppStoreのアップデートには7日ほどかかるのですが、今回はなんと1日でレビューを通りました!
上記の動作が実装されている「toOne コイントス」は以下のリンクからダウンロードできます。

その他のアプリごとの制作過程は、ブログの開発記カテゴリから一覧表示する事が出来ます。