Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ИГС / ИГС_2

.txt
Скачиваний:
3
Добавлен:
17.04.2018
Размер:
13.51 Кб
Скачать
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>


//название программы
WCHAR const szClassName[] = TEXT("Movement");
//заголовок окна   
WCHAR const szWindowTitle[] = TEXT("Korneev V.  Move, drawing in memory ");


//прототимы функций
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 msg.wParam;
}

//регистрация окна  
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)
{
	HWND hwnd;   //дескриптор окна 

	hwnd = CreateWindow(szClassName,      //название программы   
		szWindowTitle,        //заголовок окна  
		WS_OVERLAPPEDWINDOW,  //вид окна 
		CW_USEDEFAULT,        //x - координата окна  
		CW_USEDEFAULT,        //y - координата окна  
		CW_USEDEFAULT,        //ширина окна  
		CW_USEDEFAULT,        //высота окна  
		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	PtA[7], PtA0[7], PtB[7], PtB0[7], Ptd[6], Ptd0[6];

//"время" движения по траектории цента стрелки
double tA, dtA, dtA0, tB, dtB, dtB0;

//задаем угол поворота и коэффициенты растяжения стрелки
double fiA, kxA, kyA, fiB, kxB, kyB;

//создаем 6 матриц аффинный преобразований
Matrix2D R, T, D, A, T1, T2;

//началтные и текущие точки цента стрелки
double xA0, yA0, xA2, yA2, xA1, yA1, xB0, yB0, xB2, yB2, xB1, yB1;

//флаг остановки и запуска таймера
int MoveStop;

//время задержки таймера
UINT uElapse;

//функция обрабатывает сообщение  WM_CREATE
void Move_OnCreate()
{
	//размеры поля вывода в мировых и экранных координатах
	xLeft = -20; xRight = 20; yBottom = -16.0; yTop = 16.0;
	nLeft = 50; nRight = 550; mTop = 50; mBottom = 350;

	//начальные координты вершин стрелки
	PtA0[0].x = -4.0; PtA0[0].y = 1.0;
	PtA0[1].x = -2.0; PtA0[1].y = 2.0;
	PtA0[2].x = 2.0; PtA0[2].y = 2.0;
	PtA0[3].x = 3.0; PtA0[3].y = 1.0;
	PtA0[4].x = 4.0; PtA0[4].y = 1.0;
	PtA0[5].x = 4.0; PtA0[5].y = 0.0;
	PtA0[6].x = -4.0; PtA0[6].y = 0.0;

	//начальные координты вершин стрелки
	PtB0[0].x = -4.0; PtB0[0].y = 1.0;
	PtB0[1].x = -2.0; PtB0[1].y = 2.0;
	PtB0[2].x = 2.0; PtB0[2].y = 2.0;
	PtB0[3].x = 3.0; PtB0[3].y = 1.0;
	PtB0[4].x = 4.0; PtB0[4].y = 1.0;
	PtB0[5].x = 4.0; PtB0[5].y = 0.0;
	PtB0[6].x = -4.0; PtB0[6].y = 0.0;

	//задаем угол поворота и коэффициенты растяжения
	fiA = 0; kxA = 1; kyA = 1;

	//шаг по времени
	dtA0 = 0.1;
	//задаем угол поворота и коэффициенты растяжения
	fiB = 0; kxB = 1; kyB = 1;

	//шаг по времени
	dtB0 = 0.1;

	//время задержки таймера
	uElapse = 50;

	//флаг запуска таймера
	MoveStop = 1;
}



//функция обрабатывающая сообщение 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);   //закрывает окно 
}

Point TrajA(double t)
{
	Point P;
	
	if (t < 20)
	{
		P.x = (t - 8);
		P.y = (4 - (t - 8)*(t - 8) / 10);
		return P;
	}
	else
	{
		P.x = 12;
		P.y = -10.4;
		return P;
	}
}
Point TrajB(double t)
{
	Point P;
	if (t < 20)
	{
		P.x = (8 - t);
		P.y = (4 - (t - 8)*(t - 8) / 10);
		return P;
	}
	else
	{
		P.x = -12;
		P.y = -10.4;
		return P;
	}
}


void Land(HDC hdc)
{

	HBRUSH hbrush, hbrushOld;
	HPEN hpen1, hpen2, hpenOld;

	hbrush = CreateSolidBrush(RGB(0, 200, 0));
	hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);     //выбираем кисть hbrush
	hpen1 = CreatePen(PS_SOLID, 3, RGB(255, 255, 255));
	hpenOld = (HPEN)SelectObject(hdc, hpen1);         // выбираем перо hpen



	Ellipse(hdc, nLeft + 140, mTop + 170, nRight - 140, mBottom + 120);

	//рисуем координатные оси
	hpen2 = CreatePen(PS_SOLID, 1, RGB(0, 255, 255));
	SelectObject(hdc, hpen2);    // выбираем перо hpen

	int nb, ne, mb, me;

	nb = xn(xLeft); mb = ym(0);
	MoveToEx(hdc, nb, mb, 0);
	ne = xn(xRight); me = ym(0);
	LineTo(hdc, ne, me);

	nb = xn(0); mb = ym(yBottom);
	MoveToEx(hdc, nb, mb, 0);
	ne = xn(0); me = ym(yTop);
	LineTo(hdc, ne, me);

	SelectObject(hdc, hpenOld);
	DeleteObject(hpen1);           //убираем перо hpen
	DeleteObject(hpen2);           //убираем перо hpen
	SelectObject(hdc, hbrushOld);
	DeleteObject(hbrush);           //убираем перо hpen
}


