MUGEN ( フォント環境:MS ゴシック 標準 サイズ10 )  キャラクター的メモ ※■※未確認※■※   ※基本的に私の専門外です。  ※AIを作っていてこんな風な使い方もできそうかな? というメモ  ※ほぼ全て ※■※未確認※■※ です。主に想像です。 ■ 根性値再現  Win版は防御力の補整がMoveType=Hでないと行われない為、   一撃目に補整をかけられない。  その為に、相応する分を「回復」する形とか。 [State -2] Type = LifeAdd Trigger1 = GetHitVar(HitCount)=1;一撃目 Trigger1 = MoveContact=1;直撃直後 Value = GetHitVar(Damage)*(*補整*); absolute=1  あるいは、Helper経由でダメージ計算を行うとか。(※制御が困難※) ■ ブロッキング受付のStatedef化  書いたとおり、そのまま。  ブロッキングを受け付ける状態をStatedefにする。  変化は全く無いようにし、ブロッキングの受付終了時は元のステートへ戻すだけ。  アニメーションなどに支障がないよう、配慮する必要もあるが。  そのステート時のみ、ブロッキング判定を行う。  管理が大変なのかなどは、知らん。 ■ 高速化のChangeAnim管理。  動作速度をChangeAnimで管理する。  Hitdefなどの条件記述をTimeにしていると不具合を起こすが、  細かい調整ができれば、「動作速度を上げていくキャラ」や   「徐々に動作速度が遅くなっていくキャラ」なども可能かもしれない。 ( 超加速の再現や疲労の再現、などに。 ) ■ ReversalDef メモ HitDefは「相手の当たり判定」と「自分の攻撃判定」が重なる時反応するように、 ReversalDefは「相手の攻撃判定」と「自分の攻撃判定」が重なる時に反応を起こしているだけ。 ■ RoundNo メモ  2ポイント先取制(3ラウンドマッチ)では3ラウンドまでが通常。  チーム戦の場合4on4なら7ラウンドまでありうる。  サドンデスでは、ラウンド数に上限無し、かと。 ■ 必須スプライトに関するメモ  くらい状態のスプライトには、基本的な「足元基準」の他、   「頭基準」「体の中心基準」のスプライトを入れることが必須となっている。  これらのスプライトは、必須Airで指定しないのに何故必須なのか。  それはステートコントローラーには[ChangeAnim2]という   「相手に自分のAirを参照させる」コントローラーがあり、   それを使って、特殊なモーションを再現するために使われます。  例えば「頭をつかんで投げるモーション」を行う場合、   頭を基準とした、くらい状態のスプライトが必要になります。  その時、その頭を基準としたスプライトを使ったアニメーションを表示させ、   掴む手の座標に相手の座標を持ってくることで、正確に頭を掴む事ができるわけです。  それら以外にも頭を下にした投げられ動作や、   胴を突き刺されているようなくらい動作などの再現には、   それらの「頭基準」や「体の中心基準」が必要になります。  その為の必須スプライトというわけです。  スプライト以外にも、Sizeで指定されるHead.PosやMid.Posも、   「頭の位置を基準に」や「体の中心へ」という制御を行う際に使われます。 ( 相手へと向かう飛び道具など。 )  AI的な話を言えば、大きさを感知するために必須な要素です。  Head.Posは身長の感知や「めくり攻撃」などで使います。  Mid.Posからは「ふっとび動作中の基準位置」である中心を察知し、   コンボ動作の安定性を向上させるといった事に使えます。  何気なく記入だけしているかもしれませんが、かなり重要な項目です。 ■ 大量な飛び道具のHelper+Pojectile方式の案 ※要追記確認。  大量の飛び道具によってHelperの量を圧迫させないためのもの。  主にグレイズを考慮した方式。平たく言うと、「毎フレームProjectileを更新させる方式」  飛び道具射出時、基準位置へHelperを1つ設置し、そこからProjectileを管理する。  Projectileは、projremovetime(消失までの時間)を2Fに設定(=1でした)。Animは1F目で判定などを設定し、2F以降は画像判定を消す。   個別に管理する為、全てのProjectileにHelperのIDを加えた個別のProjIDを持たせること。   HelperのIDを加えることで、複数回同じ飛び道具を出しても、Projの重複を起こさせません。  HelperはProjectileの「軌道を計算し位置を算出してProjectileを出現させる。」   条件式は「HelperのTimeがxx」の始動と「NumProjID(**)が1である && ProjContactTime(**)=-1」の継続で判定。   位置の計算はHelperのFloor((Time-xx)*速度)で可能かもしれない。    射出位置にズレが生じる場合はズレをVarで記録して計算。   グレイズ可能時には、ProjectileのAnim番号を変更して判定を消す。   本体が攻撃を受けたときに消失させる場合には、Projの射出をやめ、Projの有無でExplodを射出し消滅させる。  管理しているProjectileが全て無くなった場合にも、消滅させる。  追尾などの場合は、座標をVarで記憶するなど。  本体→射撃時Helperを配置。  Helper→Projectileの射出管理。場合によってExplodなど。  Projectile→1F目に判定 2F目は透過・消失  欠点・設定がやや面倒。 AngleDraw(スプライトの回転)を使えない。  利点・大量の弾でHelperの量を気にしないでも良い。     設定を調整すれば複雑な飛び道具もProjectileで使える、はず。     Helperという基準位置や位置の計算を行っている為、Projの飛び道具がどこにあるのか分かる。 2:21 2011/05/22追記:ProjはHelperから射出しても本体管理になるので注意。  ↑では省いてますが、Root,NumProjID〜で管理してください。 1:36 2011/05/22追記:Projの発射は「発射開始(!timeなど)」と「発射継続(Root,NumProjID(***+ID))」で管理します。  ProjIDは、yyxx00+IDという感じで管理します。5発の技なら10100+ID,10200+ID,10300+ID,10400+ID,10500+IDという具合。 ( これによりProjが残っている時に再度射出してもProjID番号が重複せず不具合が起こりません。 ) 1:55 2011/05/22追記:調べた結果、ProjRemoveTime=1が良いみたいです。  あと開始と継続は同じ記述に別条件で収めるか、継続を上側に、開始を下側にすること。 ( 下側に継続を奥と直後に継続用を射出するため、Projが2個になり、同時に消えてしまう。 ) 2:24 2011/05/22追記:あとProjContactTime(**)=-1もいらない模様。 2:35 2011/05/22追記:[HelperAndProj.txt]←記述例 ■ スケール変更の諸処理への反映。  基本[Data]のxscale,yscaleを処理へ反映させるだけ。  Xの処理へ *(Const(Size.XScale))を追加し、  Yの処理に *(Const(Size.YScale))を追加すればいいはず。  Velなどの処理も同様なので、全ての処理を書き換えるのは凄い根気がいる作業。  他ExplodやProjectile、Helperに*Scaleのパラメーターが無い場合、追加する必要も。   一度追加してしまえば、あとでどんな数値を入れても対応してくれる。  Commonの処理を変えればDataのVelocityは変更しなくてもよい。  ちなみに元々のサイズが0.5の場合は*(Const(Size.XScale)*2)にしないといけない。  それ以外の数値は1かその近似になるよう乗算にする必要が。  より細かい指定をする場合はSizeの各種数値や   Movementのairjump.height、yaccelなどもいじる必要があります。  ただ全画面演出系を縮小すると寂しい事になるかも 18:47 2011/10/31,6:43 2011/11/01追記  ●両者を縮小させたい場合はステージをいじってしまうのが楽かも。   まず適当な倍率を決めて「(1*縮小倍率)と(1/縮小倍率)」の数値を作っておく。   2倍縮小なら2:0.5、1.5倍なら1.5:0.66、1.33倍なら1.33:0.75。   ↓では拡大:縮小と表記。拡大ならx*拡大、縮小ならx*縮小(=x/拡大)。    ステージのdefファイル内にある   1.[Camera]のBoundLeftやBoundRightを拡大   2.[Scaling]のTopScaleとBotScaleを1.0から縮小(別の数値でも1/拡大の数値に設定)   3.[BG ***]全てのDeltaを縮小させる。([BG 0]など全て)   4.ステージを実際に確認して、[PlayerInfo]のP1StartXとP2StartXを拡大。   5.キャラを実際動かして[Camera]のFloorTensionとTensionを調整する。    これでステージの調整は完了です。   ※こうするとExplod以外は全て縮小処理された状態で処理されます。   ※キャラクター側は付加タイプのエフェクトのExplodはScale(無ければ追加で)やPos,velなどに縮小処理を加えてください。   ※全画面に表示させるタイプの画像はScaleを調整するかExplodで処理させるように調整してくさい。   ※「全画面判定」や「画面外まで判定が届く」というタイプの攻撃は判定が届き切らない場合があります。   ※それらはAirファイルを弄って判定を伸ばしたり、エフェクトを付け加えて画像を伸ばしたりしてください。   ※2倍縮小だと小さすぎるので1.3倍縮小とかその程度がオススメ。   ※背景のスプライトの倍率自体はいじれないので、そこは面倒なんですけど。 ■ AIの挙動不安定化システム(キャラ)  HelperType=PlayerやStateTypeの変更などを使い、   わざとAIに誤認させ(認識を遅らせ)て、AIの挙動を不安定にし   AIに人のような認識を行わせてしまうもの。  HelperType=Playerよりも、Simulでその処理をするキャラクターの方が、   EnemyNear,などにも反映させられるのでその方がいいかも。   その場合「相手のレベル」として、反映速度を設定したり。  利用方法は、それを使うことで超反応AIでも   遅延処理を行っているのと同じ動作をしてくれるというもの。  ちなみに、EnemyNearと攻撃するユニットが異なるようになるので、   一部の記憶システムなどが正常に記憶できなくなってしまうかも。 ■ ステートを戻すフレームでの動作を可能にする方法。  全ての動作ステートの最後にそれらを入力する方法は面倒すぎるが、   -3ステートで戻すフレームでCtrlも戻してしまう方法もある。  ただしその場合は技フレームの処理が1フレーム少なくなってしまうという不具合が出る。  気にしないという手もあるが、解決方法としては   そうした動作処理を-3ステートで全て行ってしまうという手もある。 ■メモ  -3ステートでVarに番号を入れ、   -1ステートのCommand記述のところに||AI時+Var=xx。  その場合、使うVarは3つ以上にし1つを「代入Var管理」、   それ以外を「入力Var」とし、複数の入力Varを管理する。  入力Varは代入Var管理を使って var( var(x) ) = ( Var(x):=(Var(x)+1) )*0 + #入力StateNo#  という風な感じで、複数入力できるように管理する。  基本は初めに入力したStateNoを優先するが、   「失敗記憶」などがある場合、二番目〜という風に別の動作を行わせる。  そうすることで、ワンパターンの失敗を防ぐことができる。  より単純な方式としては失敗記憶Varの情報を TriggerAll = Var(x)!= #StateNo# && Var(xx)!= #StateNo# ;  という感じでそれぞれの StateNoが失敗記憶に無い事を条件にする。  こっちの方が管理も楽。 ■ 相手の状態に合わせて判定を変更する正確な方法 15:16 2011/06/03  正確に相手の状態に対する判定を出したい場合、   「2Fだけ硬直させるHitDef判定」にし、命中した後相手の状態を確認して   それに合わせた判定のProjをヘルパーから出すことで処理する。  これなら1P側と2P側の差が生まれにくくなる。  ただし、判定の処理が複雑化して不具合が出やすい。  HitDef判定を与えた時からProjが命中するまで1Fの猶予がありその猶予中特殊な処理をされると困る。  Proj側が当たらないと自分側の不利だけが残るので、   2Fだけ硬直させるより通常HitDefに追加で命中させて調整する方がいいかも。 ■ GuardDist発生を1P2Pの差無く遅らせる方法 16:48 2011/06/03  「相手に」ガードで受けている間以外ガードモーションさせたくない場合、   判定の発生する1F前にヘルパーからAttackDist出せば判定と同時にGuardDistを出せ、1P2P問題なくInGuardDistになる。  技などで範囲と相手までの距離を確認すればよりタイミングよくAttackDistを発生させられる、かな。 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■以下、没ネタ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ だめだ。 ;9:34 2011/04/17追記:ヘルパー型のカードデッキ管理理論[Carddeck.txt] ボツ■ カードデッキのRandomによるシャッフルのメモ(Helper管理の計算・40枚まで) ;番号保持(本体設定からまたは振りなおし)Ifelse(fvar(x),(カード番号),var(x)) Trigger1 = fvar(0):= (カードNo);1枚目 Trigger1 = fvar(1):= (カードNo);2枚目 Trigger1 = fvar(2):= (カードNo) Trigger1 = fvar(3):= (カードNo) Trigger1 = fvar(4):= (カードNo) Trigger1 = fvar(5):= (カードNo) Trigger1 = fvar(6):= (カードNo) Trigger1 = fvar(7):= (カードNo) Trigger1 = fvar(8):= (カードNo) Trigger1 = fvar(9):= (カードNo) TriggerAll = fvar(0);振り分け fvar(0) Trigger1 = Var(Random%10) :=fvar(0) ;枚数に応じてRandom%xxを調整 TriggerAll = fvar(1);振り分け fvar(1) TriggerAll = Var(1) :=Random Trigger1 = !Var(Floor(Var(0));入っていない Trigger1 = Var(Floor(Var(0)) :=fvar(2) Trigger2 = Var(Floor(Var(0)+1) < 11; Trigger2 = Var(Floor(Var(0)+1) :=fvar(2) Trigger3 = Var(Floor(Var(0)-1) :=fvar(2) IfElse((1||Var(1):=Random%10 &&Var(Var(1))))  「 := 」の性質  Var(x):= Ifelse( var(x):=y ,z ,a);yを代入するが、最終的にはzかaがVar(x)代入される。   つまり、Ifelseの優先度が高く、Var(x):=の処理は、Ifelseの後になっているわけである。   ちなみにIfelseの参照は、「左から順に全ての参照を行う」ことになっている為、    ,z,aの位置で:=の代入を行った場合、条件に関係なくzで:=が代入され、aでも:=が代入される。  古いAI制作メモからのコピペ ;◇ := 条件式・代入記述 Trigger*** = Var(**):=xx ;◇この行が参照された時、Var(**)へxxを代入する。 ;◇その行のトリガーが参照された場合、代入する。 ;◇トリガー参照の順番については、;◆トリガーの説明。を参照。 ;◇なお、この記述は[数値]と同じである為、真偽判定はその数値に寄る。 Trigger1 = Var(**):= 1 ;◇!0真。 Trigger1 = Var(**):= 0 ;◇ 0偽。参照はされるため代入される。 Trigger2 = Var(**):= 3 ;◇!0真。前のトリガーグループが偽だった為、参照され代入される。 Trigger2 = Var(**):= 0 ;◇ 0偽。参照はされるため代入される。 Trigger2 = Var(**):= 5 ;◇!0真だが、前のトリガーが偽なので参照されない。 Trigger3 = Var(**):= 7 ;◇!0真。前のトリガーグループが偽だった為、参照され代入される。 Trigger4 = Var(**):= 9 ;◇!0真。前のトリガーグループが真だった為、参照されない。 ;◇上記の例の場合、最終的に代入されている数値は、Trigger3で代入した7。 ;◇ Var(**) := xx || 1 という記述であれば代入数値に関わらず、真にでき、 ;◇ Var(**) := xx && 0 という記述であれば代入数値に関わらず、偽にできる。 ;◇そうした代入数値に関係ない記述が基本かもしれない。 ;◇なお、トリガー参照で書いたとおり、TriggarAllが偽の場合、次の条件は参照されない。 ;◇その為、Var(**)=0から TriggarAll = Var(**)=1 Trigger1 = Var(**):=1 Trigger2 = 1 ;◇こういった記述をしても、TriggerAllが偽の為、trigger1は参照されない。 ;◇また、TriggerAllが参照されるのは最初の一度だけであり、Var(**)=0から、 TriggerAll = Var(**) = 0 ;◇Var(**) = 0で真 Trigger1 = Var(**):=1 ;◇真 Trigger1 = 0 ;◇偽 Trigger2 = 1 ;◇真 ;◇こうした記述でも、Trigger2でのTriggerAllは既に真を返している為、 ;◇  Var(**)=1 になりながら、処理は行われる。 ;◇その他、Triggerの情報は番号が順不同であっても、番号が飛んでおらず、 ;◇ 同トリガーグループで偽が出ていないかぎり、上側から真偽判定の処理を行う。 ;◇( 処理は トリガーの番号がどこまで続いているか→上から情報の処理 のようだ ) Trigger1 = 0&&Var(**) := 0 ;◇偽。Varを0に。 Trigger3 = 1||Var(**) = 1 ;◇偽。手前でVarが0になっているので、偽。 Trigger2 = 0&&Var(**) := 1 ;◇偽。Varを1に。 Trigger3 = 1||Var(**) := 2 ; 既にTrigger3は偽を返している為、参照されない。 Trigger4 = 0&&Var(**) = 1 ;◇偽。Trigger3が偽を返している為、参照される。 ;◇ こうした例を出してはいるが、なるべく● 上から順に番号をふる ●事をオススメする。