source: 2014/30/MiskaK/The Reclaim/The Reclaim/The Reclaim/The Reclaim/The_Reclaim.cs @ 5555

Revision 5555, 20.2 KB checked in by mikrkana, 6 years ago (diff)

Korjattu SeesObject?-bugi ja lisätty etu- ja sukunimiä.

Line 
1using System;
2using System.Collections.Generic;
3using Jypeli;
4using Jypeli.Assets;
5using Jypeli.Controls;
6using Jypeli.Effects;
7using Jypeli.Widgets;
8
9public class The_Reclaim : PhysicsGame
10{
11    public static The_Reclaim Peli;
12
13    /// <summary>
14    /// Verkko reitinhakua varten.
15    /// </summary>
16    public Map NavigationMesh { get; private set; }
17
18    public List<Soldier> HostileTroops = new List<Soldier>();
19    public List<Soldier> FriendlyTroops = new List<Soldier>();
20    public List<Soldier> SelectedTroops = new List<Soldier>();
21
22    public Timer AITick = new Timer();
23
24    public List<LevelData> Levels = new List<LevelData>();
25    public LevelData CurrentLevel;
26
27    public List<GameObject> effectObjects = new List<GameObject>();
28
29    private Vector TroopSelectionCorner;
30    private bool SelectingTroops;
31    private ActionMenu actionMenu;
32    private Behaviour CurrentBehaviour = Behaviour.Idle;
33
34    private bool SelectingShootingTarget;
35    private Vector ShootingTargetCorner;
36
37#if !DEBUG
38    Label waterprint = new Label("The Reclaim (development version)\n by Miska Kananen");
39#endif
40
41    public override void Begin()
42    {
43        Peli = this;
44#if !DEBUG
45        waterprint.Position = new Vector(Screen.Left + waterprint.Width / 2, Screen.Bottom + 30);
46        waterprint.TextScale = new Vector(0.8, 0.8);
47        waterprint.TextColor = Color.White;
48        Add(waterprint);
49#endif
50        MainMenu();
51    }
52
53    void MainMenu()
54    {
55        StartGame("ruinedcity", 1);
56    }
57
58    void StartGame(string world, int levelCount)
59    {
60        LoadLevels(world, levelCount);
61        LoadLevel(1);
62        SetControls();
63        InitializeAI();
64    }
65
66    #region grafiikka
67
68    /// <summary>
69    /// Zoomataan kameraa hiiren rullan mukaan.
70    /// </summary>
71    void ZoomCamera()
72    {
73        double zoom = Camera.ZoomFactor + ((Mouse.WheelChange * 0.05) / Camera.ZoomFactor);
74        if (zoom > 0)
75            Camera.ZoomFactor += (Mouse.WheelChange * 0.05);
76        //if (Mouse.WheelChange > 0)
77        //Camera.Position = Mouse.PositionOnWorld;
78    }
79
80    protected override void Paint(Canvas canvas)
81    {
82        Vector mousePos = Mouse.PositionOnWorld;
83
84        if (SelectingTroops)
85        {
86            canvas.BrushColor = Color.Blue;
87            canvas.DrawLine(TroopSelectionCorner, new Vector(TroopSelectionCorner.X, mousePos.Y));
88            canvas.DrawLine(TroopSelectionCorner, new Vector(mousePos.X, TroopSelectionCorner.Y));
89            canvas.DrawLine(mousePos, new Vector(mousePos.X, TroopSelectionCorner.Y));
90            canvas.DrawLine(mousePos, new Vector(TroopSelectionCorner.X, mousePos.Y));
91        }
92
93        if (SelectingShootingTarget)
94        {
95            canvas.BrushColor = Color.Red;
96            canvas.DrawLine(ShootingTargetCorner, new Vector(ShootingTargetCorner.X, mousePos.Y));
97            canvas.DrawLine(ShootingTargetCorner, new Vector(mousePos.X, ShootingTargetCorner.Y));
98            canvas.DrawLine(mousePos, new Vector(mousePos.X, ShootingTargetCorner.Y));
99            canvas.DrawLine(mousePos, new Vector(ShootingTargetCorner.X, mousePos.Y));
100        }
101
102        /*for (int i = 0; i < SelectedTroops.Count; i++) // piirretään ampuvien sotilaiden kohdealueet
103        {
104            if (SelectedTroops[i].CurrentBehaviour == Behaviour.Shoot && SelectedTroops[i].ShootingTargetArea != null)
105            {
106                canvas.BrushColor = new Color(255, 0, 0, 32);
107                canvas.DrawLine(SelectedTroops[i].ShootingTargetArea.FirstCorner, new Vector(SelectedTroops[i].ShootingTargetArea.SecondCorner.X, SelectedTroops[i].ShootingTargetArea.FirstCorner.Y));
108                canvas.DrawLine(SelectedTroops[i].ShootingTargetArea.FirstCorner, new Vector(SelectedTroops[i].ShootingTargetArea.FirstCorner.X, SelectedTroops[i].ShootingTargetArea.SecondCorner.Y));
109                canvas.DrawLine(SelectedTroops[i].ShootingTargetArea.SecondCorner, new Vector(SelectedTroops[i].ShootingTargetArea.SecondCorner.X, SelectedTroops[i].ShootingTargetArea.FirstCorner.Y));
110                canvas.DrawLine(SelectedTroops[i].ShootingTargetArea.SecondCorner, new Vector(SelectedTroops[i].ShootingTargetArea.FirstCorner.X, SelectedTroops[i].ShootingTargetArea.SecondCorner.Y));
111            }
112        }*/
113        base.Paint(canvas);
114    }
115
116    /// <summary>
117    /// Piirretään valojuovia.
118    /// </summary>
119    /// <param name="position">Valojuovan tämänhetkinen sijainti.</param>
120    /// <param name="color">Valojuovan väri.</param>
121    /// <param name="lifetimeInSeconds">Kauanko valojuova pysyy kentällä.</param>
122    public void DrawTracers(Vector position, Color color, double lifetimeInSeconds, double brightnessFactor)
123    {
124        color.AlphaComponent = (byte)(32 * brightnessFactor); // 64 toimii
125        GameObject tracer = new GameObject(2, 2);
126        tracer.Shape = Shape.Circle;
127        tracer.Color = color;
128        tracer.Position = position;
129        tracer.MaximumLifetime = TimeSpan.FromSeconds(lifetimeInSeconds);
130        Add(tracer, -2);
131    }
132
133    /// <summary>
134    /// Piirretään valojuovia.
135    /// </summary>
136    /// <param name="tracingObject">Olio, josta valojuovat tulevat.</param>
137    /// <param name="color">Valojuovan väri.</param>
138    /// <param name="lifetimeInSeconds">Kauanko valojuova pysyy kentällä.</param>
139    /// <param name="brightnessFactor">Valojuovan kirkkaus.</param>
140    public void DrawTracers(GameObject tracingObject, Color color, double lifetimeInSeconds, double brightnessFactor)
141    {
142        color.AlphaComponent = (byte)(32 * brightnessFactor); // 64 toimii
143        GameObject tracer = new GameObject(60, 2);
144        tracer.Shape = Shape.Circle;
145        tracer.Color = color;
146        tracer.Position = tracingObject.Position;
147        tracer.Angle = tracingObject.Angle;
148        tracer.MaximumLifetime = TimeSpan.FromSeconds(lifetimeInSeconds);
149        Add(tracer, -2);
150    }
151
152    /// <summary>
153    /// Lisätään tietorakenteeseen uusi tehosteobjekti ja poistetaan
154    /// vanha, jos objekteja on liikaa.
155    /// </summary>
156    /// <param name="tehoste">Lisättävä objekti.</param>
157    public void LisaaTehosteObjekti(GameObject tehoste)
158    {
159        effectObjects.Add(tehoste);
160        if (effectObjects.Count > GameConstants.MAX_NUMBER_OF_EFFECT_OBJECTS)
161        {
162            effectObjects[0].Destroy();
163            effectObjects.RemoveAt(0);
164        }
165    }
166
167    void UpdateFoW(GameObject fow)
168    {
169        SetTransparent(fow.Image, Vector.Zero, 0);
170    }
171
172    void SetTransparent(Image kuva, Vector position, double radius)
173    {
174        uint[,] bmp = kuva.GetDataUInt();
175        int ny = kuva.Height;
176        int nx = kuva.Width;
177
178        int minY = (int)(position.Y / 10 + ny / 2);
179        // ny / 2 olis y = o
180        // nx / 2 x = 0
181        // yks pikseli = 10 koordinaatistossa
182
183        for (int iy = 0; iy < ny; iy++)
184            for (int ix = 0; ix < nx; ix++)
185            {
186                uint c = bmp[iy, ix];
187                byte r = Color.GetRed(c);
188                byte g = Color.GetGreen(c);
189                byte b = Color.GetBlue(c);
190                byte a = Color.GetAlpha(c);
191
192                byte newAlpha = (byte)(a - 1);
193
194                bmp[iy, ix] = Color.PackRGB(r, g, b, newAlpha);
195            }
196        kuva.SetData(bmp);
197    }
198
199    #endregion
200
201    #region kentta
202
203    /// <summary>
204    /// Luodaan maailma ruutukarttojen pohjalta.
205    /// </summary>
206    /// <param name="data">Luomiseen tarvittavat tiedot.</param>
207    void CreateWorld(LevelData data)
208    {
209        SmoothTextures = false;
210        Level.BackgroundColor = Color.White;
211        Camera.ZoomToAllObjects();
212        Mouse.IsCursorVisible = true;
213
214        GameObject backgroundImage = new GameObject(data.GroundTexture.Width * 2, data.GroundTexture.Height * 2); // *64
215        backgroundImage.Image = data.GroundTexture;
216        backgroundImage.Tag = "background";
217        Add(backgroundImage, -3);
218
219        NavigationMesh = new Map(data.Walls.Width, data.Walls.Height);
220
221        ColorTileMap walls = new ColorTileMap(data.Walls);
222        walls.SetTileMethod(Color.Black, CreateWall, Color.Transparent);
223        walls.SetTileMethod(Color.Gold, CreateWall, Color.Transparent);
224        walls.SetTileMethod(Color.BrightGreen, CreateEntrance, Entrance.Owner.Friendly);
225        walls.SetTileMethod(Color.Red, CreateEntrance, Entrance.Owner.Enemy);
226        walls.Execute(GameConstants.TILE_WIDTH, GameConstants.TILE_HEIGHT);
227
228
229
230        /*ColorTileMap roofs = new ColorTileMap(data.Roofs);
231        roofs.SetTileMethod(Color.DarkGray, CreateRoof, Color.DarkGray);
232        roofs.Execute(GameConstants.TILE_WIDTH, GameConstants.TILE_HEIGHT);*/
233
234        //GameObject fogOfWar = new GameObject(backgroundImage.Width, backgroundImage.Height);
235        //fogOfWar.Image = new Image(data.GroundTexture.Width, data.GroundTexture.Height, Color.Black);
236        //Add(fogOfWar, 2);
237
238        //Timer fowTimer = new Timer();
239        //fowTimer.Interval = 0.1;
240        //fowTimer.Timeout += delegate { UpdateFoW(fogOfWar); };
241        //fowTimer.Start();     
242    }
243
244    void CreateWall(Vector paikka, double leveys, double korkeus, IntPoint positionInLevelArray, Color vari) // vari DEBUG
245    {
246        PhysicsObject seina = PhysicsObject.CreateStaticObject(leveys, korkeus);
247        seina.Position = paikka;
248        seina.Color = vari;
249        seina.Tag = "seina";
250        Add(seina);
251
252        NavigationMesh.Nodes[positionInLevelArray.X, positionInLevelArray.Y].IsFull = true;
253    }
254
255    void CreateRoof(Vector paikka, double leveys, double korkeus, IntPoint positionInLevelArray, Color vari) // vari DEBUG
256    {
257        GameObject katto = new GameObject(leveys, korkeus);
258        katto.Position = paikka;
259        katto.Color = vari;
260        /*katto.NeedsUpdateCall = true;
261        katto.IsUpdated = true;
262        katto.NeedsUpdateCall = true;
263        katto.Updated += UpdateRoofTransparency;*/
264        Add(katto, 1);
265    }
266
267    void CreateEntrance(Vector paikka, double leveys, double korkeus, IntPoint posInLevel, Entrance.Owner owner)
268    {
269        Entrance e = new Entrance(paikka, GameConstants.ENTRANCE_RADIUS, owner, GameConstants.SECONDS_TO_CAPTURE);
270        //e.Spawn();
271        CurrentLevel.Entrances.Add(e);
272    }
273
274    /// <summary>
275    /// Ladataan kenttä ja luodaan se.
276    /// </summary>
277    /// <param name="level">Monesko kenttä.</param>
278    void LoadLevel(int level)
279    {
280        if (level < 0 || level > Levels.Count) return;
281        CurrentLevel = Levels[level - 1];
282        ClearGameObjects();
283        CreateWorld(CurrentLevel);
284    }
285
286    /// <summary>
287    /// Ladataan kaikki kentät.
288    /// </summary>
289    /// <param name="world">Maailmakansion nimi.</param>
290    /// <param name="levelCount">Ruutujen määrä maailmassa.</param>
291    void LoadLevels(String world, int levelCount)
292    {
293        Levels.Clear();
294        for (int i = 1; i < levelCount + 1; i++)
295        {
296            Image walls = LoadImage(world + "/" + "ruutu" + i.ToString() + "_seinat");
297            Image maatekstuuri = LoadImage(world + "/" + "ruutu" + i.ToString() + "_maatekstuuri");
298
299            LevelData data = new LevelData(maatekstuuri, walls, null);
300            Levels.Add(data);
301        }
302    }
303
304    /*void UpdateRoofTransparency(GameObject roof)
305    {
306        const double MIN_DISTANCE = 400.0;
307
308        if (Vector.Distance(roof.Position, Mouse.PositionOnWorld) < MIN_DISTANCE)
309        {
310
311        }
312        else roof.Color.AlphaComponent = 255;
313    }*/
314
315#endregion
316
317    #region hahmot
318
319    public Soldier CreateSoldier(Vector paikka, Image kuva, bool isPlayerControlled, double speed, Ase ase, Angle kulma)
320    {
321        Soldier s = new Soldier(kuva, 0.5, isPlayerControlled);
322        s.Position = paikka;
323        s.Shape = Shape.Circle;
324        s.Angle = kulma;
325        s.MovingSpeed = speed;
326        s.CollisionIgnoreGroup = 1;
327        s.Weapon = ase;
328        s.Weapon.UsesTracers = true;
329        s.LinearDamping = 0.98;
330
331        if (isPlayerControlled)
332        {
333            FriendlyTroops.Add(s);
334        }
335        else
336        {
337            HostileTroops.Add(s);
338        }
339        Add(s);
340        return s;
341    }
342
343    #endregion
344
345    #region ohjaimet
346
347    void SetControls()
348    {
349        Mouse.ListenWheel(ZoomCamera, null);
350        Mouse.Listen(MouseButton.Left, ButtonState.Pressed, delegate {
351            TroopSelectionCorner = Mouse.PositionOnWorld;
352            SelectingTroops = true;
353        }, null);
354        Mouse.Listen(MouseButton.Left, ButtonState.Released, delegate {
355            SelectingTroops = false;
356            SelectTroops();
357        }, null);
358        Mouse.Listen(MouseButton.Middle, ButtonState.Pressed, delegate {
359            CreateActionMenu();
360        }, null);
361        Mouse.Listen(MouseButton.Middle, ButtonState.Released, delegate
362        {
363            actionMenu.ButtonClicked(actionMenu.GetButtonClosestToMouse());
364        }, null);
365        Mouse.Listen(MouseButton.Right, ButtonState.Pressed, delegate {
366            if (SelectedTroops.Count != 0)  ApplyBehaviour();
367        }, null);
368
369
370        Keyboard.Listen(Key.Space, ButtonState.Pressed, delegate { CreateSoldier(Mouse.PositionOnWorld, Images.PelaajaTesti, true, RandomGen.NextDouble(GameConstants.SOLDIER_MIN_SPEED, GameConstants.SOLDIER_MAX_SPEED), Aseet.GetRandomWeapon(), Angle.Zero); }, null);
371        Keyboard.Listen(Key.RightControl, ButtonState.Pressed, delegate { CreateSoldier(Mouse.PositionOnWorld, Images.PelaajaTesti, false, RandomGen.NextDouble(GameConstants.SOLDIER_MIN_SPEED, GameConstants.SOLDIER_MAX_SPEED), Aseet.GetRandomWeapon(), Angle.Zero); }, null);
372        //Keyboard.Listen(Key.Space, ButtonState.Pressed, delegate { MessageDisplay.Add(Mouse.PositionOnWorld.ToString()); MessageDisplay.Add(NavigationMesh.GetCorrespondingNode(Mouse.PositionOnWorld).ToString()); }, null);
373        Keyboard.Listen(Key.W, ButtonState.Down, LiikutaKameraa, null, new Vector(0.0, 1.0));
374        Keyboard.Listen(Key.S, ButtonState.Down, LiikutaKameraa, null, new Vector(0.0, -1.0));
375        Keyboard.Listen(Key.A, ButtonState.Down, LiikutaKameraa, null, new Vector(-1.0, 0.0));
376        Keyboard.Listen(Key.D, ButtonState.Down, LiikutaKameraa, null, new Vector(1.0, 0.0));
377
378    }
379
380    void LiikutaKameraa(Vector suunta)
381    {
382        Camera.Position += (suunta * GameConstants.CAMERA_MOVEMENT_SPEED);
383    }
384
385    void SelectTroops()
386    {
387        Vector corner = Mouse.PositionOnWorld;
388
389        SelectedTroops.ForEach(x => x.SelectionMarker.IsVisible = false); 
390        SelectedTroops.Clear();
391
392        for (int i = 0; i < HostileTroops.Count; i++)
393        {
394            HostileTroops[i].SelectionMarker.IsVisible = false;
395        }
396
397        List<GameObject> selected = GetObjects(x => x is Soldier && IsInside(x.Position, TroopSelectionCorner, corner));
398
399        for (int i = 0; i < selected.Count; i++)
400        {
401            Soldier s = (Soldier)selected[i];
402            if (s.IsPlayerControlled)
403            {
404                SelectedTroops.Add(s);
405                s.SelectionMarker.IsVisible = true;
406
407                if (s.TargetSoldiers != null)
408                {
409                    for (int j = 0; j < s.TargetSoldiers.Count; j++)
410                    {
411                        s.TargetSoldiers[j].SelectionMarker.IsVisible = true;
412                    }
413                }
414            }
415        }
416    }
417
418    /// <summary>
419    /// Onko piste kahden pisteen muodostaman suorakulmion sisällä.
420    /// </summary>
421    /// <param name="pos">Piste.</param>
422    /// <param name="firstCorner">Ensimmäinen nurkka.</param>
423    /// <param name="secondCorner">Toinen nurkka.</param>
424    /// <returns>Onko piste suorakulmion sisällä.</returns>
425    public bool IsInside(Vector pos, Vector firstCorner, Vector secondCorner)
426    {
427        if (pos.X < Math.Min(firstCorner.X, secondCorner.X) || pos.X > Math.Max(firstCorner.X, secondCorner.X)) return false;
428        if (pos.Y < Math.Min(firstCorner.Y, secondCorner.Y) || pos.Y > Math.Max(firstCorner.Y, secondCorner.Y)) return false;
429        return true;
430    }
431
432    void CreateActionMenu()
433    {
434        Vector mousePos = Mouse.PositionOnWorld;
435
436        actionMenu = new ActionMenu(300, 60, Behaviour.Idle, Behaviour.Move, Behaviour.Shoot);
437        actionMenu.Position = new Vector(Mouse.PositionOnScreen.X, Mouse.PositionOnScreen.Y);
438        actionMenu.Clicked += delegate(Behaviour action) { ActionButtonClicked(action, mousePos); actionMenu.Destroy(); };
439        Add(actionMenu);
440    }
441
442    void ActionButtonClicked(Behaviour action, Vector targetPosition)
443    {
444        CurrentBehaviour = action;
445        MessageDisplay.Add("Current action: " + action.ToString());
446    }
447   
448    #endregion
449
450    #region tekoaly
451
452    void ApplyBehaviour()
453    {
454        switch (CurrentBehaviour)
455        {
456            case Behaviour.Idle:
457                for (int i = 0; i < SelectedTroops.Count; i++)
458                {
459                    SelectedTroops[i].CurrentBehaviour = CurrentBehaviour;
460                    //SelectedTroops[i].ShootingTargetArea = null;
461                }
462                break;
463            case Behaviour.Move:
464                for (int i = 0; i < SelectedTroops.Count; i++)
465                {
466                    SelectedTroops[i].CurrentBehaviour = CurrentBehaviour;
467                    SelectedTroops[i].TargetLocation = Mouse.PositionOnWorld;
468                }
469                break;
470            case Behaviour.Shoot:
471                for (int i = 0; i < SelectedTroops.Count; i++)
472                {
473                    SelectedTroops[i].CurrentBehaviour = CurrentBehaviour;
474                }
475                if (!SelectingShootingTarget)
476                {
477                    ShootingTargetCorner = Mouse.PositionOnWorld; // tallennetaan ensimmäinen nurkka
478                    SelectingShootingTarget = true;
479
480                    Mouse.Listen(MouseButton.Right, ButtonState.Released, delegate
481                    {
482                        if (!SelectingShootingTarget) return;
483                        for (int i = 0; i < SelectedTroops.Count; i++)
484                        {
485                            SelectedTroops[i].TargetSoldiers.Clear();
486                            Area a = new Area(ShootingTargetCorner, Mouse.PositionOnWorld);
487                            List<GameObject> soldiersInArea = GetObjects(x => x is Soldier && a.IsInside(x.Position));
488                            for (int j = 0; j < soldiersInArea.Count; j++)
489                            {
490                                Soldier s = (Soldier)soldiersInArea[j];
491                                if (!s.IsPlayerControlled)
492                                    SelectedTroops[i].TargetSoldiers.Add(s);
493                            }
494                            for (int j = 0; j < SelectedTroops[i].TargetSoldiers.Count; j++)
495                            {
496                                // käydään läpi kaikki viholliset alueella
497                                SelectedTroops[i].TargetSoldiers[j].SelectionMarker.IsVisible = true;
498                            }
499                        }
500                        SelectingShootingTarget = false;
501                    }, null);
502                }
503                break;
504            default:
505                break;
506        }
507    }
508
509    void InitializeAI()
510    {
511        AITick.Interval = GameConstants.AI_REFRESH_RATE;
512        AITick.Timeout += DoAITick;
513        AITick.Start();
514    }
515
516    void DoAITick()
517    {
518        for (int i = 0; i < FriendlyTroops.Count; i++)
519        {
520            FriendlyTroops[i].UpdateAI();
521        }
522
523        for (int i = 0; i < HostileTroops.Count; i++)
524        {
525            HostileTroops[i].UpdateAI();
526        }
527    }
528
529    #endregion
530
531    #region testit
532    /*void DrawRoute()
533    {
534        route = NavigationMesh.DijkstraSearch(NavigationMesh.GetCorrespondingNode(pos1), NavigationMesh.GetCorrespondingNode(pos2));
535
536        for (int i = 0; i < route.Length; i++)
537        {
538            GameObject g = new GameObject(25, 25, Shape.Rectangle);
539            g.Position = NavigationMesh.GetPositionOnWorld(route[i].Position);
540            g.Color = Color.Red;
541            Add(g, 3);
542            g.MaximumLifetime = TimeSpan.FromSeconds(5.0);
543        }
544    }*/
545
546    #endregion
547}
Note: See TracBrowser for help on using the repository browser.