czwartek, 6 czerwca 2013

Snake, Visual Studio C++

Gra napisana w Visual Studio 2008, Snake C++


Snake, snejk, wąż - wszyscy chyba znają tą grę. Bardzo prosty kod, gra napisana na standardowej formie. Obsługa za pomocą klawiatury, proste zliczanie punktów, wąż się powiększa z każdym zjedzonym kawałkiem.
Teoretycznie nie ma końca gry, za wyjątkiem kolizji. Wszystko zależy od prędkości ustawianej w kodzie. 

Przekompilowałem ostatnio pod VS2010, więc nie powinno być raczej problemu z odpaleniem


Dostępny cały kod źródłowy z kodem projektu - pobierz w dysku google.

Poniżej kawałek kodu:
snejk.h
#pragma once


ref class snejk //klasa modułu węża
{
public:
    System::Drawing::Pen ^kolor; //zawiera pen który przechowuje kolor
    System::Drawing::Rectangle ^modul; //zawiera prostokąt (jak i jego współrzędne)

    snejk(System::Drawing::Color color,int x,int y) //konstruktor, podajemy kolor i współrzędne
    {
        this->modul = gcnew System::Drawing::Rectangle(x,y,10,10);
        this->kolor = gcnew System::Drawing::Pen(color,3);
    }
    virtual ~snejk(void) //destruktor
    {


    }
    void przesun_na_pozycje(snejk^ modul_tmp) //przesuwa na pozycję podanego obiektu tej samej klasy
    {
        this->modul->X = modul_tmp->modul->X;
        this->modul->Y = modul_tmp->modul->Y;
    }
    void przesun_na_pozycje(int x, int y) //przesuwa na pozycję podanych współrzędnych
    {
        this->modul->X = x;
        this->modul->Y = y;
    }

    void rysuj(System::Drawing::Graphics^ grafa) //rysuje prostokąt
    {
        grafa->DrawRectangle(this->kolor,*this->modul);
    }

    bool sprawdz_kolizje_z_punktem(int x, int y) //sprawdza kolizję z punktem
    {
       
        if((this->modul->X == x )&&(this->modul->Y == y)) //jezeli punkty mają te same pozycje
            return true;
        else //jeśli nie ma kolizji
            return false;
    }   
};

form1.h

#pragma once
#include "snejk.h"

namespace projekt_s {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;

    /// <summary>
    /// Summary for Form1
    ///
    /// WARNING: If you change the name of this class, you will need to change the
    ///          'Resource File Name' property for the managed resource compiler tool
    ///          associated with all .resx files this class depends on.  Otherwise,
    ///          the designers will not be able to interact properly with localized
    ///          resources associated with this form.
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
    System::Drawing::Pen^ pen; //pen do rysowania weza oraz jabłek
    System::Collections::Generic::List<snejk^>^ waz;//lista zawierająca elementy klasy snejk - reprezentuje weza
    int jablko_x, jablko_y, xx, yy, kierunek, punkty; //xx, yy to obecna pozycja kursora
    bool gra; //zmienna pomocnicza ustalajaca czy gra jest w trakcie czy nie

    private: System::Windows::Forms::Label^  label1;
    private: System::Windows::Forms::Label^  label2;
    private: System::Windows::Forms::Label^  label3;
    private: System::Windows::Forms::Timer^  timer1;
    public:

        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
            this->gra = false;
            this->pen = gcnew System::Drawing::Pen(Color::Red,3); //pen do jabłek
            this->timer1->Interval = 250; //czas na 25ms
            //this->nowa_gra(); //nowa gra //rysuje się waz niepotrzebnie na początku, a pozniej zmienia pozycję jabłko po enterze bo jescze raz jest jest losowana pozycja

        }

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::ComponentModel::IContainer^  components;
    protected:
    protected:
    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>

