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

Revision 6415, 19.1 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
434        Flags.InBattle = false;
435
436        for (int i = 0; i < AllyNames.Count; i++)
437        {
438            AllyNames[i].Destroy();
439        }
440
441        for (int i = 0; i < ToDeleteOnExit.Count; i++)
442        {
443            ToDeleteOnExit[i].Destroy();
444        }
445
446        BattleHUD.Destroy();
447        BattleMenu.Destroy();
448        Background.Destroy();
449
450        OverworldView.CurrentMapData.InitializeEnemies(OverworldView.CurrentMapData.CurrentMapIndex);
451
452        JRPG.Game.ClearControls();
453       
454
455        JRPG.Game.LoadOWControlsKeyboard();
456        JRPG.Game.LoadOWControlsXboxController();
457
458        JRPG.Game.Camera.StayInLevel = true;
459
460        JRPG.Game.FadeMusicOut();
461        Timer.SingleShot(0.5, delegate { JRPG.Game.FadeMusicIn("Music//WildArms"); });
462    }
463
464    Action<CharacterBase> LoadBattleMenu(CharacterBase character)
465    {
466        return delegate
467        {
468            if (!character.IsDead)
469            {
470                SelectedAllyIndex = character.Index;
471
472                IsInMenu = true;
473
474                AllyNames[character.Index].IsFlashing = true;
475
476                BattleMenu = new ScrollingTextMenu();
477                BattleMenu.Position = new Vector(-100, -225);
478                BattleMenu.DrawMenuImage = true;
479                BattleMenu.MenuImage = Images.HUD.BattleMenu;
480                BattleMenu.MenuOffset = new Vector(80.5, -12.5);
481                BattleMenu.SetTextBases(JRPG.Game.MainFont, TextAlignment.Left);
482
483                for (int i = 0; i < character.LearnedAttacks.Count; i++)
484                {
485                    int Index = i;
486
487                    BattleMenu.AddMenuElement(character.LearnedAttacks[i].Name);
488                    BattleMenu.ActionWhenSelected.Add(
489                        delegate
490                        {
491                            _AllyQueue.Cut(character);
492                            IsInMenu = true;
493                            AllyNames[character.Index].IsFlashing = true;
494                            character.LearnedAttacks[Index].OnUse();
495                        }
496                        );
497                }
498
499                BattleMenu.AddMenuElement("Skills");
500                BattleMenu.ActionWhenSelected.Add(delegate { });
501
502                BattleMenu.AddMenuElement("Items");
503                BattleMenu.ActionWhenSelected.Add(delegate { });
504                BattleMenu.AddMenuElement("Flee");
505                BattleMenu.ActionWhenSelected.Add(Flee());
506
507                BattleMenu.ActionOnExit = delegate
508                {
509                    IsInMenu = false;
510                    AllyNames[character.Index].IsFlashing = false;
511                    AllyNames[character.Index].TextColor = Microsoft.Xna.Framework.Color.White;
512                };
513
514                BattleMenu.LoadMenuElements();
515            }
516        };
517    }
518
519    void BattleTimer(double deltaTime)
520    {
521        for (int i = 0; i < Allies.Count; i++)
522        {
523            if (!Allies[i].CanMakeAction && !Allies[i].IsDead)
524            {
525                Allies[i].ElapsedTime += deltaTime;
526                Allies[i].WaitTimeMeter.Value += deltaTime;
527                if (Allies[i].ElapsedTime >= Allies[i].WaitTime)
528                {
529                    Allies[i].ElapsedTime = 0.0;
530                    Allies[i].CanMakeAction = true;
531                    _AllyQueue.Enqueue(Allies[i]);
532                    AllyQueue.Enqueue(LoadBattleMenu(Allies[i]));
533                }
534            }
535        }
536
537        for (int i = 0; i < Enemies.Count; i++)
538        {
539            if (!Enemies[i].CanMakeAction)
540            {
541                Enemies[i].ElapsedTime += deltaTime;
542                if (Enemies[i].ElapsedTime >= Enemies[i].WaitTime)
543                {
544                    Enemies[i].ElapsedTime = 0.0;
545                    Enemies[i].CanMakeAction = true;
546
547                    int Index = i;
548
549                    ActionQueue.Enqueue(delegate
550                    {
551                        Attacker = Enemies[Index];
552                        Enemies[Index].PickRandomAttack().OnUse();
553                    });
554                }
555            }
556        }
557    }
558
559    public override void Update(Time time)
560    {
561        if (Flags.InBattle)
562        {
563            if (AllyQueue.Count > 0 && !IsInMenu)
564            {
565                AllyQueue.Dequeue().Invoke(_AllyQueue.Peek());
566            }
567
568            if (ActionQueue.Count > 0 && !IsAttackAnimationPlaying)
569            {
570                IsAttackAnimationPlaying = true;
571                IsTimerActive = false;
572                ActionQueue.Dequeue().Invoke();
573            }
574
575            if (IsTimerActive)
576            {
577                double deltaTime = (float)time.SinceLastUpdate.TotalSeconds;
578                BattleTimer(deltaTime);
579            }
580        }
581
582        base.Update(time);
583    }
584}
Note: See TracBrowser for help on using the repository browser.