//рисует стрелку по координатам вершин Pt в точке x2, y2

//рисует полигон (стрелку) по координатам вершин Pt
void Arrow(HDC hdc, Point *Pt, int N, double x1, double y1,
	double x2, double y2, double fi, double kx, double ky, bool color)
{

	//создаем матрицы аффинного преобразования
	T1.transl(-x1, -y1);
	R.rotate(fi);
	D.displa(kx, ky);
	T.transl(x2 - x1, y2 - y1);
	T2.transl(x1, y1);

	A = T2*T*D*R*T1;

	//совершаем аффинное преобразование точек фигуры
	for (int n = 0; n<7; n++)
		Pt[n] = affine(A, Pt[n]);


	POINT pt[7];
	for (int i = 0; i < N; i++)
	{
		pt[i].x = xn(Pt[i].x); pt[i].y = ym(Pt[i].y);
	}

	HBRUSH hbrush, hbrushOld;
	HPEN hpen, hpenOld;

	if (color)
	{
		hbrush = CreateSolidBrush(RGB(255, 0, 0));
		hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);     //выбираем кисть hbrush
		hpen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
		hpenOld = (HPEN)SelectObject(hdc, hpen);         // выбираем перо hpen
	}
	else
	{
		hbrush = CreateSolidBrush(RGB(38, 38, 185));
		hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);     //выбираем кисть hbrush
		hpen = CreatePen(PS_SOLID, 2, RGB(255, 242, 0));
		hpenOld = (HPEN)SelectObject(hdc, hpen);         // выбираем перо hpen
	}

	Polygon(hdc, pt, N);

	SelectObject(hdc, hpenOld);
	DeleteObject(hpen);           //убираем перо hpen
	SelectObject(hdc, hbrushOld);
	DeleteObject(hbrush);           //убираем перо hpen

}