#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->components = (gcnew System::ComponentModel::Container());
            this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
            this->label1 = (gcnew System::Windows::Forms::Label());
            this->label2 = (gcnew System::Windows::Forms::Label());
            this->label3 = (gcnew System::Windows::Forms::Label());
            this->SuspendLayout();
            //
            // timer1
            //
            this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
            //
            // label1
            //
            this->label1->AutoSize = true;
            this->label1->Location = System::Drawing::Point(-1, 483);
            this->label1->Name = L"label1";
            this->label1->Size = System::Drawing::Size(43, 13);
            this->label1->TabIndex = 0;
            this->label1->Text = L"Punkty:";
            //
            // label2
            //
            this->label2->AutoSize = true;
            this->label2->Location = System::Drawing::Point(48, 483);
            this->label2->Name = L"label2";
            this->label2->Size = System::Drawing::Size(13, 13);
            this->label2->TabIndex = 1;
            this->label2->Text = L"0";
            //
            // label3
            //
            this->label3->AutoSize = true;
            this->label3->ForeColor = System::Drawing::Color::Red;
            this->label3->Location = System::Drawing::Point(7, 30);
            this->label3->Name = L"label3";
            this->label3->Size = System::Drawing::Size(202, 13);
            this->label3->TabIndex = 2;
            this->label3->Text = L"Aby rozpocząć nową grę naciśnij ENTER";
            //
            // Form1
            //
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(484, 497);
            this->Controls->Add(this->label3);
            this->Controls->Add(this->label2);
            this->Controls->Add(this->label1);
            this->MaximizeBox = false;
            this->MaximumSize = System::Drawing::Size(500, 535);
            this->MinimumSize = System::Drawing::Size(500, 535);
            this->Name = L"Form1";
            this->Text = L"Snejk";
            this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &Form1::Form1_Paint);
            this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &Form1::Form1_KeyDown);
            this->ResumeLayout(false);
            this->PerformLayout();

        }
#pragma endregion
   
    public:    void losuj_jablko(){ //losuje pozycje połozenia jabłka
    Random^ randObj = gcnew Random;
    this->jablko_x=(randObj->Next(1,48)*10); //połozenie x,y jabłka musi znajdować się w obszarze gry
    this->jablko_y=(randObj->Next(1,48)*10);                    
}
    public: void losuj_start() //losujemy kierunek w którym będzie się poruszał waz po starcie
    {
        Random^ rand = gcnew Random;
        int los;
        los = rand->Next(1,4); //losujemy liczbę od 1 do 3
        if(los==3) //3 jest zabronione bo 3 oznacza kierunek w lewo (wąż ma głowę z prawej strony i jest rysowany z prawej do lewej)
        this->kierunek = 4; //zeby nie było 3 kierunku to przypisuje 4 i problem z głowy
        else
        this->kierunek = los; //jezeli to 1 lub 2 (góra/dół)
    }

    private: System::Void Form1_KeyDown(System::Object^  sender, System::Windows::Forms::KeyEventArgs^  e) {
                 switch(e->KeyCode)
                 {
                 case Keys::Up:
                     if(kierunek!=2) //zapobiega obróceniu węża w górę jeśli porusza się w dół
                        kierunek = 1;
                     break;
                 case Keys::Down:
                      if(kierunek!=1) //jw tylko na odwrót
                        kierunek = 2;
                     break;
                 case Keys::Left:
                      if(kierunek!=4) //zapobiega odwróceniu węża w lewo jeśli jest zwrócony w prawo
                        kierunek = 3;
                     break;
                 case Keys::Right:
                      if(kierunek!=3) //jw tylko na odwrót
                         kierunek = 4;           
                     break;
                 case Keys::Enter:
                     if(!this->gra) //jezeli false, jeżeli gra stoi
                     {
                     this->label3->Visible = false; //wyłączy widocznosc tekstu
                     this->timer1->Enabled = true; //załączy timer
                     this->gra = true; //aktywuje gre
                     this->nowa_gra();
                     }
                     break;
                 }
           
             }

    private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
    this->Refresh(); //odświeżam widok formy
        if (kierunek == 1) //jezeli w górę
                {
                this->xx=this->xx;
                this->yy=this->yy-10;
                }
        if (kierunek == 2)//jezeli w dół
                {
                this->xx=this->xx;
                this->yy=this->yy+10;
                }
        if (kierunek == 3) //jeżeli w lewo
                {
                this->xx=this->xx-10;
                this->yy=this->yy;
                }
        if (kierunek == 4)//jezeli w prawo
                {
                this->xx=this->xx+10;
                this->yy=this->yy;
                }
