図1を参照して、この発明の一実施例であるゲームシステム10は、ビデオゲーム装置(以下、単に「ゲーム装置」という)12、コントローラ22および荷重コントローラ36を含む。なお、図示は省略するが、この実施例のゲーム装置12は、最大4つのコントローラ(22,36)と通信可能に設計されている。また、ゲーム装置12と各コントローラ(22,36)とは、無線によって接続される。たとえば、無線通信は、Bluetooth(登録商標)規格に従って実行されるが、赤外線や無線LANなど他の規格に従って実行されてもよい。
ゲーム装置12は、略直方体のハウジング14を含み、ハウジング14の前面にはディスクスロット16が設けられる。ディスクスロット16から、情報処理プログラムの一例としてのゲームプログラム等を記憶した情報記憶媒体の一例である光ディスク18が挿入されて、ハウジング14内のディスクドライブ54(図2参照)に装着される。ディスクスロット16の周囲には、LEDと導光板が配置され、さまざまな処理に応答させて点灯させることが可能である。
また、ゲーム装置12のハウジング14の前面であり、その上部には、電源ボタン20aおよびリセットボタン20bが設けられ、その下部には、イジェクトボタン20cが設けられる。さらに、リセットボタン20bとイジェクトボタン20cとの間であり、ディスクスロット16の近傍には、外部メモリカード用コネクタカバー28が設けられる。この外部メモリカード用コネクタカバー28の内側には、外部メモリカード用コネクタ62(図2参照)が設けられ、図示しない外部メモリカード(以下、単に「メモリカード」という)が挿入される。メモリカードは、光ディスク18から読み出したゲームプログラム等をローディングして一時的に記憶したり、このゲームシステム10を利用してプレイしたゲームのゲームデータ(ゲームの結果データまたは途中データ)を保存(セーブ)しておいたりするために利用される。ただし、上記のゲームデータの保存は、メモリカードに対して行うことに代えて、たとえばゲーム装置12の内部に設けられるフラッシュメモリ44(図2参照)のような内部メモリに対して行うようにしてもよい。また、メモリカードは、内部メモリのバックアップメモリとして用いるようにしてもよい。
なお、メモリカードとしては、汎用のSDカードを用いることができるが、メモリスティックやマルチメディアカード(登録商標)のような他の汎用のメモリカードを用いることもできる。
ゲーム装置12のハウジング14の後面には、AVコネクタ58(図2参照)が設けられ、そのAVコネクタ58を用いて、AVケーブル32aを通してゲーム装置12にモニタ34およびスピーカ34aを接続する。このモニタ34およびスピーカ34aは典型的にはカラーテレビジョン受像機であり、AVケーブル32aは、ゲーム装置12からの映像信号をカラーテレビのビデオ入力端子に入力し、音声信号を音声入力端子に入力する。したがって、カラーテレビ(モニタ)34の画面上にたとえば3次元(3D)ビデオゲームのゲーム画像が表示され、左右のスピーカ34aからゲーム音楽や効果音などのステレオゲーム音声が出力される。また、モニタ34の周辺(この実施例では、モニタ34の上側)には、2つの赤外LED(マーカ)340m,340nを備えるマーカ部34bが設けられる。このマーカ部34bは、電源ケーブル32bを通してゲーム装置12に接続される。したがって、マーカ部34bには、ゲーム装置12から電源が供給される。これによって、マーカ340m,340nは発光し、それぞれモニタ34の前方に向けて赤外光を出力する。
なお、ゲーム装置12の電源は、一般的なACアダプタ(図示せず)によって与えられる。ACアダプタは家庭用の標準的な壁ソケットに差し込まれ、ゲーム装置12は、家庭用電源(商用電源)を、駆動に適した低いDC電圧信号に変換する。他の実施例では、電源としてバッテリが用いられてもよい。
このゲームシステム10において、ユーザまたはプレイヤがゲーム(またはゲームに限らず、他のアプリケーション)をプレイするために、ユーザはまずゲーム装置12の電源をオンし、次いで、ユーザはビデオゲーム(もしくはプレイしたいと思う他のアプリケーション)のプログラムを記録している適宜の光ディスク18を選択し、その光ディスク18をゲーム装置12のディスクドライブ54にローディングする。応じて、ゲーム装置12がその光ディスク18に記録されているプログラムに基づいてビデオゲームもしくは他のアプリケーションを実行し始めるようにする。ユーザはゲーム装置12に入力を与えるためにコントローラ22を操作する。たとえば、入力手段26のどれかを操作することによってゲームもしくは他のアプリケーションをスタートさせる。また、入力手段26に対する操作以外にも、コントローラ22自体を動かすことによって、動画オブジェクト(プレイヤオブジェクト)を異なる方向に移動させ、または3Dのゲーム世界におけるユーザの視点(カメラ位置)を変化させることができる。
図2は図1実施例のビデオゲームシステム10の電気的な構成を示すブロック図である。図示は省略するが、ハウジング14内の各コンポーネントは、プリント基板に実装される。図2に示すように、ゲーム装置12には、CPU40が設けられる。このCPU40は、ゲームプロセッサとして機能する。このCPU40には、システムLSI42が接続される。このシステムLSI42には、外部メインメモリ46、ROM/RTC48、ディスクドライブ54およびAV IC56が接続される。
外部メインメモリ46は、ゲームプログラム等のプログラムを記憶したり、各種データを記憶したりし、CPU40のワーク領域やバッファ領域として用いられる。ROM/RTC48は、いわゆるブートROMであり、ゲーム装置12の起動用のプログラムが組み込まれるとともに、時間をカウントする時計回路が設けられる。ディスクドライブ54は、光ディスク18からプログラムデータやテクスチャデータ等を読み出し、CPU40の制御の下で、後述する内部メインメモリ42eまたは外部メインメモリ46に書き込む。
システムLSI42には、入出力プロセッサ42a、GPU(Graphics Processor Unit)42b,DSP(Digital Signal Processor)42c,VRAM42dおよび内部メインメモリ42eが設けられ、図示は省略するが、これらは内部バスによって互いに接続される。
入出力プロセッサ(I/Oプロセッサ)42aは、データの送受信を実行したり、データのダウンロードを実行したりする。データの送受信やダウンロードについては後で詳細に説明する。
GPU42bは、描画手段の一部を形成し、CPU40からのグラフィクスコマンド(作画命令)を受け、そのコマンドに従ってゲーム画像データを生成する。ただし、CPU40は、グラフィクスコマンドに加えて、ゲーム画像データの生成に必要な画像生成プログラムをGPU42bに与える。
図示は省略するが、上述したように、GPU42bにはVRAM42dが接続される。GPU42bが作画コマンドを実行するにあたって必要なデータ(画像データ:ポリゴンデータやテクスチャデータなどのデータ)は、GPU42bがVRAM42dにアクセスして取得する。なお、CPU40は、描画に必要な画像データを、GPU42bを介してVRAM42dに書き込む。GPU42bは、VRAM42dにアクセスして描画のためのゲーム画像データを作成する。
なお、この実施例では、GPU42bがゲーム画像データを生成する場合について説明するが、ゲームアプリケーション以外の任意のアプリケーションを実行する場合には、GPU42bは当該任意のアプリケーションについての画像データを生成する。
また、DSP42cは、オーディオプロセッサとして機能し、内部メインメモリ42eや外部メインメモリ46に記憶されるサウンドデータや音波形(音色)データを用いて、スピーカ34aから出力する音、音声或いは音楽に対応するオーディオデータを生成する。
上述のように生成されたゲーム画像データおよびオーディオデータは、AV IC56によって読み出され、AVコネクタ58を介してモニタ34およびスピーカ34aに出力される。したがって、ゲーム画面がモニタ34に表示され、ゲームに必要な音(音楽)がスピーカ34aから出力される。
また、入出力プロセッサ42aには、フラッシュメモリ44、無線通信モジュール50および無線コントローラモジュール52が接続されるとともに、拡張コネクタ60およびメモリカード用コネクタ62が接続される。また、無線通信モジュール50にはアンテナ50aが接続され、無線コントローラモジュール52にはアンテナ52aが接続される。
入出力プロセッサ42aは、無線通信モジュール50を介して、ネットワークに接続される他のゲーム装置や各種サーバと通信することができる。ただし、ネットワークを介さずに、直接的に他のゲーム装置と通信することもできる。入出力プロセッサ42aは、定期的にフラッシュメモリ44にアクセスし、ネットワークへ送信する必要があるデータ(送信データとする)の有無を検出し、当該送信データが有る場合には、無線通信モジュール50およびアンテナ50aを介してネットワークに送信する。また、入出力プロセッサ42aは、他のゲーム装置から送信されるデータ(受信データとする)を、ネットワーク、アンテナ50aおよび無線通信モジュール50を介して受信し、受信データをフラッシュメモリ44に記憶する。ただし、一定の場合には、受信データをそのまま破棄する。さらに、入出力プロセッサ42aは、ダウンロードサーバからダウンロードしたデータ(ダウンロードデータとする)をネットワーク、アンテナ50aおよび無線通信モジュール50を介して受信し、ダウンロードデータをフラッシュメモリ44に記憶する。
また、入出力プロセッサ42aは、コントローラ22や荷重コントローラ36から送信される入力データをアンテナ52aおよび無線コントローラモジュール52を介して受信し、内部メインメモリ42eまたは外部メインメモリ46のバッファ領域に記憶(一時記憶)する。入力データは、CPU40のゲーム処理によって利用された後、バッファ領域から消去される。
なお、この実施例では、上述したように、無線コントローラモジュール52は、Bluetooth規格にしたがってコントローラ22や荷重コントローラ36との間で通信を行う。
また、図面の都合上、図2では、コントローラ22と荷重コントローラ36とをまとめて記載してある。
さらに、入出力プロセッサ42aには、拡張コネクタ60およびメモリカード用コネクタ62が接続される。拡張コネクタ60は、USBやSCSIのようなインターフェイスのためのコネクタであり、外部記憶媒体のようなメディアを接続したり、他のコントローラのような周辺機器を接続したりすることができる。また、拡張コネクタ60に有線LANアダプタを接続し、無線通信モジュール50に代えて当該有線LANを利用することもできる。メモリカード用コネクタ62には、メモリカードのような外部記憶媒体を接続することができる。したがって、たとえば、入出力プロセッサ42aは、拡張コネクタ60やメモリカード用コネクタ62を介して、外部記憶媒体にアクセスし、データを保存したり、データを読み出したりすることができる。
詳細な説明は省略するが、図1にも示したように、ゲーム装置12(ハウジング14)には、電源ボタン20a、リセットボタン20bおよびイジェクトボタン20cが設けられる。電源ボタン20aは、システムLSI42に接続される。この電源ボタン20aがオンされると、システムLSI42は、ゲーム装置12の各コンポーネントに図示しないACアダプタを経て電源が供給され、通常の通電状態となるモード(以下、「通常モード」という)を設定する。一方、電源ボタン20aがオフされると、システムLSI42は、ゲーム装置12の一部のコンポーネントのみに電源が供給され、消費電力を必要最低限に抑えるモード(以下、「スタンバイモード」という)を設定する。この実施例では、スタンバイモードが設定された場合には、システムLSI42は、入出力プロセッサ42a、フラッシュメモリ44、外部メインメモリ46、ROM/RTC48および無線通信モジュール50、無線コントローラモジュール52以外のコンポーネントに対して、電源供給を停止する指示を行う。したがって、このスタンバイモードは、CPU40によってアプリケーションの実行が行われないモードである。
なお、システムLSI42には、スタンバイモードにおいても電源が供給されるが、GPU42b、DSP42cおよびVRAM42dへのクロックの供給を停止することにより、これらを駆動させないようにして、消費電力を低減するようにしてある。
また、図示は省略するが、ゲーム装置12のハウジング14内部には、CPU40やシステムLSI42などのICの熱を外部に排出するためのファンが設けられる。スタンバイモードでは、このファンも停止される。
ただし、スタンバイモードを利用したくない場合には、スタンバイモードを利用しない設定にしておくことにより、電源ボタン20aがオフされたときに、すべての回路コンポーネントへの電源供給が完全に停止される。
また、通常モードとスタンバイモードの切り替えは、コントローラ22の電源スイッチ26hのオン/オフの切り替えによっても遠隔操作によって行うことが可能である。当該遠隔操作を行わない場合には、スタンバイモードにおいて無線コントローラモジュール52aへの電源供給を行わない設定にしてもよい。
リセットボタン20bもまた、システムLSI42に接続される。リセットボタン20bが押されると、システムLSI42は、ゲーム装置12の起動プログラムを再起動する。イジェクトボタン20cは、ディスクドライブ54に接続される。イジェクトボタン20cが押されると、ディスクドライブ54から光ディスク18が排出される。
図3(A)ないし図3(E)は、コントローラ22の外観の一例を示す。図3(A)はコントローラ22の先端面を示し、図3(B)はコントローラ22の上面を示し、図3(C)はコントローラ22の右側面を示し、図3(D)はコントローラ22の下面を示し、そして、図3(E)はコントローラ22の後端面を示す。
図3(A)ないし図3(E)を参照して、コントローラ22は、たとえばプラスチック成型によって形成されたハウジング22aを有している。ハウジング22aは、略直方体形状であり、ユーザが片手で把持可能な大きさである。ハウジング22a(コントローラ22)には、入力手段(複数のボタンないしスイッチ)26が設けられる。具体的には、図3(B)に示すように、ハウジング22aの上面には、十字キー26a、1ボタン26b、2ボタン26c、Aボタン26d、−ボタン26e、HOMEボタン26f、+ボタン26gおよび電源スイッチ26hが設けられる。また、図3(C)および図3(D)に示すように、ハウジング22aの下面に傾斜面が形成されており、この傾斜面に、Bトリガースイッチ26iが設けられる。
十字キー26aは、4方向プッシュスイッチであり、矢印で示す4つの方向、前(または上)、後ろ(または下)、右および左の操作部を含む。この操作部のいずれか1つを操作することによって、プレイヤによって操作可能なキャラクタまたはオブジェクト(プレイヤキャラクタまたはプレイヤオブジェクト)の移動方向を指示したり、カーソルの移動方向を指示したりすることができる。
1ボタン26bおよび2ボタン26cは、それぞれ、押しボタンスイッチである。たとえば3次元ゲーム画像を表示する際の視点位置や視点方向、すなわち仮想カメラの位置や画角を調整する等のゲームの操作に使用される。または、1ボタン26bおよび2ボタン26cは、Aボタン26dおよびBトリガースイッチ26iと同じ操作或いは補助的な操作をする場合に用いるようにしてもよい。
Aボタンスイッチ26dは、押しボタンスイッチであり、プレイヤキャラクタまたはプレイヤオブジェクトに、方向指示以外の動作、すなわち、打つ(パンチ)、投げる、つかむ(取得)、乗る、ジャンプするなどの任意のアクションをさせるために使用される。たとえば、アクションゲームにおいては、ジャンプ、パンチ、武器を動かすなどを指示することができる。また、ロールプレイングゲーム(RPG)やシミュレーションRPGにおいては、アイテムの取得、武器やコマンドの選択および決定等を指示することができる。
−ボタン26e、HOMEボタン26f、+ボタン26gおよび電源スイッチ26hもまた、押しボタンスイッチである。−ボタン26eは、ゲームモードを選択するために使用される。HOMEボタン26fは、ゲームメニュー(メニュー画面)を表示するために使用される。+ボタン26gは、ゲームを開始(再開)したり、一時停止したりするなどのために使用される。電源スイッチ26hは、ゲーム装置12の電源を遠隔操作によってオン/オフするために使用される。
なお、この実施例では、コントローラ22自体をオン/オフするための電源スイッチは設けておらず、コントローラ22の入力手段26のいずれかを操作することによってコントローラ22はオンとなり、一定時間(たとえば、30秒)以上操作しなければ自動的にオフとなるようにしてある。
Bトリガースイッチ26iもまた、押しボタンスイッチであり、主として、弾を撃つなどのトリガを模した入力を行ったり、コントローラ22で選択した位置を指定したりするために使用される。また、Bトリガースイッチ26iを押し続けると、プレイヤオブジェクトの動作やパラメータを一定の状態に維持することもできる。また、一定の場合には、Bトリガースイッチ26iは、通常のBボタンと同様に機能し、Aボタン26dによって決定したアクションを取り消すなどのために使用される。
また、図3(E)に示すように、ハウジング22aの後端面に外部拡張コネクタ22bが設けられ、また、図3(B)に示すように、ハウジング22aの上面であり、後端面側にはインジケータ22cが設けられる。外部拡張コネクタ22bは、図示しない別の拡張コントローラを接続するためなどに使用される。インジケータ22cは、たとえば、4つのLEDで構成され、4つのうちのいずれか1つを点灯することにより、点灯LEDに対応するコントローラ22の識別情報(コントローラ番号)を示したり、点灯させるLEDの個数によってコントローラ22の電源残量を示したりすることができる。
さらに、コントローラ22は、撮像情報演算部80(図4参照)を有しており、図3(A)に示すように、ハウジング22aの先端面には撮像情報演算部80の光入射口22dが設けられる。また、コントローラ22は、スピーカ86(図4参照)を有しており、このスピーカ86は、図3(B)に示すように、ハウジング22aの上面であり、1ボタン26bとHOMEボタン26fとの間に設けられる音抜き孔22eに対応して、ハウジング22a内部に設けられる。
なお、図3(A)ないし図3(E)に示したコントローラ22の形状や、各入力手段26の形状、数および設置位置等は単なる一例に過ぎず、それらが適宜改変された場合であっても、本発明を実現できることは言うまでもない。
図4はコントローラ22の電気的な構成を示すブロック図である。この図4を参照して、コントローラ22はプロセッサ70を含み、このプロセッサ70には、内部バス(図示せず)によって、外部拡張コネクタ22b、入力手段26、メモリ72、加速度センサ74、無線モジュール76、撮像情報演算部80、LED82(インジケータ22c)、バイブレータ84、スピーカ86および電源回路88が接続される。また、無線モジュール76には、アンテナ78が接続される。
プロセッサ70は、コントローラ22の全体制御を司り、入力手段26、加速度センサ74および撮像情報演算部80によって入力された情報(入力情報)を、入力データとして無線モジュール76およびアンテナ78を介してゲーム装置12に送信(入力)する。このとき、プロセッサ70は、メモリ72を作業領域ないしバッファ領域として用いる。
上述した入力手段26(26a−26i)からの操作信号(操作データ)は、プロセッサ70に入力され、プロセッサ70は操作データを一旦メモリ72に記憶する。
また、加速度センサ74は、コントローラ22の縦方向(y軸方向)、横方向(x軸方向)および前後方向(z軸方向)の3軸で各々の加速度を検出する。この加速度センサ74は、典型的には、静電容量式の加速度センサであるが、他の方式のものを用いるようにしてもよい。
たとえば、加速度センサ74は、第1所定時間毎に、x軸,y軸,z軸の各々についての加速度(ax,ay,az)を検出し、検出した加速度のデータ(加速度データ)をプロセッサ70に入力する。たとえば、加速度センサ74は、各軸方向の加速度を、−2.0g〜2.0g(gは重力加速度である。以下、同じ。)の範囲で検出する。プロセッサ70は、加速度センサ74から与えられる加速度データを、第2所定時間毎に検出し、一旦メモリ72に記憶する。プロセッサ70は、操作データ、加速度データおよび後述するマーカ座標データの少なくとも1つを含む入力データを作成し、作成した入力データを、第3所定時間(たとえば、5msec)毎にゲーム装置12に送信する。
なお、図3(A)−図3(E)では省略したが、この実施例では、加速度センサ74は、ハウジング22a内部の基板上の十字キー26aが配置される付近に設けられる。
無線モジュール76は、たとえばBluetoothの技術を用いて、所定周波数の搬送波を入力データで変調し、その微弱電波信号をアンテナ78から放射する。つまり、入力データは、無線モジュール76によって微弱電波信号に変調されてアンテナ78(コントローラ22)から送信される。この微弱電波信号が上述したゲーム装置12に設けられた無線コントローラモジュール52によって受信される。受信された微弱電波は、復調および復号の処理を施され、したがって、ゲーム装置12(CPU40)は、コントローラ22からの入力データを取得することができる。そして、CPU40は、取得した入力データとプログラム(ゲームプログラム)とに従ってゲーム処理を行う。
さらに、上述したように、コントローラ22には、撮像情報演算部80が設けられる。この撮像情報演算部80は、赤外線フィルタ80a、レンズ80b、撮像素子80cおよび画像処理回路80dによって構成される。赤外線フィルタ80aは、コントローラ22の前方から入射する光から赤外線のみを通過させる。上述したように、モニタ34の表示画面近傍(周辺)に配置されるマーカ340mおよび340nは、モニタ34の前方に向かって赤外光を出力する赤外LEDである。したがって、赤外線フィルタ80aを設けることによってマーカ340mおよび340nの画像をより正確に撮像することができる。レンズ84は、赤外線フィル82を透過した赤外線を集光して撮像素子80cへ出射する。撮像素子80cは、たとえばCMOSセンサあるいはCCDのような固体撮像素子であり、レンズ80bによって集光された赤外線を撮像する。したがって、撮像素子80cは、赤外線フィルタ80aを通過した赤外線だけを撮像して画像データを生成する。以下では、撮像素子80cによって撮像された画像を撮像画像と呼ぶ。撮像素子80cによって生成された画像データは、画像処理回路80dで処理される。画像処理回路80dは、撮像画像内における撮像対象(マーカ340mおよび340n)の位置を算出し、第4所定時間毎に、当該位置を示す各座標値を撮像データとしてプロセッサ70に出力する。なお、画像処理回路80dにおける処理については後述する。
図5は図1に示した荷重コントローラ36の外観を示す斜視図である。図5に示すように、荷重コントローラ36は、プレイヤがその上に乗る(プレイヤの足を乗せる)台36a、および台36aにかかる荷重を検出するための少なくとも4つの荷重センサ36bを備える。なお、各荷重センサ36bは台36aに内包されており(図6,図7参照)、図5においてはその配置が点線で示されている。
台36aは、略直方体に形成されており、上面視で略長方形状である。たとえば長方形の短辺が30cm程度に設定され、その長辺が50cm程度に設定される。プレイヤが乗る台36aの上面は平坦にされる。台36aの4隅の側面は、部分的に円柱状に張り出すように形成されている。
この台36aにおいて、4つの荷重センサ36bは、所定の間隔を置いて配置される。この実施例では、4つの荷重センサ36bは、台36aの周縁部に、具体的には4隅にそれぞれ配置される。荷重センサ36bの間隔は、台36aに対するプレイヤの荷重のかけ方によるゲーム操作の意図をより精度良く検出できるように適宜な値に設定される。
図6は、図5に示した荷重コントローラ36のVI−VI断面図を示すとともに、荷重センサ36bの配置された隅の部分が拡大表示されている。この図6から分かるように、台36aは、プレイヤが乗るための支持板360と脚362を含む。脚362は、荷重センサ36bが配置される箇所に設けられる。この実施例では4つの荷重センサ36bが4隅に配置されるので、4つの脚362が4隅に設けられる。脚362は、たとえばプラスチック成型によって略有底円筒状に形成されており、荷重センサ36bは、脚362内の底面に設けられた球面部品362a上に配置される。支持板360は、この荷重センサ36bを介して脚362に支持される。
支持板360は、上面と側面上部とを形成する上層板360a、下面と側面下部とを形成する下層板360b、および上層板360aと下層板360bとの間に設けられる中層板360cを含む。上層板360aと下層板360bとは、たとえばプラスチック成型により形成されており、接着等により一体化される。中層板360cは、たとえば1枚の金属板のプレス成型により形成されている。この中層板360cが、4つの荷重センサ36bの上に固定される。上層板360aは、その下面に格子状のリブ(図示しない)を有しており、当該リブを介して中層板360cに支持されている。
したがって、台36aにプレイヤが乗ったときには、その荷重は、支持板360、荷重センサ36bおよび脚362を伝達する。図6に矢印で示したように、入力される荷重によって生じた床からの反作用は、脚362から、球面部品362a、荷重センサ36b、中層板360cを介して、上層板360aに伝達する。
荷重センサ36bは、たとえば歪ゲージ(歪センサ)式ロードセルであり、入力された荷重を電気信号に変換する荷重変換器である。荷重センサ36bでは、荷重入力に応じて、起歪体370aが変形して歪が生じる。この歪が、起歪体に貼り付けられた歪センサ370bによって、電気抵抗の変化に変換され、さらに電圧変化に変換される。したがって、荷重センサ36bは、入力荷重を示す電圧信号を出力端子から出力する。
なお、荷重センサ36bは、音叉振動式、弦振動式、静電容量式、圧電式、磁歪式、またはジャイロ式のような他の方式の荷重センサであってもよい。
図5に戻って、荷重コントローラ36には、さらに、電源ボタン36cが設けられる。この電源ボタン36cがオンされると、荷重コントローラ36の各回路コンポーネント(図7参照)に電源が供給される。ただし、荷重コントローラ36は、ゲーム装置12からの指示に従ってオンされる場合もある。また、荷重コントローラ36は、プレイヤが乗っていない状態が一定時間(たとえば、30秒)以上継続すると、電源がオフされる。ただし、荷重コントローラ36が起動されている状態で、電源ボタン36cをオンしたときに、電源がオフされてもよい。
図7のブロック図には、荷重コントローラ36の電気的な構成の一例が示される。なお、この図7では、信号および通信の流れは実線矢印で示される。破線矢印は、電源の供給を示している。
荷重コントローラ36は、その動作を制御するためのマイクロコンピュータ(マイコン)100を含む。マイコン100は図示しないCPU、ROMおよびRAM等を含み、CPUはROMに記憶されたプログラムに従って荷重コントローラ36の動作を制御する。
マイコン100には、電源ボタン36c、ADコンバータ102、DC−DCコンバータ104および無線モジュール106が接続される。さらに、無線モジュール106には、アンテナ106aが接続される。また、4つの荷重センサ36bは、図3ではロードセル36bとして示される。4つの荷重センサ36bは、それぞれ、増幅器108を介してADコンバータ102に接続される。
また、荷重コントローラ36には電源供給のために電池100が収容されている。他の実施例では、電池に代えてACアダプタを接続し、商用電源を供給するようにしてもよい。かかる場合には、DC−DCコンバータに代えて、交流を直流に変換し、直流電圧を降圧および整流する電源回路を設ける必要がある。この実施例では、マイコン100および無線モジュール106への電源の供給は、電池から直接的に行われる。つまり、マイコン100内部の一部のコンポーネント(CPU)と無線モジュール106とには、常に電源が供給されており、電源ボタン36cがオンされたか否か、ゲーム装置12から電源オン(荷重検出)のコマンドが送信されたか否かを検出する。一方、荷重センサ36b、ADコンバータ102および増幅器108には、電池110からの電源がDC−DCコンバータ104を介して供給される。DC−DCコンバータ104は、電池110からの直流電流の電圧値を異なる電圧値に変換して、荷重センサ36b、ADコンバータ102および増幅器108に与える。
これら荷重センサ36b、ADコンバータ102および増幅器108への電源供給は、マイコン100によるDC−DCコンバータ104の制御によって、必要に応じて行われるようにしてよい。つまり、マイコン100は、荷重センサ36bを動作させて荷重を検出する必要があると判断されるときに、DC−DCコンバータ104を制御して、各荷重センサ36b、ADコンバータ102および各増幅器108に電源を供給するようにしてよい。
電源が供給されると、各荷重センサ36bは、入力された荷重を示す信号を出力する。当該信号は各増幅器108で増幅され、ADコンバータ102でアナログ信号からディジタルデータに変換されて、マイコン100に入力される。各荷重センサ36bの検出値には各荷重センサ36bの識別情報が付与されて、いずれの荷重センサ36bの検出値であるかが識別可能にされる。このようにして、マイコン100は、同一時刻における4つの荷重センサ36bのそれぞれの荷重検出値を示すデータを取得することができる。
一方、マイコン100は、荷重センサ36bを動作させる必要がないと判断されるとき、つまり、荷重検出タイミングでないとき、DC−DCコンバータ104を制御して、荷重センサ36b、ADコンバータ102および増幅器108への電源の供給を停止する。このように、荷重コントローラ36では、必要なときにだけ、荷重センサ36bを動作させて荷重の検出を行うことができるので、荷重検出のための電力消費を抑制することができる。
荷重検出の必要なときとは、典型的には、ゲーム装置12(図1)が荷重データを取得したいときである。たとえば、ゲーム装置12が荷重情報を必要とするとき、ゲーム装置12は荷重コントローラ36に対して荷重取得命令を送信する。マイコン100は、ゲーム装置12から荷重取得命令を受信したときに、DC−DCコンバータ104を制御して、荷重センサ36b等に電源を供給し、荷重を検出する。一方、マイコン100は、ゲーム装置12から荷重取得命令を受信していないときには、DC−DCコンバータ104を制御して、電源供給を停止する。あるいは、マイコン100は、一定時間ごとに荷重検出タイミングであると判断して、DC−DCコンバータ104を制御するようにしてもよい。このような周期的な荷重取得を行う場合、周期情報は、たとえば、初めにゲーム装置12からマイコン100に与えられ、または、予めマイコン100に記憶されてよい。
荷重センサ36bからの検出値を示すデータは、荷重コントローラ36の操作データ(入力データ)として、マイコン100から無線モジュール106およびアンテナ106bを介してゲーム装置12(図1)に送信される。たとえば、ゲーム装置12からの命令を受けて荷重検出を行った場合、マイコン100は、ADコンバータ102から荷重センサ36bの検出値データを受信したときに、当該検出値データをゲーム装置12に送信する。あるいは、マイコン100は、一定時間ごとに検出値データをゲーム装置12に送信するようにしてもよい。
なお、無線モジュール106は、ゲーム装置12の無線コントローラモジュール52と同じ無線規格(Bluetooth、無線LANなど)で通信可能にされる。したがって、ゲーム装置12のCPU40は、無線コントローラモジュール52等を介して荷重取得命令を荷重コントローラ36に送信することができる。荷重コントローラ36のマイコン100は、無線モジュール106およびアンテナ106aを介して、ゲーム装置12からの命令を受信し、また、各荷重センサ36bの荷重検出値(または荷重算出値)を含む入力データをゲーム装置12に送信することができる。
図8は、コントローラ22および荷重コントローラ36を用いて仮想ゲームをプレイするときの状態を概説する図解図である。図8に示すように、ビデオゲームシステム10でコントローラ22および荷重コントローラ36を用いて仮想ゲームをプレイする際、プレイヤは、荷重コントローラ36の上に乗り、一方の手でコントローラ22を把持する。厳密に言うと、プレイヤは、コントローラ22の先端面(撮像情報演算部80が撮像する光の入射口22d側)がマーカ340mおよび340nの方を向く状態で、荷重コントローラ36に乗り、コントローラ22を把持する。ただし、図1からも分かるように、マーカ340mおよび340nは、モニタ34の画面の横方向と平行に配置されている。この状態で、プレイヤは、コントローラ22が指示する画面上の位置を変更したり、コントローラ22と各マーカ340mおよび340nとの距離を変更したりすることによってゲーム操作を行う。
なお、図8では、プレイヤがモニタ34の画面に対して横を向くように荷重コントローラ36を縦置きにしてあるが、ゲームによっては、プレイヤがモニタ34の画面に対して正面を向くように荷重コントローラ36を横置きにしてよい。
図9は、マーカ340mおよび340nと、コントローラ22との視野角を説明するための図である。図9に示すように、マーカ340mおよび340nは、それぞれ、視野角θ1の範囲で赤外光を放射する。また、撮像情報演算部80の撮像素子80cは、コントローラ22の視線方向を中心とした視野角θ2の範囲で入射する光を受光することができる。たとえば、マーカ340mおよび340nの視野角θ1は、共に34°(半値角)であり、一方、撮像素子80cの視野角θ2は41°である。プレイヤは、撮像素子80cが2つのマーカ340mおよび340nからの赤外光を受光することが可能な位置および向きとなるように、コントローラ22を把持する。具体的には、撮像素子80cの視野角θ2の中に少なくとも一方のマーカ340mおよび340nが存在し、かつ、マーカ340mまたは340nの少なくとも一方の視野角θ1の中にコントローラ22が存在する状態となるように、プレイヤはコントローラ22を把持する。この状態にあるとき、コントローラ22は、マーカ340mおよび340nの少なくとも一方を検知することができる。プレイヤは、この状態を満たす範囲でコントローラ22の位置および向きを変化させることによってゲーム操作を行うことができる。
なお、コントローラ22の位置および向きがこの範囲外となった場合、コントローラ22の位置および向きに基づいたゲーム操作を行うことができなくなる。以下では、上記範囲を「操作可能範囲」と呼ぶ。
操作可能範囲内でコントローラ22が把持される場合、撮像情報演算部80によって各マーカ340mおよび340nの画像が撮像される。すなわち、撮像素子80cによって得られる撮像画像には、撮像対象である各マーカ340mおよび340nの画像(対象画像)が含まれる。図10は、対象画像を含む撮像画像の一例を示す図である。対象画像を含む撮像画像の画像データを用いて、画像処理回路80dは、各マーカ340mおよび340nの撮像画像における位置を表す座標(マーカ座標)を算出する。
撮像画像の画像データにおいて対象画像は高輝度部分として現れるため、画像処理回路80dは、まず、この高輝度部分を対象画像の候補として検出する。次に、画像処理回路80dは、検出された高輝度部分の大きさに基づいて、その高輝度部分が対象画像であるか否かを判定する。撮像画像には、対象画像である2つのマーカ340mおよび340nの画像340m’および340n’のみならず、窓からの太陽光や部屋の蛍光灯の光によって対象画像以外の画像が含まれていることがある。高輝度部分が対象画像であるか否かの判定処理は、対象画像であるマーカ340mおよび340nの画像340m’および340n’と、それ以外の画像とを区別し、対象画像を正確に検出するために実行される。具体的には、当該判定処理においては、検出された高輝度部分が、予め定められた所定範囲内の大きさであるか否かが判定される。そして、高輝度部分が所定範囲内の大きさである場合には、当該高輝度部分は対象画像を表すと判定される。逆に、高輝度部分が所定範囲内の大きさでない場合には、当該高輝度部分は対象画像以外の画像を表すと判定される。
さらに、上記の判定処理の結果、対象画像を表すと判定された高輝度部分について、画像処理回路80dは当該高輝度部分の位置を算出する。具体的には、当該高輝度部分の重心位置を算出する。ここでは、当該重心位置の座標をマーカ座標と呼ぶ。また、重心位置は撮像素子80cの解像度よりも詳細なスケールで算出することが可能である。ここでは、撮像素子80cによって撮像された撮像画像の解像度が126×96であるとし、重心位置は1024×768のスケールで算出されるものとする。つまり、マーカ座標は、(0,0)から(1024,768)までの整数値で表現される。
なお、撮像画像における位置は、撮像画像の左上を原点とし、下向きをY軸正方向とし、右向きをX軸正方向とする座標系(XY座標系)で表現されるものとする。
また、対象画像が正しく検出される場合には、判定処理によって2つの高輝度部分が対象画像として判定されるので、2箇所のマーカ座標が算出される。画像処理回路80dは、算出された2箇所のマーカ座標を示すデータを出力する。出力されたマーカ座標のデータ(マーカ座標データ)は、上述したように、プロセッサ70によって入力データに含まれ、ゲーム装置12に送信される。
ゲーム装置12(CPU40)は、受信した入力データからマーカ座標データを検出すると、このマーカ座標データに基づいて、モニタ34の画面上におけるコントローラ22の指示位置(指示座標)と、コントローラ22からマーカ340mおよび340nまでの各距離とを算出することができる。具体的には、2つのマーカ座標の中点の位置から、コントローラ22の向いている位置すなわち指示位置が算出される。また、撮像画像における対象画像間の距離が、コントローラ22と、マーカ340mおよび340nとの距離に応じて変化するので、2つのマーカ座標間の距離を算出することによって、ゲーム装置12はコントローラ22とマーカ340mおよび340nとの間の距離を把握できる。
上述したように、コントローラ22および荷重コントローラ36を用いて仮想ゲームをプレイする場合、荷重コントローラ36で検出される荷重値に基づいてゲーム処理を実行することができる。この実施例では、仮想ゲームが開始されると、本編の開始に先立って、プレイヤが静止した状態において荷重コントローラ36によって4つの荷重センサ36bの荷重値が検出され、検出された4つの荷重値からプレイヤの体重値が算出(測定)され、測定された体重値が基準値として設定(メインメモリ42eまたは46に記憶)され、たとえば、設定された基準値と仮想ゲームの実行中に検出される荷重値(この実施例では、4つの荷重センサ36bで検出される荷重値の合計値)とに基づいてゲーム処理が実行される。つまり、プレイヤの体重値はゲーム処理を実行する場合の基準値となる。ただし、この実施例の仮想ゲームでは、プレイヤの体重の大小による有利不利を無くすため、現在の荷重値を基準値で割った値(以下、「体重率」という)に基づいてゲーム処理を実行するようにしてある。
図11(A)および図11(B)には、この実施例の仮想ゲームをプレイする場合に、モニタ34に表示されるゲーム画面200の例が示される。たとえば、図11(A)は、プレイヤオブジェクト202が羽ばたいて空を飛行している場合(通常飛行時)のゲーム画面200を示す。また、図11(B)は、プレイヤオブジェクト202がノンプレイヤオブジェクト204に着地するべく、羽を大きく広げてほぼ直立した状態で下降している場合(下降時)のゲーム画面200を示す。図11(A)および図11(B)に示すように、ゲーム画面200には、プレイヤオブジェクト202が表示されるとともに、複数のノンプレイヤオブジェクト204が表示される。プレイヤオブジェクト(ゲームキャラクタ)202は、鳥を模したオブジェクト(動画オブジェクト)である。ノンプレイヤオブジェクト204は、プレイヤオブジェクト202が着地する目標となるオブジェクトである。
この仮想ゲームでは、プレイヤオブジェクト202はプレイヤの操作に従って移動(飛行)し、複数のノンプレイヤオブジェクト204に着地しながら最終的な目標位置(ゴール)を目指す。たとえば、プレイヤオブジェクト202が、着地すべきすべてのノンプレイヤオブジェクト204を経由して、制限時間内にゴールに到達すると、ゲームクリアとなる。一方、プレイヤオブジェクト202がゴールに到達する前に制限時間を超えてしまったり、プレイヤオブジェクト202がノンプレイヤオブジェクト204を囲む海に落ちている時間が一定時間(たとえば、10秒)を超えてしまったり、プレイヤオブジェクト202が一定回数(たとえば、3回)海に落ちてしまったりすると、ゲームオーバとなる。
ゲーム中では、プレイヤは、荷重コントローラ36に乗り、鳥が羽ばたくように両手を上下に動かす(羽ばたき動作を行う)。すると、荷重コントローラ36で検出される荷重値が変化する。したがって、体重率WRも変化する。この体重率WRの変化に基づいて、プレイヤオブジェクト202の移動が制御される。この実施例では、プレイヤが羽ばたき動作を行うときの手(腕)の振りの強さ(体重率WRの変化量)に応じてプレイヤオブジェクト202の移動量(移動速度)が制御され、荷重コントローラ36上におけるプレイヤの重心位置に応じてプレイヤオブジェクト202の移動方向が制御される。
具体的には、図12(A)に示すように、プレイヤは、荷重コントローラ36上で、両手を大きく広げて、肩を中心に両手を大きく上下に振るように動作(大きく羽ばたく動作)を行ったり、図12(B)に示すように、プレイヤが、荷重コントローラ36上で、両手を小さく広げて、肘を中心に前腕を上下に振るように動作(小さく羽ばたく動作)を行ったりする。
図示は省略するが、プレイヤが大きく羽ばたく動作(大羽ばたき動作)を行うと、プレイヤオブジェクト202も大羽ばたき動作のアニメーションでモニタ34に表示され、プレイヤが小さく羽ばたく動作(小羽ばたき動作)を行うと、プレイヤオブジェクト202も小羽ばたき動作のアニメーションでモニタ34に表示される。同様に図示は省略するが、大羽ばたき動作のアニメーションは、小羽ばたき動作のアニメーションに比べて、羽の可動範囲(上下方向への移動範囲)が広く(大きく)される。
ここで、プレイヤが行う、大羽ばたき動作と、小羽ばたき動作との判別方法について説明する。図13には、プレイヤが図12(A)に示したような大羽ばたき動作をした場合における、体重率WRの時間変化のグラフの一例が示される。また、図14には、プレイヤが図12(B)に示したような小羽ばたき動作をした場合における、体重率WRの時間変化のグラフの一例が示される。図13および図14(図15も同じ)では、体重率WRの時間変化は実線の波形で示される。
図13および図14に示す体重率WRの時間変化を、それぞれ離散フーリエ変換すると、各々の図に示すように、パワースペクトル(周波数のインデックス番号nに対する振幅A)が得られる。図13および図14(図15も同じ)では、パワースペクトルについては、ドットで示してある。このように、離散フーリエ変換処理を実行するのは、プレイヤの羽ばたき動作(特に大羽ばたき動作)を正しく認識するためである。つまり、体重率WRの時間変化の波形からは、プレイヤの小羽ばたき動作と大羽ばたき動作とを区別するのが困難だからである。
ここで、離散フーリエ変換では、波形のデータ数をxとし、時間刻みをdt(秒)とすると、周波数fは1/(x・dt)刻みとなる。この実施例では、x=30,dt=1/60(ゲームフレーム)であるため、周波数f(Hz)は2刻みとなる。したがって、インデックス番号nを2倍した値が周波数f(Hz)となる。ただし、ゲームフレームは、画面更新単位時間である。
図13から分かるように、大羽ばたき動作の場合には、周波数のインデックス番号n=1のときに、振幅Aが最大値となる。また、図14から分かるように、小羽ばたき動作の場合には、周波数のインデックス番号n=2のときに、振幅Aが最大値となる。したがって、体重率WRの時間変化を離散フーリエ変換し、その結果、振幅Aが最大となる場合の周波数のインデックス番号nを調べることにより、大羽ばたき動作であるか、小羽ばたき動作であるかを判別することができると考えられる。ただし、図示は省略するが、実験の結果では、プレイヤが大羽ばたき動作を行った場合においても、ノイズの影響により、周波数のインデックス番号n=2のときに、振幅Aが最大値となることがあった。このため、この実施例では、大羽ばたき動作または小羽ばたき動作を、数1に従って判別するようにしてある。振幅Aが最大値となる周波数のインデックス番号n、または振幅Aが最大値となる周波数のインデックス番号nおよび当該振幅Aが、数1を満たす場合には、小羽ばたき動作と判別され、数1を満たさない場合には、大羽ばたき動作と判別される。ただし、大羽ばたき動作時のノイズ(スペクトルノイズ)の最大値をPn(0.0001)とする。
[数1]
n≧3
または
n=2でAが最大、かつn=3でA≧Pn
ただし、数1を満たさない場合に、周波数のインデックス番号n=1−15において、すべての振幅AがPn未満である場合には、周期的な動作が何ら行われていないと考えられるため、プレイヤが羽ばたき動作を行っていないと判断するようにしてある。
このように、プレイヤの羽ばたき動作の有無および羽ばたき動作の種類(大羽ばたき動作または小羽ばたき動作)が判別されると、羽ばたきの種類に応じてアニメーションが選択され、選択されたアニメーションが再生される。したがって、上述したように、プレイヤの羽ばたき動作に応じて、プレイヤオブジェクト202の羽ばたき動作のアニメーションがモニタ34に表示されるのである。
ただし、プレイヤが羽ばたき動作を行っておらず、プレイヤオブジェクト202が3次元仮想空間内を下降している場合には、プレイヤオブジェクト202が下降中のアニメーション(下降時アニメーション)が再生される。
ここで、上述したように、この実施例では、荷重コントローラ36に乗っているプレイヤが羽ばたき動作を行うことにより、その荷重コントローラ36で検出される荷重値が変動し、体重率WRも変動する。したがって、たとえば、荷重コントローラ36に乗っているプレイヤが屈伸運動を行った場合にも、プレイヤが羽ばたき動作を行った場合と同様に、その荷重コントローラ36で検出される荷重値が周期的に変動する。かかる場合の体重率WRの時間変化のグラフの一例が図15に示される。図13ないし図15を比較して分かるように、屈伸運動を行った場合には、羽ばたき動作を行った場合よりも、体重率WRの変動がかなり大きくなる。
後で具体的に示すが、この実施例では、体重率WRの大きさ(負の値)に応じた推進力がプレイヤオブジェクト202に与えられ、これによって、プレイヤオブジェクト202は3次元仮想空間内を移動する。このため、プレイヤが屈伸運動を行った場合には、プレイヤが羽ばたき動作を行った場合よりも、大きな推進力をプレイヤオブジェクト202に与えることができ、プレイヤオブジェクト202を大きく移動させることができる。しかし、このような屈伸運動は、開発者等が意図する操作方法ではない。
したがって、この実施例では、プレイヤの直前の羽ばたき動作(羽ばたき区間)において、一定の閾値(たとえば、1.3)を超える体重率WRが存在する場合には、屈伸運動のような意図しない動作が行われていると判断して、仮想ゲームのスコアを減点したり、プレイヤオブジェクト202を進行し難くしたりしてある。
この実施例では、前々回の振り下ろし動作の開始から前回(直前)の振り下ろし動作の開始までの区間を、直前の羽ばたき動作(羽ばたき区間)として認識するようにしてある。ただし、図13−図15では、振り下ろし動作の開始時点を一点鎖線で示してある。振り下ろし動作とは、羽ばたき動作において、プレイヤが両手ないし両腕を振り下ろす動作を意味する。この振り下ろし動作の開始の判定方法については、後で詳細に説明することにする。ただし、上述したように、図15に示す体重率WRの時間変化が得られるのは、プレイヤが屈伸運動を行っている場合であるため、後述する判定方法においては、振り下ろし動作の開始が判定されるのではなく、足の曲げ動作の開始が判定されているのである。
上述したように、ゲーム中では、体重率WRに基づく推進力Accがプレイヤオブジェクト202に与えられる。この実施例では、推進力Accは、数2に従って算出される。ただし、体重率WRは所定の閾値(この実施例では、0.985)未満である。このように、体重率WRが1.0よりも小さい値である場合に、推進力Accを与えるのは、鳥が羽を振り下ろしたときに推進力を得るのと同様にしたためである。また、所定の閾値未満としたのは、ノイズによる影響を無くすためである。
[数2]
推進力Acc=1.0−体重率WR
ここで、数2から分かるように、体重率WRが小さい程、推進力Accが大きくなる。つまり、荷重値の変動が大きい場合に、推進力Accが大きくなる。また、推進力Accは、体重率WRが所定の閾値未満である場合に与えられ、この推進力Accは1ゲームフレーム毎に、プレイヤオブジェクト202の移動に反映されるため、所定の閾値未満である時間が長いほど、つまり大羽ばたき動作のように羽ばたき動作の周期が長いほど、推進力Accを得る回数が多くなる。結果として、大きい推進力Accがプレイヤオブジェクト202に与えられ、したがって、プレイヤオブジェクト202の移動距離または移動速度が大きくなる(数3および数4参照)。
数2で算出される推進力Accはスカラ量であるが、3次元仮想空間においては、プレイヤオブジェクト202が直立した状態で頭頂部から真上に延びる単位ベクトル(Yベクトル)AccDirに、そのスカラ量を積分シミュレーションで用いる値(AccSim)に変換して乗算される。ただし、単位ベクトルAccDirは、後述するように、プレイヤの重心位置に応じてプレイヤオブジェクト202がローカル座標のX軸周りおよびY軸周りに回転されることにより、決定される。
積分シミュレーションでは、推進力Accに基づいて、移動後のプレイヤオブジェクト202の位置(3次元位置)Posが数3および数4に従って算出される。ただし、プレイヤオブジェクト202は、現在のゲームフレーム(現フレーム)において、頭頂部が向く方向すなわち単位ベクトルAccDirの向きに移動される。また、数3および数4においては、プレイヤオブジェクト202の次のゲームフレーム(次フレーム)の速度をVel_newとし、移動前すなわち現フレームの速度をVel_oldとし、3次元仮想空間の重力加速度ベクトルをGravityとし、現フレームの3次元位置をPos_oldとし、そして、次フレームの3次元位置をPos_newとしてある。また、数3においては、次フレームの速度Vel_newには、プレイヤオブジェクト202が下降時に前後方向に移動する場合の加速度ベクトル(AccBoard×FallTransDir)が反映される。ただし、AccBoardは並進加速度(水平方向の加速度)であり、FallTransDirは並進方向(水平方向)の方向ベクトル(プレイヤオブジェクト202の正面方向または背面方向のベクトル)である。
[数3]
Vel_new={Vel_old+(AccSim×AccDir)+(AccBoard×FallTransDir)-Gravity}×0.994
[数4]
Pos_new=Pos_old+Vel_new
ただし、この実施例では、重力加速度ベクトルGravity=(0,0.014,0)としてある。ここで、この実施例では、現実世界における距離1mを、3次元仮想空間内における距離10としてあるが、その比率に応じて重力加速度Gravityを設定すると、プレイヤの羽ばたき動作によってプレイヤオブジェクト202を飛行させるために十分な推進力を得るのは困難であるため、実験等により経験的に得られた比較的小さい値に設定される。また、0.994は空気抵抗である。したがって、定数である必要はなく、仮想ゲームの進行状況に応じて可変的に設定するようにしてもよい。
数3から分かるように、加速度ベクトル((AccSim×AccDir)または(AccBoard×FallTransDir))と重力加速度ベクトルGravityとを現フレームの速度Vel_oldに足して、空気抵抗の値を掛けることにより、次フレームの速度Vel_newを得る。また、数4から分かるように、次フレームの速度Vel_newを現フレームの座標Pos_oldに足して、次フレームの座標Pos_newを得る。これは、シミュレーションに使用する推進力AccSimを積分(2回積分)した結果である。
なお、プレイヤによる羽ばたき動作が無い場合には、体重率WRが1またはほぼ1であるため、シミュレーションに使用する推進力AccSim(加速度ベクトル(AccSim×AccDir))は0となり、数3は数5のように示される。
[数5]
Vel_new={Vel_old+(AccBoard×FallTransDir)-Gravity}×0.994
したがって、1ゲームフレーム毎に、次フレームの速度Vel_newのY成分が0.014ずつ減少する。これにより、3次元仮想空間における自由落下が表現される。つまり、数3では、3次元仮想空間の重力場において、推進力が発生したときの物体の並進運動が記述されている。
また、プレイヤによる羽ばたき動作が有り、プレイヤオブジェクト202が下降していない場合には、数3において、プレイヤオブジェクト202の下降時における前後方向の加速度ベクトル(AccBoard×FallTransDir)は0となる。
このようにして、プレイヤオブジェクトの3次元仮想空間における移動後の3次元位置Pos_newが算出され、数6に示す行列式Aに従って、プレイヤオブジェクト202は、3次元仮想空間に配置される。ただし、数6に示す行列式Aの各要素は次の意味を持つ。要素(Xx,Xy,Xz)はプレイヤオブジェクト202のローカル座標のX軸を当てはめる方向であり、要素(Yx,Yy,Yz)はプレイヤオブジェクト202のローカル座標のY軸を当てはめる方向であり、要素(Zx,Zy,Zz)はプレイヤオブジェクト202のローカル座標のZ軸を当てはめる方向であり、要素(Px,Py,Pz)はプレイヤオブジェクト202のローカル座標の中心(重心)を置くワールド座標(3次元座標)である。
また、ゲーム中では、荷重コントローラ36上におけるプレイヤの荷重の重心位置に応じて、プレイヤオブジェクト202の進行方向(移動方向)が決定(制御)される。図16(A)は、荷重コントローラ36の上面(支持板360の上層板360aの表面)すなわち重心位置の検出範囲の中心を原点O(0,0)に設定し、水平面内における原点Oからの重心位置のずれ量で、プレイヤオブジェクト202の頭部の向き(移動方向)が決定される。ここでは、荷重コントローラ36の支持板360の横方向が検出範囲のX軸方向であり、その縦方向が検出範囲のY軸方向である。ただし、荷重コントローラ36に正しく乗ったプレイヤの顔の方向(正面方向)は、図16(A)の紙面の上方である。また、図16(A)に示すように、検出範囲の右方向がX軸のプラス方向であり、検出範囲の上方向がY軸のプラス方向である。
ここで、図16(A)に示す状態において、左上の荷重センサ36bの荷重検出値をR1、左下の荷重センサ36bの荷重検出値をR2、右上の荷重センサ36bの荷重検出値をR3、右下の荷重センサ36bの荷重検出値をR4としたとき、検出範囲の座標系における重心のX座標(XG)は、右荷重値と左荷重値との差分に基づいて算出され、重心のY座標(YG)は上荷重値と下荷重値との差分に基づいて算出される。重心のX座標(XG)は数7によって算出され、重心のY座標(YG)は数8によって算出される。
[数7]
XG=((R3+R4)−(R1+R2))×k1
[数8]
YG=((R1+R3)−(R2+R4))×k2
ここで、k1,k2は定数である。ただし、−1≦XG≦1、−1≦YG≦1である。
なお、この実施例では、荷重コントローラ36の検出範囲の中心を原点Oに設定するようにしてあるが、プレイヤによって、立ち位置が異なるため、プレイヤが荷重コントローラ36に乗り、体重値を計測している場合の重心位置を原点Oに設定してもよい。
この実施例では、プレイヤオブジェクト202が飛行している場合において、下降している場合と下降していない場合とで、プレイヤオブジェクト202の移動方向の制御方法が異なる。以下、それぞれの場合について説明することにする。
プレイヤオブジェクト202が下降していない場合には、プレイヤオブジェクト202は、荷重コントローラ36で検出される荷重の重心位置のX座標に応じて左右方向に回転され、重心位置のY座標に応じて前後方向に回転される。
重心位置が検出範囲内の領域(I)または領域(III)に含まれ、重心位置のX座標が負の場合には、プレイヤオブジェクト202は、ローカル座標のY軸回りに、反時計周り(左周り)に回転される。また、重心位置が検出範囲内の領域領域(II)または領域(IV)に含まれ、重心位置のX座標が正の場合には、プレイヤオブジェクト202は、ローカル座標のY軸回りに、時計周り(右周り)に回転される。
具体的には、図16(B)に示すように、プレイヤオブジェクト202を真上から見た場合に、重心位置のX座標の負の値に応じて、プレイヤオブジェクト202のローカル座標のY軸の反時計回りの回転量が決定され、重心位置のX座標の正の値に応じて、プレイヤオブジェクト202のローカル座標のY軸の時計周りの回転量が決定される。回転量は、重心位置のX座標の大きさに比例する。また、重心位置のX座標が正の値であれば、プレイヤオブジェクト202は、そのローカル座標のY軸の時計回りに回転し続ける。
ただし、この実施例では、ローカル座標は、プレイヤオブジェクト202が直立した状態において、横(水平)方向がX軸方向であり、縦(垂直)方向がY軸方向であり、前後(奥行き)方向がZ軸方向である。また、各軸は、プレイヤオブジェクト202の中心ないし重心を通る。さらに、プレイヤオブジェクト202が直立した状態で、その左手(左の羽)の方向がローカル座標のX軸のプラス方向であり、その上方向がローカル座標のY軸のプラス方向であり、その前方向(腹の方向)がローカル座標のZ軸のプラス方向である。
また、重心位置が検出範囲内の領域(I)または領域(II)に含まれ、重心位置のY座標が正の場合には、図17に示すように、頭部が前方(正面方向)に傾くように、プレイヤオブジェクト202はローカル座標のX軸回りに回転する。正面方向への傾斜量(回転量)は、重心位置のY座標の大きさに比例するが、最大傾斜量はプレイヤオブジェクト202が直立した状態から55度である。
図示は省略するが、重心位置が検出範囲内の領域(III)または領域(IV)に含まれ、重心位置のY座標が負の場合には、プレイヤオブジェクト202は、ローカル座標のX軸回りであり、その背面方向に回転される。ただし、プレイヤオブジェクト202の背面方向への最大傾斜量は35度に設定される。これは、プレイヤオブジェクト202が腹を上にして飛行しているような所望でない状態を回避するためである。
一方、プレイヤオブジェクト202が下降している場合には、プレイヤオブジェクト202は、荷重コントローラ36で検出される荷重の重心位置のX座標に応じて左右方向に回転され、重心位置のY座標に応じて前後方向に並進される。
プレイヤオブジェクト202が下降している場合においても、重心位置のX座標に応じて、プレイヤオブジェクト202はローカル座標のY軸周りに回転される。これは、図16(B)を用いて説明したのと同じであるため、重複した説明は省略する。
また、プレイヤオブジェクト202が下降している場合には、図18に示すように、重心位置のY座標に応じて、プレイヤオブジェクト202は、前後方向に移動(並進)される。つまり、かかる場合には、プレイヤオブジェクト202の頭部は傾斜されない。また、並進する場合の移動量(変位量)は、重心位置のY座標の大きさによって決定される。このように、下降時に、重心位置のY座標に応じて並進されるのは、プレイヤオブジェクト202をノンプレイヤオブジェクト204に着地させ易くするためである。重心位置のY座標が正の場合には、プレイヤオブジェクト202は、正面方向に移動(並進)する。このとき、Y座標が大きくなると、移動量も大きくされる。一方、重心位置のY座標が負の場合には、プレイヤオブジェクト202は、正面方向とは逆向き(背面方向)に並進する。このとき、Y座標が小さくなると、つまり負の方向に大きくなると、移動量が大きくされる。ただし、プレイヤオブジェクト202が1ゲームフレームで移動する移動量の最大値は予め設定されている。
また、図13−図15に示したような体重率WRの時間変化から、プレイヤが腕を上方向に振り上げる(以下、「振り上げ」という)動作の開始を判定(振り上げ判定)するとともに、腕を下方向に振り下ろす(以下、「振り下ろし」という)動作の開始を判定(振り下ろし判定)する。これは、プレイヤの羽ばたき動作とプレイヤオブジェクト202の羽ばたき動作のアニメーションとを同期させるためである。
以下、振り下ろし判定の方法および振り上げ判定の方法、およびプレイヤの羽ばたき動作とプレイヤオブジェクト202の羽ばたき動作のアニメーションとの同期について順番に説明することにする。
この実施例では、現フレームの体重率WRが1つ手前のゲームフレーム(前フレーム)の体重率WRよりも小さく、しかも現フレームの体重率WRの値が一定値(0.985)未満になると、振り下ろし動作の開始であると判定する。また、この実施例では、体重率WRの値が一定値(0.98)以上であり、体重率WRが減少した後に増加すると、振り上げ動作の開始であると判定する。これらは、図13および図14に示したような体重率WRの時間変化に基づいて、経験的に得られた判定方法である。
ただし、体重率WRが減少するというのは、現フレームの体重率WRが前フレームの体重率WRよりも小さいことを意味し、体重率WRが増加するというのは、前フレームの体重率WRが前フレームの体重率WRよりも大きいことを意味する。また、振り上げ動作の開始を判定する場合に、体重率WRが一定値以上であることを条件としたのは、図13に示したように、体重率WRが0.9あたりの極小値の前後で振り上げ動作の開始であると判定するのを防止するためである。つまり、この実施例では、プレイヤが大羽ばたき動作を行っている場合に、両手(両腕)を肩と同じくらいの高さ或いは肩よりも上方の高さに振り上げた動作を、「振り上げ動作」として判定するようにしているのである。これが、開発者等が意図するプレイヤの「振り上げ動作」である。
なお、上述した図13−図15では、振り下ろし動作の開始時を一点鎖線で示す。また、図13では、振り上げ動作の開始時を二点鎖線で示す。
次に、プレイヤの羽ばたき動作と、プレイヤオブジェクト202の羽ばたき動作のアニメーションとの同期について説明する。まず、プレイヤオブジェクト202のアニメーションは、羽ばたきの種類(大小)に拘わらず、いずれも60フレーム(60コマ)で構成されている。上述したように、羽ばたきの種類で異なるのは、羽の可動範囲の大きさだけである。以下には、大羽ばたき動作の場合について、プレイヤの羽ばたき動作とプレイヤオブジェクト202の羽ばたき動作のアニメーションとの同期について説明するが、小羽ばたき動作についても同様である。
図19には、大羽ばたきのアニメーションについての60フレーム(アニメーションフレーム)のうち、特徴的なアニメーションフレーム(ここでは、0(60),7,15,22,30,37,45,52)が抜き出される。アニメーションフレームは、0から始まって59まで進み、次のアニメーションフレームで0(60)に戻る。ただし、図19では、簡単のため、プレイヤオブジェクト202の頭部、胴体および羽のみを示してある。また、図19では、プレイヤオブジェクト202の正面方向は、紙面に対して垂直方向である。さらに、図19では、上段に、アニメーションフレームの0から30までを示し、下段に、アニメーションフレームの30から60(0)までを示してある。
図19に示すように、アニメーションフレームが0のときには、プレイヤオブジェクト202は、たとえば、水平方向に羽を広げた状態であり、3次元仮想空間の水平面に対して羽がなす角度は0度である。この実施例では、アニメーションフレームが再生されると、プレイヤオブジェクト202は、水平方向に羽を広げた状態から上に羽を振り上げ、アニメーションフレームが15フレームで羽が最高位置に達し、その後、羽が振り下ろされる。そして、アニメーションフレームが45フレームで羽が最下位置に達し、その後、羽が振り上げられて、60フレーム(0フレーム)で初期の状態に戻る。
なお、アニメーションフレームは60個(60コマ)であるが、小数点でフレーム数(フレーム番号)を指定することもできる。たとえば、フレーム番号が0のアニメーションフレームにおけるプレイヤオブジェクト202の腕の角度(水平面となす角度)が0度であり、フレーム番号が1のアニメーションフレームにおけるプレイヤオブジェクト202の腕の角度が10度であるとし、フレーム番号として0.5を指定すると、腕の角度が5度のプレイヤオブジェクト202を得ることができる。したがって、理論上、プレイヤオブジェクト202のポーズの種類は、無限大に存在する。
この実施例では、プレイヤの羽ばたき動作と、プレイヤオブジェクト202のアニメーションフレームの同期を取る方法として、振り下ろし動作の開始の判定時におけるアニメーションフレームの進め方Aと、振り上げ動作の開始の判定時におけるアニメーションフレームの進め方Bとがある。ただし、プレイヤが小羽ばたき動作を行う場合には、振り上げ動作が判定されることがないため、アニメーションフレームの進め方Aのみによって同期が取られる。
まず、アニメーションフレームの進め方Aについて説明する。上述したように、振り下ろし動作の開始が判定されると、現在のアニメーションフレームが図19に示す振り下ろし加速度発生可能区間(フレーム番号:15以上30未満)内であるかどうかが判断される。
振り下ろし動作の開始が判定されると、アニメーションフレームが振り下ろし加速度発生可能区間内である場合に、振り下ろし加速度が発生される。つまり、アニメーションフレームの加速度FrameAccに0より大きい値が設定され、更新速度がゲームフレーム(1/60(秒))よりも速くされる。この実施例では、アニメーションフレームのフレーム加速度FrameAccは、数9に従って算出される。ただし、AnimFrameMaxは、アニメーションフレームの最大フレーム数(この実施例では、60)である。また、CycleSwingは、1回の羽ばたき動作に要した時間(羽ばたき区間)であり、ゲームフレーム数で表わされる。以下、同様である。
[数9]
FrameAcc=AnimFrameMax/CycleSwing
このように、フレーム加速度FrameAccが発生されると、その瞬間にアニメーションフレームの進行が最も速くなり、プレイヤオブジェクト202が羽を振り下ろすアニメーションが再生され、プレイヤの羽ばたき動作と、プレイヤオブジェクト202の羽ばたき動作とが同期(リンク)しているように見える。その後、アニメーションフレームは、次の振り下ろし動作または振り上げ動作が判定されるまで、惰性で進行する。つまり、何ら加速が無ければ(FrameAcc=0)、アニメーションフレームのフレーム速度が空気抵抗によって減少していき、やがて0になり、アニメーションの再生が止まる。
具体的には、ゲーム画面を表示(更新)する時のアニメーションフレームのフレーム数は、数10および数11に従って決定される。ただし、アニメーションフレームの更新(進行)速度(フレーム速度)はFrameVelで示され、アニメーションフレームの加速度(フレーム加速度)はFrameAccで示され、アニメーションフレームのフレーム数(番号)はFrameで示される。また、現フレーム(今回)の値には、oldが付され、次フレーム(次回)の値には、newが付される。したがって、数10では、空気抵抗を考慮した次回のフレーム速度が算出され、また、数11では、次回のフレーム番号が算出される。
[数10]
FrameVel_new=(FrameVel_old+FrameAcc)×0.99
[数11]
Frame_new=Frame_old+FrameVel_new
ただし、0.99は空気抵抗である。したがって、定数である必要はなく、仮想ゲームの進行状況に応じて可変的に設定してもよい。
一方、振り下ろし動作が判定されたときに、アニメーションフレームが振り下ろし加速度発生可能区間内でないときは、振り下ろし加速度発生可能区間まで、数12で算出されたフレーム速度(ただし、フレーム加速度AnimeVcc=0)に従ってアニメーションフレームが進められる。
[数12]
FrameVel_old=AnimFrameMax×1.7/CycleSwing
そして、アニメーションフレームが振り下ろし加速度発生可能区間まで進められると、上述したように、フレーム加速度FrameAccが発生され、プレイヤの羽ばたき動作と、プレイヤオブジェクト202の羽ばたき動作との同期が取られる。
次に、アニメーションフレームの進め方Bについて説明する。上述したように、振り上げ動作の開始が判定されると、現在のアニメーションフレームが図19に示す振り上げ加速度発生可能区間(フレーム番号:30以上60未満)内であるかどうかを判断する。
振り上げ動作の開始が判定さたときに、アニメーションフレームが振り上げ加速度発生可能区間内である場合には、振り上げ加速度が発生される。つまり、フレーム加速度FrameAccに0より大きい値(この実施例では、2)が設定され、更新速度がゲームフレーム(1/60(秒))よりも速くされる。つまり、フレーム加速度FrameAccを発生させた瞬間にアニメーションフレームの進行が最も速くなり、プレイヤオブジェクト202が羽を振り上げるアニメーションが再生され、プレイヤの羽ばたき動作と、プレイヤオブジェクト202の羽ばたき動作とが同期しているように見える。ただし、現在のフレーム速度FrameVel_oldが2以上である場合には、フレーム加速度FrameAccは0に設定される。
一方、振り上げ動作の開始が判定されたときに、現在のアニメーションフレームが振り上げ加速度発生可能区間内でない場合には、アニメーションフレームは、惰性で進行される。詳細な説明は省略するが、振り上げ動作の場合のフレーム数の算出も、上述した数10および数11に従って算出される。
ここで、振り下ろし加速度発生可能区間を15フレーム以上30フレーム未満に設定しているのは、その間にアニメーションフレームの進行を加速させると、プレイヤの振り下ろし動作に同期して、プレイヤオブジェクト202が羽を振り下ろしていると、プレイヤが感じるからである。
仮に、アニメーションフレームが37付近において、アニメーションフレームの進行を加速させ、アニメーションフレームが45フレーム付近まで速く進んだとすると、プレイヤオブジェクト202が、羽を振り下ろした後、直ぐに羽を振り上げたと、プレイヤが感じてしまう。
また、振り上げ加速度発生可能区間を30フレーム以上60フレーム未満に設定しているのは、そのうち、45フレーム以上フレーム60未満については、振り下げ加速度発生可能区間と同様に、その間にアニメーションフレームの進行を加速させると、プレイヤの振り上げ動作に同期して、プレイヤオブジェクト202が羽を振り上げていると、プレイヤが感じるからである。
さらに、振り上げ加速度発生可能区間に30フレーム以上45フレーム未満を含んでいるのは、数ゲームフレーム後に来るはずのプレイヤの振り下ろし動作の開始の判定に備えて、出来るだけ振り下ろし加速度発生可能区間にアニメーションフレームを近づけておくためである。この場合、アニメーションフレームの30フレーム以上45フレーム未満においては、見た目には振り下ろしのアニメーションであるため、プレイヤが振り上げ動作を行ったにも関わらず、振り下ろしのアニメーションが再生されることになるが、直後にプレイヤは振り下ろし動作を行うため、その動作とアニメーションとの同期を取ることができる。
また、図示は省略するが、プレイヤが小羽ばたき動作を行う場合には、振り上げ判定が行われなくても、振り下ろし加速度発生可能区間においてアニメーションフレームを加速するだけで、プレイヤの羽ばたき動作とプレイヤオブジェクト202の羽ばたき動作のアニメーションとの同期を取ることができる。これは、プレイヤが大羽ばたき動作を行う場合にも同様である。したがって、振り上げ動作の開始の判定処理および振り上げ加速度発生可能区間における加速処理を実行しなくてもよいとも考えられる。
しかし、この実施例では、より正確に同期を取るために、振り上げ動作の開始の判定処理を行うとともに、振り上げ加速度発生可能区間において加速処理を実行するようにしてある。
図20には、図2に示したメインメモリ(42e,46)のメモリマップ400の一例を示す図解図である。図20に示すように、メインメモリ(42e,46)には、プログラム記憶領域402およびデータ記憶領域4040が設けられる。プログラム記憶領域402には、ゲームプログラムが記憶され、ゲームプログラムは、メイン処理プログラム402a、画像生成プログラム402b、画像表示プログラム402c、荷重取得プログラム402d、体重率算出プログラム402e、重心算出プログラム402f、動作判別プログラム402g、並進運動算出プログラム402h、回転運動算出プログラム402iおよびアニメーション同期プログラム402jなどによって構成される。
メイン処理プログラム402aは、この実施例の仮想ゲームのメインルーチンを処理するためのプログラムである。画像生成プログラム402bは、後述する画像データ404bを用いて、ゲーム画像データを生成(更新)するためのプログラムである。画像表示プログラム402cは、画像生成プログラム402bに従って生成されたゲーム画像データをゲーム画面(200など)としてモニタ34に表示(出力)するためのプログラムである。
荷重取得プログラム402dは、荷重コントローラ36で計測(検出)される現在の荷重値を取得するためのプログラムである。具体的には、4つの荷重センサ36bのそれぞれで検出される荷重値が合計される。この実施例では、仮想ゲームの本編の開始に先立って、プレイヤが荷重コントローラ36の上に乗り、静止した状態で、当該プレイヤの体重値が検出される。この体重値に対応する数値データが取得され、後述する基準値データ404fとしてデータ記憶領域404に記憶される。また、ゲーム中では、1ゲームフレーム毎に荷重値が検出され、検出された荷重値に対応する数値データが取得され、後述する現荷重値データ404gとしてデータ記憶領域404に記憶される。
体重率算出プログラム402eは、荷重取得プログラム402dに従って取得された現在(現フレーム)の荷重値を、同じく荷重取得プログラム402dに従って取得されたプレイヤの体重値(基準値)で割った体重率WRを1ゲームフレーム毎に算出するためのプログラムである。この体重率算出プログラム402eに従って算出された体重率WRの数値データが体重率データとして後述する体重率データバッファ404aに時系列に従って記憶される。
重心算出プログラム402fは、荷重取得プログラム402dに従って検出された各荷重センサ36bにおける荷重値を用いて、数7および数8に従って重心位置の座標(XG,YG)を算出し、算出した座標(XG,YG)に対応する座標データを後述する重心位置データ404hとしてデータ記憶領域404に記憶するためのプログラムである。
動作判別プログラム402gは、1ゲームフレーム毎に算出される体重率WRの時間変化を、一定時間(この実施例では、30ゲームフレーム)毎に離散フーリエ変換した結果に基づいて、プレイヤによる羽ばたき動作の有無および羽ばたき動作の種類(大羽ばたき動作または小羽ばたき動作)を判別するためのプログラムである。
並進運動算出プログラム402hは、羽ばたき動作によって得られる推進力または重心算出プログラム402fに従って算出された重心位置のY座標(YG)に基づいて、プレイヤオブジェクト202の一定時間(1ゲームフレーム)後の位置(3次元座標)を算出するためのプログラムである。
回転運動算出プログラム402iは、重心算出プログラム402fに従って算出された重心位置の座標(XG,YG)に基づいて、プレイヤオブジェクト202のローカル座標のX軸回りの回転量およびローカル座標のY軸回りの回転量を算出するためのプログラムである。アニメーション同期プログラム402jは、プレイヤの羽ばたき動作に、プレイヤオブジェクト202の羽ばたき動作のアニメーションを同期させるためのプログラムである。
なお、図示は省略するが、ゲームプログラムには、音出力プログラムやバックアッププログラムなども含まれる。音出力プログラムは、プレイヤオブジェクトの音声(擬声音)、効果音、音楽(BGM)のようなゲームに必要な音を生成し、スピーカ34aから出力するためのプログラムである。バックアッププログラムは、メインメモリ(42e,46)に記憶されたゲームデータ(途中データ,結果データ)を、フラッシュメモリ44やSDカードにセーブするためのプログラムである。
図21には、データ記憶領域404の具体的な内容が示される。図21に示すように、データ記憶領域404には、体重率データバッファ404aが設けられる。また、データ記憶領域404には、画像データ404b、大羽ばたきアニメーションデータ404c、小羽ばたきアニメーションデータ404d、下降時アニメーションデータ404e、基準値データ404f、現荷重値データ404gおよび重心位置データ404hが記憶される。さらに、データ記憶領域404には、下降中フラグ404i、体重率下降フラグ404j、振り上げ判定フラグ404k、振り下ろし判定フラグ404m、振り上げ加速フラグ404n、振り下ろし加速フラグ404p、大羽ばたきフラグ404q、小羽ばたきフラグ404r、着地成功フラグ404s、着地失敗フラグ404t、ゲームクリアフラグ404uおよびゲームオーバフラグ404vが設けられる。
体重率データバッファ404aは、体重率算出プログラム402eに従って1ゲームフレーム毎に算出される体重率データを、時系列に従って記憶するためのデータバッファである。
画像データ404bは、画像生成プログラム402bに従ってゲーム画像データを生成する際に使用されるポリゴンデータやテクスチャデータなどのデータである。大羽ばたきアニメーションデータ404cは、プレイヤオブジェクト202が大羽ばたき動作する場合のアニメーションのデータであって、60個(コマ)のアニメーションフレームで構成される。小羽ばたきアニメーションデータ404dは、プレイヤオブジェクト202が小羽ばたき動作する場合のアニメーションのデータであって、60個のアニメーションフレームで構成される。上述したように、大羽ばたきと小羽ばたきとでは、羽の可動範囲が異なるだけである。下降時アニメーションデータ404eは、プレイヤオブジェクト202が下降する場合のアニメーションのデータであって、45個のアニメーションフレームで構成される。
基準値データ404fは、仮想ゲームの本編に先立って荷重取得プログラム402dに従って取得された荷重値すなわちプレイヤの体重値についての数値データである。現荷重値データ404gは、荷重取得プログラム402dに従って取得される現在(現フレーム)の荷重値についての数値データである。重心位置データ404hは、重心算出プログラム402fに従って算出される現在(現フレーム)の重心位置の座標(XG,YG)についての座標データである。
下降中フラグ404iは、プレイヤオブジェクト202が下降中であるかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。プレイヤオブジェクト202が下降中である場合には、下降中フラグ404iは成立(オン)され、レジスタにデータ値「1」が設定される。一方、プレイヤオブジェクト202が下降中でない場合には、下降中フラグ404iは不成立(オフ)され、レジスタにデータ値「0」が設定される。
体重率下降フラグ404jは、体重率WRが下降(減少)しているかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。体重率WRが下降している場合には、体重率下降フラグ404jはオンされ、レジスタにデータ値「1」が設定される。一方、体重率WRが下降していない場合すなわち体重率WRが上昇したり変化しなかったりする場合には、体重率下降フラグ404jはオフされ、レジスタにデータ値「0」が設定される。
振り上げ判定フラグ404kは、振り上げ動作の開始が判定されたかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。振り上げ動作の開始が判定されると、振り上げ判定フラグ404kはオンされ、レジスタにデータ値「1」が設定される。一方、振り下ろし動作の開始が判定されると、振り上げ判定フラグ404kはオフされ、レジスタにデータ値「0」が設定される。ただし、後述する振り下ろし判定フラグ404mがオンされた場合にも、振り上げ判定フラグ404kはオフされる。
振り下ろし判定フラグ404mは、振り下ろし動作の開始が判定されたかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。振り下ろし動作の開始が判定されると、振り下ろし判定フラグ404mはオンされ、レジスタにデータ値「1」が設定される。一方、振り上げ動作の開始が判定されると、振り下ろし判定フラグ404mはオフされ、レジスタにデータ値「0」が設定される。ただし、上述した振り上げ判定フラグ404kがオンされた場合にも、振り下ろし判定フラグ404mはオフされる。
振り上げ加速フラグ404nは、振り上げ動作に応じてアニメーションフレームを加速させたか否かを判定するためのフラグであり、1ビットのレジスタで構成される。振り上げ動作の開始が判定されると、振り上げ加速フラグ404nはオンされ、レジスタにデータ値「1」が設定される。また、振り上げ動作の開始が判定され、アニメーションフレームが加速されると、振り上げ加速フラグ404nはオフされ、レジスタにデータ値「0」が設定される。
振り下ろし加速フラグ404pは、振り下ろし動作に応じてアニメーションフレームを加速させたか否かを判定するためのフラグであり、1ビットのレジスタで構成される。振り下ろし動作の開始が判定されると、振り下ろし加速フラグ404pはオンされ、レジスタにデータ値「1」が設定される。また、振り下ろし動作の開始が判定され、アニメーションフレームが加速されると、振り下ろし加速フラグ404pはオフされ、レジスタにデータ値「0」が設定される。
大羽ばたきフラグ404qは、大羽ばたき動作が判別されたかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。大羽ばたき動作が判別されると、大羽ばたきフラグ404qはオンされ、レジスタにデータ値「1」が設定される。一方、大羽ばたき動作が判別されなければ、大羽ばたきフラグ404qはオフされ、レジスタにデータ値「0」が設定される。ただし、後述する小羽ばたきフラグ404rがオンされた場合やプレイヤが羽ばたき動作を行っていない場合にも、大羽ばたきフラグ404qはオフされる。
小羽ばたきフラグ404rは、小羽ばたき動作が判別されたかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。小羽ばたき動作が判別されると、小羽ばたきフラグ404rはオンされ、レジスタにデータ値「1」が設定される。一方、小羽ばたき動作が判別されなければ、小羽ばたきフラグ404rはオフされ、レジスタにデータ値「0」が設定される。ただし、上述した大羽ばたきフラグ404qがオンされた場合やプレイヤが羽ばたき動作を行っていない場合にも、小羽ばたきフラグ404rはオフされる。
着地成功フラグ404sは、プレイヤオブジェクト202がノンプレイヤオブジェクト204への着地に成功したかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。プレイヤオブジェクト202がノンプレイヤオブジェクト204への着地に成功すると、着地成功フラグ404sはオンされ、レジスタにデータ値「1」が設定される。一方、プレイヤオブジェクト202がノンプレイヤオブジェクト204に着地に成功していなければ、着地成功フラグ404sはオフされ、レジスタにデータ値「0」が設定される。
着地失敗フラグ404tは、プレイヤオブジェクト202がノンプレイヤオブジェクト204への着地に失敗したかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。プレイヤオブジェクト202がノンプレイヤオブジェクト204への着地に失敗すると、着地失敗フラグ404tはオンされ、レジスタにデータ値「1」が設定される。一方、プレイヤオブジェクト202がノンプレイヤオブジェクト204への着地に失敗していなければ、着地失敗フラグ404tはオフされ、レジスタにデータ値「0」が設定される。
ゲームクリアフラグ404uは、仮想ゲームがクリアされたかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。ゲームクリアされると、ゲームクリアフラグ404uがオンされ、レジスタにデータ値「1」が設定される。一方、ゲームクリアでなければ、ゲームクリアフラグ404uがオフされ、レジスタにデータ値「0」が設定される。
ゲームオーバフラグ404vは、仮想ゲームがゲームオーバになったかどうかを判定するためのフラグであり、1ビットのレジスタで構成される。ゲームオーバになると、ゲームオーバフラグ404vがオンされ、レジスタにデータ値「1」が設定される。一方、ゲームオーバでなければ、ゲームオーバフラグ404vがオフされ、レジスタにデータ値「0」が設定される。
なお、図示は省略するが、データ記憶領域404には、音データのような他のデータが記憶され、ゲームプログラムの実行に必要なタイマ(カウンタ)や他のフラグが設けられる。
具体的には、図2に示したCPU40が図22−図25に示すフロー図に従って全体処理を実行する。図示は省略するが、全体処理とは別のタスクにより、CPU40は、一定時間(30ゲームフレーム)毎に、体重率WRの時間変化を離散フーリエ変換する処理を実行する。
図22に示すように、全体処理を開始すると、ステップS1で、初期設定を実行する。このステップS1では、CPU40は、体重率データバッファ404a、基準値データ404f、現荷重値データ404gおよび重心位置データ404hをクリアしたり、画像データ404b、大羽ばたきアニメーションデータ404c、小羽ばたきアニメーションデータ404dおよび下降時アニメーションデータ404eをデータ記憶領域404にロードしたり、各種フラグ404i−404vをオフしたりする。
次のステップS3では、プレイヤの体重値を検出し、基準値として記憶する。つまり、CPU40は、仮想ゲームの本編の開始に先立って、4つの荷重センサ36bで検出された荷重値の合計を体重値として取得し、その数値データを基準値データ404fとしてデータ記憶領域404に記憶する。そして、ステップS5で、仮想ゲームの本編を開始する。
続いて、ステップS7では、現在(現フレーム)の荷重値を取得し、取得した荷重値を記憶する。つまり、CPU40は、4つの荷重センサ36bで検出された荷重値の合計を現在の荷重値として取得し、その数値データを現荷重値データ404gとしてデータ記憶領域404に記憶する。
なお、ステップS7−S79の処理のスキャンタイムは、1ゲームフレーム(1/60(秒))であるため、仮想ゲーム中では、1ゲームフレーム毎に、現在の荷重値が検出される。つまり、現荷重値データ404gは、1ゲームフレーム毎に更新される。このことは、次の重心位置データ404hも同様である。
次のステップS9では、現在の重心位置を算出し、算出した重心位置を記憶する。つまり、CPU40は、4つの荷重センサ36bから取得した荷重値を用いて、数2および数3に従って、現フレームの重心位置の座標(XG,YG)を算出し、算出した重心位置の座標(XG,YG)についての座標データを重心位置データ404hとしてデータ記憶領域404に記憶する。
続いて、ステップS11では、後述する動作判別処理(図26−図28参照)を実行する。次のステップS13では、動作判別処理の結果に基づいて、大羽ばたきかどうかを判断する。ここでは、CPU40は、大羽ばたきフラグ404qがオンであるかどうかを判断する。ステップS13で“YES”であれば、つまり大羽ばたきフラグ404qがオンであれば、大羽ばたきであると判断して、ステップS15で、積分シミュレーションで使用する推進力AccSimに、体重率WRを用いて算出された推進力Accに0.05を掛けた値を設定し(AccSim=Acc×0.05)、ステップS17で、大羽ばたきのアニメーションを選択して、図23に示すステップS25に進む。
また、ステップS13で“NO”であれば、つまり大羽ばたきフラグ404qがオフであれば、ステップS19で、小羽ばたきであるかどうかを判断する。つまり、CPU40は、小羽ばたきフラグ404rがオンであるかどうかを判断する。ステップS19で“NO”であれば、つまり小羽ばたきでなければ、プレイヤが羽ばたき動作を行っていないと判断して、そのままステップS25に進む。一方、ステップS19で“YES”であれば、つまり小羽ばたきであれば、ステップS21で、積分シミュレーションで使用する推進力AccSimに、体重率WRを用いて算出された推進力Accに0.0425を掛けた値を設定し(AccSim=Acc×0.0425)、ステップS23で、小羽ばたきのアニメーションを選択して、ステップS25に進む。
図23に示すステップS25では、重心の前後すなわち重心位置のY座標(YG)による並進加速度AccBoardを算出する。次のステップS27では、プレイヤオブジェクト202の移動後(次フレーム)の速度Vel_newを数3に従って算出する。続いて、ステップS29では、速度Vel_newが最大速度VelMaxを超えているかどうかを判断する。ステップS29で“NO”であれば、つまり速度Vel_newが最大速度VelMax以下であれば、そのままステップS33に進む。一方、ステップS29で“YES”であれば、つまり速度Vel_newが最大速度VelMaxを超えていれば、ステップS31で、速度Vel_newに最大速度VelMaxを設定して、ステップS33に進む。つまり、ステップS31では、速度Vel_newが最大速度VelMaxで制限される。
ステップS33では、プレイヤオブジェクト202の移動後の3次元位置Pos_newを数4に従って算出する。次のステップS35では、プレイヤオブジェクト202が下降中であるかどうかを判断する。ここでは、CPU40は、プレイヤオブジェクト202の現在の速度Vel_oldのY成分が一定値(この実施例では、−0.7)未満であるかどうかを判断する。ステップS35で“NO”であれば、つまり現在の速度Vel_oldのY成分が一定値以上であれば、プレイヤオブジェクト202は下降中でないと判断し、ステップS39で、重心位置のX座標(XG)およびY座標(YG)に基づいて、プレイヤオブジェクト202の回転量を算出し、ステップS41で、下降中フラグ404iをオフして、図24に示すステップ53に進む。
つまり、ステップS39では、CPU40は、重心位置のY座標(YG)に基づいてローカル座標のX軸周りの回転量と、重心位置のX座標(XG)に基づいてローカル座標のY軸周りの回転量とを算出する。このX軸周りの回転量とY軸周りの回転量とによって、まず、3次元仮想空間において、プレイヤオブジェクト202のローカル座標のZ軸を当てはめる方向(Zベクトル(Xz,Yz,Zz))を決定する。次に、このZベクトルに直交し、プレイヤオブジェクト202の左手方向に延びるローカル座標のX軸を当てはめる方向(Xベクトル(Xx,Yx,Zx))を決定する。さらに、ZベクトルとXベクトルとの外積を求めて、3次元仮想空間において、プレイヤオブジェクト202のローカル座標のY軸を当てはめる方向(Yベクトル(Xy,Yy,Zy))すなわち単位ベクトルAccDirを決定する。ただし、Xベクトル、YベクトルおよびZベクトルは、大きさ「1」の単位ベクトルである。
一方、ステップS35で“YES”であれば、つまり現在の速度Vel_oldのY成分が一定値未満であれば、プレイヤオブジェクト202は下降中であると判断して、ステップS36で、重心位置のX座標(XG)に基づいて、プレイヤオブジェクト202の回転量を算出し、ステップS39で、下降時アニメーションを選択して、図24に示すステップS43に進む。
つまり、ステップS36では、CPU40は、重心位置のX座標(XG)に基づいて、プレイヤオブジェクト202のローカル座標のY軸周りの回転量のみを算出し、3次元仮想空間において、プレイヤオブジェクト202のローカル座標のZ軸を当てはめる方向(Zベクトル)を決定する。その後、上述したように、3次元仮想空間において、プレイヤオブジェクト202のローカル座標のX軸を当てはめる方向(Xベクトル)を決定し、さらに、3次元仮想空間において、プレイヤオブジェクト202のローカル座標のY軸を当てはめる方向(Yベクトル)を決定する。
図24に示すステップS43では、下降中フラグ404iがオフであるかどうかを判断する。つまり、CPU40は、プレイヤオブジェクト202が下降を開始したかどうかを判断するのである。ステップS43で“YES”であれば、つまり下降中フラグ404iがオフであれば、プレイヤオブジェクト202が下降を開始したと判断して、ステップS45で、下降中フラグ404iをオンし、ステップS47で、アニメーションフレームFrame_newにフレーム番号の初期値(この実施例では、0)を設定し、ステップS51で、決定されたアニメーションフレームFrame_newのアニメーションを設定して、図25に示すステップS59に進む。
一方、ステップS43で“NO”であれば、つまり下降中フラグ404iがオンであれば、プレイヤオブジェクト202は既に下降中であると判断して、ステップS49でアニメーションフレームFrame_newに1加算して、ステップS51に進む。ただし、アニメーションフレームFrame_newの現在の値が「44」である場合には、つまりアニメーションフレームが最終フレームである場合には、ステップS49においてアニメーションフレームFrame_newに1加算されると、その値は「0」に設定される。つまり、アニメーションフレームのフレーム番号が初期値に戻される。
また、図23に示したように、プレイヤオブジェクト202が下降中でない場合には、ステップS37で“NO”となり、ステップS41で下降中フラグ404iをオフして後に、ステップS53で、ステップS17またはS23で選択された羽ばたきアニメーション(大羽ばたきアニメーション,小羽ばたきアニメーション)と現在の羽ばたきアニメーションとが異なるかどうかを判断する。ステップS53で“NO”であれば、つまり選択された羽ばたきアニメーションと現在の羽ばたきアニメーションとが一致している場合には、そのままステップS57に進む。一方、ステップS53で“YES”であれば、つまり選択された羽ばたきアニメーションと現在の羽ばたきアニメーションとが異なる場合には、ステップS55で、羽ばたきアニメーションを切り替えて、ステップS57に進む。
なお、ステップS55では、単にアニメーションを切り替えるようにしてあるが、大羽ばたきのアニメーションと小羽ばたきのアニメーションとを一気に切り替えると、ゲーム画面200を見ているプレイヤが違和感を覚えてしまう。このため、この実施例では、それらのアニメーションをブレンドするようにしてある。簡単に説明すると、たとえば、大羽ばたきのアニメーションから小羽ばたきのアニメーションに切り替える場合には、両方のアニメーションを再生する。たとえば、アニメーションを切り替えた瞬間では、大羽ばたきの再生比率は1.0であり、小羽ばたきの再生比率は0.0である。ただし、大羽ばたきのアニメーションと小羽ばたきのアニメーションとは、アニメーションフレームのフレーム番号は一致している。その再生比率が一定時間(この実施例では、30ゲームフレーム=0.5秒)の間で次第に(たとえば、線形的に、または段階的に)変化され、つまり大羽ばたきの再生比率が減少されるとともに、小羽ばたきの再生比率が増加され、アニメーションの切替開始から一定時間が経過すると(たとえば、30ゲームフレーム目には)、大羽ばたきの再生比率が0.0となり、小羽ばたきの再生比率が1.0となる。したがって、大羽ばたきのアニメーションから小羽ばたきのアニメーションに切り替えられる。説明は省略するが、小羽ばたきのアニメーションから大羽ばたきのアニメーションに切り替える場合も同様である。
図24に戻って、ステップS57では、後述する同期処理(図29−図31)を実行する。続いて、図25に示すステップS59では、所定の場所に着地成功したかどうかを判断する。ここでは、CPU40は、着地すべきノンプレイヤオブジェクト204に着地したかどうかを判断するのである。詳細な説明は省略するが、着地すべきノンプレイヤオブジェクト204は、予め設定されていたり、仮想ゲームの進行に応じて可変的に設定されたりする。ただし、CPU40は、プレイヤオブジェクト202と着地すべきノンプレイヤオブジェクト204との当たりを判定して、当該ノンプレイヤオブジェクト204上にプレイヤオブジェクト202が乗っているすなわち着地しているかどうかを判断するのである。
ステップS59で“YES”であれば、つまり所定の場所に着地成功したと判断すると、ステップS61で、着地成功フラグ404sをオンして、ステップS67に進む。ステップS59で“NO”であれば、つまりプレイヤオブジェクト202が飛行中であったり、海に落ちてしまったり、既に着地したことのあるノンプレイヤオブジェクト204に再度着地したりした場合には、所定の場所に着地成功していないと判断して、ステップS63で、所定の場所に着地失敗かどうかを判断する。ここでは、CPU40は、プレイヤオブジェクト202が着地すべきノンプレイヤオブジェクト204以外のノンプレイヤオブジェクト204に着地したり、ノンプレイヤオブジェクト204を囲む海に落ちたりしたかどうかを判断する。
ステップS63で“NO”であれば、つまりプレイヤオブジェクト202が飛行中である場合には、所定の場所に着地失敗していないと判断して、そのままステップS67に進む。一方、ステップS63で“YES”であれば、つまりプレイヤオブジェクト202が着地すべきノンプレイヤオブジェクト204以外のノンプレイヤオブジェクト204に着地したり、プレイヤオブジェクト202がノンプレイヤオブジェクト204を囲む海に落ちてしまったりした場合には、所定の場所に着地失敗したと判断して、ステップS65で、着地失敗フラグ404tをオンして、そのままステップS71に進む。
ステップS67では、ゲームクリアかどうかを判断する。つまり、CPU40は、プレイヤオブジェクト202が、所定の着地点をすべて経由して、ゴールに到着したかどうかを判断する。ステップS67で“YES”であれば、つまりゲームクリアであれば、ステップS69で、ゲームクリアフラグ404uをオンして、ステップS75に進む。
一方、ステップS67で“NO”であれば、つまりゲームクリアでなければ、ステップS71で、ゲームオーバであるかどうかを判断する。ここでは、CPU40は、プレイヤオブジェクト202がゴールに到達する前に、制限時間を超えてしまったり、プレイヤオブジェクト202が所定回数(たとえば、3回)着地に失敗したり、プレイヤオブジェクト202が海に落ちている時間が所定時間(たとえば、10秒)を超えたりしたかどうかを判断する。ステップS71で“NO”であれば、つまりゲームオーバでなければ、そのままステップS75に進む。一方、ステップS71で“YES”であれば、つまりゲームオーバであれば、ステップS73で、ゲームオーバフラグ404vをオンして、ステップS75に進む。
ステップS75では、ゲーム画像を生成する。ここでは、CPU40は、数6で示す行列式Aに従ってプレイヤオブジェクト202を3次元仮想空間に配置するとともに、ステップS51で設定されたアニメーションフレームのアニメーションを下降時アニメーションデータ404eから読み出したり、ステップS57の同期処理で設定されたアニメーションフレームのアニメーションを羽ばたきアニメーションデータ(404c,404d)から読み出したりして描画(更新)する。また、ノンプレイヤオブジェクト204を含む背景画像を描画(更新)する。さらに、着地成功フラグ404s、着地失敗フラグ404t、ゲームクリアフラグ404uまたはゲームオーバフラグ404vがオンであれば、着地成功、着地失敗、ゲームクリアまたはゲームオーバを表現する画像を生成する。たとえば、着地成功、着地失敗、ゲームクリアまたはゲームオーバを示す旨のテキストがゲーム画像に上書きされる。このとき、図示は省略するが、着地成功、着地失敗、ゲームクリアまたはゲームオーバに応じた効果音ないし音楽が出力される。
次のステップS77では、ゲーム画像を表示する。つまり、CPU40は、ステップS75で生成(更新)したゲーム画像をゲーム画面(200など)としてモニタ34に表示する。そして、ステップS79では、ゲーム終了かどうかを判断する。ここでは、CPU40は、プレイヤの操作によって、ゲーム終了が指示されたかどうかを判断する。ステップS79で“NO”であれば、つまりゲーム終了でなければ、図22に示したステップS7に戻る。ただし、ゲームオーバになった場合には、仮想ゲームが最初から開始される。一方、ステップS79で“YES”であれば、つまりゲーム終了であれば、そのまま全体処理を終了する。
なお、図示は省略するが、着地成功フラグ404sおよび着地失敗フラグ404tは、ステップS75よりも後であり、ステップS79で“NO”となり、ステップS7に戻るまでの間に、オフされる。
図26−図28は、図22に示したステップS11の動作判別処理のフロー図である。図26に示すように、CPU40は、動作判別処理を開始すると、ステップS91で、現在の体重率WRを算出および記憶する。つまり、現荷重値データ404gが示す荷重値を、基準値データ404fが示す基準値(体重値)で割ることにより、現在の体重率WRを算出し、その体重率データを体重率データバッファ404aに記憶する。
次のステップS93では、現在の体重率WRが第1閾値(この実施例では、0.985)未満であるかどうかを判断する。つまり、CPU40は、プイレヤオブジェクト202に推進力Accを与えるかどうかを判断しているのである。ステップS93で“YES”であれば、つまり現在の体重率WRが第1閾値未満であれば、ステップS95で、推進力Accに1−体重率WRを設定して、ステップS99に進む。つまり、体重率WRに応じた推進力Accが算出(設定)される。一方、ステップS93で“NO”であれば、つまり現在の体重率WRが第1閾値以上であれば、ステップS97で、推進力Accに0を設定して、ステップS99に進む。
ステップS99では、直前の羽ばたき動作(羽ばたき区間)における体重率WRの最大値が第2閾値(この実施例では、1.3)を超えるかどうかを判断する。つまり、CPU40は、プレイヤの操作入力が屈伸運動によるものかどうかを判断しているのである。ただし、直前の羽ばたき区間は、上述したように、前々回の振り下ろし動作の開始が判定されてから前回(直前)の振り下ろし動作の開始が判定されるまでの区間を意味する。
ステップS99で“NO”であれば、つまり直前の羽ばたき動作における体重率WRの最大値が第2閾値以下であれば、プレイヤの操作入力が屈伸運動によるものではないと判断して、ステップS101で、最大速度VelMaxをプレイヤオブジェクト202の最高速度(この実施例では、4)に設定し、ステップS103で、推進力Accを1.3倍(Acc=Acc×1.3)して、ステップS109に進む。一方、ステップS99で“YES”であれば、つまり直前の羽ばたき動作における体重率WRの最大値が第2閾値を超えていれば、プレイヤの操作入力が屈伸運動によるものであると判断して、ステップS105で、最大速度VelMaxをプレイヤオブジェクト202の最高速度の半分(この実施例では、2)に設定し、ステップS107で、推進力Accを0.8倍(Acc=Acc×0.8)して、ステップS109に進む。
このように、ステップS99−S107では、この仮想ゲームの開発者等が意図する操作入力である場合には、プレイヤオブジェクト202が前進し易くし、逆に、開発者等が意図しない操作入力である場合には、プレイヤオブジェクト202が前進し難くしてある。したがって、最大速度VelMaxに設定する数値や推進力Accに掛ける係数は、実施例の値に限定される必要はない。
ステップS109では、現在(現フレーム)の体重率WRと前回(前フレーム)の体重率WRとの差が第3閾値(この実施例では、0.001)未満であるかどうかを判断する。ステップS109で“YES”であれば、つまり現在の体重率WRと前回の体重率WRとの差が第3閾値未満であれば、図27に示すステップS111で、現在の体重率WRが第4閾値(この実施例では、0.99)以上第5閾値(この実施例では、1.01)以下であるかどうかを判断する。
ステップS111で“YES”であれば、つまり現在の体重率WRが第4閾値以上第5閾値以下である場合には、体重率WRの上昇でも下降でもないと判断して、図28に示すように、そのまま動作判別処理を終了する。一方、ステップS111で“NO”であれば、つまり現在の体重率WRが第4閾値未満であるまたは第5閾値を超えている場合には、そのまま図28に示すステップS137に進む。図示は省略するが、かかる場合には、体重率WRの上昇または下降についての前回の判定結果が維持されることになる。
図26に戻って、ステップS109で“NO”であれば、つまり現在の体重率WRと前回の体重率WRとの差が第3閾値以上であれば、図27に示すステップS113で、現在の体重率WRが前回の体重率WRよりも小さいかどうかを判断する。つまり、CPU40は、体重率WRが下降しているか上昇しているかを判断しているのである。ステップS113で“NO”であれば、つまり現在の体重率WRが前回の体重率WRよりも大きければ、体重率WRが上昇していると判断して、ステップS115で、体重率下降フラグ404jがオンであるかどうかを判断する。つまり、CPU40は、体重率WRが下降した後に、上昇したかどうかを判断する。
ステップS115で“NO”であれば、つまり体重率下降フラグ404jがオフであれば、体重率WRは上昇中であると判断して、そのままステップS137に進む。一方、ステップS115で“YES”であれば、つまり体重率下降フラグ404jがオンであれば、体重率WRが下降した後に上昇したと判断して、ステップS117で、体重率下降フラグ404jをオフし、ステップS119で、現在の体重率WRが第6閾値(この実施例では、0.98)以上であるかどうかを判断する。つまり、開発者等が意図する振り上げ動作が行われたかどうかを判断する。
ステップS119で“NO”であれば、つまり現在の体重率WRが第6閾値未満であれば、振り上げ動作でないと判断して、そのままステップS137に進む。一方、ステップS119で“YES”であれば、つまり現在の体重率WRが第6閾値以上であれば、振り上げ動作であると判断して、ステップS121で、振り上げ判定フラグ404kをオンし、ステップS123で、振り上げ加速フラグ404nをオンし、さらに、ステップS125で、振り下ろし判定フラグ404mをオフして、ステップS137に進む。
また、ステップS113で“YES”であれば、つまり現在の体重率WRが前回の体重率WRよりも小さければ、体重率WRが下降していると判断して、ステップS127で体重率下降フラグ404jをオンし、ステップS129で、現在の体重率WRが第7閾値(この実施例では、0.985)未満であるかどうかを判断する。つまり、CPU40は、振り下ろし動作であるかどうかを判断する。ステップS129で“NO”であれば、つまり現在の体重率WRが第7閾値以上であれば、振り下ろし動作ではないと判断して、そのままステップS137に進む。一方、ステップS129で“YES”であれば、つまり現在の体重率WRが第7閾値未満であれば、振り下ろし動作であると判断して、ステップS131で、振り下ろし判定フラグ404mをオンし、ステップS133で、振り下ろし加速フラグ404pをオンし、さらに、ステップS135で、振り上げ判定フラグ404kをオフして、ステップS137に進む。
図28に示すように、ステップS137では、周波数のインデックス番号n=2で振幅Aが最大であり、かつインデックス番号n=3の振幅Aが第8閾値(ここでは、0.0001)以上である、または、周波数のインデックス番号n=3以上で振幅Aが最大であるかどうかを判断する。ステップS137で“YES”であれば、つまり、周波数のインデックス番号n=2で振幅Aが最大であり、かつインデックス番号n=3の振幅Aが第8閾値以上である場合、または、インデックス番号n=3以上で振幅Aが最大である場合には、小羽ばたき動作であると判定して、ステップS139で、小羽ばたきフラグ404rをオンし、ステップS141で、大羽ばたきフラグ404qをオフして、全体処理にリターンする。
一方、ステップS137で“NO”であれば、つまり周波数のインデックス番号n=2で振幅Aが最大でない場合、または、インデックス番号n=3の振幅Aが第8閾値未満である場合、或いは、周波数のインデックス番号n=3以上で振幅Aが最大でない場合には、ステップS143で、周波数のインデックス番号n=1−15の振幅Aがすべて第8閾値未満かどうかを判断する。
ステップS143で“NO”であれば、つまり周波数のインデックス番号n=1−15の振幅Aのうち、第8閾値以上のものが有れば、大羽ばたき動作であると判断して、ステップS145で、大羽ばたきフラグ404qをオンし、ステップS147で、小羽ばたきフラグ404rをオフして、全体処理にリターンする。
一方、ステップS143で“YES”であれば、つまり周波数のインデックス番号n=1−15のすべての振幅Aが第8閾値未満であれば、羽ばたき動作を行っていないと判断して、ステップS149で、大羽ばたきフラグ404qおよび小羽ばたきフラグ404rをオフして、全体処理にリターンする。
図29−図31は、図24のステップS57に示した同期処理のフロー図である。図29に示すように、CPU40は、同期処理を開始すると、ステップS161で、振り下ろし判定フラグ404mがオンであるかどうかを判断する。詳細な説明は省略するが、同期処理では、プレイヤオブジェクト202は下降中ではなく、プレイヤによって羽ばたき動作が行われているため、振り上げ判定フラグ404kまたは振り下ろし判定フラグ404mは必ずオンである。
ステップS161で“NO”であれば、つまり振り下り判定フラグ404mがオフであり、振り上げ判定フラグ404kがオンであれば、図30に示すステップS181に進む。一方、ステップS161で“YES”であれば、つまり振り下ろし判定フラグ404mがオンであり、振り上げ判定フラグ404kがオフであれば、ステップS163で、振り下ろし加速フラグ404pがオンであるかどうかを判断する。つまり、CPU40は、プレイヤの振り下ろし動作の開始に応じてアニメーションフレームを加速させたかどうかを判断する。
ステップS163で“NO”であれば、つまり振り下ろし加速フラグ404pがオフであれば、現在の羽ばたき区間において、振り下ろし動作の開始に応じて既にアニメーションフレームを加速したと判断して、ステップS165で、フレーム加速度FrameAccに0を設定して、図31に示すステップS193に進む。一方、ステップS163で“YES”であれば、つまり振り下ろし加速フラグ404pがオンであれば、現在の羽ばたき区間において、振り下ろし動作の開始に応じて未だアニメーションフレームを加速していないと判断して、ステップS167で、現在のアニメーションフレームが15以上30未満であるかどうかを判断する。つまり、CPU40は、アニメーションフレームが振り下ろし加速度発生可能区間内であるかどうかを判断する。
ステップS167で“YES”であれば、つまり現在のアニメーションフレームが15以上30未満であれば、アニメーションフレームが振り下ろし加速度発生可能区間内であると判断して、ステップS169で、フレーム加速度FrameAccに、アニメーションフレームの最大フレーム数AnimFrameMaxを振り下ろし判定間隔CycleSwingで割った値を設定する。つまり、後でフレーム速度FrameVel_newを算出する際に、アニメーションフレームが加速される。次のステップS171では、振り下ろし加速フラグ404pをオフして、ステップS193に進む。
一方、ステップS167で“NO”であれば、つまり現在のアニメーションフレームが15以上30未満でなければ、アニメーションフレームが振り下ろし加速度発生可能区間内でないと判断して、ステップS173で、フレーム加速度FrameAccに0を設定し、ステップS175で、数12に従って、現在のフレーム速度FrameVel_oldに、アニメーションフレームの最大フレーム数AnimFrameMaxを1.7倍して振り下ろし判定間隔CycleSwingで割った値を設定する。つまり、CPU40は、アニメーションフレームを、フレーム加速度発生可能区間に早く近づけるのである。
続いて、ステップS177では、現在のフレーム速度FrameVel_oldが6よりも大きいかどうかを判断する。ステップS177で“NO”であれば、つまり現在のフレーム速度FrameVel_oldが6以下であれば、そのままステップS193に進む。一方、ステップS177で“YES”であれば、つまり現フレーム速度FrameVel_oldが6よりも大きければ、ステップS179で、現在のフレーム速度FrameVel_oldに6を設定して、ステップS181に進む。つまり、現在のフレーム速度FrameVel_oldが制限される。
図30に示すように、ステップS181では、振り上げ加速フラグ404nがオンであるかどうかを判断する。ステップS181で“NO”であれば、つまり振り上げ加速フラグ404nがオフであれば、現在の羽ばたき区間において、振り上げ動作の開始に応じて既にアニメーションフレームを加速したと判断して、ステップS191で、フレーム加速度FrameAccに0を設定して、ステップS193に進む。一方、ステップS181で“YES”であれば、つまり振り上げ加速フラグ404nがオンであれば、現在の羽ばたき区間において、振り上げ動作の開始に応じて未だアニメーションフレームを加速していないと判断して、ステップS183で、現在のアニメーションフレームが30以上60未満であるかどうかを判断する。つまり、CPU40は、アニメーションフレームが振り上げ加速度発生可能区間内であるかどうかを判断するのである。
ステップS183で“NO”であれば、つまり現在のアニメーションフレームが30以上60未満でなければ、アニメーションフレームが振り上げ加速度発生可能区間内でないと判断して、ステップS191に進む。一方、ステップS183で“YES”であれば、つまり現在のアニメーションフレームが30以上60未満であれば、アニメーションフレームが振り上げ加速度発生可能区間内であると判断して、ステップS185で、現在のフレーム速度FrameVel_oldが2未満であるかどうかを判断する。
ステップS185で“NO”であれば、つまり現在のフレーム速度FrameVel_oldが2以上であれば、ステップS191に進む。一方、ステップS187で“YES”であれば、つまり現在のフレーム速度FrameVel_oldが2未満であれば、ステップS187で、フレーム加速度FrameAccに2を設定し、ステップS189で、振り上げ加速フラグ404nをオフして、ステップS193に進む。
図31に示すステップS193では、フレーム加速度FrameAccが0でないかどうかを判断する。ステップS193で“NO”であれば、つまりフレーム加速度FrameAccが0であれば、そのままステップS197に進む。一方、ステップS193で“YES”であれば、つまりフレーム加速度FrameAccが0でなければ、ステップS195で、現在のフレーム速度FrameVel_oldに0を設定して、ステップS197に進む。
ステップS197では、積分シミュレーションにより、次のフレーム速度FrameVel_newを算出する。続いて、ステップS199では、次のアニメーションフレームFrame_newを決定する。つまり、CPU40は、数10に従って次のフレーム速度FrameVel_newを算出し、数11に従って、次のアニメーションフレームFrame_newを算出する。そして、ステップS201で、決定されたアニメーションフレームFrame_newのアニメーションを設定して、図22−図25に示した全体処理にリターンする。
この実施例によれば、プレイヤの羽ばたき動作を体重率の変動の周期に基づいて判定し、これをプレイヤオブジェクトのアニメーションに反映させるとともに、体重率の大きさに基づいてプレイヤオブジェクトの移動量を制御するので、単なる荷重の変化に応じてゲーム処理を実行する場合に比べて多彩な処理を実行することができる。
なお、この実施例では、現在の荷重値を体重値(基準値)で割った体重率を用いるようにしたが、荷重値をそのまま用いるようにしてもよい。かかる場合には、体重差によるゲームの有利不利を無くすために、体重別(体重のランク別)の閾値を設けるようにすればよい。
また、この実施例では、体重率の時間変化を離散フーリエ変換して得られた周波数スペクトルに基づいて、プレイヤによる羽ばたき動作の有無および羽ばたき動作の種類を判別するようにしたが、高速フーリエ変換するようにしてもよい。