まったりゲーム記

やはりTAPは名作だと思うのだ

いろいろ実験場(仮)

[ リスト | 詳細 ]

趣味レベルのプログラムなり何なり、その周辺の話題について書いてみようかな、と思ったりしてみた
記事検索
検索

全4ページ

[1] [2] [3] [4]

[ 次のページ ]

最近、知り合いから「携帯のFlashで暇つぶしできるゲーム作って」とか要求されたので、Flash Liteをちょこちょこ弄ってました。で、そのときにハマった話でも徒然と、、、



要求仕様は「オレの携帯で動くこと」ということで、それがまあソフトバンクの携帯だったわけです。

Flash Lite 2.0仕様(Flash Playerは7.0ベース)

で、動作確認してみたら方向キー以外のキー入力を全く拾うことができず、どうなってんだと調査。

以下、調査用のASソース
class KeyTest 
{
  private var label1:TextField;
  private var label2:TextField;
  private var label3:TextField;
  private var label4:TextField;
  
  private var keyDownFrame:Number;
  private var keyUpFrame:Number;
  
  private var pressKey:Number;
  private var downKey:Number;
  private var upKey:Number;

  function KeyTest (mc:MovieClip) {
    label1=addLabel(mc,"label1","キーダウン",0,0);
    label2=addLabel(mc,"label2","キーアップ",0,30);
    label3=addLabel(mc,"label3","キープレス", 0, 60);
    label4=addLabel(mc,"label4","キーコード", 0, 90);

    keyDownFrame = 0;
    keyUpFrame = 0;

    Key.addListener(this);

    var ref:Object = this;
    mc.onEnterFrame = function() {
      ref.tick();
    }
  }

  function tick():Void {
    label4.text = "Key.getCode() = " + Key.getCode();
    
    if (Key.isDown(13)) pressKey = 13;      // 決定
    else if(Key.isDown(37)) pressKey = 37;  // ←
    else if(Key.isDown(38)) pressKey = 38;  // ↑
    else if(Key.isDown(39)) pressKey = 39;  // →
    else if(Key.isDown(40)) pressKey = 40;  // ↓
    else if(Key.isDown(48)) pressKey = 48;  // 0
    else if(Key.isDown(49)) pressKey = 49;  // 1
    else if(Key.isDown(50)) pressKey = 50;  // 2
    else if(Key.isDown(51)) pressKey = 51;  // 3
    else if(Key.isDown(52)) pressKey = 52;  // 4
    else if(Key.isDown(53)) pressKey = 53;  // 5
    else if(Key.isDown(54)) pressKey = 54;  // 6
    else if(Key.isDown(55)) pressKey = 55;  // 7
    else if(Key.isDown(56)) pressKey = 56;  // 8
    else if(Key.isDown(57)) pressKey = 57;  // 9
    else pressKey = 0;
    
    if (downKey > 0) {
      var text:String = "onKeyDwon : " + downKey;
      if (keyDownFrame == 10) {
        text += "...発生!";
      }
      label1.text = text;
      
      keyDownFrame--;
      if (keyDownFrame == 0) {
        downKey = 0;
      }
    }else {
      label1.text = "";
    }
    
    if (upKey > 0) {
      var text:String = "onKeyUp : " + upKey;
      if (keyUpFrame == 10) {
        text += "...発生!";
      }
      label2.text = text;
      
      keyUpFrame--;
      if (keyUpFrame == 0) {
        upKey = 0;
      }
    }else {
      label2.text = "";
    }
    
    if (pressKey > 0) {
      label3.text = "isDown : " + pressKey;
    }else {
      label3.text = "";
    }
  }

  private function onKeyDown() {
    downKey = Key.getCode();
    keyDownFrame = 10;
  }

  private function onKeyUp() {
    upKey = Key.getCode();
    keyUpFrame = 10;
  }

