自己用DirectX做的简单2D桌面动画一睡眠就卡死

#include <windows.h>
#include <vector>
#include <direct.h>
#include <math.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <time.h>
#include <d3d9.h>
#define _Time long long
#pragma comment(lib,"d3d9.lib")
#include <d3dx9.h>
#pragma comment(lib,"d3dx9.lib")
using namespace std;

const int WINDOWS_WIDTH = 1920;
const int WINDOWS_HEIGHT = 1080;
const double DENSITY = 0.00001;
const double PI = 3.1415926535897932384626433832795;
const int DMARGIN = 6;
const int RedrawTimeDifference = 1000;

double KineticEnergyPre = 0;

RECT rect;
double clientx;
double clienty;

_Time tPrevious = 0, tPresent = 0;

HWND sShWnd = NULL, ShWnd = NULL;
HINSTANCE ShInstance = NULL;

LPDIRECT3D9 SD3D = nullptr;
LPDIRECT3DDEVICE9 SDevice = NULL;
LPD3DXSPRITE SSprite = nullptr;

typedef struct Round
{
	double v, angle, m, r;
	D3DXVECTOR2 Position;
	LPDIRECT3DTEXTURE9 RoundTextture;
	D3DXIMAGE_INFO ImageInformation;
}*sRound;

vector<sRound> SRound;

double GetModDecimals(double d, double mod)
{
	return ((long long)(d * 10000000000) % (long long)(mod * 10000000000)) / 10000000000.0;
}

double GetKineticEnergy()
{
	double kineticenergy = 0;
	for (int i = 0; i < SRound.size(); i++)
	{
		kineticenergy += SRound.at(i)->m * pow(SRound.at(i)->v, 2.0) / 2.0;
	}
	return kineticenergy;
}

bool OnInit()
{
	SD3D = Direct3DCreate9(D3D_SDK_VERSION);
	D3DDISPLAYMODE D3DDisplayMode;
	ZeroMemory(&D3DDisplayMode, sizeof(D3DDISPLAYMODE));
	if (FAILED(SD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &D3DDisplayMode)))
	{
		return false;
	}

	D3DPRESENT_PARAMETERS D3DPresent_Parameters;
	ZeroMemory(&D3DPresent_Parameters, sizeof(D3DPRESENT_PARAMETERS));
	D3DPresent_Parameters.BackBufferCount = 1;
	D3DPresent_Parameters.Windowed = TRUE;
	D3DPresent_Parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
	if (FAILED(SD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, ShWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPresent_Parameters, &SDevice)))
	{
		return false;
	}

	if (FAILED(D3DXCreateSprite(SDevice, &SSprite)))
	{
		return false;
	}

	string CurrentPath = _getcwd(NULL, 0);
	CurrentPath += "\\image\\";
	string FileName[] = { "bubble0.png", "bubble1.png", "bubble2.png", "bubble3.png", "bubble4.png", "bubble5.png", "bubble6.png" };
	for (int i = 0; i < _countof(FileName); i++)
	{
		Round* round = new Round();
		ZeroMemory(round, sizeof(round));
		if (FAILED(D3DXCreateTextureFromFileEx(SDevice, (CurrentPath + FileName[i]).c_str(), D3DX_FROM_FILE, D3DX_FROM_FILE,
			0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, D3DCOLOR_XRGB(255, 255, 255),
			&(round->ImageInformation), nullptr, &(round->RoundTextture))))
		{
			MessageBox(NULL, "资源加载失败:image/下找不到image资源!", "错误", MB_ICONINFORMATION | MB_OK);
			return false;
		}
		round->v = rand() % 8;
		round->angle = rand() % 360 / 360.0 * PI * 2;
		round->r = (round->ImageInformation.Width - DMARGIN) / 2.0;
		round->m = PI * round->r * round->r * DENSITY;
		SRound.push_back(round);
	}

	GetClientRect(ShWnd, &rect);
	clientx = rect.right - rect.left;
	clienty = rect.bottom - rect.top;
	for (int i = 0; i < SRound.size(); i++)
	{
	LOOP:
		SRound.at(i)->Position.x = rand() % WINDOWS_WIDTH;
		SRound.at(i)->Position.y = rand() % WINDOWS_HEIGHT;
		if (SRound.at(i)->Position.x < SRound.at(i)->r || SRound.at(i)->Position.x > clientx - SRound.at(i)->r
			|| SRound.at(i)->Position.y < SRound.at(i)->r || SRound.at(i)->Position.y > clienty - SRound.at(i)->r)
		{
			goto LOOP;
		}

		for (int j = 0; j < i; j++)
		{
			int distance = sqrt(pow(SRound.at(i)->Position.x - SRound.at(j)->Position.x, 2)
				+ pow(SRound.at(i)->Position.y - SRound.at(j)->Position.y, 2));
			int limitdistance = SRound.at(i)->r + SRound.at(j)->r;
			if (distance < limitdistance)
			{
				goto LOOP;
			}
		}
	}

	KineticEnergyPre = GetKineticEnergy();

	return true;
}

