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

Revision 6304, 17.5 KB checked in by mijoliim, 5 years ago (diff)

Taistelut melkein toimivat.

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