Добавил:
nyan
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
//идентификатор приложения
HINSTANCE hInstApp;
//название программы
WCHAR const szClassName[] = TEXT("Movement");
//заголовок окна
WCHAR const szWindowTitle[] =
TEXT("Korneev V. Pictures from bmp-files. Ship and Birds");
//прототимы функций
BOOL RegisterApp(HINSTANCE hInst);
HWND CreateApp(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Move_OnCreate();
void Move_OnDestroy(HWND hwnd);
void Move_OnTimer(HWND hwnd);
void Move_OnKeydown(HWND hwnd);
void Move_OnPaint(HWND);
//главная функция
//#pragma argsused
int PASCAL WinMain(HINSTANCE hInst, //дескриптор(идентификатор) программы
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
MSG msg; //структура для работы с сообщениями
if(!RegisterApp(hInst)) //регистрация окна
return FALSE;
if(!CreateApp(hInst,nCmdShow)) //создание окна
return FALSE;
while(GetMessage(&msg,NULL,0,0)) //цикл обработка сообщений
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
//регистрация окна
BOOL RegisterApp(HINSTANCE hInst)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW; //стиль окна
wc.lpfnWndProc = WndProc; //имя оконной процедуры
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst; //дескриптор программы
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //иконка
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //форма курсора
wc.hbrBackground = GetStockBrush(GRAY_BRUSH); //цвет окна
wc.lpszMenuName = TEXT("APP_MENU"); //имя меню окна
wc.lpszClassName = szClassName; //название программы
return RegisterClass(&wc); //регистрация окна
}
//создание окна
HWND CreateApp(HINSTANCE hInstance, int nCmdShow)
{
hInstApp = hInstance;
HWND hwnd; //дескриптор окна
hwnd = CreateWindow(szClassName, //название программы
szWindowTitle, //заголовок окна
WS_OVERLAPPEDWINDOW, //вид окна
CW_USEDEFAULT, //x - координата окна
CW_USEDEFAULT, //y - координата окна
// CW_USEDEFAULT, //ширина окна
// CW_USEDEFAULT, //высота окна
640,
480,
NULL,
NULL,
hInstance,
NULL);
if(hwnd == NULL)
return hwnd;
ShowWindow(hwnd,nCmdShow); //показать окно
UpdateWindow(hwnd); //обновить окно
return hwnd;
}
//оконная процедура обрабатывающая сообщения
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
Move_OnCreate();
break;
case WM_PAINT:
Move_OnPaint(hwnd);
break;
case WM_TIMER:
Move_OnTimer(hwnd);
break;
case WM_KEYDOWN:
Move_OnKeydown(hwnd);
break;
case WM_DESTROY:
Move_OnDestroy(hwnd);
break;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0L;
}
//размеры окна вывода в мировой системе координат
double xLeft, xRight, yBottom, yTop;
//размеры окна вывода в пикселах в окне программы
int nLeft, nRight, mBottom, mTop;
//переход от x к пикселу n
inline int xn(double x)
{
return (int)((x - xLeft)/(xRight - xLeft)*(nRight - nLeft)) + nLeft;
}
//переход от y к пикселу m
inline int ym(double y)
{
return (int)((y - yBottom)/(yTop - yBottom)*(mTop - mBottom)) + mBottom;
}
//класс для работы с матрицами аффинных преобразований
//используются однородные координаты
class Matrix2D
{
public:
double x[3][3];
Matrix2D(); //матрица единичная
void rotate(double fi); //матрица поворота
void displa(double kx, double ky); //матрица растяжения
void transl(double tx, double ty ); //матрица трансляции
//перемножение матриц
friend Matrix2D operator * (const Matrix2D&, const Matrix2D&);
};
Matrix2D::Matrix2D()
{
x[0][0] = 1; x[0][1] = 0; x[0][2] = 0;
x[1][0] = 0; x[1][1] = 1; x[1][2] = 0;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
void Matrix2D::rotate(double fi)
{
double cosfi = cos(fi), sinfi = sin(fi);
x[0][0] = cosfi; x[0][1] = -sinfi; x[0][2] = 0;
x[1][0] = sinfi; x[1][1] = cosfi; x[1][2] = 0;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
void Matrix2D::displa(double kx, double ky)
{
x[0][0] = kx; x[0][1] = 0; x[0][2] = 0;
x[1][0] = 0; x[1][1] = ky; x[1][2] = 0;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
void Matrix2D::transl(double tx, double ty )
{
x[0][0] = 1; x[0][1] = 0; x[0][2] = tx;
x[1][0] = 0; x[1][1] = 1; x[1][2] = ty;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
Matrix2D operator * (const Matrix2D& a, const Matrix2D& b)
{
Matrix2D c;
double s;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
{
s = 0;
for(int n=0; n<3; n++)
s += a.x[i][n]*b.x[n][j];
c.x[i][j] = s;
}
return c;
}
//структура для описания точек фигуры
struct Point
{
double x;
double y;
};
//аффинное преобразование координат точки P с помощью
//матрицы A
Point affine( Matrix2D A, Point P)
{
Point Pp;
Pp.x = A.x[0][0]*P.x + A.x[0][1]*P.y + A.x[0][2]*1;
Pp.y = A.x[1][0]*P.x + A.x[1][1]*P.y + A.x[1][2]*1;
return Pp;
}
//координты вершин птицы
Point PtB[25], PtB0[25];
//"время" движения по траектории цента птицы
double tB , dtB, dtB0;
//создаем 6 матриц аффинный преобразований
Matrix2D R, R1, T, D, A, T1, T2;
//началтные и текущие точки цента птицы
double xB0, yB0, xB2, yB2, xB1, yB1;
//флаг остановки и запуска таймера
int MoveStop;
//время задержки таймера
UINT uElapse;
//флаг движения кадров растровой картинки
int flagBmp;
//флаг остановки движения после вызрыва
int flagEnd;
HGLOBAL hBuf;
//имена bmp-файлов
char nameShip[50][20];
//функция обрабатывает сообщение WM_CREATE
void Move_OnCreate()
{
//размеры поля вывода в мировых и экранных координатах
xLeft = -10; xRight = 10; yBottom = -7.5; yTop = 7.5;
// nLeft = 60; nRight = 700; mTop = 15; mBottom = 495;
nLeft = 0; nRight = 640; mTop = 0; mBottom = 480;
//время задержки таймера
uElapse = 250;
//флаг запуска таймера
MoveStop = 1;
//заполняем массив имен bmp-файлов nameShip[k]
//имена следущего вида: Ship10.bmp, Ship11.bmp, ... Ship59.bmp
//всего 50 имен
char is[3] = "";
char ssss[30] = "";
for( int k=0; k<50; k++)
{
_itoa_s(k+10,is,3,10);
strcpy_s(ssss,"BMP\\Ship");
strcat_s(ssss,is);
strcat_s(ssss,".bmp");
strcpy_s(nameShip[k],ssss);
}
//открываем файл для чтения
HFILE hFile = _lopen(nameShip[0], OF_READ);
//определяем размер файла
LONG FileSize = _llseek(hFile, 0L, FILE_END);
//выделяет заданное число байт в памяти
hBuf = GlobalAlloc(GMEM_FIXED, FileSize);
//закрываем файл
_lclose(hFile);
flagBmp = 1;
flagEnd = 0;
}
//функция обрабатывающая сообщение WM_KEYDOWN
void Move_OnKeydown(HWND hwnd)
{
if(MoveStop == 0)
{
KillTimer(hwnd, 1);
MoveStop = 1;
}
else
{
SetTimer(hwnd, 1, uElapse, NULL);
MoveStop = 0;
}
}
//функция обрабатывает сообщение WM_DESTROY
void Move_OnDestroy(HWND hwnd)
{
KillTimer(hwnd, 1);
PostQuitMessage(0); //закрывает окно
}
//траектория птицы a
Point TrajBa(double t)
{
Point P;
P.x = 11 - 0.5*t;
P.y = -2 + 0.2*t;
return P;
}
//траектория птицы b
Point TrajBb(double t)
{
Point P;
P.x = 11 - 0.5*(t-4);
P.y = -2 + 0.2*(t-4);
return P;
}
//рисует птицу точке x, y
void Bird(HDC hdc, double x,double y, double t)
{
PtB0[0].x = 2.5; PtB0[0].y = 2*cos(t);
PtB0[1].x = 3.0; PtB0[1].y = 2*cos(t);
PtB0[2].x = 2.0; PtB0[2].y = 1 + 1*cos(t);
PtB0[3].x = 1.0; PtB0[3].y = 1 + 1*cos(t);
PtB0[4].x = -0.5; PtB0[4].y = 0.0;
PtB0[5].x = 1.5; PtB0[5].y = 0.0;
PtB0[6].x = 0.0; PtB0[6].y = 1 + 1*cos(t);
PtB0[7].x = -1.0; PtB0[7].y = 1 + 1*cos(t);
PtB0[8].x = -2.5; PtB0[8].y = 2*cos(t);
PtB0[9].x = -2.0; PtB0[9].y = 2*cos(t);
PtB0[10].x = 3.0; PtB0[10].y = 0.0;
PtB0[11].x = -1.5; PtB0[11].y = 0.0;
PtB0[12].x = -1.2; PtB0[12].y = 0.4;
PtB0[13].x = -2.0; PtB0[13].y = 0.7;
PtB0[14].x = -4.5; PtB0[14].y = 0.5 + 0.3*cos(3*t);
PtB0[15].x = -2.5; PtB0[15].y = 0.25;
PtB0[16].x = -4.2; PtB0[16].y = -0.2 - 0.3*cos(3*t);
PtB0[17].x = -2.2; PtB0[17].y = 0.0;
PtB0[18].x = -0.9; PtB0[18].y = -0.9;
PtB0[19].x = 2.0; PtB0[19].y = -0.1;
PtB0[20].x = 4.0; PtB0[20].y = -0.2;
PtB0[21].x = 3.5; PtB0[21].y = 0.0;
PtB0[22].x = 4.0; PtB0[22].y = 0.1;
PtB0[23].x = -1.9; PtB0[23].y = 0.9;
PtB0[24].x = -1.6; PtB0[24].y = 0.6;
double kx, ky, fi;
kx = 0.1 + 0.02*t; ky = 0.1 + 0.02*t; fi = -0.25;
// kx = 1; ky = 1;
//создаем матрицы аффинного преобразования
T1.transl(x,y);
R1.rotate(fi);
D.displa(kx, ky);
A = T1*R1*D;
//совершаем аффинное преобразование точек фигуры
for(int n=0; n<23; n++)
PtB0[n] = affine(A,PtB0[n]);
A = T1*D;
//совершаем аффинное преобразование точек фигуры
for(int n=23; n<25; n++)
PtB0[n] = affine(A,PtB0[n]);
HBRUSH hbrush1 = CreateSolidBrush(RGB(100,120,100));
HBRUSH hbrushOld = (HBRUSH)SelectObject(hdc,hbrush1); //выбираем кисть hbrush
HPEN hpen = CreatePen(PS_SOLID,1,RGB(0x70,0x70,0x70));
HPEN hpenOld = (HPEN)SelectObject(hdc,hpen); // выбираем перо hpen
POINT pt[20];
pt[0].x = xn(PtB0[6].x); pt[0].y = ym(PtB0[6].y);
pt[1].x = xn(PtB0[7].x); pt[1].y = ym(PtB0[7].y);
pt[2].x = xn(PtB0[8].x); pt[2].y = ym(PtB0[8].y);
pt[3].x = xn(PtB0[9].x); pt[3].y = ym(PtB0[9].y);
Polygon(hdc,pt,4);
HBRUSH hbrush2 = CreateSolidBrush(RGB(125,145,125));
SelectObject(hdc,hbrush2); //выбираем кисть hbrush
pt[0].x = xn(PtB0[4].x); pt[0].y = ym(PtB0[4].y);
pt[1].x = xn(PtB0[5].x); pt[1].y = ym(PtB0[5].y);
pt[2].x = xn(PtB0[6].x); pt[2].y = ym(PtB0[6].y);
pt[3].x = xn(PtB0[7].x); pt[3].y = ym(PtB0[7].y);
Polygon(hdc,pt,4);
HBRUSH hbrush3 = CreateSolidBrush(RGB(150,170,150));
SelectObject(hdc,hbrush3); //выбираем кисть hbrush
pt[0].x = xn(PtB0[10].x); pt[0].y = ym(PtB0[10].y);
pt[1].x = xn(PtB0[11].x); pt[1].y = ym(PtB0[11].y);
pt[2].x = xn(PtB0[12].x); pt[2].y = ym(PtB0[12].y);
pt[3].x = xn(PtB0[13].x); pt[3].y = ym(PtB0[13].y);
pt[4].x = xn(PtB0[14].x); pt[4].y = ym(PtB0[14].y);
pt[5].x = xn(PtB0[15].x); pt[5].y = ym(PtB0[15].y);
pt[6].x = xn(PtB0[16].x); pt[6].y = ym(PtB0[16].y);
pt[7].x = xn(PtB0[17].x); pt[7].y = ym(PtB0[17].y);
pt[8].x = xn(PtB0[18].x); pt[8].y = ym(PtB0[18].y);
pt[9].x = xn(PtB0[19].x); pt[9].y = ym(PtB0[19].y);
pt[10].x = xn(PtB0[20].x); pt[10].y = ym(PtB0[20].y);
pt[11].x = xn(PtB0[21].x); pt[11].y = ym(PtB0[21].y);
pt[12].x = xn(PtB0[22].x); pt[12].y = ym(PtB0[22].y);
Polygon(hdc,pt,13);
HBRUSH hbrush4 = CreateSolidBrush(RGB(175,195,175));
SelectObject(hdc,hbrush4); //выбираем кисть hbrush
pt[0].x = xn(PtB0[2].x); pt[0].y = ym(PtB0[2].y);
pt[1].x = xn(PtB0[3].x); pt[1].y = ym(PtB0[3].y);
pt[2].x = xn(PtB0[4].x); pt[2].y = ym(PtB0[4].y);
pt[3].x = xn(PtB0[5].x); pt[3].y = ym(PtB0[5].y);
Polygon(hdc,pt,4);
HBRUSH hbrush5 = CreateSolidBrush(RGB(200,220,200));
SelectObject(hdc,hbrush5); //выбираем кисть hbrush
pt[0].x = xn(PtB0[0].x); pt[0].y = ym(PtB0[0].y);
pt[1].x = xn(PtB0[1].x); pt[1].y = ym(PtB0[1].y);
pt[2].x = xn(PtB0[2].x); pt[2].y = ym(PtB0[2].y);
pt[3].x = xn(PtB0[3].x); pt[3].y = ym(PtB0[3].y);
Polygon(hdc,pt,4);
HBRUSH hbrush6 = CreateSolidBrush(RGB(255,0,128));
SelectObject(hdc,hbrush6); //выбираем кисть hbrush
Ellipse(hdc, xn(PtB0[23].x), ym(PtB0[23].y), xn(PtB0[24].x), ym(PtB0[24].y));
SelectObject(hdc,hpenOld);
DeleteObject(hpen); //убираем перо hpen
SelectObject(hdc,hbrushOld);
DeleteObject(hbrush1); //убираем перо hpen
DeleteObject(hbrush2); //убираем перо hpen
DeleteObject(hbrush3); //убираем перо hpen
DeleteObject(hbrush4); //убираем перо hpen
DeleteObject(hbrush5); //убираем перо hpen
DeleteObject(hbrush6); //убираем перо hpen
}
//копируем файл в память, получаем указатель на первый байт памяти
BYTE* ReadFileToMem(LPSTR lPstr)
{
//открываем файл для чтения
HFILE hFile = _lopen(lPstr, OF_READ);
//определяем размер файла
LONG FileSize = _llseek(hFile, 0L, FILE_END);
//указатель файла ставим в начало файла
_llseek(hFile, 0L, FILE_BEGIN);
//выделяет заданное число байт в памяти
// hBuf = GlobalAlloc(GMEM_MOVEABLE, FileSize);
//получаем указатель на первый байт выделенной памяти
BYTE* lpBuf = (BYTE*)GlobalLock(hBuf);
//копируем файл в память
_hread(hFile, lpBuf, FileSize);
//закрываем файл
_lclose(hFile);
return lpBuf;
}
//получаем указатель на первый байт изображения
BYTE* ImageBytes(BYTE* lpBuf)
{
//получаем указатель на первый байт структуры BITMAPFILEHEADER
LPBITMAPFILEHEADER lpfh = (LPBITMAPFILEHEADER)lpBuf;
//получаем указатель на первый байт изображения
BYTE* lpOff = (BYTE*)lpfh + lpfh->bfOffBits;
return lpOff;
}
//получаем указатель на первый байт структуры BITMAPINFOHEADER
LPBITMAPINFOHEADER BmpInfHead(BYTE* lpBuf)
{
//получаем указатель на первый байт структуры BITMAPINFOHEADER
LPBITMAPINFOHEADER lpih = (LPBITMAPINFOHEADER)(lpBuf + sizeof(BITMAPFILEHEADER));
return lpih;
}
//функция обрабатывает сообщение WM_PAINT
void Move_OnPaint(HWND hwnd)
{
//получаем идентификатор контекста экрана
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
//создаем контекст памяти hdcMem, совместимый с контекстом экрана hdc
HDC hdcMem = CreateCompatibleDC(hdc);
//создаем (пустую) битовую карту совместмую с контекстом экрана
HBITMAP hBmp = CreateCompatibleBitmap(hdc, 640, 480);
//выбираем битовую карту hBmp в контекст памяти hdcMem
HBITMAP hBmpOld = (HBITMAP)SelectObject(hdcMem, hBmp);
//получаем указатель на первый байт блока памяти, куда скопирован файл "ship58.bmp"
BYTE* lpBuf = ReadFileToMem(nameShip[48]);
//получаем указатель на первый байт изображения
BYTE* lpOff = ImageBytes(lpBuf);
//получаем указатель на первый байт структуры BITMAPINFOHEADER
LPBITMAPINFOHEADER lpih = BmpInfHead(lpBuf);
//устанавливает в битовой карте hBmp пиксели изображения по адресом lpOff
SetDIBits(hdcMem, hBmp, 0, lpih->biHeight, lpOff, (LPBITMAPINFO)lpih, DIB_RGB_COLORS);
SetTextColor(hdcMem,RGB(230,230,220));
SetBkColor(hdcMem,RGB(0,0,0));
TextOut(hdcMem, 225,100,TEXT(" P r e s s a n y k e y "),27);
tB = 0;
xB2 = TrajBa(tB).x;
yB2 = TrajBa(tB).y;
Bird(hdcMem,0,0,55);
//копируем изображение из контекста памяти hdcMem в контекст экрана hdc
BitBlt(hdc, 0, 0, nRight, mBottom, hdcMem, 0, 0, SRCCOPY);
DeleteObject(hBmp); //убираем растровое изображение из памяти
SelectObject(hdcMem, hBmpOld); //востанавливаем контекст памяти
DeleteDC(hdcMem); //убираем контекст памяти
EndPaint(hwnd, &ps); //освобождаем контекст устройства
}
//функция обрабатывает сообщение WM_TIMER
void Move_OnTimer(HWND hwnd)
{
//получаем идентификатор контекста экрана
HDC hdcWin = GetDC(hwnd);
//создаем контекст памяти hdcMem, совместимый с контекстом экрана hdc
HDC hdcMem = CreateCompatibleDC(hdcWin);
//создаем (пустую) битовую карту совместмую с контекстом экрана
HBITMAP hBmp = CreateCompatibleBitmap(hdcWin, 640, 480);
//выбираем битовую карту hBmp в контекст памяти hdcMem
HBITMAP hBmpOld = (HBITMAP)SelectObject(hdcMem, hBmp);
//номер bitmap-ресурса
static int iBmp = 0;
int numberBmp;
if(flagEnd == 1)
numberBmp = 30;
else
numberBmp = iBmp;
//получаем указатель на первый байт блока памяти, куда скопирован файл nameShip[]
BYTE* lpBuf = ReadFileToMem(nameShip[numberBmp]);
//получаем указатель на первый байт изображения
BYTE* lpOff = ImageBytes(lpBuf);
//получаем указатель на первый байт структуры BITMAPINFOHEADER
LPBITMAPINFOHEADER lpih = BmpInfHead(lpBuf);
//устанавливает в битовой карте hBmp пиксели изображения по адресом lpOff
SetDIBits(hdcMem, hBmp, 0, lpih->biHeight, lpOff, (LPBITMAPINFO)lpih, DIB_RGB_COLORS);
if(flagBmp == 1)
{
iBmp++;
if(iBmp>49)
{
flagBmp = 2;
iBmp--;
}
}
if(flagBmp == 2)
{
iBmp--;
if(iBmp<0)
{
flagBmp = 1;
iBmp++;
}
}
tB += 0.5;
xB2 = TrajBa(tB).x;
yB2 = TrajBa(tB).y;
Bird(hdcMem,xB2,yB2,tB);
xB2 = TrajBb(tB).x;
yB2 = TrajBb(tB).y;
Bird(hdcMem,xB2,yB2,tB);
if(xB2 < -10)
tB = 0;
//копируем изображение из контекста памяти hdcMem в контекст экрана hdcWin
BitBlt(hdcWin, 0, 0, nRight, mBottom, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hBmpOld); //востанавливаем контекст памяти
DeleteObject(hBmp); //убираем битовую карту
DeleteDC(hdcMem); //освобождаем контекст памяти
ReleaseDC(hwnd,hdcWin); //освобождаем контекст экрана
}