//функция обрабатывает сообщение  WM_PAINT
void Move_OnPaint(HWND hwnd)
{

	HDC hdc;
	PAINTSTRUCT ps;

	hdc = BeginPaint(hwnd, &ps);  //получаем контекст устройства 


	HBRUSH hbrush, hbrushOld;
	HPEN hpen, hpenOld;

	hbrush = CreateSolidBrush(RGB(0, 0, 0));
	hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);     //выбираем кисть hbrush
	hpen = CreatePen(PS_SOLID, 3, RGB(255, 255, 255));
	hpenOld = (HPEN)SelectObject(hdc, hpen);         // выбираем перо hpen

	Rectangle(hdc, nLeft, mBottom, nRight, mTop);

	SelectObject(hdc, hpenOld);
	DeleteObject(hpen);           //убираем перо hpen
	SelectObject(hdc, hbrushOld);
	DeleteObject(hbrush);           //убираем перо hpen

	Land(hdc);

	SetTextColor(hdc, RGB(230, 230, 220));
	SetBkColor(hdc, RGB(0, 0, 0));
	TextOut(hdc, 225, 100, TEXT(" P r e s s   a n y   k e y "), 27);

	//начальный момент времени для стрелки
	tA = 0; dtA = dtA0;
	//начальный момент времени для стрелки
	tB = 0; dtB = dtB0;

	//начальное положение центра лодки
	xA0 = TrajA(tA).x;
	yA0 = TrajA(tA).y;

	for (int n = 0; n<7; n++)
		PtA[n] = PtA0[n];

	//начальное положение центра лодки
	xB0 = TrajB(tB).x;
	yB0 = TrajB(tB).y;

	for (int n = 0; n<7; n++)
		PtB[n] = PtB0[n];

	//рисуем стрелку в начальной точке
	Arrow(hdc, PtA, 7, 0, 0, -8, -8, 1.04, 1, 1, 0);

	xA1 = xA0; yA1 = yA0;
 
	//рисуем стрелку в начальной точке
	Arrow(hdc, PtB, 7, 10, -3, 0, 0, 1.04, -1, 1, 1);

	xB1 = xB0; yB1 = yB0;

	EndPaint(hwnd, &ps);      //освобождаем контекст устройства 

}



//функция обрабатывает сообщение  WM_TIMER
void Move_OnTimer(HWND hwnd)
{
	HDC hdcMem, hdcWin;
	HBITMAP hBitmap, hBitmapOld;
	hdcWin = GetDC(hwnd);  //получаем контекст экрана
	hdcMem = CreateCompatibleDC(hdcWin); //создаем контекст
	//памяти связаный с контекстом экрана

	//памяти надо придать вид экрана - подходт битовая карта с форматом
	// как у экрана. В памяти будем рисовать на битовой карте
	hBitmap = CreateCompatibleBitmap(hdcWin, nRight, mBottom); //создаем
	//битовую карту совместмую с контекстом экрана
	hBitmapOld = (HBITMAP)SelectObject(hdcMem, hBitmap); //помещаем
	// битовую карту в контекст памяти

	Land(hdcMem);

	tA += dtA;
	xA2 = TrajA(tA).x;
	if (xA2 >= xRight - 1)
	{
		xA2 = xRight - 1;
		tA -= dtA;
	}
	yA2 = TrajA(tA).y;

	tB += dtB;
	xB2 = TrajB(tB).x;
	if (xB2 >= xRight - 1)
	{
		xB2 = xRight - 1;
		tB -= dtB;
	}
	yB2 = TrajB(tB).y;

	
	if (tA < 18)
		fiA -= 1.04 / 8.0 * 0.01 * dtA;
	else
		fiA = 0;
	if (tB < 18)
		fiB += 1.04 / 8.0 * 0.01 * dtB;
	else
		fiB = 0;
	

	//рисуем фигуру в точке (x2, y2)
	Arrow(hdcMem, PtA, 7, xA1, yA1, xA2, yA2, fiA, kxA, kyA, 0);

	xA1 = xA2; yA1 = yA2;

	//рисуем фигуру в точке (x2, y2)
	Arrow(hdcMem, PtB, 7, xB1, yB1, xB2, yB2, fiB, kxB, kyB, 1);

	xB1 = xB2; yB1 = yB2;


	BitBlt(hdcWin, nLeft, mTop, nRight, mBottom, hdcMem, nLeft, mTop, SRCCOPY); //копи-
	//руем контекст памяти в контекст экрана



	SelectObject(hdcMem, hBitmapOld); //востанавливаем контекст памяти
	DeleteObject(hBitmap); //убираем битовую карту
	DeleteDC(hdcMem);  //  освобождаем контекст памяти
	ReleaseDC(hwnd, hdcWin);  //освобождаем контекст экрана
}
Соседние файлы в папке ИГС