refactoring
This commit is contained in:
		
							parent
							
								
									09a3850135
								
							
						
					
					
						commit
						83986230a1
					
				|  | @ -41,10 +41,6 @@ e2d::GC::~GC() | |||
| 	Image::clearCache(); | ||||
| 
 | ||||
| 	// 删除所有单例
 | ||||
| 	Game::destroyInstance(); | ||||
| 	Renderer::destroyInstance(); | ||||
| 	Input::destroyInstance(); | ||||
| 	Window::destroyInstance(); | ||||
| 	Timer::destroyInstance(); | ||||
| 	SceneManager::destroyInstance(); | ||||
| 	ActionManager::destroyInstance(); | ||||
|  |  | |||
|  | @ -4,35 +4,38 @@ | |||
| #include <thread> | ||||
| 
 | ||||
| 
 | ||||
| e2d::Game * e2d::Game::_instance = nullptr; | ||||
| 
 | ||||
| e2d::Game::Game() | ||||
| 	: _quit(true) | ||||
| 	, _paused(false) | ||||
| 	, _config() | ||||
| 	, _window(nullptr) | ||||
| 	, _input(nullptr) | ||||
| 	, _renderer(nullptr) | ||||
| { | ||||
| 	CoInitialize(nullptr); | ||||
| 
 | ||||
| 	_input = new (std::nothrow) Input; | ||||
| 	_renderer = new (std::nothrow) Renderer; | ||||
| } | ||||
| 
 | ||||
| e2d::Game::~Game() | ||||
| { | ||||
| 	if (_renderer) | ||||
| 		delete _renderer; | ||||
| 
 | ||||
| 	if (_input) | ||||
| 		delete _input; | ||||
| 
 | ||||
| 	if (_window) | ||||
| 		delete _window; | ||||
| 
 | ||||
| 	CoUninitialize(); | ||||
| } | ||||
| 
 | ||||
| e2d::Game * e2d::Game::getInstance() | ||||
| { | ||||
| 	if (!_instance) | ||||
| 		_instance = new (std::nothrow) Game; | ||||
| 	return _instance; | ||||
| } | ||||
| 
 | ||||
| void e2d::Game::destroyInstance() | ||||
| { | ||||
| 	if (_instance) | ||||
| 	{ | ||||
| 		delete _instance; | ||||
| 		_instance = nullptr; | ||||
| 	} | ||||
| 	static Game instance; | ||||
| 	return &instance; | ||||
| } | ||||
| 
 | ||||
| void e2d::Game::start() | ||||
|  | @ -41,11 +44,11 @@ void e2d::Game::start() | |||
| 
 | ||||
| 	const int minInterval = 5; | ||||
| 	Time last = Time::now(); | ||||
| 	HWND hWnd = Window::getInstance()->getHWnd(); | ||||
| 	HWND hWnd = _window->getHWnd(); | ||||
| 	 | ||||
| 	::ShowWindow(hWnd, SW_SHOWNORMAL); | ||||
| 	::UpdateWindow(hWnd); | ||||
| 	Window::getInstance()->poll(); | ||||
| 	_window->poll(); | ||||
| 	SceneManager::getInstance()->update(); | ||||
| 	 | ||||
| 	while (!_quit) | ||||
|  | @ -56,12 +59,12 @@ void e2d::Game::start() | |||
| 		if (dur.milliseconds() > minInterval) | ||||
| 		{ | ||||
| 			last = now; | ||||
| 			Input::getInstance()->update(); | ||||
| 			_input->update(); | ||||
| 			Timer::getInstance()->update(); | ||||
| 			ActionManager::getInstance()->update(); | ||||
| 			SceneManager::getInstance()->update(); | ||||
| 			Renderer::getInstance()->render(); | ||||
| 			Window::getInstance()->poll(); | ||||
| 			_renderer->render(); | ||||
| 			_window->poll(); | ||||
| 			GC::getInstance()->flush(); | ||||
| 		} | ||||
| 		else | ||||
|  | @ -103,11 +106,18 @@ void e2d::Game::setConfig(const Config& config) | |||
| 	_config = config; | ||||
| } | ||||
| 
 | ||||
| const e2d::Config& e2d::Game::getConfig() | ||||
| const e2d::Config& e2d::Game::getConfig() const | ||||
| { | ||||
| 	return _config; | ||||
| } | ||||
| 
 | ||||
| void e2d::Game::setWindow(Window * window) | ||||
| { | ||||
| 	_window = window; | ||||
| 	_renderer->init(_window); | ||||
| 	_input->init(_window); | ||||
| } | ||||
| 
 | ||||
| void e2d::Game::quit() | ||||
| { | ||||
| 	_quit = true; | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ | |||
| #include "..\e2dmanager.h" | ||||
| #pragma comment(lib, "dinput8.lib") | ||||
| 
 | ||||
| e2d::Input * e2d::Input::_instance = nullptr; | ||||
| 
 | ||||
| e2d::Input::Input() | ||||
| 	: _directInput(false) | ||||
|  | @ -23,52 +22,6 @@ e2d::Input::Input() | |||
| 		(void**)&_directInput, | ||||
| 		nullptr | ||||
| 	); | ||||
| 
 | ||||
| 	auto window = Window::getInstance(); | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 		// 初始化键盘设备
 | ||||
| 		hr = _directInput->CreateDevice( | ||||
| 			GUID_SysKeyboard, | ||||
| 			&_keyboardDevice, | ||||
| 			nullptr | ||||
| 		); | ||||
| 
 | ||||
