Tetris mit 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(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)
    {
    }
    




  • Den Script habe ich mir noch nicht ganz durchgelesen, aber beim Spielen habe ich gesehen dass du die L förmigen steine zu lang gemacht hast.
    deine Steine:
    XX
    X
    X
    X

    Original:
    XX
    X
    X

    ansonsten gute Arbeit! 👍



  • hi danke für den Beitrag,

    das mit dem L kann man in dem Array Tile[7][4][5][5] ändern
    🙂


Anmelden zum Antworten