void OnRender()
{
	SDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(100, 100, 100), 1.0, 0);

	SDevice->BeginScene();
	SSprite->Begin(D3DXSPRITE_ALPHABLEND);
	for (int i = 0; i < SRound.size(); i++)
	{
		for (int j = i + 1; j < SRound.size(); j++)
		{
			double distance = sqrt(pow(SRound.at(i)->Position.x - SRound.at(j)->Position.x, 2)
				+ pow(SRound.at(i)->Position.y - SRound.at(j)->Position.y, 2));
			double limitdistance = SRound.at(i)->r + SRound.at(j)->r;
			if (distance < limitdistance)
			{
				double forecastix = SRound.at(i)->Position.x + SRound.at(i)->v * cos(SRound.at(i)->angle);
				double forecastiy = SRound.at(i)->Position.y + SRound.at(i)->v * sin(SRound.at(i)->angle);
				double forecastjx = SRound.at(j)->Position.x + SRound.at(j)->v * cos(SRound.at(j)->angle);
				double forecastjy = SRound.at(j)->Position.y + SRound.at(j)->v * sin(SRound.at(j)->angle);
				double forecastdistance = sqrt(pow(forecastix - forecastjx, 2) + pow(forecastiy - forecastjy, 2));
				if (forecastdistance < distance)
				{
					double rotation = atan((SRound.at(i)->Position.y - SRound.at(j)->Position.y) / (SRound.at(i)->Position.x - SRound.at(j)->Position.x));
					double anglei = SRound.at(i)->angle - rotation, anglej = SRound.at(j)->angle - rotation;
					double algebraicexpression1 = SRound.at(j)->m / SRound.at(i)->m;
					double algebraicexpression2 = SRound.at(i)->v * cos(anglei)
						+ algebraicexpression1 * SRound.at(j)->v * cos(anglej);
					double algebraicexpression3 = pow(SRound.at(i)->v * cos(anglei), 2)
						+ algebraicexpression1 * pow(SRound.at(j)->v * cos(anglej), 2);
					double v1 = (algebraicexpression2 - sqrt((algebraicexpression3 + algebraicexpression3 * algebraicexpression1
						- pow(algebraicexpression2, 2)) / algebraicexpression1)) / (algebraicexpression1 + 1);
					double v2 = (algebraicexpression2 + sqrt((algebraicexpression3 + algebraicexpression3
						* algebraicexpression1 - pow(algebraicexpression2, 2)) / algebraicexpression1)) / (algebraicexpression1 + 1);
					double vxi = 0, vxj = 0;
					if (SRound.at(i)->Position.x < SRound.at(j)->Position.x)
					{
						vxi = v1;
						vxj = v2;
					}
					else if (SRound.at(i)->Position.x > SRound.at(j)->Position.x)
					{
						vxi = v2;
						vxj = v1;
					}
					else
					{
						if (SRound.at(i)->Position.y < SRound.at(j)->Position.y)
						{
							vxi = v2;
							vxj = v1;
						}
						else if (SRound.at(i)->Position.y > SRound.at(j)->Position.y)
						{
							vxi = v1;
							vxj = v2;
						}
					}

					if (vxi == 0 && SRound.at(i)->v * sin(SRound.at(i)->angle) != 0)
					{
						if (SRound.at(i)->v * sin(SRound.at(i)->angle) > 0)
							anglei = PI / 2.0;
						else
							anglei = 3 * PI / 2.0;
					}
					else if (vxi != 0 && SRound.at(i)->v * sin(SRound.at(i)->angle) == 0)
					{
						if (vxi > 0)
							anglei = 0.0;
						else
							anglei = PI;
					}
					else if (vxi != 0 && SRound.at(i)->v * sin(SRound.at(i)->angle) != 0)
					{
						if (vxi > 0)
							anglei = GetModDecimals(2 * PI + atan(SRound.at(i)->v * sin(SRound.at(i)->angle) / vxi), 2 * PI);
						else
							anglei = PI + atan(SRound.at(i)->v * sin(SRound.at(i)->angle) / vxi);
					}

					if (vxj == 0 && SRound.at(j)->v * sin(SRound.at(j)->angle) != 0)
					{
						if (SRound.at(j)->v * sin(SRound.at(j)->angle) > 0)
							anglej = PI / 2.0;
						else
							anglej = 3 * PI / 2.0;
					}
					else if (vxj != 0 && SRound.at(j)->v * sin(SRound.at(j)->angle) == 0)
					{
						if (vxj > 0)
							anglej = 0.0;
						else
							anglej = PI;
					}
					else if (vxj != 0 && SRound.at(j)->v * sin(SRound.at(j)->angle) != 0)
					{
						if (vxj > 0)
							anglej = GetModDecimals(2 * PI + atan(SRound.at(j)->v * sin(SRound.at(j)->angle) / vxj), 2 * PI);
						else
							anglej = PI + atan(SRound.at(j)->v * sin(SRound.at(j)->angle) / vxj);
					}

					SRound.at(i)->v = sqrt(pow(vxi, 2) + pow(SRound.at(i)->v * sin(SRound.at(i)->angle), 2));
					SRound.at(j)->v = sqrt(pow(vxj, 2) + pow(SRound.at(j)->v * sin(SRound.at(j)->angle), 2));
					SRound.at(i)->angle = GetModDecimals(anglei + rotation, 2 * PI);
					SRound.at(j)->angle = GetModDecimals(anglej + rotation, 2 * PI);
				}
			}
		}

		if (SRound.at(i)->Position.x < SRound.at(i)->r || SRound.at(i)->Position.x > clientx - SRound.at(i)->r)
		{
			SRound.at(i)->angle = GetModDecimals(3 * PI - SRound.at(i)->angle, 2 * PI);
		}
		if (SRound.at(i)->Position.y < SRound.at(i)->r || SRound.at(i)->Position.y > clienty - SRound.at(i)->r)
		{
			SRound.at(i)->angle = 2 * PI - SRound.at(i)->angle;
		}

		SRound.at(i)->Position.x += SRound.at(i)->v * cos(SRound.at(i)->angle);
		SRound.at(i)->Position.y += SRound.at(i)->v * sin(SRound.at(i)->angle);

		SSprite->Draw(SRound.at(i)->RoundTextture, nullptr, &D3DXVECTOR3(SRound.at(i)->ImageInformation.Width / 2.0f,
			SRound.at(i)->ImageInformation.Height / 2.0f, 0.0f), &D3DXVECTOR3(SRound.at(i)->Position.x,
				SRound.at(i)->Position.y, 0.0), 0xffffffff);//D3DCOLOR_XRGB(0, 0, 0)
	}

	SSprite->End();
	SDevice->EndScene();

	SDevice->Present(nullptr, nullptr, 0, nullptr);
}

