//Автор: Иванченко Леонид Васильевич
//main.cpp
//Загрузка нужных библиотек
#pragma comment( lib, "winmm.lib" )	
								
#pragma comment( lib, "dxguid.lib" )	
#pragma comment( lib, "ddraw.lib" )	
#pragma comment( lib, "dsound.lib" )	
#pragma comment( lib, "dinput.lib" )	
//-----------------------------------
#include <ddraw.h>
#include <dsound.h>
#include "dinput.h"//файл находится в папке для избежания разногласия с более поздними версиями
#include <math.h>
#include "DirectDraw.h"
#include "sound.h"
#include "input.h"
#include "resource.h"
//--------------------
#include "ResFile.h"
#include "MyGraph.h"
#include "main.h"
//--------------------
#include <list>
//-----------------------------------
//поставщик сообщений
bool ProcessMessages()
{
	MSG msg;
	if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		if(msg.message==WM_QUIT)return true;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return false;
};
//Функция, вызываемая в случае ошибки
void ErrorHandle(HWND hwnd, LPCTSTR szError)
{
	//Переменная, которая будет содержать строку с текстом ошибки
	char szErrorMessage[255];
	//Перед тем как вывести сообщение,
	//завершим работу DirectDraw
	RemoveDirectDraw();
	//завершить работу DirectSound
	RemoveDirectSound();
	//завершить работу DirectInput
	RemoveDirectInput();
	//Скроем основное окно
	ShowWindow(hwnd, SW_HIDE);
	//Выведем сообщение об ошибке
	wsprintf(szErrorMessage, "Программа прервана\nОшибка в %s", szError);
	MessageBox(hwnd, szErrorMessage, "Craft", MB_OK);
	//Уничтожим окно
	DestroyWindow(hwnd);
}
//----------------------------------------------
//объявление функций
//инициализация игры
void InitGame();
//----------------------------------------------
//глобальные переменный
//зарезервированные имена цветов
DWORD black,white,blue,red,green;
DWORD orange,yellow,violet;
DWORD gray,gray1,silver,brown,oliv;
//-------------------------------------
//Флаг активности нашего приложения
bool bActive;
//присутствие джойстика
bool JOYSTICK=false;
//индикатор состояния игры
bool gameover=false;
//Размер окна
int SizeWindowX=1024,SizeWindowY=768;//размеры по умолчанию
HWND hWnd;
//-----------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	switch(message)//обработка событий
	{
    case WM_ACTIVATE:
        // Pause if minimized
        bActive = !((BOOL)HIWORD(wParam));
        return 0;
	case WM_CHAR:
		key=wParam;
		key_state=lParam;
		keypress=true;
		return 0;
	case WM_MOUSEMOVE:
		cur_x=LOWORD(lParam);
		cur_y=HIWORD(lParam);
		return 0;
	case WM_LBUTTONDOWN:
		lbutton=true;
		pointldx=cur_x;
		pointldy=cur_y;
		return 0;
	case WM_LBUTTONUP:
		lbutton=false;
		pointlux=cur_x;
		pointluy=cur_y;
		return 0;
	case WM_RBUTTONDOWN:
		rbutton=true;
		pointrdx=cur_x;
		pointrdy=cur_y;
		return 0;
	case WM_RBUTTONUP:
		rbutton=false;
		pointrux=cur_x;
		pointruy=cur_y;
		return 0;
	case WM_LBUTTONDBLCLK:
		ldblclk=true;
		pointldx=cur_x;
		pointldy=cur_y;
		return 0;
	case WM_RBUTTONDBLCLK:
		rdblclk=true;
		pointrdx=cur_x;
		pointrdy=cur_y;
		return 0;
	case WM_TIMER:
		switch(wParam)
			case TIMER_1SEC:
				;
		return 0;
	case WM_DESTROY:
		bActive=false;
		//убрать таймер
		KillTimer(hWnd,TIMER_1SEC);
		//очистить память
		RemoveDirectDraw();
		RemoveDirectSound();
		RemoveDirectInput();
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd,message,wParam,lParam);
}
//----------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmd,int nCmdShow)
{
	WNDCLASS WndClass;
	MSG msg;

	WndClass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
	WndClass.lpfnWndProc=WndProc;
	WndClass.cbClsExtra=0;
	WndClass.cbWndExtra=0;
	WndClass.hInstance=hInstance;
	WndClass.hIcon=LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
	WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
	WndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	WndClass.lpszMenuName="game";
	WndClass.lpszClassName="game";

	if(!RegisterClass(&WndClass))return 0;

	hWnd=CreateWindow("game","game",WS_POPUP,0,0,
					SizeWindowX,SizeWindowY,NULL,NULL,hInstance,NULL);

	if(!hWnd)return NULL;

	ShowWindow(hWnd,nCmdShow);
	UpdateWindow(hWnd);
	//---------------------------------
	//***********************************
	//место расположения программы юзера
	//---------------------------------
	ShowCursor(false);//убрать системный курсор
	//------------------------------
	//инициализация всего необходимого для игры
	SetTimer(hWnd,TIMER_1SEC,1000,NULL);
	//Инициализация компонентов, связанных с DirectInput
	//если джойстик отсутствует - JOYSTICK = false ,но программа не будет остановлена
	if (InitDirectInput(hWnd))JOYSTICK=true;//проверить присутствие джойстика
	if (!InitDirectSound(hWnd))//иницализация DirectSound
	{
		ErrorHandle(hWnd, "InitDirectSound");
		return(0);
	}
	SizeWindowX=800;SizeWindowY=600;//задание размеров экрана
	//Задание битового режима
	BIT_MODE=16;
	if (!InitDirectDraw (hWnd,BIT_MODE))//иницализация DirectDraw
	{
		ErrorHandle(hWnd, "InitDirectDraw");
		return (0);
	}
	//инициализация игры
	InitGame();
	//Главный цикл программы
	while (TRUE)
	{
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if (msg.message==WM_QUIT)
				break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		if(bActive)//Только если приложение активно!
		{
			//проверка на потерю поверхностей
			if(!CheckLost())break;
			//вызов игры
			game_main();
			//запрос на выход
			//если нажата клавиша ESCAPE
			if(KEYDOWN(VK_ESCAPE)||gameover)DestroyWindow(hWnd);
			//сохранение скриншота
			if(KEYDOWN(VK_F12))save_bmp(0,0,SizeWindowX,SizeWindowY,buffer,"screen.bmp");
		}
	}
	return (0);
}
//-------------------------------------------------------------
//*************** КОД ЮЗЕРА *************************
//-------------------------------------------------------------
//Объявление переменных
LPDIRECTDRAWSURFACE7 sstar;//поверхность для звезд
//структура для звезд
struct node
{
	int x,y,//положение 
		delay,//задержка
		frame,//кадр
		color,//цвет
		life;//время жизни
};
//Определение списка звезд
std::list<node>nodes;		//не слишком большое усилие для титанического труда
//----------------------------
//инициализация игры
void InitGame()
{
	//задание значений цветов 
	//COLOR() - Очень медленная функция поэтому использовать только вне цикла игры
	black=COLOR(15,15,15),white=COLOR(255,255,255),blue=COLOR(0,0,255),red=COLOR(200,0,0),green=COLOR(0,255,0);
	orange=COLOR(251,103,4),yellow=COLOR(255,255,40),violet=COLOR(180,0,180),oliv=COLOR(156,168,100);
	gray=COLOR(120,120,120),gray1=COLOR(192,192,192),silver=COLOR(152,168,168),brown=COLOR(128,0,0);
	//----------------------
	sstar=load_bmp("data\\star.bmp");//загрузка растра в поверхность
	//----------------------
}
//----------------------------
//Объявление функций
void show_stars();
//----------------------------
//главная вызывающая программа
void game_main()
{
	char s[100];
	//------------------------------
	//синхронизация
	DWORD start_time=GetTickCount();
	//---------------------------------------
	//***************************************
	//фон
	box(0,0,SizeWindowX,SizeWindowY,black);
	//--------------------------------------
	if(lbutton)//добавление узла в список
	{
		node n;//временная структура

		n.x=cur_x+8-rand()%16;//задать положение звезды
		n.y=cur_y+8-rand()%16;
		n.delay=5;n.frame=0;
		n.color=randInt(0,4);//цвет звезды
		n.life=randInt(50,150);
		//---------------
		nodes.push_back(n);//занести в список
	}
	//----------------------------
	show_stars();//показать звезды
	//--------------------------------------
	wsprintf(s,"Нажмите на левую кнопку мыши");
	print(60,10,14,RGB(255,255,255),s);
	//сосчитать колличество узлов
	int count=nodes.size();
	//--------------------------------------
	//показать скорость частоты кадров и колличество узлов в списке
	wsprintf(s,"Fps - %03d звезд: %d",UpdateFPS(),count);
	print(60,30,20,RGB(255,255,40),s);
	//---------------------
	//синхронизация вывода 
//	while((GetTickCount()-start_time)<10);
	//---------------------------------------
	Flip();//вывести вторичный буфер на экран
	//---------------------------------------
}
//-------------------------------------------------------------
//*************************************************************
//-------------------------------------------------------------
//показать звезды
void show_stars()
{
	std::list<node>::iterator iter=nodes.begin();//создать итератор
	while(iter!=nodes.end())//пока не достигнут конец списка
	{
		node& s=*iter;//создать новую структуру и указать на текущий список
		if(s.delay--<0)//задержка кончилась
		{
			s.delay=randInt(2,15);//новая задержка
			s.frame++;//сменить кадр
			if(s.frame>2)s.frame=0;
		}
		int x=s.x,y=s.y;//положение текущей звезды
		if(s.life-->0)
		{
			draw(x,y,s.frame*16,s.color*16,16,16,sstar);//показать звезду
			iter++;//перейти к следующему узлу
		}
		else iter=nodes.erase(iter);//удалить узел
	}
}