複数の任意時間に於けるコールバックメソッド

ゲーム開発に於いては単位時間の処理が欠かせないものとして iPhoneアプリの製作の際、基本的な統合的開発環境のXcode上での処理について 本ブログに稿をものしたのが以下の2017年3月27日の配信記事でした。

-(void)update:(CFTimeInterval)currentTimeメソッドに於ける任意時間のコールバックメソッド

必須となる複数の単位時間処理

処で斯くも重要な要素たる単位時間処理は 唯に一箇所のみで必要となるに限られるものでもなく 手元の開発ゲーム バルーンズ・オキュパイ でも複数箇所で利用するに如くはない事態が出来しました。 具体的にはキャラクターの移動処理とバルーン陣地の拡大処理が異なる単位時間に処理されるのが其れで 而して一つでは間に合わない様相を呈したのです。

其処で対処として考えたのが…

スポンサーリンク
日付:2014年4月17日
開発機:MacBook Air(11-inch, Mid 2013)
MacOSバージョン:OS X 10.9.2
Xcodeバージョン:5.1
言語:Objective-C
主関連アプリ:Balloons Occupy(邦題:バルーンズ・オキュパイ、バルオキュ)

任意時間別にメソッドを用意する、と言う手法でした。 此の手法を採用すれば、基本的にはメソッドを単純にコピペして名前の変更など必要な処理を施せば 後はほぼ微調整だけで上手く機能する筈だと考えたのです。 そして一時的にではありますが基本的に此の考え方で書いて稼働したのが以下のコードです。

/* アップデートメソッド */
-(void)update:(CFTimeInterval)currentTime {
  CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
  self.lastUpdateTimeInterval = currentTime;
  if (timeSinceLast > 1) { // more than a second since last update
    timeSinceLast = 1.0 / 60.0;
    self.lastUpdateTimeInterval = currentTime;
  }
  [self updateWithTimeSinceLastUpdate:timeSinceLast];
  
  CFTimeInterval timeBISinceLast = currentTime - self.lastBalloonIncreaseTimeInterval;
  self.lastBalloonIncreaseTimeInterval = currentTime;
  if (timeBISinceLast > 1) { // more than a second since last update
    timeBISinceLast = 1.0 / 60.0;
    self.lastBalloonIncreaseTimeInterval = currentTime;
  }
  [self updateWithTimeSinceLastBallonIncrease:timeSinceLast];
}

/* アップデートから呼び出される2コールバックメソッド */
- (void)updateWithTimeSinceLastBallonIncrease:(CFTimeInterval)timeSinceLast {
  self.lastBalloonIncreaseTimeInterval += timeSinceLast;
  if (self.lastBalloonIncreaseTimeInterval > 0.3) {
    self.lastBalloonIncreaseTimeInterval = 0;
    /* Called before each frame is rendered */
  }
}
- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {
  self.lastSpawnTimeInterval += timeSinceLast;
  if (self.lastSpawnTimeInterval > 3) {
    self.lastSpawnTimeInterval = 0;
    /* はなまる追加処理 */
  }
}

一時的、と上記したのは根本的な問題が表面化されず一見上手く機能しているように見えたからです。 手元の他の開発ゲームアプリ うさ犬が行く でも同様に任意単位時間を2種類とするコードを利用したのでしたが、数日を経た2014年4月28日に問題が発覚しました。 アップデートから呼び出される任意単位時間コールバックメソッドでは2つのインスタンス変数が必要となるのでした。

開発ゲームバルオキュには時間制限もある
開発ゲームバルオキュには時間制限もある

もう一度2017年3月27日の配信記事でも参照したサイト Ray Wenderlich の2013年9月22日の 初心者の為のSprite Kit チュートリアル なる情報ページを現在はページが削除されていますので本ブログへの記載を元に思い返してみます。 当該情報に於いては @property (nonatomic) NSTimeInterval lastSpawnTimeInterval; 、即ちモンスターが産み出されたと言うイベント発生からの時間を把握する為に lastSpawnTimeInterval が宣言されていますが、また同時に @property (nonatomic) NSTimeInterval lastUpdateTimeInterval; 、即ち任意単位時間を表す最後にアップデートされた時からの時間の把握に lastUpdateTimeInterval が用意されていました。 下のコードでは以下の両変数にして記載していますのでコード内に赤文字で記します。

2つのインスタンス変数

  • @property (nonatomic) NSTimeInterval lastRefPointIncreaseTimeInterval;
  • @property (nonatomic) NSTimeInterval lastRefPointUpdateTimeInterbal;
-(void)update:(CFTimeInterval)currentTime {
  CFTimeInterval timeRPSinceLast = currentTime - self.lastRefPointUpdateTimeInterbal;
  self.lastRefPointUpdateTimeInterbal = currentTime;
  if (timeRPSinceLast > 1) { // more than a second since last update
    timeRPSinceLast = 1.0 / 60.0;
    self.lastRefPointUpdateTimeInterbal = currentTime;
  }
  [self updateWithTimeSinceLastRefPointIncrease:timeRPSinceLast];
}
- (void)updateWithTimeSinceLastRefPointIncrease:(CFTimeInterval)timeSinceLast {
  self.lastRefPointIncreaseTimeInterval += timeSinceLast;
  if (self.lastRefPointIncreaseTimeInterval > 0.1) {
   // NSLog(@"Time: %f", self.lastRefPointIncreaseTimeInterval);
    self.lastRefPointIncreaseTimeInterval = 0;
    /* Called before each frame is rendered */
  }
}

lastRefPointUpdateTimeInterbalupdate メソッド中でしか用いられていないにも関わらず インスタンス変数となっているのはupdateが繰り返し呼び出される外側で値を保つためで、 勿論 updateWithTimeSinceLastRefPointIncrease メソッド内の self.lastRefPointIncreaseTimeInterval も同様の理由でインスタンス変数として扱っています。 上のコード内でコメントアウトされてはいますが 以下の部分がコンソールに当該変数を出力して動作を確認している部分です。

NSLog(@"Time: %f", self.lastRefPointIncreaseTimeInterval);
Balloons Occupy
無料:カテゴリ: ゲーム: 4+ 評価
バージョン: 3.0
リリース: 2015年1月29日
更新: 2020年9月1日
サイズ : 13 MB
互換性: iOS 8.0 以降のiPhone、iPod touch に対応。および、macOS 11.0以降とApple M1 チップを搭載したMac に対応。