void OnDestroy()
{
	SRound.clear();
	SSprite->Release();
	SDevice->Release();
	SD3D->Release();
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_SIZE:
	{
		LONG_PTR Style = GetWindowLongPtr(ShWnd, GWL_STYLE);  
		Style &= ~WS_CAPTION & ~WS_SYSMENU & ~WS_SIZEBOX | WS_EX_TOOLWINDOW;
		SetWindowLongPtr(ShWnd, GWL_STYLE, Style);

		DWORD exStyle = GetWindowLong(ShWnd, GWL_EXSTYLE);
		exStyle |= WS_EX_LAYERED;
		SetWindowLong(ShWnd, GWL_EXSTYLE, exStyle);
		SetLayeredWindowAttributes(ShWnd, RGB(100, 100, 100), 99, LWA_ALPHA | LWA_COLORKEY);
		break;
	}
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd)
{
	WNDCLASS wc;
	ZeroMemory(&wc, sizeof(WNDCLASS));
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = NULL;
	wc.cbWndExtra = NULL;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(0, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = TEXT("ii");
	RegisterClass(&wc);

	sShWnd = CreateWindow(wc.lpszClassName, TEXT("iii"), WS_EX_TOOLWINDOW, 0, 0, WINDOWS_WIDTH, WINDOWS_HEIGHT, NULL, NULL, hInstance, NULL);
	if (!sShWnd)
		return 0;

	ShWnd = CreateWindow(wc.lpszClassName, TEXT("iiii"), WS_OVERLAPPEDWINDOW, 0, 0, WINDOWS_WIDTH, WINDOWS_HEIGHT, sShWnd, NULL, hInstance, NULL);
	SetWindowPos(ShWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE);  //设置窗口最顶层

	srand(timeGetTime());

	if (ShWnd)
	{
		if (OnInit())
		{
			ShowWindow(ShWnd, SW_NORMAL);
			UpdateWindow(ShWnd);
		}
		else
		{
			MessageBox(NULL, "错误", "初始化失败!", MB_ICONINFORMATION | MB_OK);
			return 0;
		}
	}

	MSG msg;
	GetMessage(&msg, NULL, NULL, NULL);
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			tPresent = timeGetTime();
			if (tPresent - tPrevious > 10)
			{
				OnRender();
				tPrevious = tPresent;
			}
		}
		Sleep(0);
	}

	OnDestroy();
	UnregisterClass(wc.lpszClassName, hInstance);
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值