BoomFighter. Prosta gra. Pilot myśliwca / BoomFighter. A simple game. Fighter pilot


![jet-simulator-for-novice-programmer-c-sharp.png](//static.4programmers.net/uploads/attachment/5869b9e0f0412.png) Widok ekranu gry / View of game screen

Opis gry / About the game

Program jest prostą grą polegającą na podążaniu za samolotem przeciwnika w celu zestrzelenia go. Mamy do dyspozycji automatycznie zmieniającego kierunek przeciwnika, celownik i klawiaturę komputera. Strzałkami kierujemy się za uciekającym ruchem losowym samolotem przedstawionym jako trójkąt. Kiedy samolot znajdzie się w celu – na przecięciu umieszczonych w centrum osi układu współrzędnych, naciskamy spację i oddajemy strzał. Trafienie sygnalizowane jest błyskiem ekranu. Kiedy samolot zbliży się do brzegu ekranu, jego pozycja jest zmieniana, aby nigdy nie wyszedł poza ekran.

The program is a simple game involving the following of enemy aircraft to shoot down it. We have automatically changing the direction of the enemy, the viewfinder and computer keyboard. Arrows direct tracing plane random movement shown as a triangle. When the plane is in target - at the cross located in the center of the coordinate axes, press the space bar and give a shot. A hit is signaled by a flash of the screen. As the plane approaches the edge of the screen, its position is changed, that never got outside the screen.

Historia gry / Game history

Autor napisał tę grę w latach 80-tych na komputer Atari 130 XE. Praktycznie została tu odtworzona w oryginale. Brakuje jedynie dźwięku wybuchu samolotu po trafieniu. Gra była przeznaczona dla kilkuletniego dziecka – kuzyna autora. Były to czasy, kiedy nie było telefonów komórkowych, smartfonów, tabletów, etc. Dziecko nie znało w ogóle komputera, ale nauczyło się szybko i… nie można go było oderwać od gry, co akurat jest podobne do czasów współczesnych. Spotkanie rodzinne przebiegało w ciszy i spokoju, niemniej autor zdecydowanie jest zwolennikiem umiaru w pozwalaniu dzieciom na zabawy grami komputerowymi.

The author wrote this game in the 80s on a computer Atari 130 XE. Practically there has been reconstructed in the original. Missing only the sound of explosion after the plane hit. The game was designed for a few years child - a cousin. There were times when there were no cell phones, smartphones, tablets, etc. The child did not know at all the computer, but learned quickly and ... it can not be taken out from the game, which happens to be similar to modern times. There were family meeting in peace and quiet, but the author is definitely an advocate of moderation in letting children play computer games.

using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace BoomFighter
{
    public partial class FormMain : Form
    {
        bool boom;        // zmienna informujaca o zestrzeleniu samolotu
                          // the variable that tells of shooting down aircraft
        
        Brush flashColor; // kolor wybuchu zestrzelonego samolotu
                          // color explosion of the downed plane    
        
        Brush lineColor;  // kolor linii
                          // line color
        
        Brush skyColor;   // kolor tla
                          // bacground color
        
        int aircraftDx;   // przesuniecie wlasne samolotu w poziomie (auto)
                          // shift its own aircraft in level (auto)
        
        int aircraftDy;   // przesuniecie wlasne samolotu w pionie (auto)
                          // shift its own aircraft in the vertical (auto)
        
        int d;            // polowa dlugosci podstawy trojkata (samolotu)
                          // half the length of the base of the triangle (the plane)
        
        int div;          // wspolczynnik podzialu ekranu
                          // coefficient division screen
        
        int playerDx;     // przesuniecie samolotu w poziomie po nacisnieciu klawisza
                          // moving the aircraft in level when you press the key
        
        int playerDy;     // przesuniecie samolotu w pionie po nacisnieciu klawisza
                          // moving the aircraft vertically when you press the key
        
        int x;            // poczatek ukladu wspolrzednych (os X)
                          // the origin (X-axis)
        
        int y;            // poczatek ukladu wspolrzednych (os Y)
                          // the origin (X-axis)
        
        Pen pen;          // pioro rysujace linie
                          // the pen drawing a line
        
        Point boomXY;     // wspolrzedne trafienia
                          // coordinates of a hit
        
        Point[] aircraft; // tablica wspolrzednych wierzcholkow trojkata
                          // coordinate table tops triangle
        
        Random r;         // generator liczb losowych
                          // random number generator
        
        Rectangle sky;    // obszar ekranu bez ramek (bez border)
                          // area of the screen without frames (without border)
        
        Rectangle window; // prostokat formy z ramkami (z border)
                          // rectangle form with frames (with border)
        
        Timer t;          // timer (odlicza czas pomiedzy rysowaniem kolejnych kadrow)
                          // timer (counting down the time between the drawing frames in succession)
        
        public FormMain()
        {
            InitializeComponent();

            #region Initialize window

            this.Text = "BoomFighter";
            this.StartPosition = FormStartPosition.Manual;
            this.WindowState = FormWindowState.Normal;
            window = Screen.PrimaryScreen.WorkingArea;
            this.Location = new Point(0, 0);
            this.Size = new Size(window.Width, window.Height);
            this.BackColor = Color.Black;

            #endregion

            r = new Random();        // zainicjowanie generatora liczb losowych
                                     // initiating the random number generator
            
            div = 20;                // okreslenie wspolczynnika podzialu ekranu (pion i poziom)
                                     // assigning of the coefficient division screen (vertical and horizontal)
            
            aircraft = new Point[4]; // okreslenie rozmiru tablicy punktow wyznaczajacych trojkat
                                     // determining the size of the array of points that define a triangle
            
            t = new Timer();         // zainicjowanie timera
                                     // initiating the timer
            
            t.Interval = 1000;       // odstep w czasie miedzy kadrami = 1 sekunda 
                                     // timing between the frames = 1 second

            // obslugiwane zdarzenia
            // handled events

            t.Tick += new EventHandler(timer_Tick);            // wywolanie procedury timera
                                                               // procedure call timer
            
            this.Paint += new PaintEventHandler(Form_Paint);   // malowanie obrazka
                                                               // painting a picture
            
            this.KeyDown += new KeyEventHandler(Form_KeyDown); // reakcja na nacisniecie klawisza
                                                               // reaction to press a key 
            
            this.Resize += new EventHandler(Form_Resize);      // reakcja na zmiane rozmiaru formy
                                                               // reaction to change the size of the form
            
            NewGame();                                         // rozpoczecie nowej gry
                                                               // starting new game
        }

        void NewGame()   // funkcja rozpoczynajaca gre od nowa
        {                // function start the game from scratch

            t.Stop();    // zatrzymanie timera
                         // stopping the timer
            
            SetColors(); // ustawienie kolorow
                         // setting colors
            
            sky = this.ClientRectangle; // nazwanie obszaru rysowania ang. niebo
                                        // naming the drawing area sky
            
            // ustwienie poczatku ukladu wspolrzednych na srodku ekranu
            // setting the origin in the middle of the screen

            x = (sky.Right - sky.Left) / 2;
            y = (sky.Bottom - sky.Top) / 2;

            // wybranie krotszego boku prosokata ekranu i podzial ekranu na skoki (jednorazowe przesuniecia)                                                       
            // samolotu (prawo, lewo, gora, dol = d), przy czym moze byc przesuniecie w pionie i poziomie
            // równocześnie np. lewo-góra

            // select the shorter side of the rectangle of the screen and the division of the screen to jump (one-time offsets)
            // aircraft (right, left, up, down = d) whereby it is possible to shift vertically and horizontally 
            // at the same time eg. left-up

            d = Math.Min(sky.Width, sky.Height) / div;  

            if (d < 1)                                  // zabezpieczenie na wypadek A / div = 0 
                d = 1;                                  // protection against result division zero

            aircraft[0] = new Point(x, y - d);          // wierzcholek trojkata samolotu (dziob)
                                                        // tip of the triangle plane (bow)
            
            aircraft[1] = new Point(x - 2 * d, y + d);  // wierzcholek lewego skrzydla samolotu
                                                        // left wing tip of the aircraft
            
            aircraft[2] = new Point(x + 2 * d, y + d);  // wierzcholek prawego skrzydla samolotu
                                                        // left wing tip of the aircraft
            
            aircraft[3] = aircraft[0];                  // zamkniecie obrysu trojkata samolotu dla funkcji DrawLines
                                                        // closing the contour of the triangle plane for function DrawLines
            
            boomXY = aircraft[0];                       // trafienie bedzie badane w oparciu o wspolrzedne dziobu samolotu
                                                        // hit will be tested based on the coordinates bow plane
            
            boom = false; // na poczatku nie ma trafienia
                          // at the beginning there is no hit
            
            // ustawienie pozycji poczatkowej samolotu
            // uwaga: przesuwamy wszystkie wierzcholki trojkata o tyle samo
            
            // setting the starting position aircraft
            // note: move all the vertices of a triangle of the same
            
            for (int i = 0; i < aircraft.Count<Point>(); i++)
            {
                aircraft[i].X -= 5 * d;
                aircraft[i].Y -= 5 * d;
            }

            aircraftDx = 0;    // przesuniecie wlasne samolotu zero
            aircraftDy = 0;    // offset their own aircraft to zero

            playerDx = 0;      // przesuniecie samolotu przez gracza zero
            playerDy = 0;      // shift plane by the player to zero

            t.Start();         // wystartowanie timera
                               // boot timer
        }

        void Form_Paint(object sender, PaintEventArgs e)
        {
            if (boom)  // jezeli trafienie blysk ekranu - wybuch
            {          // if you hit the flash of the screen - explosion

                boom = false;
                e.Graphics.FillRectangle(flashColor, sky);
            }
            else       // jezeli celownie - zlozenie ruchu wlasnego samolotu ze zblizaniem sie do celu przez gracza
            {          // if tracking target - adding own plane moving to approaching the goal by a player
                
                e.Graphics.FillRectangle(skyColor, sky); // skasowanie obrazka
                                                         // clear image
                do
                {
                    aircraftDx = r.Next(-1, 1); // losowanie kierunku ruchu samolotu {-1, 0, 1}
                    aircraftDy = r.Next(-1, 1); // lottery the direction of moving the plane {-1, 0, 1}
                }
                while (aircraftDx == 0 && aircraftDy == 0); // musi byc przesuniecie chociaz wzdloz jednej osi
                                                            // must be offset though at least one axis

                // przesuniecie wspolrzednych samolotu
                // uwaga: przesuwamy wspolrzedne wszystkich wierzcholkow trojkata

                // coordinate displacement plane
                // note: move the coordinates of all vertices of the triangle

                for (int i = 0; i < aircraft.Count<Point>(); i++)
                {
                    // przesuniecie w danym kierunku zawsze o {-1, 0, 1} * d
                    // movement in a given direction always {-1, 0, 1} * d

                    int newX = aircraft[i].X + Math.Sign(aircraftDx + playerDx) * d;
                    int newY = aircraft[i].Y + Math.Sign(aircraftDy + playerDy) * d;
                    aircraft[i] = new Point(newX, newY);
                }

                // korekty pozycji aby samolot nigdy nie wyszedl poza ekran
                // adjustments to position the plane never came out off the screen

                if (aircraft[0].Y < 0)
                    for (int i = 0; i < aircraft.Count<Point>(); i++)
                        aircraft[i].Y += div * d / 2;

                if (aircraft[1].Y > sky.Bottom)
                    for (int i = 0; i < aircraft.Count<Point>(); i++)
                        aircraft[i].Y -= div * d / 2;

                if (aircraft[1].X < 0)
                    for (int i = 0; i < aircraft.Count<Point>(); i++)
                        aircraft[i].X += div * d / 2;

                if (aircraft[2].X > sky.Right)
                    for (int i = 0; i < aircraft.Count<Point>(); i++)
                        aircraft[i].X -= div * d / 2;

                e.Graphics.DrawLines(pen, aircraft); // narysowanie trojkata samolotu
                                                     // draw a triangle plane
                
                // narysowanie celownika (przeciecie osi X, Y)
                // drawing viewfinder (crossing axis X, Y)

                e.Graphics.DrawLine(pen, new Point(x, 0), new Point(x, sky.Bottom));
                e.Graphics.DrawLine(pen, new Point(0, y), new Point(sky.Right, y));
            }

        }

        // reakcja na nacisniecia klawiszy
        // strzelki prawo, lewo, gora, dol - celownie w samolot
        // spacja - oddanie strzalu

        // response to pressing
        // arrow left, right, up, down - sight on a plane
        // space - to fire a shot

        void Form_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                    playerDy += 1;
                    break;
                case Keys.Down:
                    playerDy -= 1;
                    break;
                case Keys.Left:
                    playerDx += 1;
                    break;
                case Keys.Right:
                    playerDx -= 1;
                    break;
                case Keys.Space:

                    // jezeli samolot jest w centrum ekranu - trafienie
                    // if the plane is at the center of the screen - hit

                    if (aircraft[0] == boomXY)
                    {
                        boom = true;
                        this.Invalidate();
                    }
                    break;
                default:
                    break;
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            this.Invalidate(); // namalowanie kolejnego kadru gry
        }                      // paint next frame game

        void Form_Resize(object sender, EventArgs e)
        {
            NewGame(); // rozpoczecie nowej gry po zmianie rozmiaru formy
        }              // starting a new game when you change the size of the form

        void SetColors() // ustawienie kolorow
        {                // setting colors

            skyColor = Brushes.Black;
            lineColor = Brushes.Lime;
            flashColor = Brushes.Lime;
            pen = new Pen(lineColor);
        }
    }
}

