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

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