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

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