Я пытаюсь сделать клон тетриса в C ++ Builder. Я начал с 2 классов. Я написал их в .h
файл и включил его в мой .cpp
файл:
class Stage
{
protected:
int Width;
int Height;
public:
Stage()
{
Width=300;
Height=733;
}
Stage(int Width0,int Height0)
{
Width=Width0;
Height=Height0;
}
};
Это мой первый класс, этап. Я не знаю наверняка, что должен содержать этот класс, поэтому, если у вас есть какие-либо предложения относительно того, что я должен включить в него, я рад их услышать.
class Tetromino : public Stage
{
protected:
Tshape *Shape1;
public:
Tetromino(Tshape *Shape1)
{
TetrisGame->Shape1->Width=33;
TetrisGame->Shape1->Height=33;
TetrisGame->Shape1->Brush->Color=clBlack;
TetrisGame->Shape1->Left=10;
TetrisGame->Shape1->Top=200;
}
void mLeft()
{
if(TetrisGame->Shape1->Left<=Widht)
TetrisGame->Shape1->Left=TetrisGame->Shape1->Left+33;
}
void mRight()
{
if(TetrisGame->Shape1->Left>=Width)
TetrisGame->Shape1->Left=TetrisGame->Shape1->Left-33;
}
void free_fall()
{
TetrisGame->PieceFallTime->Enabled=true;
}
};
Это мой второй класс, класс для фигур.
Я знаю, что это не так, как это должно работать. Я должен сделать матрицу, например, скажем:
piece[4][4]=
{(0,0,0,0),
(0,0,0,0),
(0,1,0,0),
(1,1,1,0)}
но я до сих пор понятия не имею, как мне это использовать. Я думаю, что я должен поставить форму там, где есть 1, и она должна создать мою фигуру, но я не знаю, как это сделать.
Прямо сейчас я пытаюсь понять, как заставить форму упасть и переместить ее вправо или влево с помощью клавиатуры. Я делал это раньше, но без занятий. Это немного сложнее с использованием классов, и я не понимаю.
Я пытался инициализировать объект Tetromino x(Shape1)
(код находится в form.cpp
) иметь Shape1
в моей форме. Я думаю, что это должно заставить Shape1
в моей форме, чтобы использовать методы, которые я написал в своем классе, верно?
Но я получаю эту ошибку:
[bcc32c Ошибка] StartGame.cpp (110): неизвестное имя типа «Shape1»
Вы забыли использовать new
для растрового изображения в конструкторе, так что вы загружаете bmp
файл в растровые объекты, которые еще не созданы, следовательно, нарушение прав доступа. Вы можете использовать прозрачность для растровых изображений tetrominos … вам просто нужно активировать их на целевом холсте (как ваш Form1
… в его свойствах). Однако я хотел бы визуализировать мои tetrominos непосредственно в растровое изображение вместо использования файлов … Вы можете использовать растровое изображение в качестве экранного буфера …
Здесь просто BDS2006 C ++ / VCL Tetris пример, который я кодировал со своими студентами в течение одной лекции несколько лет назад, когда они хотели написать код игры и проголосовали за тетрис … (это уродливо, но работает …)
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "win_main.h"//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
// window
TForm1 *Form1;
// keyboard map
enum{
_key_left =0,
_key_right,
_key_rot ,
_key_drop ,
_keys
};
int keys [_keys]; // is key pressed ?
WORD keys_code[_keys]; // scan code
// back/double buffer
Graphics::TBitmap *bmp = new Graphics::TBitmap;
// scoore, position of falling tetromino,next shape
int score=0,px=0,py=0,novy_dielik=0;
// actual tetromino map
BYTE pm[4][4]=
{
0,0,1,0,
0,1,1,0,
0,0,1,0,
0,0,1,0
};
// game board size
const int map_xs=10;
const int map_ys=20;
BYTE map[map_xs][map_ys];
// tetrominos
BYTE shp[7*16]=
{
0,1,0,0,
0,1,0,0,
0,1,0,0,
0,1,0,0,
0,1,0,0,
0,1,0,0,
0,1,1,0,
0,0,0,0,
0,0,1,0,
0,0,1,0,
0,1,1,0,
0,0,0,0,
0,1,0,0,
0,1,1,0,
0,0,1,0,
0,0,0,0,
0,0,1,0,
0,1,1,0,
0,1,0,0,
0,0,0,0,
0,0,0,0,
0,0,1,0,
0,1,1,1,
0,0,0,0,
0,0,0,0,
0,1,1,0,
0,1,1,0,
0,0,0,0
};
//---------------------------------------------------------------------------
// tetromino colision test
//---------------------------------------------------------------------------
int step()
{
int i,j,x,y;
for (i=0;i<4;i++)
for (j=0;j<4;j++)
if (pm[i][j]!=0)
{
x=px+j;
y=py+i;
if (x<0) return 1;
if (x>=map_xs) return 1;
if (y<0) return 1;
if (y>=map_ys) return 1;
if (map[x][y]!=0) return 1;
}
return 0;
}
//---------------------------------------------------------------------------
// render game
//---------------------------------------------------------------------------
void draw()
{
// clear screen
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(TRect(0,0,bmp->Width,bmp->Height));
// [game board]
int x,y,a,i,j,adr;
x=bmp->Width/(map_xs+4+3);
y=bmp->Height/(map_ys+2);
if (x<y) a=x; else a=y;
// border
x=a; y=a;
bmp->Canvas->Pen->Color=clBlue;
bmp->Canvas->Pen->Width=a>>1;
bmp->Canvas->Rectangle(x,y,x+(map_xs*a),y+(map_ys*a));
bmp->Canvas->Pen->Width=1;
// game board
for (j=0;j<map_ys;j++)
{
for (i=0;i<map_xs;i++)
{
// set color from map
if (map[i][j]==0) bmp->Canvas->Brush->Color=clBlack;
else bmp->Canvas->Brush->Color=clAqua;
// grid cell
bmp->Canvas->FillRect(TRect(x,y,x+a,y+a));
x+=a; // posun sa o policko vpravo
}
x-=map_xs*a; // vrat sa vlavo
y+=a; // posun sa o policko dole
}
y-=map_ys*a; // vrat sa hore
// falling tetromino
x+=px*a;
y+=py*a;
for (j=0;j<4;j++)
{
for (i=0;i<4;i++)
{
// cell
if (pm[j][i]!=0)
{
bmp->Canvas->Brush->Color=clGreen;
bmp->Canvas->FillRect(TRect(x,y,x+a,y+a));
}
x+=a; // posun sa o policko vpravo
}
x-=4*a; // vrat sa vlavo
y+=a; // posun sa o policko dole
}
y-=4*a; // vrat sa hore
x-=px*a;
y-=py*a;
x+=(map_xs+1)*a; // posun sa na pravy stlpec
// score:
bmp->Canvas->Font->Color=clWhite;
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->TextOutA(x,y,AnsiString().sprintf("Score: %i",score));
y+=a+a;
// border
bmp->Canvas->Pen->Color=clBlue;
bmp->Canvas->Pen->Width=a>>1;
bmp->Canvas->Rectangle(x,y,x+(4*a),y+(4*a));
bmp->Canvas->Pen->Width=1;
adr=16*novy_dielik;
for (j=0;j<4;j++)
{
for (i=0;i<4;i++)
{
// set color from map
if (shp[adr]==0) bmp->Canvas->Brush->Color=clBlack;
else bmp->Canvas->Brush->Color=clAqua;
// nakresli stvorcek
bmp->Canvas->FillRect(TRect(x,y,x+a,y+a));
x+=a; // go right
adr++;
}
x-=4*a; // return left
y+=a; // go down
}
y-=4*a; // return up
Form1->Canvas->Draw(0,0,bmp);
}
//--- konstruktor okna ------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
keys_code[_key_left ]='O';
keys_code[_key_right]='P';
keys_code[_key_rot ]='Q';
keys_code[_key_drop ]='A';
// new game
novy_dielik=rand()%7; // new tetromino
px=(map_xs>>1)-2; // position top/middle
py=0;
int adr=16*novy_dielik;
for (int j=0;j<4;j++) // copy it to pm
for (int i=0;i<4;i++)
{
pm[j][i]=shp[adr];
adr++;
}
for (int j=0;j<map_ys;j++) // clear map
for (int i=0;i<map_xs;i++)
map[i][j]=0;
novy_dielik=rand()%7;
}
//--- resize event ----------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
bmp->Width=ClientWidth;
bmp->Height=ClientHeight;
draw(); // force redraw
}
//--- redraw event ----------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
draw();
}
//--- falling timer ---------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
py++;
if (step()) // tetromino hit the ground?
{
py--;
int i,j,x,y,adr,e; // copy it to map
for (j=0;j<4;j++)
for (i=0;i<4;i++)
if (pm[j][i])
{
x=px+i;
y=py+j;
map[x][y]=1;
}
px=(map_xs>>1)-2; // new tetromino top/middle position
py=0;
adr=16*novy_dielik;
for (j=0;j<4;j++) // copy it to pm
for (i=0;i<4;i++)
{
pm[j][i]=shp[adr];
adr++;
}
// map full line test
int dscore=0;
for (j=map_ys-1;j>=0;j--)
{
e=1;
for (i=0;i<map_xs;i++)
if (map[i][j]==0)
{
e=0;
break;
}
if (e)
{
dscore<<=1;
dscore+=100;
e=j;
for (j=e-1;j>=0;j--)
for (i=0;i<map_xs;i++)
map[i][j+1]=map[i][j];
j=e+1;
draw();
Sleep(200);
}
}
score+=dscore;
if (step()) // end game? (no new tetromino)
{
int q;
q=bmp->Canvas->Font->Height;
bmp->Canvas->Font->Height=40;
bmp->Canvas->Font->Color=clRed;
bmp->Canvas->Brush->Style=bsClear;
AnsiString s="Game over";
bmp->Canvas->TextOutA(
(bmp->Width-bmp->Canvas->TextWidth(s))>>1,
(bmp->Height-bmp->Canvas->TextHeight(s))>>1,s);
bmp->Canvas->Brush->Style=bsSolid;
bmp->Canvas->Font->Height=q;
Form1->Canvas->Draw(0,0,bmp);
Sleep(1000);
// new game
novy_dielik=rand()%7; // new tetromino
px=(map_xs>>1)-2; // top/middle
py=0;
int adr=16*novy_dielik;
for (int j=0;j<4;j++) // copy it to pm
for (int i=0;i<4;i++)
{
pm[j][i]=shp[adr];
adr++;
}
for (int j=0;j<map_ys;j++) // clear board
for (int i=0;i<map_xs;i++)
map[i][j]=0;
novy_dielik=rand()%7;
}
novy_dielik=rand()%7; // random next tetromino 0-6
}
draw();
}
//--- keyboard timer --------------------------------------------------------
void __fastcall TForm1::Timer2Timer(TObject *Sender)
{
int e=0;
if (keys[_key_left ]!=0)
{
px--; if (step()) px++; else e=1;
}
if (keys[_key_right]!=0)
{
px++; if (step()) px--; else e=1;
}
if (keys[_key_rot ]!=0)
{
int i,j;
BYTE ori[4][4];
for (j=0;j<4;j++) for (i=0;i<4;i++) ori[i][j]=pm[i][j];
for (j=0;j<4;j++) for (i=0;i<4;i++) pm[3-j][i]=ori[i][j];
if (step()) for (j=0;j<4;j++) for (i=0;i<4;i++) pm[i][j]=ori[i][j];
else e=1;
}
if (keys[_key_drop ]!=0)
{
py++; if (step()) py--; else e=1;
}
if (e) draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
Caption=Key;
for (int i=0;i<_keys;i++) // test all keys
if (Key==keys_code[i]) // if match
keys[i]=1; // set it as pressed
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
{
for (int i=0;i<_keys;i++) // test all keys
if (Key==keys_code[i]) // if match
keys[i]=0; // set it as released
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
{
for (int i=0;i<_keys;i++) // set all keys
keys[i]=0; // as released
}
//---------------------------------------------------------------------------
---------------------------------------
Это одно приложение формы с 2 таймерами на нем
Timer1
250 мс
Timer2
это 80мс
Если вы хотите использовать мой, вы должны:
Но вы должны использовать это как подсказку о том, как может выглядеть архитектура игры. Я знаю, что это безобразно и без занятий (те студенты, где еще нет OOP способный, и мы закодировали игру вместе, так что некоторый консенсус по всем частям был сделан с целью сохранить это простым …)
Итак bmp
это как экранный буфер (чтобы избежать мерцания) управление осуществляется O P Q A
ключи. Один таймер управляет падающей анимацией / симуляцией, а другой управляет клавиатурой. Рендеринг осуществляется с помощью VCL инкапсулированный GDI и bmp
…
для получения дополнительной информации см .:
Других решений пока нет …