Rozwiązanie alternatywne / Alternative solution

Powyższe rozwiązanie jest bardzo proste. Niewiele trudniejszy sposób to użycie kontrolki PictureBox do narysowania samolotu i celownika. Takie rozwiązanie pozwala na uniknięcie migotania ekranu podczas odświeżania obrazu. Do formy należy najpierw dodać kontrolkę PictureBox i wywoływać funkcję poniżej w zdarzeniu timera oraz po naciśnięciu spacji. Zastępuje to użycie zdarzenia Paint, którego obsługę można usunąć z kodu.

The solution above is very simple. You can do it in another simple way using a PictureBox control to draw the airplane and the viewfinder. Such a way eliminates screen flicking when the picture is being refreshed. You need to add to the form a PictureBox control and call the function below in timer event and when space key is hit. It replaces usage of Paint event handling which can be deleted from code now.

void DrawPictureBoxImage()
{
    // wykorzystanie kontrolki PictureBox zamiast rysowania na formie
    // i bez wykorzystania zdarzenia Paint

    // usage of PictureBox control as replacement of painting at form canvas
    // Paint event is not used

    pictureBox.Size = new Size(ClientSize.Width, ClientSize.Height);

    // rysowanie w bitmapie
    // drawing in bitmap

    Bitmap bmp = new Bitmap(ClientSize.Width, ClientSize.Height);
    Graphics bmpGraphics = Graphics.FromImage(bmp);

    if (boom)  // jezeli trafienie blysk ekranu - wybuch
    {          // if you hit the flash of the screen - explosion

        boom = false;
        bmpGraphics.FillRectangle(flashColor, sky);
    }
    else       // jezeli celownie - zlozenie ruchu wlasnego samolotu ze zblizaniem sie do celu przez gracza
    {          // if tracking target - adding own plane moving to approaching the goal by a player

        bmpGraphics.FillRectangle(skyColor, sky); // skasowanie obrazka
 
        //...
        // tu: losowanie nowego kierunku samolotu i obliczenie jego nowych współrzędnych          
        // here: get new random direction of aircraft and set its new position       
        //...

        bmpGraphics.DrawLines(pen, aircraft);     // narysowanie trojkata samolotu
                                                  // draw a triangle plane

        // narysowanie celownika (przeciecie osi X, Y)
        // drawing viewfinder (crossing axis X, Y)

        bmpGraphics.DrawLine(pen, new Point(x, 0), new Point(x, sky.Bottom));
        bmpGraphics.DrawLine(pen, new Point(0, y), new Point(sky.Right, y));
    }

    // podstawienie bitmapy jako obrazka w kontrolce PictureBox
    // assigning bitmap to PictureBox image

    pictureBox.Image = bmp;
}

0 komentarzy