  private function addLabel(mc:MovieClip,name:String,
    text:String,x:Number,y:Number,format:TextFormat):TextField {
    if (text==undefined) text="";
    if (x   ==undefined) x=0;
    if (y   ==undefined) y=0;

    mc.createTextField(name,mc.getNextHighestDepth(),0,0,0,0);
    mc[name].autoSize  ="left";//オートサイズ
    mc[name].selectable=false; //選択不可
    mc[name].text=text;    //テキスト
    mc[name]._x  =x;       //X座標
    mc[name]._y  =y;       //Y座標
    if (format!=undefined) mc[name].setTextFormat(format);//書式
    return mc[name];
  }

  static function main() {
    var app:KeyTest=new KeyTest(_root);
  }
}


実際のFlash
※一応、PCでも動きます(要FlashPlayer7)


onKeyDown、onKeyUp、ついでにonEnterFrameでグルグル回しながらKey.isDownでkeyPressを監視。

以下、分かったこと。

  1. 方向キー(上下左右)は、ふつうにキーダウン、キーアップイベントが発生している
  2. 決定キーおよび数字キー,*,#は、キーを離したときにキーアップ・キーダウンイベントが同時発生している
  3. 決定キーは長押ししてるとキーリピートが発生、キーダウンイベントが連続で発生する
  4. 数字キー,*,#は長押ししてもリピート発生せず、さらに長押し状態からキーを離すとキーイベントが一切発生しない
  5. 方向キー以外はisDownに一度も引っかからなかった

方向キー以外については、キーを離したときにキーアップ・キーダウンイベントが同時発生、、、なんだこのクソ仕様。

しかも、数字キーetcにいたっては、長押ししてるとキーイベント自体が発生しなくなる。意味不明。

さらに性質が悪いことに、決定キー、数字キーetcは、isDownにまったく引っかからなかった。

キーを押しっぱなしにしてる間もisDownは発生せず、、、この挙動は明らかにバグだと思うんだがどうなんだ。
(Key.getCode()の値を監視していると、キーを押しっぱなしの間は値が変わらないことが分かる。
 おそらく、キーダウンイベント発生時にキーコードの値が書き変わるんだろうが、
 肝心のキーダウンイベントが発生してくれないため、isDownで押下判定できない、、、のだろう)


、、、ちなみに、確認した機種は「830SH」

これ以外では実機での動作確認はしていないので、この機種だけのバグという可能性もあり。

もしくは、ソースが悪いのかもしれんが、、、どうなんだろう。

誰か携帯Flashに詳しい人、情報プリーズ。

開く トラックバック(1)

Oracle9iで「おや?」と思ったので、メモ

あるFUNCTIONを(同じ引数で)コールし、その結果を色々と加工して3種類の値を取り出す、という処理を想定。
-- テスト用FUNCTION
create or replace function call_test return number is
begin
  dbms_output.put_line('呼ばれたよ');
  return 1;
end;

-- テスト用SELECT文
select
  value as value1,
  value * 10 as value2,
  value * 100 as value3
from
  ( select call_test() as value from dual )
;

バカ正直にSELECT句にFUNCTIONを3回書き連ねれば、全く同じ処理が3回も実行されてしまう、、、
パフォーマンス的にそれはよろしくないだろう、と↑のSELECT文を書いたわけだが。
これを実行すると、コンソールには↓のように出力される
呼ばれたよ
呼ばれたよ
呼ばれたよ

こちとら、FUNCTIONのコールを1回だけにしたくてわざわざインラインビューにしてるというのに、何故か3回きっちり実行される不思議

これを回避するには、↓のように「SELECT句内での副問合せ」にした上でインラインビューにしてやる
select
  value as value1,
  value * 10 as value2,
  value * 100 as value3
from
  ( select (select call_test() from dual) as value from dual )
;

-----
呼ばれたよ

逆に、↓のようにした場合、見た目上は3回コールしているが、実際にコールされるのは1回だけ
select
  value1
