source: 2015/26/MikkoL/JRPG/JRPG/JRPG/Battle/BattleView.cs @ 6401

Revision 6401, 19.0 KB checked in by mijoliim, 5 years ago (diff)
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Jypeli;
6using Jypeli.Widgets;
7
8using Microsoft.Xna.Framework;
9using Microsoft.Xna.Framework.Graphics;
10
11public class BattleView : GameObject
12{
13    public static BattleView CurrentBattleView { get; set; }
14
15    public _Background Background;
16    public Image Background_Image;
17
18    public EnemyGroup _EnemyGroup { get; set; }
19    public EnemyBase Attacker { get; set; }
20
21    public List<CharacterBase> Allies = new List<CharacterBase>();
22    public List<BetterLabel> AllyNames = new List<BetterLabel>();
23    public List<EnemyBase> Enemies = new List<EnemyBase>();
24    public List<GameObject> EnemiesOnScreen = new List<GameObject>();
25
26    public bool IsAttackAnimationPlaying { get; set; }
27    public bool IsTimerActive { get; set; }
28    public bool IsInMenu { get; set; }
29
30    private SpecialQueue<CharacterBase> _AllyQueue = new SpecialQueue<CharacterBase>();
31    public SpecialQueue<Action<CharacterBase>> AllyQueue = new SpecialQueue<Action<CharacterBase>>();
32    public Queue<Action> ActionQueue = new Queue<Action>();
33
34    private BetterLabel EnemyName;
35    private Pointer Pointer;
36
37    private Widget BattleHUD { get; set; }
38    private List<GameObject> ToDeleteOnExit = new List<GameObject>();
39    private ScrollingTextMenu BattleMenu { get; set; }
40
41    private int SelectedAllyIndex;
42
43    private float WaitTimeBetweenActions = 1f;
44    private float TimeBetweenActions;
45
46    int SelectedEnemy;
47    int PrevSelectedEnemy = 0;
48
49    public BattleView()
50        : base(0, 0)
51    { }
52
53    public void LoadBattle(EnemyGroup _Enemies, Image BG_Image)
54    {
55        Background_Image = BG_Image;
56        LoadBattle(_Enemies);
57    }
58
59    public void LoadBattle(EnemyGroup _Enemies)
60    {
61        JRPG.Game.ClearControls();
62
63        CurrentBattleView = this;
64
65        _EnemyGroup = _Enemies;
66
67        Background = new _Background(JRPG.Game.Content.Load<Texture2D>("BG//bg_test"));
68        JRPG.Game.Add(Background, 1);
69
70        JRPG.Game.Keyboard.Listen(Key.Enter, ButtonState.Pressed, EndBattle, null);
71
72        Allies.Add(CharacterList.Sonic());
73
74        for (int i = 0; i < Allies.Count; i++)
75        {
76            Allies[i].Index = i;
77        }
78
79        LoadAllies();
80        LoadEnemies(_Enemies);
81        LoadHUD();
82
83        Flags.InBattle = true;
84        IsTimerActive = true;
85    }
86
87    void LoadAllies()
88    {
89        for (int i = 0; i < Allies.Count; i++)
90        {
91            Allies[i].AllyOnScreen = new GameObject(Allies[i].Idle.Width, Allies[i].Idle.Height);
92            Allies[i].AllyOnScreen.Animation = Allies[i].Animation;
93            //Allies[i].AllyOnScreen.Image = Allies[i].Idle;
94           
95
96            if (Allies.Count == 1)
97            {
98                Allies[i].AllyOnScreen.Position = JRPG.Game.Camera.Position + new Vector(240, 0);
99            }
100
101            JRPG.Game.Add(Allies[i].AllyOnScreen, 2);
102            ToDeleteOnExit.Add(Allies[i].AllyOnScreen);
103        }
104    }
105
106    void LoadEnemies(EnemyGroup _Enemies)
107    {
108        for (int i = 0; i < _Enemies.Count; i++)
109        {
110           
111            _Enemies[i].EnemyOnScreen = new GameObject(_Enemies[i].Idle.Width, _Enemies[i].Idle.Height);
112            _Enemies[i].EnemyOnScreen.Image = _Enemies[i].Idle;
113
114            if (_Enemies.Count == 1)
115            {
116               
117                _Enemies[i].EnemyOnScreen.Position = JRPG.Game.Camera.Position + new Vector(-240, 0);
118               
119            }
120            else if (_Enemies.Count == 2)
121            {
122                _Enemies[i].EnemyOnScreen.Position = JRPG.Game.Camera.Position + new Vector(-160 - (i*100), 120 + (i*-160));
123            }
124            else if (_Enemies.Count == 3)
125            {
126                _Enemies[i].EnemyOnScreen.Position = JRPG.Game.Camera.Position + new Vector(-260+i*100, 160+i*-120);
127                if (i == 2)
128                {
129                    _Enemies[i].EnemyOnScreen.X = (_Enemies[0].EnemyOnScreen.Position.X + _Enemies[1].EnemyOnScreen.X) / 2;
130                }
131            }
132            else if (_Enemies.Count == 4)
133            {
134                _Enemies[i].EnemyOnScreen.Y = JRPG.Game.Camera.Position.Y - (100 * i - 200);
135                if (i % 2 == 0)
136                {
137                    _Enemies[i].EnemyOnScreen.X = JRPG.Game.Camera.Position.X - 160;
138                }
139                else if (i % 2 == 1)
140                {
141                    _Enemies[i].EnemyOnScreen.X = JRPG.Game.Camera.Position.X - 260;
142                }
143            }
144
145            Enemies.Add(_Enemies[i]);
146
147            JRPG.Game.Add(_Enemies[i].EnemyOnScreen, 2);
148            EnemiesOnScreen.Add(_Enemies[i].EnemyOnScreen);
149        }
150    }
151
152    void LoadHUD()
153    {
154        Vector Position = new Vector(-60, -235);
155        double Offset = 40;
156
157        BattleHUD = new Widget(Images.HUD.BattleHUD.Width, Images.HUD.BattleHUD.Height);
158        BattleHUD.Image = Images.HUD.BattleHUD;
159        BattleHUD.Position = Position + new Vector(64.5, -34.5);
160        JRPG.Game.Add(BattleHUD);
161
162        for (int i = 0; i < Allies.Count; i++)
163        {
164            int Index = i;
165
166            BetterLabel Name = new BetterLabel(JRPG.Game.MainFont, Position + new Vector(-200, i * -Offset), Allies[i].Name);
167            JRPG.Game.Add(Name);
168            AllyNames.Add(Name);
169
170            string HP = Allies[i].CurrentHP.Value.ToString() + "/" + Allies[i].CurrentHP.MaxValue.ToString();
171            BetterLabel HPMeter = new BetterLabel(JRPG.Game.MainFont, Position + new Vector(0, i * -Offset), HP);
172            HPMeter.BorderType = TextBorderType.Thick;
173            JRPG.Game.Add(HPMeter);
174
175            string SP = Allies[i].CurrentSP.Value.ToString();
176            BetterLabel SPMeter = new BetterLabel(JRPG.Game.MainFont, Position + new Vector(150, i * -Offset), SP);
177            SPMeter.BorderType = TextBorderType.Thick;
178            JRPG.Game.Add(SPMeter);
179
180            ProgressBar WaitBar = new ProgressBar(104, 12);
181            WaitBar.Position = Position + new Vector(280, i * -Offset);
182            WaitBar.BindTo(Allies[i].WaitTimeMeter);
183            WaitBar.BarImage = Images.HUD.Wait_Full;
184            WaitBar.Image = Images.HUD.Wait_Empty;
185            JRPG.Game.Add(WaitBar);
186
187            ToDeleteOnExit.Add(HPMeter);
188            ToDeleteOnExit.Add(SPMeter);
189            ToDeleteOnExit.Add(WaitBar);
190
191            Allies[Index].OnCurrentHPChange = delegate
192            {
193                HPMeter.Text = Allies[Index].CurrentHP.Value.ToString() + "/" + Allies[Index].CurrentHP.MaxValue.ToString();
194
195               
196                if (Allies[Index].CurrentHP.Value == 0)
197                {
198                    if (SelectedAllyIndex == Allies[Index].Index)
199                    {
200                        JRPG.Game.ClearControls();
201
202                        IsInMenu = false;
203                        AllyNames[SelectedAllyIndex].IsFlashing = false;
204                        BattleMenu.Destroy();
205                        if (EnemyName != null) EnemyName.Destroy();
206                        if (Pointer != null) Pointer.Destroy();
207                    }
208
209                    Name.TextColor = Microsoft.Xna.Framework.Color.Gray;
210                    HPMeter.TextColor = Microsoft.Xna.Framework.Color.Gray;
211                    SPMeter.TextColor = Microsoft.Xna.Framework.Color.Gray;
212
213                    Allies[Index].WaitTimeMeter.Value = 0;
214
215                    Allies[Index].IsDead = true;
216                }
217            };
218
219            Allies[Index].OnCurrentSPChange = delegate
220            {
221                SPMeter.Text = Allies[Index].CurrentSP.Value.ToString();
222            };
223        }
224    }
225
226    public void SelectSingleEnemyForAttackTarget(AttackBase ATK)
227    {
228        JRPG.Game.ClearControls();
229
230        SelectedEnemy = PrevSelectedEnemy;
231
232        EnemyName = new BetterLabel(JRPG.Game.MainFont, Vector.Zero, Enemies[SelectedEnemy].Name);
233        EnemyName.IsFlashing = true;
234        Pointer = new Pointer(Vector.Zero);
235        Pointer.IsFlashing = true;
236
237        JRPG.Game.Add(Pointer);
238        JRPG.Game.Add(EnemyName);
239
240        bool Selected = false;
241        bool Cancelled = false;
242
243        JRPG.Game.Keyboard.Listen(Key.Z, ButtonState.Pressed,
244            delegate
245            {
246                Selected = true;
247
248                if (!Cancelled)
249                {
250                    JRPG.Game.ClearControls();
251                    PrevSelectedEnemy = SelectedEnemy;
252
253                    double BaseDamage = ATK.BaseDamage(_AllyQueue.Peek().CurrentStats.Str, _AllyQueue.Peek().Level);
254                    int TrueDamage = 0;
255                    bool Crit = false;
256
257                    int r = RandomGen.NextInt(0, 100);
258
259                    if (r < BattleAlgorithms.CriticalRate(_AllyQueue.Peek().CurrentStats.Luck))
260                    {
261                        TrueDamage = BattleAlgorithms.DamageFromCriticalHit(BaseDamage, Enemies[SelectedEnemy].Stats.Def);
262                        Crit = true;
263                    }
264                    else TrueDamage = BattleAlgorithms.DamageFromBasicAttack(BaseDamage, Enemies[SelectedEnemy].Stats.Def);
265
266 
267                    IsInMenu = false;
268
269                    if (SoundEffects.Menu.Move.IsPlaying)
270                    {
271                        SoundEffects.Menu.Move.Stop();
272                    }
273                    SoundEffects.Menu.Move.Play();
274
275
276                    EnemyName.Destroy();
277                    Pointer.Destroy();
278
279                    AllyNames[_AllyQueue.Peek().Index].IsFlashing = false;
280                    AllyNames[_AllyQueue.Peek().Index].TextColor = Microsoft.Xna.Framework.Color.White;
281
282                    CharacterBase CurrentAlly = _AllyQueue.Dequeue();
283
284                    ActionQueue.Enqueue(delegate
285                    {
286                        if (ATK.Animation != null)
287                        {
288                            ATK.Animation.Invoke(CurrentAlly, SelectedEnemy, TrueDamage, Crit);
289
290                        }
291                        else
292                        {
293
294                            HitSplat(SelectedEnemy, TrueDamage, Crit);
295                        }
296                        _AllyQueue.Peek().WaitTimeMeter.Value = 0;
297                        _AllyQueue.Dequeue().CanMakeAction = false;
298                         
299                    });
300                }
301            }
302        ,null);
303        JRPG.Game.Keyboard.Listen(Key.X, ButtonState.Pressed,
304            delegate
305            {
306                Cancelled = true;
307
308                if (!Selected)
309                {
310
311                    JRPG.Game.ClearControls();
312
313                    Pointer.Destroy();
314                    EnemyName.Destroy();
315
316                    LoadBattleMenu(_AllyQueue.Peek()).Invoke(_AllyQueue.Dequeue());
317
318                    if (SoundEffects.Menu.Cancel.IsPlaying)
319                    {
320                        SoundEffects.Menu.Cancel.Stop();
321                    }
322                    SoundEffects.Menu.Cancel.Play();
323                }
324            }
325        , null);
326
327        JRPG.Game.Keyboard.Listen(Key.Up, ButtonState.Pressed,
328            delegate
329            {
330                if (SelectedEnemy > 0)
331                {
332                    SelectedEnemy--; SetEnemyPointerPosition(Pointer, EnemyName);
333                    if (SoundEffects.Menu.Move.IsPlaying)
334                    {
335                        SoundEffects.Menu.Move.Stop();
336                    }
337                    SoundEffects.Menu.Move.Play();
338                }
339            }
340        ,null);
341        JRPG.Game.Keyboard.Listen(Key.Down, ButtonState.Pressed,
342            delegate
343            {
344                if (SelectedEnemy < Enemies.Count - 1)
345                {
346                    SelectedEnemy++; SetEnemyPointerPosition(Pointer, EnemyName);
347                    if (SoundEffects.Menu.Move.IsPlaying)
348                    {
349                        SoundEffects.Menu.Move.Stop();
350                    }
351                    SoundEffects.Menu.Move.Play();
352                }
353            }
354        , null);
355
356        SetEnemyPointerPosition(Pointer, EnemyName);
357    }
358
359    public void HitSplat(int enemy, int damage, bool crit)
360    {
361        DamageHitsplat(EnemiesOnScreen[enemy].Position - JRPG.Game.Camera.Position, damage, crit);
362        Enemies[enemy].Stats.HP -= damage;
363
364        if (Enemies[enemy].Stats.HP <= 0)
365        {
366            Enemies[enemy].EnemyOnScreen.Destroy();
367            Enemies.RemoveAt(enemy);
368            EnemiesOnScreen.RemoveAt(enemy);
369            PrevSelectedEnemy = 0;
370
371            if (Enemies.Count == 0)
372            {
373                EndBattle();
374            }
375        }
376    }
377    public void HitSplatPlayer(CharacterBase character, int damage)
378    {
379        DamageHitsplat(character.AllyOnScreen.Position - JRPG.Game.Camera.Position, damage, false);
380    }
381
382    void SetEnemyPointerPosition(Pointer Pointer, BetterLabel EnemyName)
383    {
384        Pointer.BorderPosition = EnemiesOnScreen[SelectedEnemy].Position + new Vector(0, 20 + EnemiesOnScreen[SelectedEnemy].Height / 2) - JRPG.Game.Camera.Position;
385        EnemyName.Text = Enemies[SelectedEnemy].Name;
386        EnemyName.FontPosition = VectorConverter.JypeliVectorToXNA(Pointer.BorderPosition + new Vector(0, 25));
387        EnemyName.Alignment = TextAlignment.Center;
388    }
389
390    public void DamageHitsplat(Vector StartingPosition, int Damage, bool Crit)
391    {
392        BetterLabel DMG = new BetterLabel(JRPG.Game.MainFont, StartingPosition, Damage.ToString(), TextAlignment.Center);
393        DMG.Position = StartingPosition;
394        if (Crit) DMG.TextColor = Microsoft.Xna.Framework.Color.Gold;
395        JRPG.Game.Add(DMG);
396
397        DMG.Hitsplat(350, 0.8f, 2f, delegate {
398            DMG.Destroy();
399        });
400    }
401
402    Action Flee()
403    {
404        return delegate
405        {
406            int r = RandomGen.NextInt(0, 100);
407
408            if (r < BattleAlgorithms.FleePercent(_EnemyGroup))
409            {
410                ActionQueue.Enqueue(delegate
411                {
412
413                });
414            }
415            else
416            {
417
418            }
419        };
420    }
421
422    public CharacterBase SelectRandomAlly()
423    {
424        int r = RandomGen.NextInt(0, Allies.Count);
425
426        while (Allies[r].CurrentHP.Value == 0)
427        {
428            r = RandomGen.NextInt(0, Allies.Count);
429        }
430
431        return Allies[r];
432    }
433
434    void EndBattle()
435    {
436
437        Flags.InBattle = false;
438
439        for (int i = 0; i < AllyNames.Count; i++)
440        {
441            AllyNames[i].Destroy();
442        }
443
444        for (int i = 0; i < ToDeleteOnExit.Count; i++)
445        {
446            ToDeleteOnExit[i].Destroy();
447        }
448
449        BattleHUD.Destroy();
450        BattleMenu.Destroy();
451        Background.Destroy();
452
453        OverworldView.CurrentMapData.InitializeEnemies(OverworldView.CurrentMapData.CurrentMapIndex);
454
455        JRPG.Game.ClearControls();
456       
457
458        JRPG.Game.LoadOWControlsKeyboard();
459        JRPG.Game.LoadOWControlsXboxController();
460
461        JRPG.Game.Camera.StayInLevel = true;
462
463        JRPG.Game.FadeMusicOut();
464        Timer.SingleShot(0.5, delegate { JRPG.Game.FadeMusicIn("Music//WildArms"); });
465    }
466
467    Action<CharacterBase> LoadBattleMenu(CharacterBase character)
468    {
469        return delegate
470        {
471            if (!character.IsDead)
472            {
473                SelectedAllyIndex = character.Index;
474
475                IsInMenu = true;
476
477                AllyNames[character.Index].IsFlashing = true;
478
479                BattleMenu = new ScrollingTextMenu();
480                BattleMenu.SetTextBases(JRPG.Game.MainFont, TextAlignment.Left);
481
482                for (int i = 0; i < character.LearnedAttacks.Count; i++)
483                {
484                    int Index = i;
485
486                    BattleMenu.AddMenuElement(character.LearnedAttacks[i].Name);
487                    BattleMenu.ActionWhenSelected.Add(
488                        delegate
489                        {
490                            _AllyQueue.Cut(character);
491                            IsInMenu = true;
492                            AllyNames[character.Index].IsFlashing = true;
493                            character.LearnedAttacks[Index].OnUse();
494                        }
495                        );
496                }
497
498                BattleMenu.AddMenuElement("Skills");
499                BattleMenu.ActionWhenSelected.Add(delegate { });
500
501                BattleMenu.AddMenuElement("Items");
502                BattleMenu.ActionWhenSelected.Add(delegate { });
503                BattleMenu.AddMenuElement("Flee");
504                BattleMenu.ActionWhenSelected.Add(Flee());
505
506                BattleMenu.ActionOnExit = delegate
507                {
508                    IsInMenu = false;
509                    AllyNames[character.Index].IsFlashing = false;
510                    AllyNames[character.Index].TextColor = Microsoft.Xna.Framework.Color.White;
511                };
512
513                BattleMenu.LoadMenuElements();
514            }
515        };
516    }
517
518    void BattleTimer(double deltaTime)
519    {
520        for (int i = 0; i < Allies.Count; i++)
521        {
522            if (!Allies[i].CanMakeAction && !Allies[i].IsDead)
523            {
524                Allies[i].ElapsedTime += deltaTime;
525                Allies[i].WaitTimeMeter.Value += deltaTime;
526                if (Allies[i].ElapsedTime >= Allies[i].WaitTime)
527                {
528                    Allies[i].ElapsedTime = 0.0;
529                    Allies[i].CanMakeAction = true;
530                    _AllyQueue.Enqueue(Allies[i]);
531                    AllyQueue.Enqueue(LoadBattleMenu(Allies[i]));
532                }
533            }
534        }
535
536        for (int i = 0; i < Enemies.Count; i++)
537        {
538            if (!Enemies[i].CanMakeAction)
539            {
540                Enemies[i].ElapsedTime += deltaTime;
541                if (Enemies[i].ElapsedTime >= Enemies[i].WaitTime)
542                {
543                    Enemies[i].ElapsedTime = 0.0;
544                    Enemies[i].CanMakeAction = true;
545
546                    int Index = i;
547
548                    ActionQueue.Enqueue(delegate
549                    {
550                        Attacker = Enemies[Index];
551                        Enemies[Index].PickRandomAttack().OnUse();
552                    });
553                }
554            }
555        }
556    }
557
558    public override void Update(Time time)
559    {
560        if (Flags.InBattle)
561        {
562            if (AllyQueue.Count > 0 && !IsInMenu)
563            {
564                AllyQueue.Dequeue().Invoke(_AllyQueue.Peek());
565            }
566
567            if (ActionQueue.Count > 0 && !IsAttackAnimationPlaying)
568            {
569                IsAttackAnimationPlaying = true;
570                IsTimerActive = false;
571                ActionQueue.Dequeue().Invoke();
572            }
573
574            if (IsTimerActive)
575            {
576                double deltaTime = (float)time.SinceLastUpdate.TotalSeconds;
577                BattleTimer(deltaTime);
578            }
579        }
580
581        base.Update(time);
582    }
583}
Note: See TracBrowser for help on using the repository browser.