Tetris (wxWidgets)



  • Hallo Community,
    ich habe ein simples Tetris geschreiben. Ich programmiere noch nicht so lange in C++ und mit wxWidgets und würde gerne Eure Meinung zum Aufbau, Umsetzung usw. hören. :p

    Header :

    Variables.h

    #ifndef VARIABLES_H_
    #define VARIABLES_H_
    
    enum tDir{Left,Right};
    
    const int BlockX=20;
    const int BlockY=20;
    const int FieldX=10;
    const int FieldY=30;
    
    #endif
    

    Tiles.h

    #ifndef TILE_H_
    #define TILE_H_
    
    #include "Variables.h"
    
    class tTile
    {
      static bool Tile[7][4][5][5];
      static int TileStartPos[7][4][2];
      int Rotation;
      int NrTile;
      int x,y;
    public:
      tTile(){
        x=0;
        y=0;
        Rotation=0;
      }
      void setTile();
      bool rotate(int Dir);
      void draw(wxDC &dc);
      bool isPlaced();
      void save();
      void move(int Dir);
      void fallDown();
    };
    
    #endif
    

    Field.h

    #ifndef FIELD_H_
    #define FIELD_H_
    
    #include "Variables.h"
    
    enum tState{Empty,Full};
    
    class tField
    {
      bool GameOver;
      tState Field[FieldX][FieldY];
      tField(){}
      static tField* instance;
    public:
      static tField* getInstance();
      void init();
      void set(int x,int y,tState s);
      void deleteRow(int r);
      void clear();
      bool fullRow(int r);
      tState get(int x,int y);
      void draw(wxDC& dc);
      bool isGameOver();
    };
    
    #endif
    

    TetrisFrame.h

    #ifndef TETRISFRAME_H_
    #define TETRISFRAME_H_
    
    class MyApp : public wxApp
    {
    public:
    	virtual bool OnInit();
    };
    
    class TetrisFrame : public wxFrame
    {
      wxTimer timer;
    public:
      TetrisFrame(const wxString& title, const wxPoint &pos, const wxSize& size);
      void OnPaint(wxPaintEvent& event);
      void OnTimer(wxTimerEvent& event);
      void OnKeyDown(wxKeyEvent& event);
      void OnEraseBackground(wxEraseEvent& event);
      void OnAbout(wxCommandEvent& event);
      void neuesSpiel();
    };
    
    #endif
    

    und jezt die Implementierungsdateien...

    Tile.cpp

    #include "Tile.h"
    #include "Field.h"
    
    bool tTile::Tile[7][4][5][5]=
    {
      {//I
        {
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {1,1,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {0,1,1,1,1},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
      },
      {//T
        {
          {0,0,0,0,0},
          {0,1,1,1,0},
          {0,0,1,0,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,1,1,0,0},
          {0,0,1,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,1,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,0,1,1,0},
          {0,0,1,0,0},
          {0,0,0,0,0}
        },
      },
      {//Z
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {0,1,1,0,0},
          {0,0,1,1,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,1,1,0,0},
          {0,1,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {0,1,1,0,0},
          {0,0,1,1,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,1,1,0,0},
          {0,1,0,0,0},
          {0,0,0,0,0}
        },
      },
      {//Z gespiegelt
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {0,0,1,1,0},
          {0,1,1,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,1,0,0,0},
          {0,1,1,0,0},
          {0,0,1,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,1,0},
          {0,1,1,0,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,0,0},
          {0,0,1,1,0},
          {0,0,0,1,0},
          {0,0,0,0,0}
        },
      },
      {//L
        {
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,1,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {0,1,1,1,1},
          {0,1,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,1,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,0,1,0},
          {1,1,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
      },
      {//L gespiegelt
        {
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,1,1,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,1,0,0,0},
          {0,1,1,1,1},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,1,1,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,1,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,0,0,0},
          {0,1,1,1,1},
          {0,0,0,0,1},
          {0,0,0,0,0}
        },
      },
      {//Block
        {
          {0,0,0,0,0},
          {0,0,1,1,0},
          {0,0,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,1,0},
          {0,0,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,1,0},
          {0,0,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
        {
          {0,0,0,0,0},
          {0,0,1,1,0},
          {0,0,1,1,0},
          {0,0,0,0,0},
          {0,0,0,0,0}
        },
      },
    };
    
    int tTile::TileStartPos[7][4][2/*1.x 2.y*/]=
    {
      {// I
        {
          {
            2,//x
          },
          {
            0,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -2,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            1,//x
          },
          {
            -2,//y
          },
        },
      },
      { // T
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
      },
      {//Z
        {
          {
            2,//x
          },
          {
            -2,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -2,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
      },
      {//Z gespiegelt
        {
          {
            2,//x
          },
          {
            -2,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
      },
      {//L
        {
          {
            2,//x
          },
          {
           0,//y
          },
        },
        { 
          {
            2,//x
          },
          {
            -2,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
      },
      {//L gespiegelt
        {
          {
            2,//x
          },
          {
           0,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            0,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -2,//y
          },
        },
      },
      {//Block
        {
          {
            2,//x
          },
          {
           -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
        {
          {
            2,//x
          },
          {
            -1,//y
          },
        },
      },
    };
    
    void tTile::setTile()
    {
      NrTile=rand()%7;
      Rotation=rand()%4;
      x=TileStartPos[NrTile][Rotation][0];
      y=TileStartPos[NrTile][Rotation][1];
    }
    
    void tTile::draw(wxDC &dc)
    {
      dc.SetBrush(wxColour(0,0,255));
      for(int py=0;py<5;py++){
        for(int px=0;px<5;px++){
          if(Tile[NrTile][Rotation][py][px]){
            dc.DrawRectangle((x+px)*BlockX,(y+py)*BlockY,BlockX,BlockY);
          }
        }
      }
    }
    
    bool tTile::isPlaced()
    {
      tField *Field=tField::getInstance();
      for(int px=0;px<5;px++){
        for(int py=0;py<5;py++){
          if(Tile[NrTile][Rotation][py][px]){
            if(py+y==FieldY)return true;
            if(Field->get(px+x,py+y)==Full)return true;
          }
        }
      }
      return false;
    }
    
    void tTile::save()
    {
      tField *Field=tField::getInstance();
      for(int px=0;px<5;px++){
        for(int py=0;py<5;py++){
          if(Tile[NrTile][Rotation][py][px])
            Field->set(px+x,py+y-1,Full);
        }
      }
    }
    
    bool tTile::rotate(int Dir)
    {
      tField *Field=tField::getInstance();
      int OldRot=Rotation;
      switch(Dir)
      {
      case Left:
        if(Rotation-->0);
        else
          Rotation=3;
        break;
      case Right:
        if(Rotation++<3);
        else
          Rotation=0;
        break;
      }
      for(int px=0;px<5;px++){
        for(int py=0;py<5;py++){
          if(Tile[NrTile][Rotation][py][px]){
            if(px+x<0 || px+x>=FieldX
              || py+y<0 || py+y>=FieldY
              || Field->get(px+x,py+y)==Full){
                Rotation=OldRot;
                return false;
            }
          }
        }
      }
      return true;
    }
    
    void tTile::move(int Dir)
    {
      tField *Field=tField::getInstance();
      int oldx,oldy;
      oldx=x;
      oldy=y;
      switch(Dir)
      {
      case Left:
        x--;
        break;
      case Right:
        x++;
        break;
      }
      for(int px=0;px<5;px++){
        for(int py=0;py<5;py++){
          if(Tile[NrTile][Rotation][py][px]){
            if(px+x<0 || px+x>=FieldX 
              || Field->get(px+x,py+y)==Full){
                x=oldx;
                y=oldy;
            }
          }
        }
      }
    }
    
    void tTile::fallDown()
    {
      y++;
    }
    

    Field.cpp

    #include "Field.h"
    
    tField *tField::instance=0;
    
    tField* tField::getInstance()
    {
      if(!instance)
        instance=new tField();
      return instance;
    }
    
    void tField::init()
    {
      GameOver=false;
      clear();
    }
    
    void tField::set(int x,int y,tState s)
    {
      if(y<=0)GameOver=true;
      Field[x][y]=s;
    }
    
    void tField::deleteRow(int r)
    {
      if(r<1)return;
      for(int i=0;i<FieldX;i++){
          Field[i][r]=Field[i][r-1];
          Field[i][r-1]=Empty;
      }
      deleteRow(r-1);
    }
    
    void tField::clear()
    {
      for(int x=0;x<FieldX;x++){
        for(int y=0;y<FieldY;y++){
          Field[x][y]=Empty;
        }
      }
    }
    
    bool tField::fullRow(int r)
    {
      for(int i=0;i<FieldX;i++)
        if(Field[i][r]==Empty)
          return false;
      return true;
    }
    
    tState tField::get(int x,int y)
    {
      return Field[x][y];
    }
    
    void tField::draw(wxDC &dc)
    {
      dc.SetBrush(wxColour(255,255,255));
      dc.DrawRectangle(0,0,FieldX*BlockX,FieldY*BlockY);
      dc.SetBrush(wxColour(255,0,0));
      for(int x=0;x<FieldX;x++){
        for(int y=0;y<FieldY;y++){
          if(Field[x][y]==Full){
            dc.DrawRectangle(x*BlockX,y*BlockY,BlockX,BlockY);
          }
        }
      }
    }
    
    bool tField::isGameOver()
    {
      return GameOver;
    }
    

    TetrisFrame.cpp

    #include <wx/wx.h>
    #include <ctime>
    #include "TetrisFrame.h"
    #include "Field.h"
    #include "Tile.h"
    
    enum tGame{Paused,Running}Game;
    const int About_ID=12;
    tTile Tile;
    
    IMPLEMENT_APP( MyApp );
    
    bool MyApp::OnInit()
    {
    	TetrisFrame* frame = new TetrisFrame(wxString()<<wxT("Tetris"),wxDefaultPosition,wxSize(220,690));
    	frame->SetIcon( wxICON( amain ) );
    	frame->Show();
    	return true;
    }
    
    TetrisFrame::TetrisFrame(const wxString& title,const wxPoint &pos, const wxSize& size) :
    wxFrame((wxFrame*) NULL,-1,title,pos,size),timer(this)
    {
      srand((unsigned int)time(0));
      wxMenu* menu=new wxMenu;
      menu->Append(About_ID,wxT("Über"));
      wxMenuBar *menuBar=new wxMenuBar;
      menuBar->Append(menu,wxT("Datei"));
      SetMenuBar(menuBar);
      CreateStatusBar();
      Connect(wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler(TetrisFrame::OnAbout));
      Connect(wxEVT_PAINT,wxPaintEventHandler(TetrisFrame::OnPaint));
      Connect(wxEVT_TIMER,wxTimerEventHandler(TetrisFrame::OnTimer));
      Connect(wxEVT_KEY_DOWN,wxKeyEventHandler(TetrisFrame::OnKeyDown));
      Connect(wxEVT_ERASE_BACKGROUND,wxEraseEventHandler(TetrisFrame::OnEraseBackground));
      Game=Running;
      neuesSpiel();
    }
    
    void TetrisFrame::OnAbout(wxCommandEvent &event)
    {
      wxMessageBox(wxT("2011 by Daniel S."),wxT("Tetris"));
    }
    
    void TetrisFrame::neuesSpiel()
    {
      tField* Field=tField::getInstance();
      Field->init();
      Tile.setTile();
      timer.Start(150);
    }
    
    #include <wx/dcbuffer.h>
    
    void TetrisFrame::OnPaint(wxPaintEvent &event)
    {
      tField* Field=tField::getInstance();
      wxBufferedPaintDC dc(this);
      Field->draw(dc);
      Tile.draw(dc);
    }
    
    void TetrisFrame::OnTimer(wxTimerEvent& event)
    {
      if(Game==Running){
        tField* Field=tField::getInstance();
        Tile.fallDown();
        if(Field->isGameOver()){
          timer.Stop();
          wxMessageBox(wxT("Game Over !"));
          neuesSpiel();
        }
        if(Tile.isPlaced()){
          Tile.save();
          Tile.setTile();
        }
        for(int i=0;i<FieldY;i++)
          if(Field->fullRow(i)){
            Field->deleteRow(i);
          }
        Refresh();
        SetStatusText(wxT("Tetris"));
      }
      else SetStatusText(wxT("Pausiert ..."));
    }
    
    void TetrisFrame::OnKeyDown(wxKeyEvent &event)
    {
      int key=event.GetKeyCode();
      if(key=='P')
        if(Game==Running){
          Game=Paused;
        }
        else Game=Running;
      if(Game==Paused)return;
      switch(key)
      {
      case WXK_DOWN :
        Tile.rotate(Left);
        break;
      case WXK_UP :
        Tile.rotate(Right);
        break;
      case WXK_LEFT :
        Tile.move(Left);
        break;
      case WXK_RIGHT : 
        Tile.move(Right);
        break;
      }
    }
    
    void TetrisFrame::OnEraseBackground(wxEraseEvent &event)
    {
    }
    


  • 1. Tipp:
    Pack dein Projekt in eine .rar/.zip Datei und lade die irgendwo hoch. (zB. auf zippyshare)
    Die Datei musst Du dann nur noch verlinken, denn das lesen von viel Quelltext hier im Forum ist doch recht anstrengend..



  • Ok hier sind die .cpp und .h Dateien
    http://www3.zippyshare.com/v/60213284/file.html


Anmelden zum Antworten