from (
  select
    call_test() as value1,
    call_test() * 10 as value2,
    call_test() * 100 as value3
  from dual
)
;

-----
呼ばれたよ


FROM句を展開する際、SELECT句やWHERE句などで使用されていなければ暗黙のうちに切捨ててしまうらしい。
それがFUNCTIONのコールであれば、FUNCTION自体がコールされない。

逆に、複数個所で使用されている場合、FROM句が参照している要素をそのまま割り当てるだけになる?
単なる値なら問題ないが、それがFUNCTIONのコールであれば、使用している箇所が全てFUNCTIONのコールに置き換わる、、、

SELECT句で副問合せを使った場合、内部でFUNCTIONをコールしていても、単なる値に置き換えてエスカレーションするのだろうか。
何にせよ、気持ち悪い動きをしてくれるものである。



、、、マニュアルとかに載ってるのかもしれないけど、そんなマニアックな動作まで調べないよ、一般人は。

色々調べてみたらWindowsOSだとonKeyDownの取扱がonKeyPressと同じになっちゃってるということを今更知りました。

とりあえず、Win+IE,Firefoxで↑の通りの結果になることを確認。

Google Chromeも同様、キーを押し続けている間はonKeyPressとonKeyDownが発生し続けているようです。

MacOS+SafariやFirefoxの動作が理想的なんですが、、、

たぶん、キーリピートを拾っちゃってるんだろうなぁ。



ちなみに、↓のサイトで手軽にJavascriptのキーボードイベントの発生状況を確認できるようです(これは便利!)





SleipnirはEscのonKeyDownとonKeyPressを単独で取れない(Shift+EscならOK)とな、、、

試してみたら本当にそうでした、、、orz

なんでこんなにブラウザ間で挙動が違うんだよ、めんどくさいなぁ、、、



あと、当たり前?のことなんでしょうけど、、、

onKeyDown&onKeyUpとonKeyPressでは、アルファベットのキーコードを取得したとき、何故か値が異なる。

どうもonKeyPressは大文字・小文字(Shiftの有無)によって返すキーコードが変わるらしい。

例えば「a」を押すと
onKeyDown : 65
onKeyUp : 65
onKeyPress : 97
なのですが、Caps LockをONにした状態だと
onKeyDown : 65
onKeyUp : 65
onKeyPress : 65
となります。

、、、onKeyPressは封印の方向で。


スクリーンショット
イメージ 1


キー対応一覧
    "UP"     : 38,  //「↑」
    "DOWN"   : 40,  //「↓」
    "LEFT"   : 37,  //「←」
    "RIGHT"  : 39,  //「→」
    "A"      : 100, //「4」(テンキー使用を想定)
    "B"      : 101, //「5」(テンキー使用を想定)
    "C"      : 102, //「6」(テンキー使用を想定)
    "D"      : 96,  //「0」(テンキー使用を想定)
    "START"  : 226, //「/」
    "SELECT" : 191, //「\」
    "R1"     : 107, //「+」    (矢印キー+テンキー使用で、右手小指を使うことを想定)
    "R2"     : 105, //「9」    (矢印キー+テンキー使用で、右手薬指を使うことを想定)
    "L1"     : 16,  //「Shift」(矢印キー+テンキー使用で、左手小指を使うことを想定)
    "L2"     : 13,  //「Enter」(矢印キー+テンキー使用で、左手薬指を使うことを想定)
    "EXIT"   : 27   //「ESC」


ゲームパッドのボタンに対応させようかとか、そんな雰囲気のキーマップ。

ABCDはどう考えてもTGMやってるときの指配置だけど。

あとでキーコンフィグいじれるようにしとかんとなぁ。



単にonKeyDownとかonKeyUpとか呼ぶだけだとイベント発生したタイミングでパラメータ制御しなきゃならんので、KeyInfoなるクラス作ってそこでキーイベントの状態保存しとく。

