// 一時変数を共有するクロージャとイテレータを同時に使うのを避けるため関数化する // TODO: // 周囲八マスからランダムに選ぶ // その位置に敵がいないことを確認 private Func <IEnumerator>[] Summon(Loc src, MainSystem sys) { var xs = new List <Loc>(src.Neighbors()); Utils.Shuffle(xs); var rand = new System.Random(); int n = rand.Next(2, 3); var locs = new List <Loc>(); for (int i = 0; i < xs.Count; i++) { // TODO: 敵の配置だけでなく、敵が配置可能かも調べる if (!sys.ExistsEnemy(xs[i])) { locs.Add(xs[i]); if (locs.Count == n) { break; } } } List <Func <IEnumerator> > fns = new List <Func <IEnumerator> >(); for (int i = 0; i < locs.Count; i++) { int p = i; fns.Add(() => sys.Summon(locs[p])); } return(fns.ToArray()); }
protected override IEnumerator Run(MainSystem sys) { // 攻撃キャラを、ターゲットとの中間に移動させる(攻撃アニメーションの代替) var src = Actor.Position; var dst = src; dst.x = (src.x + _target.Position.x) / 2; dst.y = (src.y + _target.Position.y) / 2; Actor.Position = dst; // ターゲットの方を向く Actor.ChangeDir(Actor.Loc.Toward(_target.Loc)); _target.HideDirection(); // ターゲットは攻撃者の方を向く。ただし以下の場合は振り向かない // - 目の前に敵が存在する // - 攻撃者が透明状態 if (!sys.ExistsEnemy(_target.Front()) && !Actor.IsInvisible()) { _target.ChangeDir(_target.Loc.Toward(Actor.Loc)); } _target.RemoveStatus(StatusType.Sleep); var dmg = 16 + new System.Random().Next(30); yield return(Anim.Par(sys, () => _target.DamageAnim(dmg), () => EffectAnim.PopupWhiteDigits(_target, dmg))); _target.DamageHp(dmg); Actor.Position = src; }