忍者ブログ
  • 2024.04
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 2024.06
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/05/03 00:11 】 |
Inputクラス・実装第2版
Inputクラスの実装。の第2版。
旧版はこちら

現状対応しているのは、大きさのあるボタンだけ。=つまりタッチスクリーン。


ゲーム側からの使い方=================

○ボタンの追加・削除
bool addButton(id_t, rect_t);
bool moveButton(id_t, rect_t);
bool removeButton(id_t);
bool hasButton(id_t);
追加・削除は状況に応じてどんどん行う。
画面が変わったときに一斉にadd,removeを行い、タッチスクリーン上のボタンが動いているときにmoveを行うイメージ。
ボタンを一意に表すidは、ゲーム側が自由に設定できる。そのほうがゲーム側が便利なので。
その代わり、idがかぶらないようにする責任もゲーム側が負う。(ゲーム側はたぶんenumでボタンを管理するだろうが、enumのスタート値にオフセットを付けておくとか)
idがかぶると、ボタン追加に失敗する。
なお、id=0は予約済。エラー扱い。id=1も予約するかもしれない。
とりあえず、idは0x1000_0000以上の値を使うようにしたい。

○ボタンの有効・無効
bool enableButton(id_t);
bool disableButton(id_t);
bool isEnableButton(id_t);
追加したらデフォルトで有効になる。
無効にすると、ボタンの中の時間は止まる。つまり、prevOnとかが維持される。

○ボタン状態取得
bool isOn(id_t);
bool isOff(id_t);
bool hasPressed(id_t);
bool hasReleased(id_t);
bool hasMoved(id_t);
bool hasRepeated();
uint32_t getPressedCount();
point_t getPoint(id_t);
point_t getMovedSize(id_t);
point_t getPrevPoint(id_t);
SButtonSized& getButton(id_t);

一般的な情報がそのまま取れる。
On,Offの状態、Press,Releaseの瞬間が取得可能。

大きさのあるボタンなので、ボタンのどこを押しているかも取得可能。
getPoint()でボタン内のどこを押したか取得。
また、hasMoved(), getMovedSize()でボタン内で押下場所が動いたことも検出可。

リピート押しはまだ実装していない。
リピート押しを実装。
hasRepeated()で取得可能。
リピート間隔は
void setRepeatCount(size_t c);
で指定する。取得も可能。
size_t getRepeatCount();
デフォルト値は0。つまりリピート判定をしない。その場合、hasPressed()の瞬間だけhasRepeated()が真になる。
ボタンごとにリピート間隔を指定できるように作ってはあるが、あまりリピート間隔がバラバラすぎるとUIとして良くないので、推奨値のようなものも用意しておいた。メニュー周りなどは同じ値を使うのが望ましいだろう。

連打回数を取得可能。
getPressedCount()で取得できる。iOSの機能にあったので付け足した。主にダブルタップ用か。


getButton()で取得してからisOn()などを使うこともできる。
存在しないidを指定したときの動作は未定義。

○サンプリング
void sampling();
ボタン状態をサンプリング(更新)する。
ゲームのexecが走る前に呼び出すのがよい。

○デバッグ表示
void description();
登録されているボタンすべての情報が表示される。


Inputクラス内部の実装=======================
○ボタンの持ち方
マップ。ボタンの追加・削除などの操作は、ほぼmapの操作だけ。
SInputButton構造体は、Inputクラスの中でのボタンの状態を表す。
std::map<id_t, SInputButton>


struct Input::SInputButton{
id_t id; //id. mapのキーと同じ値
bool isEnable; //有効かどうか
SButtonSized button; //ボタン
char name[16]; //識別名
};


SButtonSized構造体は、大きさのあるボタンを表す。
SButton構造体は、大きさの無いボタンを表す。(Aボタンや、キーボードのキーなど想定)

struct SButton{
bool isOn();
bool isOff();
bool hasPressed();
bool hasReleased();
bool hasRepeated();
uint32_t getPressedCount();

void update(bool isOn);
private:
typedef enum State {
INVALID = -1,
OFF = 0,
ON
} State;

State on_;
State prevOn_;

};
struct SButtonSized: public SButton{
bool hasMoved();
point_t getPoint();
point_t getPrevPoint();
point_t getMovedSize();
rect_t getRect();
void setRect(rect_t);

void update(bool isOn, point_t pos/*=point_t(0.f,0.f)*/);
private:
rect_t rect;
point_t point;
point_t prevPoint;
};


○ボタンの状態
ONとOFFだけでなく、INVALIDも追加し3値で扱うようにした。
ボタンが追加されたとき(addButton)または有効になったとき(enableButton)は、OFFでなくINVALIDの状態から始まるようにする。
hasPressed()などは、前状態がOFFの場合にのみフラグが立つようにする。
でないと、ボタンが生成される前からボタンの位置をタッチしていた場合、ボタンが生成された瞬間にhasPressed()になってしまう。
これは、ボタンを押したことによって画面遷移した瞬間、同じ位置にまた別のボタンがあったような場合、その瞬間にまたボタンを押したことになってしまうから。
また、アプリの処理が中断したときにINVALID状態に遷移することで、iOSでいうtouchCancelledへの対応も可能になる。

○update()
現状態を前状態にコピーし、新状態を代入。
ボタンを押している時間をカウント(hasRepeated()のため)
SButtonとSButtonSizedのupdate()は、オーバーライドしているわけではない

○サンプリングの方法
iPhoneのタッチイベントを保持しておき、サンプリング周期ごとに翻訳。
InputSamplerクラスが行う。


○流れ
(iPhoneコード)
→-(void) touchesBegan: withEvent;
→InputSampler::addTouchBegan();

(ゲーム内)
→Input::sampling();
→InputSampler::samplingData(Input&);


○コード
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (id touch in touches) {
inputSampler.addTouchBegan(touch);
}
}

void InputSampler::addTouchBegan(UITouch *touch){
//リストに追加
}



void InputSampler::samplingData(Input&){
//Inputの内部を直接触る
//on->prevOn, point->prevPointに代入
//リストを走査、ボタンの範囲内のタッチがあったら、on,pointを書き込み
}


PR
【2011/03/19 23:52 】 | 自作エンジン | 有り難いご意見(0) | トラックバック()
<<テクスチャ描画関数 | ホーム | CoreGraphicsでフォント描画>>
有り難いご意見
貴重なご意見の投稿














虎カムバック
トラックバックURL

<<前ページ | ホーム | 次ページ>>