Процесс разработки игры занимает в среднем около года: в случае с ААА проектом — может затянуться до 2-3 лет, казуальные игры делаются примерно 4-6 месяцев.
Этап первый. Идея
Придумывание того, что будет в игре, выбор жанра, продумывание сюжета и персонажей.
Этап второй. Диздок
Создание дизайн-документа — полного описание игрового мира. В нем прописывается сюжет, атмосфера, графика, описание каждого предмета, звуки. Это библия, по которой разработчик корпит над игрой. Диздок постоянно меняется и дополняется в процессе разработке и не будет завершен до тех пор, пока игра не выйдет на золото.
Этап третий. Команда
Программисты, художники, аниматоры, звукорежиссеры, сценаристы и другие звери собираются в кучу, чтобы делать игру, а командует ими обычно геймдизайнер.
Этап четвертый. Препродакшн
Основная команда программистов и художников создает начальные прототипы одной или нескольких возможностей, которые хотят видеть в игре, чтобы показать издателю и получить финансирование (если проект не инди, и не делается на энтузиазме рабами).
Этап пятый. Бюджет
Разработчик приползает на коленях к издателю с протянутой рукой, ведь разработка ААА проекта стоит от миллиона долларов и более: средний бюджет такой игры колеблется от 18 до 24 млн. долларов. Для отечественных компаний разработка среднего проекта обходится от 100.000 до 1.000.000$.
Этап шестой. Добро
Получение благословения и денег от издателя.
Этап седьмой. Производство
Программисты пишут исходный код игрового движка(или покупается уже готовый), художники рисуют графику, звукооператоры разрабатывают звуковые эффекты, а композиторы пишут музыку для игры. Дизайнеры уровней создают....(угадай что). Писатели пишут диалоги для скриптовых сцен и неигровых персонажей. Параллельно геймдизайнер дополняет и изменяет диздок(библию) и игровой дизайн, чтобы отразить текущее видение игры. Некоторые особенности или уровни могут быть удалены, некоторые добавлены, сюжет — измениться.
Этап восьмой. Первый уровень
Первый уровень игры делается дольше всех остальных — до трети общего времени разработки. С появлением новых возможностей некоторые уровни могут устареть, поэтому в первый уровень игры могут вноситься различные, порою кардинальные, исправления.
Этап девятый. Тестинг
Тестеры подключаются к игре, когда появляется что-то играбельное. Сегодня тестирование является жизненно важным для игр, поскольку, в силу сложности большинства из них, одно единственное изменение может привести к катастрофическим последствиям.
Этап десятый. Выход на золото
Распространение проекта на дисках или через цифровую дистрибуцию.
Этап одиннадцатый. Поддержка
В обычном случае поддержка заключается в выпуске патчей для исправления ошибок, найденных уже после выхода игры.
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <string.h>
#include <shellapi.h>
#include <stdio.h>
#include «c:\lcc\project\tetris\tetrisres.h»
//---------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
void initscreen();
void newfigure();
void gameover();
void bind(int x,int y,int keys);
void delfull();
void unrotate();
void rotate();
void show();
//---------------------------------------------------------------------------------------
static char szAppName[] = «Tetris»;
HWND hwnd ,hwndDlg=NULL;
MSG msg;
WNDCLASSEX wndclass;
HINSTANCE hinst;
static int screen[16][18];
static int oldscreen[16][18];
static int cup[16][18];
static int figure[4][4];
static int oldfigure[4][4];
static int deltax=3, deltay=0;
static int speed,oldspeed;
static int idTimer = -1;
static int scores;
static char title[25];
static int cxClient, cyClient;
BOOL endgame=FALSE;
//---------------------------------------------------------------------------------------
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
wndclass.cbSize = sizeof (wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = DLGWINDOWEXTRA;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (hInstance, «Tetris»);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon (hInstance, «Tetris»);
RegisterClassEx (&wndclass);
hwnd = CreateDialog (hInstance, «Tetris», 0, NULL);
ShowWindow (hwnd, iCmdShow);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
//----------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
int countx,county;
HDC hdc;
PAINTSTRUCT ps;
COLORREF colorbrick;
HBRUSH hBrush;
RECT rect;
switch (iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_EXIT:
SendMessage(hwnd,WM_CLOSE,0,0L);
break;
case ID_NEW:
scores=0;
speed=300;
endgame=FALSE;
oldspeed=speed;
SetTimer(hwnd, idTimer = 1, speed, NULL);
SetWindowText(hwnd,«Tetris»);
initscreen();
newfigure();
bind(deltax,deltay,0);
break;
case ID_HI:
KillTimer(hwnd, 1);
DialogBox(hinst, MAKEINTRESOURCE(IDD_SCOREDIALOG), hwnd, (DLGPROC) DialogFunc);
SetTimer(hwnd, idTimer = 1, speed, NULL);
break;
case ID_ABOUT:
KillTimer(hwnd, 1);
ShellAbout(hwnd,«Tetris(ver. 1.3b)»,«WebSite: htpp:\\\\freecpp.newmail.ru»,NULL);
SetTimer(hwnd, idTimer = 1, speed, NULL);
break;
}
return 0;
case WM_SIZE:
cxClient=LOWORD (lParam)/10;
cyClient=HIWORD (lParam)/16;
return 0;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
for (countx=0;countx<10;countx++)
{
for (county=0;county<16;county++)
{
if(screen[countx][county]!=0)
{
switch(screen[countx][county])
{
case 0:
colorbrick=RGB(0,0,0);
break;
case 1:
colorbrick=RGB(255,0,0);
break;
case 2:
colorbrick=RGB(0,255,0);
break;
case 3:
colorbrick=RGB(0,0,255);
break;
case 4:
colorbrick=RGB(0,255,255);
break;
case 5:
colorbrick=RGB(255,0,255);
break;
case 6:
colorbrick=RGB(255,255,0);
break;
break;
}
SetRect (&rect, countx*cxClient,county*cyClient,
countx*cxClient+cxClient,county*cyClient+cyClient);
hBrush = CreateSolidBrush (colorbrick);
hBrush = CreateSolidBrush (colorbrick);
FillRect (hdc, &rect, hBrush);
DeleteObject (hBrush);
}
}
}
EndPaint (hwnd, &ps);
return 0;
case WM_KEYDOWN:
switch (LOWORD(wParam))
{
case VK_ESCAPE:
SendMessage(hwnd,WM_CLOSE,0,0L);
break;
case VK_LEFT:
deltax=deltax-1;
bind(deltax,deltay,4);
break;
case VK_RIGHT:
deltax=deltax+1;
bind(deltax,deltay,6);
break;
case VK_UP:
rotate();
bind(deltax,deltay,5);
break;
case VK_DOWN:
oldspeed=speed;
speed=100;
SetTimer(hwnd, idTimer = 1, speed, NULL);
break;
}
return 0;
case WM_TIMER:
deltay=deltay+1;
bind(deltax,deltay,2);
return 0;
case WM_DESTROY:
KillTimer(hwnd, 1);
PostQuitMessage (0);
return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam);
}
//--------------------------------------------------------------------------------------
void initscreen()
{
int countx,county;
for (countx=0;countx<10;countx++)
{
for (county=0;county<16;county++)
{
cup[countx][county]=0;
}
}
}
//---------------------------------------------------------------------------------------
void newfigure()
{
int i,numfigure;
if(endgame)return;
speed=oldspeed;
SetTimer(hwnd, idTimer = 1, speed, NULL);
for(i = 2;i<9;i++)
{
if(cup[i][3]>0) gameover();
}
deltax = 3;
deltay = 0;
srand(rand()%100);
numfigure = rand ()%6+1;
switch (numfigure)
{
case 1:
figure[0][0] = 0;
figure[1][0] = 0;
figure[2][0] = 0;
figure[3][0] = 0;
figure[0][1] = 0;
figure[1][1] = numfigure;
figure[2][1] = numfigure;
figure[3][1] = 0;
figure[0][2] = 0;
figure[1][2] = 0;
figure[2][2] = numfigure;
figure[3][2] = 0;
figure[0][3] = 0;
figure[1][3] = 0;
figure[2][3] = numfigure;
figure[3][3] = 0;
break;
case 2:
figure[0][0] = 0;
figure[1][0] = 0;
figure[2][0] = 0;
figure[3][0] = 0;
figure[0][1] = 0;
figure[1][1] = numfigure;
figure[2][1] = numfigure;
figure[3][1] = 0;
figure[0][2] = 0;
figure[1][2] = numfigure;
figure[2][2] = 0;
figure[3][2] = 0;
figure[0][3] = 0;
figure[1][3] = numfigure;
figure[2][3] = 0;
figure[3][3] = 0;
break;
case 3:
figure[0][0] = 0;
figure[1][0] = numfigure;
figure[2][0] = 0;
figure[3][0] = 0;
figure[0][1] = 0;
figure[1][1] = numfigure;
figure[2][1] = numfigure;
figure[3][1] = 0;
figure[0][2] = 0;
figure[1][2] = 0;
figure[2][2] = numfigure;
figure[3][2] = 0;
figure[0][3] = 0;
figure[1][3] = 0;
figure[2][3] = 0;
figure[3][3] = 0;
break;
case 4:
figure[0][0] = 0;
figure[1][0] = 0;
figure[2][0] = numfigure;
figure[3][0] = 0;
figure[0][1] = 0;
figure[1][1] = numfigure;
figure[2][1] = numfigure;
figure[3][1] = 0;
figure[0][2] = 0;
figure[1][2] = numfigure;
figure[2][2] = 0;
figure[3][2] = 0;
figure[0][3] = 0;
figure[1][3] = 0;
figure[2][3] = 0;
figure[3][3] = 0;
break;
case 5:
figure[0][0] = 0;
figure[1][0] = 0;
figure[2][0] = 0;
figure[3][0] = 0;
figure[0][1] = 0;
figure[1][1] = numfigure;
figure[2][1] = numfigure;
figure[3][1] = 0;
figure[0][2] = 0;
figure[1][2] = numfigure;
figure[2][2] = numfigure;
figure[3][2] = 0;
figure[0][3] = 0;
figure[1][3] = 0;
figure[2][3] = 0;
figure[3][3] = 0;
break;
case 6:
figure[0][0] = 0;
figure[1][0] = numfigure;
figure[2][0] = 0;
figure[3][0] = 0;
figure[0][1] = 0;
figure[1][1] = numfigure;
figure[2][1] = 0;
figure[3][1] = 0;
figure[0][2] = 0;
figure[1][2] = numfigure;
figure[2][2] = 0;
figure[3][2] = 0;
figure[0][3] = 0;
figure[1][3] = numfigure;
figure[2][3] = 0;
figure[3][3] = 0;
break;
}
scores=scores+numfigure;
wsprintf (title, "%s — %i", szAppName,scores);
SetWindowText(hwnd,title);
}
//---------------------------------------------------------------------------------------
void gameover()
{
char result[30]=«You score: »;
KillTimer(hwnd, 1);
endgame=TRUE;
DialogBox(hinst, MAKEINTRESOURCE(IDD_SCOREDIALOG), hwnd, (DLGPROC) DialogFunc);
}
//---------------------------------------------------------------------------------------
void bind(int x,int y,int keys)
{
int i,j,i1,j1;
for(j=0;j<16;j++)
{
for(i=0;i<10;i++)
{
oldscreen[i][j]= screen[i][j];
}
}
for(j=0;j<16;j++)
{
for(i=0;i<10;i++)
{
screen[i][j]= cup[i][j];
}
}
for(j=0;j<4;j++)
{
for(i=0;i<4;i++)
{
if((figure[i][j]>0)&&((screen[i+x][j+y]>0)||(i+x+1==0)||(j+y==16)||(i+x==10)))
{
switch(keys)
{
case 4:
deltax = deltax + 1;
break;
case 6:
deltax = deltax — 1;
break;
case 2:
for(j1 = 0;j1<4;j1++)
{
for (i1 = 0;i1<4;i1++)
{
if(figure[i1][j1] > 0)
{
cup[i1 + x][j1 + y — 1] = figure[i1][j1];
}
}
}
for (j1=0;j1<16;j1++)
{
for(i1=0;i1<10;i1++)
{
screen[i1][j1] = cup[i1][j1];
}
}
delfull();
newfigure();
break;
case 5:
unrotate();
}
x = deltax;
y = deltay;
}
}
}
for(j=0;j<4;j++)
{
for(i = 0;i<4;i++)
{
if(figure[i][j]>0)
{
screen[i + x][j + y] = figure[i][j];
}
else
{
screen[i + x][j + y] = cup[i + x][j + y];
}
}
}
show();
}
//---------------------------------------------------------------------------------------
void delfull()
{
int i,j,row,col;
BOOL flag;
for(j=0;j<16;j++)
{
flag = TRUE;
for(i=0;i<10;i++)
{
if(cup[i][j]==0) flag=FALSE;
}
if(flag)
{
scores=scores+25;
wsprintf (title, "%s — %i", szAppName,scores);
SetWindowText(hwnd,title);
speed=speed-2;
SetTimer(hwnd, idTimer = 1, speed, NULL);
for(row=j;row>1;row--)
{
for(col=0;col<10;col++)
{
cup[col][row] = cup[col][row — 1];
}
}
}
flag = TRUE;
}
}
//---------------------------------------------------------------------------------------
void unrotate()
{
int i,j;
for(j=0;j<4;j++)
{
for(i=0;i<4;i++)
{
figure[i][j] = oldfigure[i][j];
}
}
}
//---------------------------------------------------------------------------------------
void rotate()
{
int i,j;
for(j = 0;j<4;j++)
{
for(i=0;i<4;i++)
{
oldfigure[i][j]=figure[i][j];
}
}
for(j = 0;j<4;j++)
{
for(i=0;i<4;i++)
{
figure[i][j]=oldfigure[3-j][i];
}
}
}
//---------------------------------------------------------------------------------------
void show()
{
HDC hdc;
int countx,county;
COLORREF colorbrick;
HBRUSH hBrush;
RECT rect;
hdc = GetDC (hwnd);
for (countx=0;countx<10;countx++)
{
for (county=0;county<16;county++)
{
if(screen[countx][county]!=oldscreen[countx][county])
{
switch(screen[countx][county])
{
case 0:
colorbrick=RGB(0,0,0);
break;
case 1:
colorbrick=RGB(255,0,0);
break;
case 2:
colorbrick=RGB(0,255,0);
break;
case 3:
colorbrick=RGB(0,0,255);
break;
case 4:
colorbrick=RGB(0,255,255);
break;
case 5:
colorbrick=RGB(255,0,255);
break;
case 6:
colorbrick=RGB(255,255,0);
break;
break;
}
SetRect (&rect, countx*cxClient,county*cyClient,
countx*cxClient+cxClient,county*cyClient+cyClient);
hBrush = CreateSolidBrush (colorbrick);
FillRect (hdc, &rect, hBrush);
DeleteObject (hBrush);
}
}
}
ReleaseDC (hwnd, hdc);
}
static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
FILE *f;
char name[5][25];
char score[5][10];
int maxscore[5];
int i;
switch (msg) {
case WM_INITDIALOG:
f=fopen(«tetris.dat»,«rb»);
if(f==NULL) break;
for(i=0;i<5;i++)
{
fread(name[i],1,25,f);
fread(score[i],1,10,f);
maxscore[i]=atoi(score[i]);
}
fclose(f);
for(i=0;i<5;i++)
{
if(scores>maxscore[i]&&endgame)
{
itoa(scores,score[i],10);
SendDlgItemMessage(hwndDlg,102+i,EM_SETREADONLY,(WPARAM)FALSE,(LPARAM)0);
i=5;
scores=0;
}
}
for(i=0;i<5;i++)
{
SendDlgItemMessage(hwndDlg,102+i,WM_SETTEXT,(WPARAM)0,(LPARAM)name[i]);
SendDlgItemMessage(hwndDlg,107+i,WM_SETTEXT,(WPARAM)0,(LPARAM)score[i]);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
for(i=0;i<5;i++)
{
SendDlgItemMessage(hwndDlg,102+i,WM_GETTEXT,(WPARAM)25,(LPARAM)name[i]);
SendDlgItemMessage(hwndDlg,107+i,WM_GETTEXT,(WPARAM)10,(LPARAM)score[i]);
}
f=fopen(«tetris.dat»,«wb»);
for(i=0;i<5;i++)
{
fwrite(name[i],1,25,f);
fwrite(score[i],1,10,f);
}
fclose(f);
EndDialog(hwndDlg,1);
return 1;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg,0);
return TRUE;
}
return FALSE;
}
Лучшие комментарии
нечеловек.) = \