| 		if (SUCCEEDED(hr)) | ||||
| 		{ | ||||
| 			_keyboardDevice->SetCooperativeLevel( | ||||
| 				window->getHWnd(), | ||||
| 				DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | ||||
| 			); | ||||
| 			_keyboardDevice->SetDataFormat( | ||||
| 				&c_dfDIKeyboard); | ||||
| 			_keyboardDevice->Acquire(); | ||||
| 			_keyboardDevice->Poll(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			throw SystemException(L"Keyboard not found!"); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 		// 初始化鼠标设备
 | ||||
| 		hr = _directInput->CreateDevice(GUID_SysMouse, &_mouseDevice, nullptr); | ||||
| 
 | ||||
| 		if (SUCCEEDED(hr)) | ||||
| 		{ | ||||
| 			_mouseDevice->SetCooperativeLevel(window->getHWnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); | ||||
| 			_mouseDevice->SetDataFormat(&c_dfDIMouse); | ||||
| 			_mouseDevice->Acquire(); | ||||
| 			_mouseDevice->Poll(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			throw SystemException(L"Mouse not found!"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| e2d::Input::~Input() | ||||
|  | @ -85,20 +38,37 @@ e2d::Input::~Input() | |||
| 	CoUninitialize(); | ||||
| } | ||||
| 
 | ||||
| e2d::Input * e2d::Input::getInstance() | ||||
| void e2d::Input::init(Window * window) | ||||
| { | ||||
| 	if (!_instance) | ||||
| 		_instance = new (std::nothrow) Input; | ||||
| 	return _instance; | ||||
| } | ||||
| 	HWND hwnd = window->getHWnd(); | ||||
| 
 | ||||
| void e2d::Input::destroyInstance() | ||||
| { | ||||
| 	if (_instance) | ||||
| 	{ | ||||
| 		delete _instance; | ||||
| 		_instance = nullptr; | ||||
| 	} | ||||
| 	// 初始化键盘设备
 | ||||
| 	ThrowIfFailed( | ||||
| 		_directInput->CreateDevice( | ||||
| 			GUID_SysKeyboard, | ||||
| 			&_keyboardDevice, | ||||
| 			nullptr | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	_keyboardDevice->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); | ||||
| 	_keyboardDevice->SetDataFormat(&c_dfDIKeyboard); | ||||
| 	_keyboardDevice->Acquire(); | ||||
| 	_keyboardDevice->Poll(); | ||||
| 
 | ||||
| 	// 初始化鼠标设备
 | ||||
| 	ThrowIfFailed( | ||||
| 		_directInput->CreateDevice( | ||||
| 			GUID_SysMouse, | ||||
| 			&_mouseDevice, | ||||
| 			nullptr | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	_mouseDevice->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); | ||||
| 	_mouseDevice->SetDataFormat(&c_dfDIMouse); | ||||
| 	_mouseDevice->Acquire(); | ||||
| 	_mouseDevice->Poll(); | ||||
| } | ||||
| 
 | ||||
| void e2d::Input::update() | ||||
|  | @ -160,7 +130,7 @@ float e2d::Input::getMouseY() | |||
| 
 | ||||
| e2d::Point e2d::Input::getMousePos() | ||||
| { | ||||
| 	auto window = Window::getInstance(); | ||||
| 	auto window = Game::getInstance()->getWindow(); | ||||
| 
 | ||||
| 	POINT mousePos; | ||||
| 	::GetCursorPos(&mousePos); | ||||
|  |  | |||
|  | @ -3,39 +3,6 @@ | |||
| #include "..\e2dnode.h" | ||||
| 
 | ||||
| 
 | ||||
| e2d::Renderer*		e2d::Renderer::_instance = nullptr; | ||||
| ID2D1Factory*		e2d::Renderer::_d2dFactory = nullptr; | ||||
| IWICImagingFactory*	e2d::Renderer::_imagingFactory = nullptr; | ||||
| IDWriteFactory*		e2d::Renderer::_writeFactory = nullptr; | ||||
| ID2D1StrokeStyle*	e2d::Renderer::_miterStrokeStyle = nullptr; | ||||
| ID2D1StrokeStyle*	e2d::Renderer::_bevelStrokeStyle = nullptr; | ||||
| ID2D1StrokeStyle*	e2d::Renderer::_roundStrokeStyle = nullptr; | ||||
| 
 | ||||
| e2d::Renderer * e2d::Renderer::getInstance() | ||||
| { | ||||
| 	if (!_instance) | ||||
| 	{ | ||||
| 		_instance = new (std::nothrow) Renderer; | ||||
| 	} | ||||
| 	return _instance; | ||||
| } | ||||
| 
 | ||||
| void e2d::Renderer::destroyInstance() | ||||
| { | ||||
| 	if (_instance) | ||||
| 	{ | ||||
| 		delete _instance; | ||||
| 		_instance = nullptr; | ||||
| 
 | ||||
| 		SafeRelease(_miterStrokeStyle); | ||||
| 		SafeRelease(_bevelStrokeStyle); | ||||
| 		SafeRelease(_roundStrokeStyle); | ||||
| 		SafeRelease(_d2dFactory); | ||||
| 		SafeRelease(_imagingFactory); | ||||
| 		SafeRelease(_writeFactory); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| e2d::Renderer::Renderer() | ||||
| 	: _lastRenderTime(Time::now()) | ||||
| 	, _renderTimes(0) | ||||
|  | @ -44,9 +11,40 @@ e2d::Renderer::Renderer() | |||
| 	, _renderTarget(nullptr) | ||||
| 	, _solidBrush(nullptr) | ||||
| 	, _textRenderer(nullptr) | ||||
| 	, _factory(nullptr) | ||||
| 	, _imagingFactory(nullptr) | ||||
| 	, _writeFactory(nullptr) | ||||
| 	, _miterStrokeStyle(nullptr) | ||||
| 	, _bevelStrokeStyle(nullptr) | ||||
| 	, _roundStrokeStyle(nullptr) | ||||
| 	, _clearColor(D2D1::ColorF(D2D1::ColorF::Black)) | ||||
| { | ||||
| 	CoInitialize(nullptr); | ||||
| 
 | ||||
| 	ThrowIfFailed( | ||||
| 		D2D1CreateFactory( | ||||
| 			D2D1_FACTORY_TYPE_SINGLE_THREADED, | ||||
| 			&_factory | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	ThrowIfFailed( | ||||
| 		CoCreateInstance( | ||||
| 			CLSID_WICImagingFactory, | ||||
| 			nullptr, | ||||
| 			CLSCTX_INPROC_SERVER, | ||||
| 			IID_IWICImagingFactory, | ||||
| 			reinterpret_cast<void**>(&_imagingFactory) | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	ThrowIfFailed( | ||||
| 		DWriteCreateFactory( | ||||
| 			DWRITE_FACTORY_TYPE_SHARED, | ||||
| 			__uuidof(IDWriteFactory), | ||||
| 			reinterpret_cast<IUnknown**>(&_writeFactory) | ||||
| 		) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| e2d::Renderer::~Renderer() | ||||
|  | @ -57,27 +55,69 @@ e2d::Renderer::~Renderer() | |||
| 	SafeRelease(_solidBrush); | ||||
| 	SafeRelease(_renderTarget); | ||||
| 
 | ||||
| 	SafeRelease(_miterStrokeStyle); | ||||
| 	SafeRelease(_bevelStrokeStyle); | ||||
| 	SafeRelease(_roundStrokeStyle); | ||||
| 	SafeRelease(_factory); | ||||
| 	SafeRelease(_imagingFactory); | ||||
| 	SafeRelease(_writeFactory); | ||||
| 
 | ||||
| 	CoUninitialize(); | ||||
| } | ||||
| 
 | ||||
| void e2d::Renderer::discardDeviceResources() | ||||
| void e2d::Renderer::init(Window * window) | ||||
| { | ||||
| 	SafeRelease(_renderTarget); | ||||
| 	SafeRelease(_solidBrush); | ||||
| 	SafeRelease(_textRenderer); | ||||
| 	if (!window) | ||||
| 		return; | ||||
| 
 | ||||
| 	HWND hWnd = window->getHWnd(); | ||||
| 
 | ||||
| 	RECT rc; | ||||
| 	GetClientRect(hWnd, &rc); | ||||
| 
 | ||||
| 	D2D1_SIZE_U size = D2D1::SizeU( | ||||
| 		rc.right - rc.left, | ||||
| 		rc.bottom - rc.top | ||||
| 	); | ||||
| 
 | ||||
| 	// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
 | ||||
| 	// 创建一个 Direct2D 渲染目标
 | ||||
| 	ThrowIfFailed( | ||||
| 		_factory->CreateHwndRenderTarget( | ||||
| 			D2D1::RenderTargetProperties(), | ||||
| 			D2D1::HwndRenderTargetProperties( | ||||
| 				hWnd, | ||||
| 				size, | ||||
| 				D2D1_PRESENT_OPTIONS_NONE), | ||||
| 			&_renderTarget | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	// 创建画刷
 | ||||
| 	ThrowIfFailed( | ||||
| 		_renderTarget->CreateSolidColorBrush( | ||||
| 			D2D1::ColorF(D2D1::ColorF::White), | ||||
| 			&_solidBrush | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	// 创建自定义的文字渲染器
 | ||||
| 	ThrowIfFailed( | ||||
| 		TextRenderer::Create( | ||||
| 			&_textRenderer, | ||||
| 			_factory, | ||||
| 			_renderTarget, | ||||
| 			_solidBrush | ||||
| 		) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| void e2d::Renderer::render() | ||||
| { | ||||
| 	auto renderTarget = this->getRenderTarget(); | ||||
| 	// 仅当窗口没有被遮挡时进行渲染
 | ||||
| 	if (renderTarget->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED) | ||||
| 		return; | ||||
| 
 | ||||
| 	// 开始渲染
 | ||||
| 	renderTarget->BeginDraw(); | ||||
| 	_renderTarget->BeginDraw(); | ||||
| 	// 使用背景色清空屏幕
 | ||||
| 	renderTarget->Clear(_clearColor); | ||||
| 	_renderTarget->Clear(_clearColor); | ||||
| 
 | ||||
| 	// 渲染场景
 | ||||
| 	SceneManager::getInstance()->render(); | ||||
|  | @ -89,19 +129,24 @@ void e2d::Renderer::render() | |||
| 	} | ||||
| 
 | ||||
| 	// 终止渲染
 | ||||
| 	HRESULT hr = renderTarget->EndDraw(); | ||||
| 	HRESULT hr = _renderTarget->EndDraw(); | ||||
| 
 | ||||
| 	if (hr == D2DERR_RECREATE_TARGET) | ||||
| 	{ | ||||
| 		// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
 | ||||
| 		// 并在下一次调用时重建资源
 | ||||
| 		hr = S_OK; | ||||
| 		this->discardDeviceResources(); | ||||
| 
 | ||||
| 		SafeRelease(_fpsFormat); | ||||
| 		SafeRelease(_fpsLayout); | ||||
| 		SafeRelease(_textRenderer); | ||||
| 		SafeRelease(_solidBrush); | ||||
| 		SafeRelease(_renderTarget); | ||||
| 	} | ||||
| 
 | ||||
| 	if (FAILED(hr)) | ||||
| 	{ | ||||
| 		throw SystemException(L"Device loss recovery failed"); | ||||
| 		throw SystemException("Device loss recovery failed"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -116,10 +161,10 @@ void e2d::Renderer::_renderFps() | |||
| 		_lastRenderTime = Time::now(); | ||||
| 		_renderTimes	= 0; | ||||
| 
 | ||||
| 		auto writeFactory = Renderer::getWriteFactory(); | ||||
| 		if (!_fpsFormat) | ||||
| 		{ | ||||
| 			HRESULT hr = writeFactory->CreateTextFormat( | ||||
| 			ThrowIfFailed( | ||||
| 				_writeFactory->CreateTextFormat( | ||||
| 					L"", | ||||
| 					nullptr, | ||||
| 					DWRITE_FONT_WEIGHT_NORMAL, | ||||
|  | @ -128,36 +173,33 @@ void e2d::Renderer::_renderFps() | |||
| 					20, | ||||
| 					L"", | ||||
| 					&_fpsFormat | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				_fpsFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); | ||||
| 			} | ||||
| 			ThrowIfFailed( | ||||
| 				_fpsFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP) | ||||
| 			); | ||||
| 		} | ||||
| 
 | ||||
| 		SafeRelease(_fpsLayout); | ||||
| 
 | ||||
| 		if (_fpsFormat) | ||||
| 		{ | ||||
| 			writeFactory->CreateTextLayout( | ||||
| 		ThrowIfFailed( | ||||
| 			_writeFactory->CreateTextLayout( | ||||
| 				(const WCHAR *)fpsText, | ||||
| 				(UINT32)fpsText.getLength(), | ||||
| 				_fpsFormat, | ||||
| 				0, | ||||
| 				0, | ||||
| 				&_fpsLayout | ||||
| 			) | ||||
| 		); | ||||
| 	} | ||||
| 	} | ||||
| 
 | ||||
| 	if (_fpsLayout) | ||||
| 	{ | ||||
| 		this->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		this->getSolidColorBrush()->SetOpacity(1.0f); | ||||
| 
 | ||||
| 		auto textRenderer = this->getTextRenderer(); | ||||
| 		textRenderer->SetTextStyle( | ||||
| 		_renderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		_solidBrush->SetOpacity(1.0f); | ||||
| 		_textRenderer->SetTextStyle( | ||||
| 			D2D1::ColorF(D2D1::ColorF::White), | ||||
| 			TRUE, | ||||
| 			D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | ||||
|  | @ -165,7 +207,9 @@ void e2d::Renderer::_renderFps() | |||
| 			D2D1_LINE_JOIN_ROUND | ||||
| 		); | ||||
| 
 | ||||
| 		_fpsLayout->Draw(nullptr, textRenderer, 10, 0); | ||||
| 		ThrowIfFailed( | ||||
| 			_fpsLayout->Draw(nullptr, _textRenderer, 10, 0) | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -179,139 +223,12 @@ void e2d::Renderer::setBackgroundColor(Color color) | |||
| 	_clearColor = (D2D1_COLOR_F)color; | ||||
| } | ||||
| 
 | ||||
| ID2D1HwndRenderTarget * e2d::Renderer::getRenderTarget() | ||||
| { | ||||
| 	if (!_renderTarget) | ||||
| 	{ | ||||
| 		HWND hWnd = Window::getInstance()->getHWnd(); | ||||
| 
 | ||||
| 		// 创建设备相关资源。这些资源应在 Direct3D 设备消失时重建
 | ||||
| 		RECT rc; | ||||
| 		GetClientRect(hWnd, &rc); | ||||
| 
 | ||||
| 		D2D1_SIZE_U size = D2D1::SizeU( | ||||
| 			rc.right - rc.left, | ||||
| 			rc.bottom - rc.top | ||||
| 		); | ||||
| 
 | ||||
| 		// 创建一个 Direct2D 渲染目标
 | ||||
| 		HRESULT hr = Renderer::getFactory()->CreateHwndRenderTarget( | ||||
| 			D2D1::RenderTargetProperties(), | ||||
| 			D2D1::HwndRenderTargetProperties( | ||||
| 				hWnd, | ||||
| 				size, | ||||
| 				D2D1_PRESENT_OPTIONS_NONE), | ||||
| 			&_renderTarget | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create ID2D1HwndRenderTarget failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _renderTarget; | ||||
| } | ||||
| 
 | ||||
| ID2D1SolidColorBrush * e2d::Renderer::getSolidColorBrush() | ||||
| { | ||||
| 	if (!_solidBrush) | ||||
| 	{ | ||||
| 		// 创建画刷
 | ||||
| 		HRESULT hr = this->getRenderTarget()->CreateSolidColorBrush( | ||||
| 			D2D1::ColorF(D2D1::ColorF::White), | ||||
| 			&_solidBrush | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create ID2D1SolidColorBrush failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _solidBrush; | ||||
| } | ||||
| 
 | ||||
| e2d::TextRenderer * e2d::Renderer::getTextRenderer() | ||||
| { | ||||
| 	if (!_textRenderer) | ||||
| 	{ | ||||
| 		// 创建自定义的文字渲染器
 | ||||
| 		HRESULT hr = TextRenderer::Create( | ||||
| 			&_textRenderer, | ||||
| 			Renderer::getFactory(), | ||||
| 			this->getRenderTarget(), | ||||
| 			this->getSolidColorBrush() | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create TextRenderer failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _textRenderer; | ||||
| } | ||||
| 
 | ||||
| ID2D1Factory * e2d::Renderer::getFactory() | ||||
| { | ||||
| 	if (!_d2dFactory) | ||||
| 	{ | ||||
| 		HRESULT hr = D2D1CreateFactory( | ||||
| 			D2D1_FACTORY_TYPE_SINGLE_THREADED, | ||||
| 			&_d2dFactory | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create ID2D1Factory failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _d2dFactory; | ||||
| } | ||||
| 
 | ||||
| IWICImagingFactory * e2d::Renderer::getImagingFactory() | ||||
| { | ||||
| 	if (!_imagingFactory) | ||||
| 	{ | ||||
| 		// 创建 WIC 绘图工厂,用于统一处理各种格式的图片
 | ||||
| 		HRESULT hr = CoCreateInstance( | ||||
| 			CLSID_WICImagingFactory, | ||||
| 			nullptr, | ||||
| 			CLSCTX_INPROC_SERVER, | ||||
| 			IID_IWICImagingFactory, | ||||
| 			reinterpret_cast<void**>(&_imagingFactory) | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create IWICImagingFactory failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _imagingFactory; | ||||
| } | ||||
| 
 | ||||
| IDWriteFactory * e2d::Renderer::getWriteFactory() | ||||
| { | ||||
| 	if (!_writeFactory) | ||||
| 	{ | ||||
| 		// 创建 DirectWrite 工厂
 | ||||
| 		HRESULT hr = DWriteCreateFactory( | ||||
| 			DWRITE_FACTORY_TYPE_SHARED, | ||||
| 			__uuidof(IDWriteFactory), | ||||
| 			reinterpret_cast<IUnknown**>(&_writeFactory) | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create IDWriteFactory failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _writeFactory; | ||||
| } | ||||
| 
 | ||||
| ID2D1StrokeStyle * e2d::Renderer::getMiterStrokeStyle() | ||||
| { | ||||
| 	if (!_miterStrokeStyle) | ||||
| 	{ | ||||
| 		HRESULT hr = Renderer::getFactory()->CreateStrokeStyle( | ||||
| 		ThrowIfFailed( | ||||
| 			_factory->CreateStrokeStyle( | ||||
| 				D2D1::StrokeStyleProperties( | ||||
| 					D2D1_CAP_STYLE_FLAT, | ||||
| 					D2D1_CAP_STYLE_FLAT, | ||||
|  | @ -323,12 +240,8 @@ ID2D1StrokeStyle * e2d::Renderer::getMiterStrokeStyle() | |||
| 				nullptr, | ||||
| 				0, | ||||
| 				&_miterStrokeStyle | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create ID2D1StrokeStyle failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _miterStrokeStyle; | ||||
| } | ||||
|  | @ -337,7 +250,8 @@ ID2D1StrokeStyle * e2d::Renderer::getBevelStrokeStyle() | |||
| { | ||||
| 	if (!_bevelStrokeStyle) | ||||
| 	{ | ||||
| 		HRESULT hr = Renderer::getFactory()->CreateStrokeStyle( | ||||
| 		ThrowIfFailed( | ||||
| 			_factory->CreateStrokeStyle( | ||||
| 				D2D1::StrokeStyleProperties( | ||||
| 					D2D1_CAP_STYLE_FLAT, | ||||
| 					D2D1_CAP_STYLE_FLAT, | ||||
|  | @ -349,12 +263,8 @@ ID2D1StrokeStyle * e2d::Renderer::getBevelStrokeStyle() | |||
| 				nullptr, | ||||
| 				0, | ||||
| 				&_bevelStrokeStyle | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create ID2D1StrokeStyle failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _bevelStrokeStyle; | ||||
| } | ||||
|  | @ -363,7 +273,8 @@ ID2D1StrokeStyle * e2d::Renderer::getRoundStrokeStyle() | |||
| { | ||||
| 	if (!_roundStrokeStyle) | ||||
| 	{ | ||||
| 		HRESULT hr = Renderer::getFactory()->CreateStrokeStyle( | ||||
| 		ThrowIfFailed( | ||||
| 			_factory->CreateStrokeStyle( | ||||
| 				D2D1::StrokeStyleProperties( | ||||
| 					D2D1_CAP_STYLE_FLAT, | ||||
| 					D2D1_CAP_STYLE_FLAT, | ||||
|  | @ -375,12 +286,8 @@ ID2D1StrokeStyle * e2d::Renderer::getRoundStrokeStyle() | |||
| 				nullptr, | ||||
| 				0, | ||||
| 				&_roundStrokeStyle | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			throw SystemException(L"Create ID2D1StrokeStyle failed"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _roundStrokeStyle; | ||||
| } | ||||
|  |  | |||
|  | @ -8,46 +8,95 @@ | |||
| #define REGISTER_CLASS	L"Easy2DApp" | ||||
| 
 | ||||
| 
 | ||||
| e2d::Window * e2d::Window::_instance = nullptr; | ||||
| 
 | ||||
| e2d::Window::Window() | ||||
| e2d::Window::Window(const String & title, int width, int height, int iconID) | ||||
| 	: _hWnd(nullptr) | ||||
| 	, _size(640, 480) | ||||
| 	, _title(L"Easy2D Game") | ||||
| 	, _iconID(0) | ||||
| 	, _width(width) | ||||
| 	, _height(height) | ||||
| 	, _title(title) | ||||
| 	, _iconID(iconID) | ||||
| 	, _dpi(0.f) | ||||
| { | ||||
| 	CoInitialize(nullptr); | ||||
| 
 | ||||
| 	WNDCLASSEX wcex = { 0 }; | ||||
| 	wcex.cbSize = sizeof(WNDCLASSEX); | ||||
| 	wcex.lpszClassName = REGISTER_CLASS; | ||||
| 	wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; | ||||
| 	wcex.lpfnWndProc = Window::WndProc; | ||||
| 	wcex.hIcon = nullptr; | ||||
| 	wcex.cbClsExtra = 0; | ||||
| 	wcex.cbWndExtra = sizeof(LONG_PTR); | ||||
| 	wcex.hInstance = HINST_THISCOMPONENT; | ||||
| 	wcex.hbrBackground = nullptr; | ||||
| 	wcex.lpszMenuName = nullptr; | ||||
| 	wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW); | ||||
| 
 | ||||
| 	if (_iconID != 0) | ||||
| 	{ | ||||
| 		wcex.hIcon = (HICON)::LoadImage( | ||||
| 			HINST_THISCOMPONENT, | ||||
| 			MAKEINTRESOURCE(_iconID), | ||||
| 			IMAGE_ICON, | ||||
| 			0, | ||||
| 			0, | ||||
| 			LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	// 注册窗口类
 | ||||
| 	RegisterClassEx(&wcex); | ||||
| 
 | ||||
| 	// 计算窗口大小
 | ||||
| 	Rect clientRect = __adjustWindow(_width, _height); | ||||
| 
 | ||||
| 	// 创建窗口
 | ||||
| 	HWND hWnd = ::CreateWindowEx( | ||||
| 		NULL, | ||||
| 		REGISTER_CLASS, | ||||
| 		(LPCTSTR)_title, | ||||
| 		WINDOW_STYLE, | ||||
| 		int(clientRect.origin.x), | ||||
| 		int(clientRect.origin.y), | ||||
| 		int(clientRect.size.width), | ||||
| 		int(clientRect.size.height), | ||||
| 		nullptr, | ||||
| 		nullptr, | ||||
| 		HINST_THISCOMPONENT, | ||||
| 		this | ||||
| 	); | ||||
| 
 | ||||
| 	if (hWnd) | ||||
| 	{ | ||||
| 		// 禁用输入法
 | ||||
| 		setTypewritingEnabled(false); | ||||
| 		// 禁用控制台关闭按钮
 | ||||
| 		HWND consoleHWnd = ::GetConsoleWindow(); | ||||
| 		if (consoleHWnd) | ||||
| 		{ | ||||
| 			HMENU hmenu = ::GetSystemMenu(consoleHWnd, FALSE); | ||||
| 			::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); | ||||
| 		} | ||||
| 		// 获取 DPI
 | ||||
| 		_dpi = static_cast<float>(::GetDpiForWindow(hWnd)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT); | ||||
| 		throw SystemException("Create window failed"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| e2d::Window::~Window() | ||||
| { | ||||
| 	// 关闭控制台
 | ||||
| 	if (::GetConsoleWindow()) | ||||
| 	{ | ||||
| 		::FreeConsole(); | ||||
| 	} | ||||
| 
 | ||||
| 	// 关闭窗口
 | ||||
| 	if (_hWnd) | ||||
| 	{ | ||||
| 		::DestroyWindow(_hWnd); | ||||
| 		_hWnd = nullptr; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| e2d::Window * e2d::Window::getInstance() | ||||
| { | ||||
| 	if (!_instance) | ||||
| 		_instance = new (std::nothrow) Window; | ||||
| 	return _instance; | ||||
| } | ||||
| 
 | ||||
| void e2d::Window::destroyInstance() | ||||
| { | ||||
| 	if (_instance) | ||||
| 	{ | ||||
| 		delete _instance; | ||||
| 		_instance = nullptr; | ||||
| 	} | ||||
| 	CoUninitialize(); | ||||
| } | ||||
| 
 | ||||
| bool e2d::Window::createMutex(const String & mutex) | ||||
|  | @ -87,80 +136,11 @@ bool e2d::Window::createMutex(const String & mutex) | |||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| HWND e2d::Window::__registerWindow() | ||||
| { | ||||
| 	WNDCLASSEX wcex = { 0 }; | ||||
| 	wcex.cbSize			= sizeof(WNDCLASSEX); | ||||
| 	wcex.lpszClassName	= REGISTER_CLASS; | ||||
| 	wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; | ||||
| 	wcex.lpfnWndProc	= Window::WndProc; | ||||
| 	wcex.hIcon			= nullptr; | ||||
| 	wcex.cbClsExtra		= 0; | ||||
| 	wcex.cbWndExtra		= sizeof(LONG_PTR); | ||||
| 	wcex.hInstance		= HINST_THISCOMPONENT; | ||||
| 	wcex.hbrBackground	= nullptr; | ||||
| 	wcex.lpszMenuName	= nullptr; | ||||
| 	wcex.hCursor		= ::LoadCursor(nullptr, IDC_ARROW); | ||||
| 
 | ||||
| 	if (_iconID != 0) | ||||
| 	{ | ||||
| 		wcex.hIcon = (HICON)::LoadImage( | ||||
| 			HINST_THISCOMPONENT, | ||||
| 			MAKEINTRESOURCE(_iconID), | ||||
| 			IMAGE_ICON, | ||||
| 			0, | ||||
| 			0, | ||||
| 			LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	// 注册窗口类
 | ||||
| 	RegisterClassEx(&wcex); | ||||
| 
 | ||||
| 	// 计算窗口大小
 | ||||
| 	Rect wRect = __adjustWindow(int(_size.width), int(_size.height)); | ||||
| 
 | ||||
| 	// 创建窗口
 | ||||
| 	HWND hWnd = ::CreateWindowEx( | ||||
| 		NULL, | ||||
| 		REGISTER_CLASS, | ||||
| 		(LPCTSTR)_title, | ||||
| 		WINDOW_STYLE, | ||||
| 		int(wRect.origin.x), | ||||
| 		int(wRect.origin.y), | ||||
| 		int(wRect.size.width), | ||||
| 		int(wRect.size.height), | ||||
| 		nullptr, | ||||
| 		nullptr, | ||||
| 		HINST_THISCOMPONENT, | ||||
| 		nullptr | ||||
| 	); | ||||
| 
 | ||||
| 	if (hWnd) | ||||
| 	{ | ||||
| 		// 禁用输入法
 | ||||
| 		setTypewritingEnabled(false); | ||||
| 		// 禁用控制台关闭按钮
 | ||||
| 		HWND consoleHWnd = ::GetConsoleWindow(); | ||||
| 		if (consoleHWnd) | ||||
| 		{ | ||||
| 			HMENU hmenu = ::GetSystemMenu(consoleHWnd, FALSE); | ||||
| 			::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); | ||||
| 		} | ||||
| 		// 获取 DPI
 | ||||
| 		_dpi = static_cast<float>(::GetDpiForWindow(hWnd)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT); | ||||
| 	} | ||||
| 	return hWnd; | ||||
| } | ||||
| 
 | ||||
| e2d::Rect e2d::Window::__adjustWindow(int width, int height) | ||||
| { | ||||
| 	float dpiScaleX = 0.f, dpiScaleY = 0.f; | ||||
| 	Renderer::getFactory()->GetDesktopDpi(&dpiScaleX, &dpiScaleY); | ||||
| 	auto renderer = Game::getInstance()->getRenderer(); | ||||
| 	renderer->getFactory()->GetDesktopDpi(&dpiScaleX, &dpiScaleY); | ||||
| 
 | ||||
| 	Rect result; | ||||
| 	RECT wRECT		= { 0, 0, LONG(ceil(width * dpiScaleX / 96.f)), LONG(ceil(height * dpiScaleY / 96.f)) }; | ||||
|  | @ -190,47 +170,44 @@ void e2d::Window::poll() | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| float e2d::Window::getWidth() | ||||
| int e2d::Window::getWidth() const | ||||
| { | ||||
| 	return _size.width; | ||||
| 	return _width; | ||||
| } | ||||
| 
 | ||||
| float e2d::Window::getHeight() | ||||
| int e2d::Window::getHeight() const | ||||
| { | ||||
| 	return _size.height; | ||||
| 	return _height; | ||||
| } | ||||
| 
 | ||||
| e2d::Size e2d::Window::getSize() | ||||
| e2d::Size e2d::Window::getSize() const | ||||
| { | ||||
| 	return _size; | ||||
| 	return Size(float(_width), float(_height)); | ||||
| } | ||||
| 
 | ||||
| float e2d::Window::getDpi() | ||||
| float e2d::Window::getDpi() const | ||||
| { | ||||
| 	return _dpi; | ||||
| } | ||||
| 
 | ||||
| e2d::String e2d::Window::getTitle() | ||||
| e2d::String e2d::Window::getTitle() const | ||||
| { | ||||
| 	return _title; | ||||
| } | ||||
| 
 | ||||
| HWND e2d::Window::getHWnd() | ||||
| HWND e2d::Window::getHWnd() const | ||||
| { | ||||
| 	if (!_hWnd) | ||||
| 	{ | ||||
| 		_hWnd = __registerWindow(); | ||||
| 		if (_hWnd == nullptr) | ||||
| 		{ | ||||
| 			throw SystemException(L"注册窗口失败"); | ||||
| 		} | ||||
| 	} | ||||
| 	return _hWnd; | ||||
| } | ||||
| 
 | ||||
| void e2d::Window::setSize(int width, int height) | ||||
| { | ||||
| 	_size = Size(static_cast<float>(width), static_cast<float>(height)); | ||||
| 	if (_width == width && _height == height) | ||||
| 		return; | ||||
| 
 | ||||
| 	_width = width; | ||||
| 	_height = height; | ||||
| 
 | ||||
| 	if (_hWnd) | ||||
| 	{ | ||||
| 		Rect wRect = __adjustWindow(width, height); | ||||
|  | @ -390,12 +367,33 @@ bool e2d::Window::popup(const String & text, const String & title, Popup style, | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||
| LRESULT e2d::Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | ||||
| { | ||||
| 	LRESULT result = 0; | ||||
| 	bool hasHandled = false; | ||||
| 
 | ||||
| 	switch (message) | ||||
| 	if (uMsg == WM_CREATE) | ||||
| 	{ | ||||
| 		LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam; | ||||
| 		Window *window = (Window *)pcs->lpCreateParams; | ||||
| 
 | ||||
| 		::SetWindowLongPtrW( | ||||
| 			hWnd, | ||||
| 			GWLP_USERDATA, | ||||
| 			PtrToUlong(window) | ||||
| 		); | ||||
| 
 | ||||
| 		result = 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		bool hasHandled = false; | ||||
| 		Window *window = reinterpret_cast<Window *>( | ||||
| 			static_cast<LONG_PTR>( | ||||
| 				::GetWindowLongPtrW(hWnd, GWLP_USERDATA) | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		switch (uMsg) | ||||
| 		{ | ||||
| 
 | ||||
| 		// 处理鼠标消息
 | ||||
|  | @ -411,7 +409,7 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar | |||
| 		case WM_MOUSEMOVE: | ||||
| 		case WM_MOUSEWHEEL: | ||||
| 		{ | ||||
| 		SceneManager::getInstance()->dispatch(MouseEvent(hWnd, message, wParam, lParam)); | ||||
| 			SceneManager::getInstance()->dispatch(MouseEvent(hWnd, uMsg, wParam, lParam, window->_dpi)); | ||||
| 		} | ||||
| 		result = 0; | ||||
| 		hasHandled = true; | ||||
|  | @ -421,7 +419,7 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar | |||
| 		case WM_KEYDOWN: | ||||
| 		case WM_KEYUP: | ||||
| 		{ | ||||
| 		SceneManager::getInstance()->dispatch(KeyEvent(hWnd, message, wParam, lParam)); | ||||
| 			SceneManager::getInstance()->dispatch(KeyEvent(hWnd, uMsg, wParam, lParam)); | ||||
| 		} | ||||
| 		result = 0; | ||||
| 		hasHandled = true; | ||||
|  | @ -435,14 +433,15 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar | |||
| 
 | ||||
| 			if (wParam == SIZE_RESTORED) | ||||
| 			{ | ||||
| 			_instance->_size.width = width * 96.f / _instance->_dpi; | ||||
| 			_instance->_size.height = height * 96.f / _instance->_dpi; | ||||
| 				window->_width = static_cast<int>(width * 96.f / window->_dpi); | ||||
| 				window->_height = static_cast<int>(height * 96.f / window->_dpi); | ||||
| 			} | ||||
| 
 | ||||
| 			// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
 | ||||
| 			// 目标适当。它可能会调用失败,但是这里可以忽略有可能的
 | ||||
| 			// 错误,因为这个错误将在下一次调用 EndDraw 时产生
 | ||||
| 		auto pRT = Renderer::getInstance()->getRenderTarget(); | ||||
| 			auto renderer = Game::getInstance()->getRenderer(); | ||||
| 			auto pRT = renderer->getRenderTarget(); | ||||
| 			if (pRT) | ||||
| 			{ | ||||
| 				pRT->Resize(D2D1::SizeU(width, height)); | ||||
|  | @ -453,7 +452,7 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar | |||
| 		// 处理窗口标题变化消息
 | ||||
| 		case WM_SETTEXT: | ||||
| 		{ | ||||
| 		_instance->_title = (const wchar_t*)lParam; | ||||
| 			window->_title = (const wchar_t*)lParam; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
|  | @ -470,7 +469,8 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar | |||
| 		// 重绘窗口
 | ||||
| 		case WM_PAINT: | ||||
| 		{ | ||||
| 		e2d::Renderer::getInstance()->render(); | ||||
| 			auto renderer = Game::getInstance()->getRenderer(); | ||||
| 			renderer->render(); | ||||
| 			ValidateRect(hWnd, nullptr); | ||||
| 		} | ||||
| 		result = 0; | ||||
|  | @ -503,8 +503,8 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar | |||
| 
 | ||||
| 		if (!hasHandled) | ||||
| 		{ | ||||
| 		result = DefWindowProc(hWnd, message, wParam, lParam); | ||||
| 			result = DefWindowProc(hWnd, uMsg, wParam, lParam); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
|  | @ -80,7 +80,7 @@ void e2d::Collider::render() | |||
| { | ||||
| 	if (_geometry && _enabled && _visible) | ||||
| 	{ | ||||
| 		auto renderer = Renderer::getInstance(); | ||||
| 		auto renderer = Game::getInstance()->getRenderer(); | ||||
| 		// 获取纯色画刷
 | ||||
| 		ID2D1SolidColorBrush * brush = renderer->getSolidColorBrush(); | ||||
| 		// 设置画刷颜色和透明度
 | ||||
|  | @ -131,13 +131,14 @@ void e2d::Collider::recreate() | |||
| 		return; | ||||
| 
 | ||||
| 	SafeRelease(_geometry); | ||||
| 	auto factory = Game::getInstance()->getRenderer()->getFactory(); | ||||
| 
 | ||||
| 	switch (_shape) | ||||
| 	{ | ||||
| 	case Shape::Rect: | ||||
| 	{ | ||||
| 		ID2D1RectangleGeometry* rectangle = nullptr; | ||||
| 		Renderer::getFactory()->CreateRectangleGeometry( | ||||
| 		factory->CreateRectangleGeometry( | ||||
| 			D2D1::RectF(0, 0, _parentNode->getRealWidth(), _parentNode->getRealHeight()), | ||||
| 			&rectangle | ||||
| 		); | ||||
|  | @ -150,7 +151,7 @@ void e2d::Collider::recreate() | |||
| 		float minSide = std::min(_parentNode->getRealWidth(), _parentNode->getRealHeight()); | ||||
| 
 | ||||
| 		ID2D1EllipseGeometry* circle = nullptr; | ||||
| 		Renderer::getFactory()->CreateEllipseGeometry( | ||||
| 		factory->CreateEllipseGeometry( | ||||
| 			D2D1::Ellipse( | ||||
| 				D2D1::Point2F( | ||||
| 					_parentNode->getRealWidth() / 2, | ||||
|  | @ -171,7 +172,7 @@ void e2d::Collider::recreate() | |||
| 			halfHeight = _parentNode->getHeight() / 2; | ||||
| 
 | ||||
| 		ID2D1EllipseGeometry* ellipse = nullptr; | ||||
| 		Renderer::getFactory()->CreateEllipseGeometry( | ||||
| 		factory->CreateEllipseGeometry( | ||||
| 			D2D1::Ellipse( | ||||
| 				D2D1::Point2F( | ||||
| 					halfWidth, | ||||
|  | @ -186,7 +187,7 @@ void e2d::Collider::recreate() | |||
| 	} | ||||
| 
 | ||||
| 	ID2D1TransformedGeometry * _transformed; | ||||
| 	Renderer::getFactory()->CreateTransformedGeometry( | ||||
| 	factory->CreateTransformedGeometry( | ||||
| 		_geometry, | ||||
| 		_parentNode->_finalMatri, | ||||
| 		&_transformed | ||||
|  |  | |||
|  | @ -160,7 +160,7 @@ bool e2d::Image::preload(const Resource& res) | |||
| 	IWICStream *pStream = nullptr; | ||||
| 	IWICFormatConverter *pConverter = nullptr; | ||||
| 	ID2D1Bitmap *pBitmap = nullptr; | ||||
| 	IWICImagingFactory *pImagingFactory = Renderer::getImagingFactory(); | ||||
| 	IWICImagingFactory *pImagingFactory = Game::getInstance()->getRenderer()->getImagingFactory(); | ||||
| 
 | ||||
| 	if (!res.isFile()) | ||||
| 	{ | ||||
|  | @ -273,7 +273,7 @@ bool e2d::Image::preload(const Resource& res) | |||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 		// 从 WIC 位图创建一个 Direct2D 位图
 | ||||
| 		hr = Renderer::getInstance()->getRenderTarget()->CreateBitmapFromWicBitmap( | ||||
| 		hr = Game::getInstance()->getRenderer()->getRenderTarget()->CreateBitmapFromWicBitmap( | ||||
| 			pConverter, | ||||
| 			nullptr, | ||||
| 			&pBitmap | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ e2d::Exception::Exception() E2D_NOEXCEPT | |||
| { | ||||
| } | ||||
| 
 | ||||
| e2d::Exception::Exception(const String& message) E2D_NOEXCEPT | ||||
| e2d::Exception::Exception(const char * message) E2D_NOEXCEPT | ||||
| 	: _message(message) | ||||
| { | ||||
| } | ||||
|  | @ -31,7 +31,7 @@ e2d::Exception::~Exception() E2D_NOEXCEPT | |||
| { | ||||
| } | ||||
| 
 | ||||
| e2d::String e2d::Exception::msg() const | ||||
| const char * e2d::Exception::msg() const | ||||
| { | ||||
| 	return _message; | ||||
| } | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| #include "..\e2dcustom.h" | ||||
| 
 | ||||
| e2d::SystemException::SystemException() E2D_NOEXCEPT | ||||
| 	: Exception(L"未知的系统异常") | ||||
| 	: Exception("Unknown system exception") | ||||
| { | ||||
| } | ||||
| 
 | ||||
| e2d::SystemException::SystemException(const String& message) E2D_NOEXCEPT | ||||
| e2d::SystemException::SystemException(const char * message) E2D_NOEXCEPT | ||||
| 	: Exception(message) | ||||
| { | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -59,16 +59,18 @@ STDMETHODIMP_(void) TextRenderer::SetTextStyle( | |||
| 	sOutlineColor_ = outlineColor; | ||||
| 	fOutlineWidth = 2 * outlineWidth; | ||||
| 
 | ||||
| 	auto pRenderer = Game::getInstance()->getRenderer(); | ||||
| 
 | ||||
| 	switch (outlineJoin) | ||||
| 	{ | ||||
| 	case D2D1_LINE_JOIN_MITER: | ||||
| 		pCurrStrokeStyle_ = Renderer::getMiterStrokeStyle(); | ||||
| 		pCurrStrokeStyle_ = pRenderer->getMiterStrokeStyle(); | ||||
| 		break; | ||||
| 	case D2D1_LINE_JOIN_BEVEL: | ||||
| 		pCurrStrokeStyle_ = Renderer::getBevelStrokeStyle(); | ||||
| 		pCurrStrokeStyle_ = pRenderer->getBevelStrokeStyle(); | ||||
| 		break; | ||||
| 	case D2D1_LINE_JOIN_ROUND: | ||||
| 		pCurrStrokeStyle_ = Renderer::getRoundStrokeStyle(); | ||||
| 		pCurrStrokeStyle_ = pRenderer->getRoundStrokeStyle(); | ||||
| 		break; | ||||
| 	default: | ||||
| 		pCurrStrokeStyle_ = nullptr; | ||||
|  |  | |||
|  | @ -1,13 +1,12 @@ | |||
| #include "..\e2devent.h" | ||||
| #include "..\e2dbase.h" | ||||
| 
 | ||||
| e2d::MouseEvent::MouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||
| e2d::MouseEvent::MouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, float dpi) | ||||
| 	: _message(message) | ||||
| 	, _wParam(wParam) | ||||
| 	, _lParam(lParam) | ||||
| 	, _type(Type(message)) | ||||
| { | ||||
| 	float dpi = Window::getInstance()->getDpi(); | ||||
| 	_pos.x = ((float)(short)LOWORD(lParam)) * 96.f / dpi; | ||||
| 	_pos.y = ((float)(short)HIWORD(lParam)) * 96.f / dpi; | ||||
| } | ||||
|  |  | |||
|  | @ -151,7 +151,7 @@ void e2d::ActionManager::start(Action * action, Node * target, bool paused) | |||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			throw Exception(L"该 Action 已有执行目标"); | ||||
| 			throw Exception("该 Action 已有执行目标"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -188,7 +188,22 @@ void e2d::SceneManager::render() | |||
| 	} | ||||
| 	else if (_currScene) | ||||
| 	{ | ||||
| 		_currScene->visit(); | ||||
| 		auto renderer = Game::getInstance()->getRenderer(); | ||||
| 		_currScene->visit(renderer); | ||||
| 
 | ||||
| 		auto& config = Game::getInstance()->getConfig(); | ||||
| 		if (config.isOutlineVisible()) | ||||
| 		{ | ||||
| 			auto brush = renderer->getSolidColorBrush(); | ||||
| 			brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f)); | ||||
| 			brush->SetOpacity(1.f); | ||||
| 			_currScene->drawOutline(renderer); | ||||
| 		} | ||||
| 		if (config.isColliderVisible()) | ||||
| 		{ | ||||
| 			renderer->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 			_currScene->drawCollider(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -189,20 +189,20 @@ bool e2d::Button::dispatch(const MouseEvent & e, bool handled) | |||
| 	return Node::dispatch(e, handled); | ||||
| } | ||||
| 
 | ||||
| void e2d::Button::visit() | ||||
| void e2d::Button::visit(Renderer* renderer) | ||||
| { | ||||
| 	Node::visit(); | ||||
| 	Node::visit(renderer); | ||||
| 
 | ||||
| 	if (_visible && | ||||
| 		!_enabled && | ||||
| 		_normal && | ||||
| 		_normal->containsPoint(Input::getInstance()->getMousePos())) | ||||
| 		_normal->containsPoint(Game::getInstance()->getInput()->getMousePos())) | ||||
| 	{ | ||||
| 		Window::getInstance()->setCursor(Window::Cursor::No); | ||||
| 		Game::getInstance()->getWindow()->setCursor(Window::Cursor::No); | ||||
| 	} | ||||
| 	else if (_status == Status::Mouseover || _status == Status::Selected) | ||||
| 	{ | ||||
| 		Window::getInstance()->setCursor(Window::Cursor::Hand); | ||||
| 		Game::getInstance()->getWindow()->setCursor(Window::Cursor::Hand); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -79,7 +79,7 @@ e2d::Node::~Node() | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void e2d::Node::visit() | ||||
| void e2d::Node::visit(Renderer * renderer) | ||||
| { | ||||
| 	if (!_visible) | ||||
| 		return; | ||||
|  | @ -90,7 +90,7 @@ void e2d::Node::visit() | |||
| 	// 保留差别属性
 | ||||
| 	_extrapolate = this->getProperty(); | ||||
| 
 | ||||
| 	auto pRT = Renderer::getInstance()->getRenderTarget(); | ||||
| 	auto pRT = renderer->getRenderTarget(); | ||||
| 	if (_clipEnabled) | ||||
| 	{ | ||||
| 		pRT->SetTransform(_finalMatri); | ||||
|  | @ -103,7 +103,7 @@ void e2d::Node::visit() | |||
| 	if (_children.empty()) | ||||
| 	{ | ||||
| 		pRT->SetTransform(_finalMatri); | ||||
| 		this->draw(); | ||||
| 		this->draw(renderer); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
|  | @ -117,7 +117,7 @@ void e2d::Node::visit() | |||
| 			// 访问 Order 小于零的节点
 | ||||
| 			if (child->getOrder() < 0) | ||||
| 			{ | ||||
| 				child->visit(); | ||||
| 				child->visit(renderer); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
|  | @ -126,11 +126,11 @@ void e2d::Node::visit() | |||
| 		} | ||||
| 
 | ||||
| 		pRT->SetTransform(_finalMatri); | ||||
| 		this->draw(); | ||||
| 		this->draw(renderer); | ||||
| 
 | ||||
| 		// 访问剩余节点
 | ||||
| 		for (; i < _children.size(); ++i) | ||||
| 			_children[i]->visit(); | ||||
| 			_children[i]->visit(renderer); | ||||
| 	} | ||||
| 
 | ||||
| 	if (_clipEnabled) | ||||
|  | @ -139,11 +139,10 @@ void e2d::Node::visit() | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void e2d::Node::_renderOutline() | ||||
| void e2d::Node::drawOutline(Renderer * renderer) | ||||
| { | ||||
| 	if (_visible) | ||||
| 	{ | ||||
| 		auto renderer = Renderer::getInstance(); | ||||
| 		renderer->getRenderTarget()->SetTransform(_finalMatri); | ||||
| 		renderer->getRenderTarget()->DrawRectangle( | ||||
| 			D2D1::RectF(0, 0, _width, _height), | ||||
|  | @ -154,12 +153,12 @@ void e2d::Node::_renderOutline() | |||
| 		// 渲染所有子节点的轮廓
 | ||||
| 		for (const auto& child : _children) | ||||
| 		{ | ||||
| 			child->_renderOutline(); | ||||
| 			child->drawOutline(renderer); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void e2d::Node::_renderCollider() | ||||
| void e2d::Node::drawCollider() | ||||
| { | ||||
| 	if (_visible) | ||||
| 	{ | ||||
|  | @ -168,7 +167,7 @@ void e2d::Node::_renderCollider() | |||
| 		// 绘制所有子节点的几何碰撞体
 | ||||
| 		for (const auto& child : _children) | ||||
| 		{ | ||||
| 			child->_renderCollider(); | ||||
| 			child->drawCollider(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -610,14 +609,14 @@ void e2d::Node::addChild(Node * child, int order  /* = 0 */) | |||
| 	{ | ||||
| 		if (child->_parent != nullptr) | ||||
| 		{ | ||||
| 			throw Exception(L"节点已有父节点, 不能再添加到其他节点"); | ||||
| 			throw Exception("节点已有父节点, 不能再添加到其他节点"); | ||||
| 		} | ||||
| 
 | ||||
| 		for (Node * parent = this; parent != nullptr; parent = parent->getParent()) | ||||
| 		{ | ||||
| 			if (child == parent) | ||||
| 			{ | ||||
| 				throw Exception(L"一个节点不能同时是另一个节点的父节点和子节点"); | ||||
| 				throw Exception("一个节点不能同时是另一个节点的父节点和子节点"); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -825,21 +824,23 @@ bool e2d::Node::containsPoint(const Point& point) | |||
| 	// 为节点创建一个轮廓
 | ||||
| 	BOOL ret = 0; | ||||
| 	ID2D1RectangleGeometry * rectGeo = nullptr; | ||||
| 	auto factory = Renderer::getFactory(); | ||||
| 	auto factory = Game::getInstance()->getRenderer()->getFactory(); | ||||
| 
 | ||||
| 	HRESULT hr = factory->CreateRectangleGeometry( | ||||
| 	ThrowIfFailed( | ||||
| 		factory->CreateRectangleGeometry( | ||||
| 			D2D1::RectF(0, 0, _width, _height), | ||||
| 			&rectGeo | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 	ThrowIfFailed( | ||||
| 		rectGeo->FillContainsPoint( | ||||
| 			D2D1::Point2F(point.x, point.y), | ||||
| 			_finalMatri, | ||||
| 			&ret | ||||
| 		) | ||||
| 	); | ||||
| 	} | ||||
| 
 | ||||
| 	SafeRelease(rectGeo); | ||||
| 
 | ||||
| 	return ret != 0; | ||||
|  | @ -855,48 +856,46 @@ bool e2d::Node::intersects(Node * node) | |||
| 	D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN; | ||||
| 	ID2D1RectangleGeometry *rectGeo = nullptr, *rectGeo2 = nullptr; | ||||
| 	ID2D1TransformedGeometry *transGeo = nullptr, *transGeo2 = nullptr; | ||||
| 	auto factory = Renderer::getFactory(); | ||||
| 	auto factory = Game::getInstance()->getRenderer()->getFactory(); | ||||
| 
 | ||||
| 	HRESULT hr = factory->CreateRectangleGeometry( | ||||
| 	ThrowIfFailed( | ||||
| 		factory->CreateRectangleGeometry( | ||||
| 			D2D1::RectF(0, 0, _width, _height), | ||||
| 			&rectGeo | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 		hr = factory->CreateRectangleGeometry( | ||||
| 	ThrowIfFailed( | ||||
| 		factory->CreateRectangleGeometry( | ||||
| 			D2D1::RectF(0, 0, node->_width, node->_height), | ||||
| 			&rectGeo2 | ||||
| 		) | ||||
| 	); | ||||
| 	} | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 		hr = factory->CreateTransformedGeometry( | ||||
| 	ThrowIfFailed( | ||||
| 		factory->CreateTransformedGeometry( | ||||
| 			rectGeo, | ||||
| 			_finalMatri, | ||||
| 			&transGeo | ||||
| 		) | ||||
| 	); | ||||
| 	} | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 		hr = factory->CreateTransformedGeometry( | ||||
| 	ThrowIfFailed( | ||||
| 		factory->CreateTransformedGeometry( | ||||
| 			rectGeo2, | ||||
| 			node->_finalMatri, | ||||
| 			&transGeo2 | ||||
| 		) | ||||
| 	); | ||||
| 	} | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	{ | ||||
| 	ThrowIfFailed( | ||||
| 		// 获取相交状态
 | ||||
| 		transGeo->CompareWithGeometry( | ||||
| 			transGeo2, | ||||
| 			D2D1::Matrix3x2F::Identity(), | ||||
| 			&relation | ||||
| 		) | ||||
| 	); | ||||
| 	} | ||||
| 
 | ||||
| 	SafeRelease(rectGeo); | ||||
| 	SafeRelease(rectGeo2); | ||||
|  |  | |||
|  | @ -9,22 +9,3 @@ e2d::Scene::Scene() | |||
| e2d::Scene::~Scene() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void e2d::Scene::visit() | ||||
| { | ||||
| 	Node::visit(); | ||||
| 
 | ||||
| 	if (Game::getInstance()->getConfig().isOutlineVisible()) | ||||
| 	{ | ||||
| 		auto brush = Renderer::getInstance()->getSolidColorBrush(); | ||||
| 		brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f)); | ||||
| 		brush->SetOpacity(1.f); | ||||
| 		Node::_renderOutline(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (Game::getInstance()->getConfig().isColliderVisible()) | ||||
| 	{ | ||||
| 		Renderer::getInstance()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		Node::_renderCollider(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ e2d::Image * e2d::Sprite::getImage() const | |||
| 	return _image; | ||||
| } | ||||
| 
 | ||||
| void e2d::Sprite::draw() const | ||||
| void e2d::Sprite::draw(Renderer * renderer) const | ||||
| { | ||||
| 	if (_image && _image->getBitmap()) | ||||
| 	{ | ||||
|  | @ -100,7 +100,7 @@ void e2d::Sprite::draw() const | |||
| 		float fCropX = _image->getCropX(); | ||||
| 		float fCropY = _image->getCropY(); | ||||
| 		// äÖȾͼƬ
 | ||||
| 		Renderer::getInstance()->getRenderTarget()->DrawBitmap( | ||||
| 		renderer->getRenderTarget()->DrawBitmap( | ||||
| 			_image->getBitmap(), | ||||
| 			D2D1::RectF(0, 0, _width, _height), | ||||
| 			_displayOpacity, | ||||
|  |  | |||
|  | @ -287,11 +287,10 @@ void e2d::Text::setOutlineJoin(LineJoin outlineJoin) | |||
| 	_style.outlineJoin = outlineJoin; | ||||
| } | ||||
| 
 | ||||
| void e2d::Text::draw() const | ||||
| void e2d::Text::draw(Renderer * renderer) const | ||||
| { | ||||
| 	if (_textLayout) | ||||
| 	{ | ||||
| 		auto renderer = Renderer::getInstance(); | ||||
| 		// 创建文本区域
 | ||||
| 		D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, _width, _height); | ||||
| 		// 设置画刷颜色和透明度
 | ||||
|  | @ -321,7 +320,7 @@ void e2d::Text::_createFormat() | |||
| { | ||||
| 	SafeRelease(_textFormat); | ||||
| 
 | ||||
| 	HRESULT hr = Renderer::getWriteFactory()->CreateTextFormat( | ||||
| 	HRESULT hr = Game::getInstance()->getRenderer()->getWriteFactory()->CreateTextFormat( | ||||
| 		(const WCHAR *)_font.family, | ||||
| 		nullptr, | ||||
| 		DWRITE_FONT_WEIGHT(_font.weight), | ||||
|  | @ -384,14 +383,14 @@ void e2d::Text::_createLayout() | |||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	UINT32 length = (UINT32)_text.getLength(); | ||||
| 
 | ||||
| 	// ´´½¨ TextLayout
 | ||||
| 	HRESULT hr; | ||||
| 	UINT32 length = (UINT32)_text.getLength(); | ||||
| 	auto writeFactory = Game::getInstance()->getRenderer()->getWriteFactory(); | ||||
| 
 | ||||
| 	// 对文本自动换行情况下进行处理
 | ||||
| 	if (_style.wrapping) | ||||
| 	{ | ||||
| 		hr = Renderer::getWriteFactory()->CreateTextLayout( | ||||
| 		hr = writeFactory->CreateTextLayout( | ||||
| 			(const WCHAR *)_text, | ||||
| 			length, | ||||
| 			_textFormat, | ||||
|  | @ -410,7 +409,7 @@ void e2d::Text::_createLayout() | |||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		hr = Renderer::getWriteFactory()->CreateTextLayout((const WCHAR *)_text, length, _textFormat, 0, 0, &_textLayout); | ||||
| 		hr = writeFactory->CreateTextLayout((const WCHAR *)_text, length, _textFormat, 0, 0, &_textLayout); | ||||
| 		// 为防止文本对齐问题,根据刚才创建的 layout 宽度重新创建它
 | ||||
| 		if (_textLayout) | ||||
| 		{ | ||||
|  | @ -421,7 +420,7 @@ void e2d::Text::_createLayout() | |||
| 			this->setSize(metrics.width, metrics.height); | ||||
| 			// 重新创建 layout
 | ||||
| 			SafeRelease(_textLayout); | ||||
| 			hr = Renderer::getWriteFactory()->CreateTextLayout((const WCHAR *)_text, length, _textFormat, _width, 0, &_textLayout); | ||||
| 			hr = writeFactory->CreateTextLayout((const WCHAR *)_text, length, _textFormat, _width, 0, &_textLayout); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -160,11 +160,14 @@ bool e2d::File::createFolder(const String & dirPath) | |||
| 
 | ||||
| e2d::String e2d::File::getSaveFilePath(const String& title, const String& defExt) | ||||
| { | ||||
| 	auto window = Game::getInstance()->getWindow(); | ||||
| 	HWND hwnd = window->getHWnd(); | ||||
| 
 | ||||
| 	// 弹出保存对话框
 | ||||
| 	OPENFILENAME ofn = { 0 }; | ||||
| 	wchar_t strFilename[MAX_PATH] = { 0 };				// 用于接收文件名
 | ||||
| 	ofn.lStructSize = sizeof(OPENFILENAME);				// 结构体大小
 | ||||
| 	ofn.hwndOwner = Window::getInstance()->getHWnd();	// ´°¿Ú¾ä±ú
 | ||||
| 	ofn.hwndOwner = hwnd;								// ´°¿Ú¾ä±ú
 | ||||
| 	ofn.lpstrFilter = L"所有文件\0*.*\0\0";				// 设置过滤
 | ||||
| 	ofn.nFilterIndex = 1;								// 过滤器索引
 | ||||
| 	ofn.lpstrFile = strFilename;						// 接收返回的文件路径和文件名
 | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ bool e2d::Transition::_init(Scene * prev) | |||
| 	 | ||||
| 	// ´´½¨Í¼²ã
 | ||||
| 	HRESULT hr = S_OK; | ||||
| 	auto renderer = Renderer::getInstance(); | ||||
| 	auto renderer = Game::getInstance()->getRenderer(); | ||||
| 	if (_inScene) | ||||
| 	{ | ||||
| 		hr = renderer->getRenderTarget()->CreateLayer(&_inLayer); | ||||
|  | @ -57,7 +57,7 @@ bool e2d::Transition::_init(Scene * prev) | |||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	_windowSize = Window::getInstance()->getSize(); | ||||
| 	_windowSize = Game::getInstance()->getWindow()->getSize(); | ||||
| 	_outLayerParam = _inLayerParam = D2D1::LayerParameters( | ||||
| 		D2D1::InfiniteRect(), | ||||
| 		nullptr, | ||||
|  | @ -86,7 +86,8 @@ void e2d::Transition::_update() | |||
| 
 | ||||
| void e2d::Transition::_render() | ||||
| { | ||||
| 	auto pRT = Renderer::getInstance()->getRenderTarget(); | ||||
| 	auto renderer = Game::getInstance()->getRenderer(); | ||||
| 	auto pRT = renderer->getRenderTarget(); | ||||
| 
 | ||||
| 	if (_outScene) | ||||
| 	{ | ||||
|  | @ -101,7 +102,7 @@ void e2d::Transition::_render() | |||
| 		pRT->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); | ||||
| 		pRT->PushLayer(_outLayerParam, _outLayer); | ||||
| 
 | ||||
| 		_outScene->visit(); | ||||
| 		_outScene->visit(renderer); | ||||
| 
 | ||||
| 		pRT->PopLayer(); | ||||
| 		pRT->PopAxisAlignedClip(); | ||||
|  | @ -120,7 +121,7 @@ void e2d::Transition::_render() | |||
| 		pRT->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); | ||||
| 		pRT->PushLayer(_inLayerParam, _inLayer); | ||||
| 
 | ||||
| 		_inScene->visit(); | ||||
| 		_inScene->visit(renderer); | ||||
| 
 | ||||
| 		pRT->PopLayer(); | ||||
| 		pRT->PopAxisAlignedClip(); | ||||
|  |  | |||
							
								
								
									
										236
									
								
								core/e2dbase.h
								
								
								
								
							
							
						
						
									
										236
									
								
								core/e2dbase.h
								
								
								
								
							|  | @ -72,58 +72,6 @@ protected: | |||
| }; | ||||
| 
 | ||||
| 
 | ||||
| // 游戏主体
 | ||||
| class Game | ||||
| { | ||||
| public: | ||||
| 	// 获取游戏实例
 | ||||
| 	static Game * getInstance(); | ||||
| 
 | ||||
| 	// 销毁实例
 | ||||
| 	static void destroyInstance(); | ||||
| 
 | ||||
| 	// 启动游戏
 | ||||
| 	void start(); | ||||
| 
 | ||||
| 	// 暂停游戏
 | ||||
| 	void pause(); | ||||
| 
 | ||||
| 	// 继续游戏
 | ||||
| 	void resume(); | ||||
| 
 | ||||
| 	// 结束游戏
 | ||||
| 	void quit(); | ||||
| 
 | ||||
| 	// 清理资源
 | ||||
| 	void cleanup(); | ||||
| 
 | ||||
| 	// 游戏是否暂停
 | ||||
| 	bool isPaused(); | ||||
| 
 | ||||
| 	// 修改游戏配置
 | ||||
| 	void setConfig( | ||||
| 		const Config& config | ||||
| 	); | ||||
| 
 | ||||
| 	// 获取游戏配置
 | ||||
| 	const Config& getConfig(); | ||||
| 
 | ||||
| private: | ||||
| 	Game(); | ||||
| 
 | ||||
| 	~Game(); | ||||
| 
 | ||||
| 	E2D_DISABLE_COPY(Game); | ||||
| 
 | ||||
| private: | ||||
| 	bool		_quit; | ||||
| 	bool		_paused; | ||||
| 	Config		_config; | ||||
| 
 | ||||
| 	static Game * _instance; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| // 窗体
 | ||||
| class Window | ||||
| { | ||||
|  | @ -147,11 +95,14 @@ public: | |||
| 	}; | ||||
| 
 | ||||
| public: | ||||
| 	// 获取窗体实例
 | ||||
| 	static Window * getInstance(); | ||||
| 	Window( | ||||
| 		const String& title,	/* 窗体标题 */ | ||||
| 		int width,				/* 窗体宽度 */ | ||||
| 		int height,				/* 窗体高度 */ | ||||
| 		int iconID = 0			/* 窗体图标 */ | ||||
| 	); | ||||
| 
 | ||||
| 	// 销毁窗体实例
 | ||||
| 	static void destroyInstance(); | ||||
| 	~Window(); | ||||
| 
 | ||||
| 	// 创建窗体互斥体
 | ||||
| 	bool createMutex( | ||||
|  | @ -180,22 +131,22 @@ public: | |||
| 	); | ||||
| 
 | ||||
| 	// 获取窗体标题
 | ||||
| 	String getTitle(); | ||||
| 	String getTitle() const; | ||||
| 
 | ||||
| 	// 获取窗体宽度
 | ||||
| 	float getWidth(); | ||||
| 	int getWidth() const; | ||||
| 
 | ||||
| 	// 获取窗体高度
 | ||||
| 	float getHeight(); | ||||
| 	int getHeight() const; | ||||
| 
 | ||||
| 	// 获取窗体大小
 | ||||
| 	Size getSize(); | ||||
| 	Size getSize() const; | ||||
| 
 | ||||
| 	// 获取窗口 DPI
 | ||||
| 	float getDpi(); | ||||
| 	float getDpi() const; | ||||
| 
 | ||||
| 	// 获取窗口句柄
 | ||||
| 	HWND getHWnd(); | ||||
| 	HWND getHWnd() const; | ||||
| 
 | ||||
| 	// 打开或隐藏控制台
 | ||||
| 	void setConsoleEnabled( | ||||
|  | @ -220,15 +171,6 @@ public: | |||
| 	void poll(); | ||||
| 
 | ||||
| private: | ||||
| 	Window(); | ||||
| 
 | ||||
| 	~Window(); | ||||
| 
 | ||||
| 	E2D_DISABLE_COPY(Window); | ||||
| 
 | ||||
| 	// 注册窗口
 | ||||
| 	HWND __registerWindow(); | ||||
| 
 | ||||
| 	// 根据客户区大小计算合适的窗口区域
 | ||||
| 	Rect __adjustWindow( | ||||
| 		int width, | ||||
|  | @ -238,7 +180,7 @@ private: | |||
| 	// Win32 窗口消息回调程序
 | ||||
| 	static LRESULT CALLBACK WndProc( | ||||
| 		HWND hWnd, | ||||
| 		UINT message,  | ||||
| 		UINT uMsg, | ||||
| 		WPARAM wParam, | ||||
| 		LPARAM lParam | ||||
| 	); | ||||
|  | @ -246,12 +188,11 @@ private: | |||
| private: | ||||
| 	HWND	_hWnd; | ||||
| 	MSG		_msg; | ||||
| 	Size	_size; | ||||
| 	int		_width; | ||||
| 	int		_height; | ||||
| 	String	_title; | ||||
| 	int		_iconID; | ||||
| 	float	_dpi; | ||||
| 
 | ||||
| 	static Window * _instance; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -259,11 +200,9 @@ private: | |||
| class Input | ||||
| { | ||||
| public: | ||||
| 	// 获取输入设备实例
 | ||||
| 	static Input * getInstance(); | ||||
| 	Input(); | ||||
| 
 | ||||
| 	// 销毁输入设备实例
 | ||||
| 	static void destroyInstance(); | ||||
| 	~Input(); | ||||
| 
 | ||||
| 	// 检测键盘某按键是否正被按下
 | ||||
| 	bool isDown( | ||||
|  | @ -296,12 +235,10 @@ public: | |||
| 	// 刷新输入设备状态
 | ||||
| 	void update(); | ||||
| 
 | ||||
| private: | ||||
| 	Input(); | ||||
| 
 | ||||
| 	~Input(); | ||||
| 
 | ||||
| 	E2D_DISABLE_COPY(Input); | ||||
| 	// 初始化渲染器(不应手动调用该函数)
 | ||||
| 	void init( | ||||
| 		Window * window | ||||
| 	); | ||||
| 
 | ||||
| private: | ||||
| 	IDirectInput8W* _directInput; | ||||
|  | @ -309,20 +246,16 @@ private: | |||
| 	IDirectInputDevice8W* _mouseDevice; | ||||
| 	DIMOUSESTATE _mouseState; | ||||
| 	char _keyBuffer[256]; | ||||
| 
 | ||||
| 	static Input * _instance; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| // 渲染器
 | ||||
| // 图形设备
 | ||||
| class Renderer | ||||
| { | ||||
| public: | ||||
| 	// 获取渲染器实例
 | ||||
| 	static Renderer * getInstance(); | ||||
| 	Renderer(); | ||||
| 
 | ||||
| 	// 销毁实例
 | ||||
| 	static void destroyInstance(); | ||||
| 	~Renderer(); | ||||
| 
 | ||||
| 	// 获取背景色
 | ||||
| 	Color getBackgroundColor(); | ||||
|  | @ -332,46 +265,42 @@ public: | |||
| 		Color color | ||||
| 	); | ||||
| 
 | ||||
| 	// 获取文字渲染器
 | ||||
| 	TextRenderer * getTextRenderer(); | ||||
| 
 | ||||
| 	// 获取 ID2D1HwndRenderTarget 对象
 | ||||
| 	ID2D1HwndRenderTarget * getRenderTarget(); | ||||
| 
 | ||||
| 	// 获取 ID2D1SolidColorBrush 对象
 | ||||
| 	ID2D1SolidColorBrush * getSolidColorBrush(); | ||||
| 
 | ||||
| 	// 渲染游戏画面
 | ||||
| 	void render(); | ||||
| 
 | ||||
| 	// 删除设备相关资源
 | ||||
| 	void discardDeviceResources(); | ||||
| 	// 获取文字渲染器
 | ||||
| 	TextRenderer * getTextRenderer() const { return _textRenderer; } | ||||
| 
 | ||||
| 	// 获取 ID2D1HwndRenderTarget 对象
 | ||||
| 	ID2D1HwndRenderTarget * getRenderTarget() const { return _renderTarget; } | ||||
| 
 | ||||
| 	// 获取 ID2D1SolidColorBrush 对象
 | ||||
| 	ID2D1SolidColorBrush * getSolidColorBrush() const { return _solidBrush; } | ||||
| 
 | ||||
| 	// 获取 ID2D1Factory 对象
 | ||||
| 	static ID2D1Factory * getFactory(); | ||||
| 	ID2D1Factory * getFactory() const { return _factory; } | ||||
| 
 | ||||
| 	// 获取 IWICImagingFactory 对象
 | ||||
| 	static IWICImagingFactory * getImagingFactory(); | ||||
| 	IWICImagingFactory * getImagingFactory() const { return _imagingFactory; } | ||||
| 
 | ||||
| 	// 获取 IDWriteFactory 对象
 | ||||
| 	static IDWriteFactory * getWriteFactory(); | ||||
| 	IDWriteFactory * getWriteFactory() const { return _writeFactory; } | ||||
| 
 | ||||
| 	// 获取 Miter 样式的 ID2D1StrokeStyle
 | ||||
| 	static ID2D1StrokeStyle * getMiterStrokeStyle(); | ||||
| 	ID2D1StrokeStyle * getMiterStrokeStyle(); | ||||
| 
 | ||||
| 	// 获取 Bevel 样式的 ID2D1StrokeStyle
 | ||||
| 	static ID2D1StrokeStyle * getBevelStrokeStyle(); | ||||
| 	ID2D1StrokeStyle * getBevelStrokeStyle(); | ||||
| 
 | ||||
| 	// 获取 Round 样式的 ID2D1StrokeStyle
 | ||||
| 	static ID2D1StrokeStyle * getRoundStrokeStyle(); | ||||
| 	ID2D1StrokeStyle * getRoundStrokeStyle(); | ||||
| 
 | ||||
| 	// 初始化渲染器(不应手动调用该函数)
 | ||||
| 	void init( | ||||
| 		Window * window | ||||
| 	); | ||||
| 
 | ||||
| private: | ||||
| 	Renderer(); | ||||
| 
 | ||||
| 	~Renderer(); | ||||
| 
 | ||||
| 	E2D_DISABLE_COPY(Renderer); | ||||
| 
 | ||||
| 	// 渲染 FPS
 | ||||
| 	void _renderFps(); | ||||
| 
 | ||||
|  | @ -384,14 +313,77 @@ private: | |||
| 	IDWriteTextLayout*		_fpsLayout; | ||||
| 	ID2D1SolidColorBrush*	_solidBrush; | ||||
| 	ID2D1HwndRenderTarget*	_renderTarget; | ||||
| 	ID2D1Factory*			_factory; | ||||
| 	IWICImagingFactory*		_imagingFactory; | ||||
| 	IDWriteFactory*			_writeFactory; | ||||
| 	ID2D1StrokeStyle*		_miterStrokeStyle; | ||||
| 	ID2D1StrokeStyle*		_bevelStrokeStyle; | ||||
| 	ID2D1StrokeStyle*		_roundStrokeStyle; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| // 游戏
 | ||||
| class Game | ||||
| { | ||||
| public: | ||||
| 	// 获取 Game 实例
 | ||||
| 	static Game * getInstance(); | ||||
| 
 | ||||
| 	// 启动游戏
 | ||||
| 	void start(); | ||||
| 
 | ||||
| 	// 暂停游戏
 | ||||
| 	void pause(); | ||||
| 
 | ||||
| 	// 继续游戏
 | ||||
| 	void resume(); | ||||
| 
 | ||||
| 	// 结束游戏
 | ||||
| 	void quit(); | ||||
| 
 | ||||
| 	// 清理资源
 | ||||
| 	void cleanup(); | ||||
| 
 | ||||
| 	// 游戏是否暂停
 | ||||
| 	bool isPaused(); | ||||
| 
 | ||||
| 	// 修改游戏配置
 | ||||
| 	void setConfig( | ||||
| 		const Config& config | ||||
| 	); | ||||
| 
 | ||||
| 	// 获取游戏配置
 | ||||
| 	const Config& getConfig() const; | ||||
| 
 | ||||
| 	// 设置窗体
 | ||||
| 	void setWindow( | ||||
| 		Window * window | ||||
| 	); | ||||
| 
 | ||||
| 	// 获取窗体
 | ||||
| 	Window * getWindow() const { return _window; } | ||||
| 
 | ||||
| 	// 获取输入设备
 | ||||
| 	Input * getInput() const { return _input; } | ||||
| 
 | ||||
| 	// 获取图形设备
 | ||||
| 	Renderer * getRenderer() const { return _renderer; } | ||||
| 
 | ||||
| protected: | ||||
| 	Game(); | ||||
| 
 | ||||
| 	~Game(); | ||||
| 
 | ||||
| 	E2D_DISABLE_COPY(Game); | ||||
| 
 | ||||
| private: | ||||
| 	bool		_quit; | ||||
| 	bool		_paused; | ||||
| 	Config		_config; | ||||
| 	Window *	_window; | ||||
| 	Input *		_input; | ||||
| 	Renderer *	_renderer; | ||||
| 	 | ||||
| 	static ID2D1Factory*		_d2dFactory; | ||||
| 	static IWICImagingFactory*	_imagingFactory; | ||||
| 	static IDWriteFactory*		_writeFactory; | ||||
| 	static ID2D1StrokeStyle*	_miterStrokeStyle; | ||||
| 	static ID2D1StrokeStyle*	_bevelStrokeStyle; | ||||
| 	static ID2D1StrokeStyle*	_roundStrokeStyle; | ||||
| 	static Renderer *			_instance; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,17 +6,6 @@ namespace e2d | |||
| { | ||||
| 
 | ||||
| 
 | ||||
| template<class Interface> | ||||
| inline void SafeRelease(Interface*& p) | ||||
| { | ||||
| 	if (p != nullptr) | ||||
| 	{ | ||||
| 		p->Release(); | ||||
| 		p = nullptr; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class Music; | ||||
| 
 | ||||
| // 音源回调
 | ||||
|  | @ -173,7 +162,7 @@ class Exception | |||
| public: | ||||
| 	Exception() E2D_NOEXCEPT; | ||||
| 
 | ||||
| 	explicit Exception(const String& message) E2D_NOEXCEPT; | ||||
| 	explicit Exception(const char * message) E2D_NOEXCEPT; | ||||
| 
 | ||||
| 	Exception(Exception const& other) E2D_NOEXCEPT; | ||||
| 
 | ||||
|  | @ -182,10 +171,10 @@ public: | |||
| 	Exception& operator=(Exception const& other) E2D_NOEXCEPT; | ||||
| 
 | ||||
| 	// 获取异常信息
 | ||||
| 	virtual String msg() const; | ||||
| 	virtual const char * msg() const; | ||||
| 
 | ||||
| private: | ||||
| 	String _message; | ||||
| 	const char * _message; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -196,7 +185,30 @@ class SystemException | |||
| public: | ||||
| 	SystemException() E2D_NOEXCEPT; | ||||
| 
 | ||||
| 	explicit SystemException(const String& message) E2D_NOEXCEPT; | ||||
| 	explicit SystemException(const char * message) E2D_NOEXCEPT; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| template<class Interface> | ||||
| inline void SafeRelease(Interface*& p) | ||||
| { | ||||
| 	if (p != nullptr) | ||||
| 	{ | ||||
| 		p->Release(); | ||||
| 		p = nullptr; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| inline void ThrowIfFailed(HRESULT hr) | ||||
| { | ||||
| 	if (FAILED(hr)) | ||||
| 	{ | ||||
| 		// 在此处设置断点以捕获 D2D API 异常.
 | ||||
| 		static char s_str[64] = {}; | ||||
| 		sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast<unsigned int>(hr)); | ||||
| 		throw SystemException(s_str); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  | @ -70,7 +70,8 @@ public: | |||
| 		HWND hWnd, | ||||
| 		UINT message, | ||||
| 		WPARAM wParam, | ||||
| 		LPARAM lParam | ||||
| 		LPARAM lParam, | ||||
| 		float dpi | ||||
| 	); | ||||
| 
 | ||||
| 	// 資函報炎罪恫炎
 | ||||
|  |  | |||
|  | @ -47,7 +47,9 @@ public: | |||
| 	virtual ~Node(); | ||||
| 
 | ||||
| 	// 渲染节点
 | ||||
| 	virtual void draw() const {} | ||||
| 	virtual void draw( | ||||
| 		Renderer * renderer | ||||
| 	) const {} | ||||
| 
 | ||||
| 	// 获取节点显示状态
 | ||||
| 	virtual bool isVisible() const; | ||||
|  | @ -395,17 +397,21 @@ public: | |||
| 	); | ||||
| 
 | ||||
| 	// 遍历节点
 | ||||
| 	virtual void visit(); | ||||
| 	virtual void visit( | ||||
| 		Renderer * renderer | ||||
| 	); | ||||
| 
 | ||||
| 	// äÖȾ½ÚµãÂÖÀª
 | ||||
| 	virtual void drawOutline( | ||||
| 		Renderer * renderer | ||||
| 	); | ||||
| 
 | ||||
| 	// äÖȾÅöײÌåÂÖÀª
 | ||||
| 	virtual void drawCollider(); | ||||
| 
 | ||||
| protected: | ||||
| 	E2D_DISABLE_COPY(Node); | ||||
| 
 | ||||
| 	// 渲染节点轮廓
 | ||||
| 	virtual void _renderOutline(); | ||||
| 
 | ||||
| 	// 渲染碰撞体轮廓
 | ||||
| 	virtual void _renderCollider(); | ||||
| 
 | ||||
| 	// 设置节点所在场景
 | ||||
| 	virtual void _setParentScene( | ||||
| 		Scene * scene | ||||
|  | @ -468,9 +474,6 @@ public: | |||
| 	// 说明:返回 false 将阻止窗口关闭
 | ||||
| 	virtual bool onCloseWindow() { return true; } | ||||
| 
 | ||||
| 	// 渲染场景
 | ||||
| 	virtual void visit() override; | ||||
| 
 | ||||
| protected: | ||||
| 	E2D_DISABLE_COPY(Scene); | ||||
| }; | ||||
|  | @ -531,7 +534,9 @@ public: | |||
| 	virtual Image * getImage() const; | ||||
| 
 | ||||
| 	// 渲染精灵
 | ||||
| 	virtual void draw() const override; | ||||
| 	virtual void draw( | ||||
| 		Renderer * renderer | ||||
| 	) const override; | ||||
| 
 | ||||
| protected: | ||||
| 	E2D_DISABLE_COPY(Sprite); | ||||
|  | @ -735,7 +740,9 @@ public: | |||
| 	); | ||||
| 
 | ||||
| 	// 渲染文字
 | ||||
| 	virtual void draw() const override; | ||||
| 	virtual void draw( | ||||
| 		Renderer * renderer | ||||
| 	) const override; | ||||
| 
 | ||||
| protected: | ||||
| 	E2D_DISABLE_COPY(Text); | ||||
|  | @ -837,7 +844,9 @@ public: | |||
| 	) override; | ||||
| 
 | ||||
| 	// 渲染节点
 | ||||
| 	virtual void visit() override; | ||||
| 	virtual void visit( | ||||
| 		Renderer * renderer | ||||
| 	) override; | ||||
| 
 | ||||
| protected: | ||||
| 	E2D_DISABLE_COPY(Button); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue