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

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