if((this->sprawdz_kolizje_z_wezem(this->xx,this->yy))||this->sprawdz_kolizje_ze_sciana())
{ //jezeli nastapiła kolizja z jedna ze scian lub z samym sobą to koniec gry
    this->gra = false; //dezaktywuje gre
    return this->game_over();   
}
else
{ //w przeciwnym wypadku sprawdzamy kolizje z jabłkiem
    if (this->waz[0]->sprawdz_kolizje_z_punktem(this->jablko_x,this->jablko_y))//jezeli pierwszy element wejdzie na pozycje jabłka
                {
                snejk ^temp;
                this->losuj_jablko(); //losuje nowa pozycje jabłka
                temp = gcnew snejk(System::Drawing::Color::Red,0, 0); //tworzy nowy obiekt klasy snejk (dowolne współrzedne, pozniej dostanie współrzedne po ostatnim elemencie)
                this->waz->Add(temp); //dodaje element do listy
                this->punkty+=10; //zwiekszamy punkty
                this->label2->Text = this->punkty.ToString(); //wyswietlamy punkty
                }
//a następnie przesuwamy punkty od elementów
            snejk ^tmp, ^tmp1;
            tmp1 = gcnew snejk(System::Drawing::Color::Red,10,10); //nowy obiekt pomocniczy
            tmp = gcnew snejk(System::Drawing::Color::Red,10,10); //nowy obiekt pomocniczy

            for(int i=0;i<=this->waz->Count-1;i++) //przeglada kazdy modul w liscie
            {       
                if(i==0)//dla pierwszego elementu
                {
                tmp->przesun_na_pozycje(this->waz[i]); //przekazuje obecne wspólrzedne modułu do pomocniczej
                this->waz[i]->przesun_na_pozycje(this->xx,this->yy); //obecny moduł (pierwszy) przesuwa na pozycje xx, yy
                }
                else //dla pozostałych elementów
                {
                tmp1->przesun_na_pozycje(this->waz[i]); //zapisuje obecną pozycje do drugiej pomocniczej
                this->waz[i]->przesun_na_pozycje(tmp); //obecny element przestawia na pozycje poprzedniego elementu
                tmp->przesun_na_pozycje(tmp1); //do pomocniczej zapisuje poprzednia pozycję (przed przedstawieniem) do pomocniczej
                }       
            }
    tmp1->~snejk(); //destruktory pomocniczych obiektów;
    tmp->~snejk();   
}
             }
       
           
    private: System::Void Form1_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e) {
        if(this->gra) //jezeli gra jest aktywna to zezwala na rysowanie
        {
            e->Graphics->DrawRectangle(this->pen, this->jablko_x, this->jablko_y, 10, 10); //rysuje jablko na pozycji
            for each(snejk ^modul1 in this->waz) //dla kazdego modulu weza
                modul1->rysuj(e->Graphics); //rysuje ten element
        }   
        }

bool sprawdz_kolizje_z_wezem(int x, int y) //sprawdza czy współrzedne punktu nie są równe współrzednym każdego modułu
    {
        for each(snejk ^tmp in this->waz) //dla kazdego elementu
        {
            if(tmp->sprawdz_kolizje_z_punktem(x,y)) //sprawdza kolizje pojedynczego modułu
                return true;
        }
        return false;
    }
bool sprawdz_kolizje_ze_sciana() // sprawdza czy obecny punkt nie wchodzi na scianę
{
    if((this->xx==-10)&&(this->yy<=490)) //sciana lewa
        return true;
    else if((this->xx<=490) && (this->yy==-10))// sciana górna
        return true;
    else if((this->xx==490) && (this->yy<=490))//sciana prawa
        return true;
    else if((this->xx<=490) && (this->yy==490))//sciana dolna
        return true;
    else
        return false; //jezeli brak kolizji ze ścianą
}

void nowa_gra() //nowa gra
{
this->pen->Color = System::Drawing::Color::Red; //kolor czerwony
this->waz = gcnew System::Collections::Generic::List<snejk^>();
this->punkty = 0; //reset punktów
this->label2->Text = "0"; //wyswietlanie punktów tez
snejk ^modul; //tworzymy sobie 4 elementowego weza
modul = gcnew snejk(System::Drawing::Color::Green,250,250); //o zielonej głowie, obróconego w prawo
this->waz->Add(modul); //wszystko dodajemy do listy po kolei
modul = gcnew snejk(System::Drawing::Color::Red,240,250);//kolejne moduły już czerwone
this->waz->Add(modul); //itd
modul = gcnew snejk(System::Drawing::Color::Red,230,250);
this->waz->Add(modul);
modul = gcnew snejk(System::Drawing::Color::Red,220,250);
this->waz->Add(modul);
           
this->losuj_jablko();//losujemy pozycje jabłka (mozna dodać funcję zeby nie wrzuciło jabłka na węża)
this->losuj_start(); //losujemy pozycje kierunku w którym pojdzie wąż po włączeniu timera (3 jest zabroniony)

this->xx = 250; //wpółrzedne poruszania się takie jak pozycja głowy
this->yy = 250;
this->pen->Color = System::Drawing::Color::GreenYellow; //zmieniamy kolor - bo później już same jabłka się będą rysowały


}

void game_over() //koniec gry
{
this->label3->Visible = true; //włączy widocznośc tekstu
this->timer1->Enabled=false; //zatrzymujemy timer
this->label3->Text = "GAME OVER \nTwoje punkty: "+this->punkty.ToString()+"\nAby rozpoczac grę naciśnij ENTER";  //statystyki + info

for each(snejk ^tmp in this->waz) //czyscimy liste węża
    tmp->~snejk();
this->waz->Clear();
}

};

   


}

Brak komentarzy:

Prześlij komentarz