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;
}