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

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