んで、メインループ内で制御呼ぶ間はキーイベント発生しても無視するようにしといて、終わったらまたフラグ立てる。

JavaScriptはスレッドがないんで、setTimeoutで擬似的に制御。

DateでFPS調整しようとしてるせいで、タイマーの精度がものいっそ悪いけど、とりあえずこんな構造かな?っていうサンプルなので気にしない。

この程度の制御ならそこかしこに落ちてそうな気がするけど、自分で色々試してみるのがいいんだと無理やり納得してみる。

つか、FPS調整のロジック絶対間違ってるだろ、これ。

ちゃんとした解説サイト探して、後で直しておくか、、、

あ、マウスイベントも扱えるようにしておかないと。

その前に、DIVタグの左上を原点にしてオフセットで座標決定するようにすべきか、、、むむむ


ちなみに、IEとかChromeでしか動かないので、その辺りヨロシク(Firefoxとかだとキーイベントの拾い方が違うっぽい)



追記:
JavaScriptのタイマーの精度
IEがダメなだけなのか、、、
Chromeの場合
けっこう昔のプレゼンだけど、初めて知った。そもそもOSのカーネルと制御行き来する間隔がデフォで15.6msなのか、、、
ちゅか、ムリヤリ割り込み間隔変えられるんだね。へー。
というわけで、勢いに任せてやってみました、領域選択→拡大表示

マウスで範囲選択したり、選択範囲の矩形が残らないようにグラフのピクセルイメージで上書きしたり、余計な処理のおかげで4時間もかかった、、、


サンプル実行
※サンプルを見るには、ブラウザの設定でJavaの実行を許可するようにしておいてください

操作の仕方:

・クリック→ドラッグで、拡大したいグラフの領域を選択

・範囲選択している状態でマウスボタンを離すと、選択領域のグラフを再描画

・範囲選択している状態で別のマウスボタンをクリックすると、範囲選択をキャンセル

・キーボードの「P」を押すと、拡大前のグラフを描画(初期状態まで遡れます)

・キーボードの「R」を押すと、パラメータを初期状態に戻してグラフを描画

※いずれもグラフの描画が完了している状態で操作できるようになります



実行結果
イメージ 1


前回と同じ a = 3.5〜4.0 の範囲を選択
イメージ 2


前回と同じようなグラフですね
イメージ 3


真ん中らへんを選択
イメージ 4


拡大されたグラフが描画される
イメージ 5


もう一度選択
イメージ 6


同じような図形が出てくる
イメージ 7


さらに選択して、、、
イメージ 8


自己相似図形が繰り返し表れる
イメージ 9


もっと拡大
イメージ 10


美しいフラクタルですね!
イメージ 11





補足:ロジスティック写像について

ロジスティック写像とは、以下の差分方程式によって与えられる写像のことです。
 X(n+1) = a・X(n)・(1-X(n))  (ただし、0.0<=a<=4.0 , 0.0<=X(0)<=1.0)

この式の a を横軸に、 X(n) を縦軸にとったグラフが、↑で貼り付けた画像になります。

ロジスティック写像は、a が小さいうち(3.5くらい)は収束(もしくは2値・4値・8値…の間を振動)するのですが、a がある値を超えると収束することなく予測不可能な振る舞いを始めます。

いわゆる「カオス」というやつです。


ただ、この結果をそのままプロットしたのでは、正しい結果になりません。

ロジスティック写像(というかカオス)は、初期値の微妙なズレが以後の結果に大きく影響するのが特徴ですが、コンピュータの数値計算では扱える桁数に限界があり、さらに描画となると解像度の問題があるため、どうしても「丸めた」結果のグラフしか得られません。

そこで、グラフに描画する際は、結果の分布密度を示すことで、より「正解に近い」グラフを得ることができます。

↓の画像と比較してみると、その美しさがより際立って見えると思います。

イメージ 12
イメージ 13

全4ページ

[1] [2] [3] [4]

[ 次のページ ]


.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事