diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2e612965 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# ignore all files in the /Easy2D/** directory +Easy2D/Win32/ +Easy2D/x64/ \ No newline at end of file diff --git a/Easy2D.sln b/Easy2D.sln new file mode 100644 index 00000000..6b3b67bc --- /dev/null +++ b/Easy2D.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Easy2D", "Easy2D\Easy2D.vcxproj", "{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + DebugW|x64 = DebugW|x64 + DebugW|x86 = DebugW|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + ReleaseW|x64 = ReleaseW|x64 + ReleaseW|x86 = ReleaseW|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x64.ActiveCfg = Debug|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x64.Build.0 = Debug|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x86.ActiveCfg = Debug|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x86.Build.0 = Debug|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x64.ActiveCfg = DebugW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x64.Build.0 = DebugW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x86.ActiveCfg = DebugW|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x86.Build.0 = DebugW|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x64.ActiveCfg = Release|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x64.Build.0 = Release|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x86.ActiveCfg = Release|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x86.Build.0 = Release|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x64.ActiveCfg = ReleaseW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x64.Build.0 = ReleaseW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x86.ActiveCfg = ReleaseW|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x86.Build.0 = ReleaseW|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FAC2BE2F-19AF-477A-8DC6-4645E66868A4} + EndGlobalSection +EndGlobal diff --git a/Easy2D/Application.cpp b/Easy2D/Application.cpp new file mode 100644 index 00000000..a0abbb56 --- /dev/null +++ b/Easy2D/Application.cpp @@ -0,0 +1,368 @@ +#include "easy2d.h" +#include "EasyX\easyx.h" +#include +#include +#include +#pragma comment(lib, "imm32.lib") +#include +#pragma comment(lib, "winmm.lib") + + +// Application Ψһʵ +static Application * s_pInstance = nullptr; +// ԭ +static int originX = 0; +static int originY = 0; + +Application::Application() : + m_currentScene(nullptr), + m_nextScene(nullptr), + m_bRunning(false), + m_bPause(false), + m_nWidth(0), + m_nHeight(0), + m_nWindowMode(0) +{ + assert(!s_pInstance); // ͬʱ Application ʵ + s_pInstance = this; // ʵ + setFPS(60); // Ĭ FPS Ϊ 60 +} + +Application::~Application() +{ + destory(); // Application +} + +Application * Application::get() +{ + assert(s_pInstance); // ʵ + return s_pInstance; // ȡ Application Ψһʵ +} + +void Application::setOrigin(int originX, int originY) +{ + ::originX = originX; + ::originY = originY; + setorigin(originX, originY); +} + +int Application::getOriginX() +{ + return ::originX; +} + +int Application::getOriginY() +{ + return ::originY; +} + +int Application::run() +{ + // ͼ + BeginBatchDraw(); + // ޸ʱ侫 + timeBeginPeriod(1); + // ȡ CPU ÿδ + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + // ʱ + LARGE_INTEGER nLast; + LARGE_INTEGER nNow; + // ¼ǰʱ + QueryPerformanceCounter(&nLast); + // ʱ + LONGLONG interval = 0LL; + // ʱ + LONG waitMS = 0L; + // صĴʾ + ShowWindow(GetHWnd(), SW_NORMAL); + // Ϸ + m_bRunning = true; + + // ѭ + while (m_bRunning) + { + // ȡǰʱ + QueryPerformanceCounter(&nNow); + // ʱ + interval = nNow.QuadPart - nLast.QuadPart; + // жϼʱǷ㹻 + if (interval >= m_nAnimationInterval.QuadPart) + { + // ¼ǰʱ + nLast.QuadPart = nNow.QuadPart; + // ִϷ߼ + _mainLoop(); + } + else + { + // ʱ + waitMS = LONG((m_nAnimationInterval.QuadPart - interval) * 1000LL / freq.QuadPart) - 1L; + // ̣߳ͷ CPU ռ + if (waitMS > 1L) + Sleep(waitMS); + } + } + // ֹͣͼ + EndBatchDraw(); + // رմ + close(); + // ͷڴռ + destory(); + // ʱ侫 + timeEndPeriod(1); + + return 0; +} + +void Application::_initGraph() +{ + // ͼ + initgraph(m_nWidth, m_nHeight, m_nWindowMode); + // صǰڣֹڼؽ׶ʾڴڣ + ShowWindow(GetHWnd(), SW_HIDE); + // ȡĻֱ + int screenWidth = GetSystemMetrics(SM_CXSCREEN); + int screenHeight = GetSystemMetrics(SM_CYSCREEN); + // ȡڴС + CRect rcWindow; + GetWindowRect(GetHWnd(), &rcWindow); + // ôĻ + SetWindowPos(GetHWnd(), HWND_TOP, + (screenWidth - rcWindow.Size().cx) / 2, + (screenHeight - rcWindow.Size().cy) / 2, + rcWindow.Size().cx, + rcWindow.Size().cy, + SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOSIZE); + // 뷨 + ImmAssociateContext(GetHWnd(), NULL); + // ûͼ + reset(); + // ôڱ + if (m_sTitle.empty()) + { + // 浱ǰ + TCHAR title[31]; + GetWindowText(GetHWnd(), title, 30); + m_sTitle = title; + } + else + { + setWindowText(m_sTitle); + } +} + +void Application::_mainLoop() +{ + // Ϸͣ + if (m_bPause) + { + return; + } + // һ + if (m_nextScene) + { + _enterNextScene(); + } + // Եǰǿ + assert(m_currentScene); + + cleardevice(); // ջ + m_currentScene->_onDraw(); // Ƶǰ + FlushBatchDraw(); // ˢ» + + // ִг + MouseMsg::__exec(); // + KeyMsg::__exec(); // ̰ + Timer::__exec(); // ʱִг + FreePool::__flush(); // ˢڴ +} + +void Application::createWindow(int width, int height, int mode) +{ + // 洰Ϣ + m_nWidth = width; + m_nHeight = height; + m_nWindowMode = mode; + // + _initGraph(); +} + +void Application::createWindow(tstring title, int width, int height, int mode) +{ + // 洰Ϣ + m_nWidth = width; + m_nHeight = height; + m_nWindowMode = mode; + m_sTitle = title; + // + _initGraph(); +} + +void Application::setWindowSize(int width, int height) +{ + // Ϸʱ޸ĴڴС + assert(m_bRunning); + + // + closegraph(); + /* ڻᵼڴռüӣҲ EasyX BUG yangw80 */ + initgraph(width, height, m_nWindowMode); + + /* EasyX ֧ Windows API ޸ĴڴС */ + ///////////////////////////////////////////////////////////////////////////////// + // // ȡĻֱ + // int screenWidth = GetSystemMetrics(SM_CXSCREEN); + // int screenHeight = GetSystemMetrics(SM_CYSCREEN); + // // ȡڴС˵ + // CRect rcWindow; + // GetWindowRect(GetHWnd(), &rcWindow); + // // ȡͻС + // CRect rcClient; + // GetClientRect(GetHWnd(), &rcClient); + // // ߿С + // width += (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left); + // height += (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top); + // // ޸ĴڴСôĻ + // SetWindowPos( + // GetHWnd(), + // HWND_TOP, + // (screenWidth - width) / 2, + // (screenHeight - height) / 2, + // width, + // height, + // SWP_SHOWWINDOW | SWP_NOREDRAW); + ////////////////////////////////////////////////////////////////////////////////// +} + +void Application::setWindowText(tstring title) +{ + // ôڱ + SetWindowText(GetHWnd(), title.c_str()); + // 浱ǰ⣬޸ĴڴСʱָ + m_sTitle = title; +} + +void Application::close() +{ + // رջͼ + closegraph(); +} + +void Application::enterScene(Scene * scene, bool save) +{ + // һָ + m_nextScene = scene; + // лʱǷ񱣴浱ǰ + m_bSaveScene = save; +} + +void Application::backScene() +{ + // ջȡָ룬Ϊһ + m_nextScene = m_sceneStack.top(); + // 浱ǰ + m_bSaveScene = false; +} + +void Application::_enterNextScene() +{ + // һջ˵ڷһ + if (m_sceneStack.size() && m_nextScene == m_sceneStack.top()) + { + m_sceneStack.pop(); // ɾջ + } + + if (m_bSaveScene) + { + m_sceneStack.push(m_currentScene); // Ҫ浱ǰָŵջ + } + else + { + SAFE_DELETE(m_currentScene); // ɾǰ + } + + m_currentScene = m_nextScene; // л + m_nextScene = nullptr; // һÿ +} + +void Application::quit() +{ + m_bRunning = false; +} + +void Application::end() +{ + m_bRunning = false; +} + +void Application::pause() +{ + m_bPause = true; +} + +bool Application::isRunning() +{ + return m_bRunning && !m_bPause; +} + +void Application::reset() +{ + // ûͼ + graphdefaults(); + setbkmode(TRANSPARENT); + setbkcolor(Color::black); +} + +Scene * Application::getCurrentScene() +{ + // ȡǰָ + return m_currentScene; +} + +LPCTSTR easy2d::Application::getVersion() +{ + return _T("1.0.0"); +} + +void Application::setFPS(DWORD fps) +{ + // û֡ʣԺΪλ + LARGE_INTEGER nFreq; + QueryPerformanceFrequency(&nFreq); + m_nAnimationInterval.QuadPart = (LONGLONG)(1.0 / fps * nFreq.QuadPart); +} + +int Application::getWidth() const +{ + return m_nWidth; +} + +int Application::getHeight() const +{ + return m_nHeight; +} + +void Application::free() +{ + // ͷųڴ + SAFE_DELETE(m_currentScene); + SAFE_DELETE(m_nextScene); + // ճջ + while (m_sceneStack.size()) + { + auto temp = m_sceneStack.top(); + SAFE_DELETE(temp); + m_sceneStack.pop(); + } + // ɾжʱ + Timer::clearAllTimers(); +} + +void Application::destory() +{ + // ͷڴ + free(); + // ʵָÿ + s_pInstance = nullptr; +} diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj new file mode 100644 index 00000000..da303326 --- /dev/null +++ b/Easy2D/Easy2D.vcxproj @@ -0,0 +1,374 @@ + + + + + DebugW + Win32 + + + DebugW + x64 + + + Debug + Win32 + + + ReleaseW + Win32 + + + ReleaseW + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF} + Win32Proj + Easy2D + 10.0.15063.0 + + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + false + MultiByte + + + StaticLibrary + false + v141 + false + Unicode + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + false + MultiByte + + + StaticLibrary + false + v141 + false + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + Easy2Dd + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + true + Easy2Ddw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + true + Easy2Dd + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + true + Easy2Ddw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2D + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2Dw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2D + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2Dw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + false + + + EasyXa.lib;GdiPlus.lib + EasyX\x86 + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + EasyXw.lib;GdiPlus.lib + + + EasyX\x86 + + + false + + + + + NotUsing + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + EasyX\x64 + EasyXa.lib;GdiPlus.lib + + + + + NotUsing + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + EasyXw.lib;GdiPlus.lib + EasyX\x64 + + + + + NotUsing + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyX\x86 + EasyXa.lib;GdiPlus.lib + + + + + NotUsing + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyXw.lib;GdiPlus.lib + EasyX\x86 + + + + + + + NotUsing + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyX\x64 + EasyXa.lib;GdiPlus.lib + + + + + NotUsing + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyXw.lib;GdiPlus.lib + EasyX\x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters new file mode 100644 index 00000000..e17f1845 --- /dev/null +++ b/Easy2D/Easy2D.vcxproj.filters @@ -0,0 +1,126 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {18e7fd5c-0935-47bb-9a2e-38da40377f7d} + + + {682a1a3c-39d8-4ac9-ba03-fa90c089c9ab} + + + {d6778635-8947-4f9b-9388-dd088642b5b2} + + + {e5ec6183-113b-4140-8285-18b18ea37d15} + + + {051f9343-e5a5-4491-8110-f13fc27c3827} + + + {065a3244-7169-4a45-bc9f-f2a80d8a9759} + + + {72dbabab-8278-4ee4-917f-bfffb474a51b} + + + + + + + + 源文件 + + + 源文件 + + + 源文件\Style + + + 源文件\Tool + + + 源文件\Tool + + + 源文件\Tool + + + 源文件\Style + + + 源文件\Node + + + 源文件\Node + + + 源文件\Node + + + 源文件\Node + + + 源文件\Node\Sprite + + + 源文件\Node\Sprite + + + 源文件\Node\Shape + + + 源文件\Node\Shape + + + 源文件\Node\Shape + + + 源文件\Node\Button + + + 源文件\Node + + + 源文件\Node\Button + + + 源文件\Node\Button + + + 源文件\Style + + + 源文件 + + + 源文件 + + + 源文件\Style + + + 源文件\Msg + + + 源文件\Msg + + + + + 头文件 + + + \ No newline at end of file diff --git a/Easy2D/Easy2D.vcxproj.user b/Easy2D/Easy2D.vcxproj.user new file mode 100644 index 00000000..be250787 --- /dev/null +++ b/Easy2D/Easy2D.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Easy2D/EasyX/easyx.h b/Easy2D/EasyX/easyx.h new file mode 100644 index 00000000..d5a35fac --- /dev/null +++ b/Easy2D/EasyX/easyx.h @@ -0,0 +1,321 @@ +/****************************************************** + * EasyX Library for C++ (Ver:20170827(beta)) + * http://www.easyx.cn + * + * EasyX.h + * VC ʵּ򵥵Ļͼ + ******************************************************/ + +#pragma once + +#ifndef WINVER +#define WINVER 0x0400 // Specifies that the minimum required platform is Windows 95 and Windows NT 4.0. +#endif + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 // Specifies that the minimum required platform is Windows 2000. +#endif + +#ifndef _WIN32_WINDOWS +#define _WIN32_WINDOWS 0x0410 // Specifies that the minimum required platform is Windows 98. +#endif + + +#ifndef __cplusplus +#error EasyX is only for C++ +#endif + + +#include +#include + +// ͼڳʼ +#define SHOWCONSOLE 1 // ͼδʱ̨ʾ +#define NOCLOSE 2 // ûйرչ +#define NOMINIMIZE 4 // ûС + +// ɫ +#define BLACK 0 +#define BLUE 0xAA0000 +#define GREEN 0x00AA00 +#define CYAN 0xAAAA00 +#define RED 0x0000AA +#define MAGENTA 0xAA00AA +#define BROWN 0x0055AA +#define LIGHTGRAY 0xAAAAAA +#define DARKGRAY 0x555555 +#define LIGHTBLUE 0xFF5555 +#define LIGHTGREEN 0x55FF55 +#define LIGHTCYAN 0xFFFF55 +#define LIGHTRED 0x5555FF +#define LIGHTMAGENTA 0xFF55FF +#define YELLOW 0x55FFFF +#define WHITE 0xFFFFFF + +// ɫת +#define BGR(color) ( (((color) & 0xFF) << 16) | ((color) & 0xFF00FF00) | (((color) & 0xFF0000) >> 16) ) + + +class IMAGE; + +// ߵʽ +class LINESTYLE +{ +public: + LINESTYLE(); + LINESTYLE(const LINESTYLE &style); + LINESTYLE& operator = (const LINESTYLE &style); // ֵغ + virtual ~LINESTYLE(); + + DWORD style; + DWORD thickness; + DWORD *puserstyle; + DWORD userstylecount; +}; + +class FILLSTYLE +{ +public: + FILLSTYLE(); + FILLSTYLE(const FILLSTYLE &style); + FILLSTYLE& operator = (const FILLSTYLE &style); // ֵغ + virtual ~FILLSTYLE(); + + int style; // ʽ + long hatch; // ͼʽ + IMAGE* ppattern; // ͼ +}; + +// ͼ +class IMAGE +{ +public: + int getwidth() const; // ȡĿ + int getheight() const; // ȡĸ߶ + +private: + int width, height; // Ŀ + HBITMAP m_hBmp; + HDC m_hMemDC; + int m_MemCurX; // ǰX + int m_MemCurY; // ǰY + float m_data[6]; + COLORREF m_LineColor; // ǰɫ + COLORREF m_FillColor; // ǰɫ + COLORREF m_TextColor; // ǰɫ + COLORREF m_BkColor; // ǰɫ + DWORD* m_pBuffer; // ͼڴ + + LINESTYLE m_LineStyle; // ʽ + FILLSTYLE m_FillStyle; // ʽ + + virtual void SetDefault(); // ΪĬ״̬ + +public: + IMAGE(int _width = 0, int _height = 0); // ͼ + IMAGE(const IMAGE &img); // 캯 + IMAGE& operator = (const IMAGE &img); // ֵغ + virtual ~IMAGE(); + virtual void Resize(int _width, int _height); // ߴ +}; + + + +// ͼģʽغ + +HWND initgraph(int width, int height, int flag = NULL); // ʼͼλ +void closegraph(); // رͼλ + +// ͼ + +void cleardevice(); // +void setcliprgn(HRGN hrgn); // õǰͼ豸IJü +void clearcliprgn(); // üĻ + +void getlinestyle(LINESTYLE* pstyle); // ȡǰʽ +void setlinestyle(const LINESTYLE* pstyle); // õǰʽ +void setlinestyle(int style, int thickness = 1, const DWORD *puserstyle = NULL, DWORD userstylecount = 0); // õǰʽ +void getfillstyle(FILLSTYLE* pstyle); // ȡǰʽ +void setfillstyle(const FILLSTYLE* pstyle); // õǰʽ +void setfillstyle(int style, long hatch = NULL, IMAGE* ppattern = NULL); // õǰʽ +void setfillstyle(BYTE* ppattern8x8); // õǰʽ + +void setorigin(int x, int y); // ԭ +void getaspectratio(float *pxasp, float *pyasp); // ȡǰ +void setaspectratio(float xasp, float yasp); // õǰ + +int getrop2(); // ȡǰĶԪդģʽ +void setrop2(int mode); // ǰĶԪդģʽ +int getpolyfillmode(); // ȡģʽ +void setpolyfillmode(int mode); // öģʽ + +void graphdefaults(); // лͼΪĬֵ + +COLORREF getlinecolor(); // ȡǰɫ +void setlinecolor(COLORREF color); // õǰɫ +COLORREF gettextcolor(); // ȡǰɫ +void settextcolor(COLORREF color); // õǰɫ +COLORREF getfillcolor(); // ȡǰɫ +void setfillcolor(COLORREF color); // õǰɫ +COLORREF getbkcolor(); // ȡǰͼɫ +void setbkcolor(COLORREF color); // õǰͼɫ +int getbkmode(); // ȡģʽ +void setbkmode(int mode); // ñģʽ + +// ɫģת +COLORREF RGBtoGRAY(COLORREF rgb); +void RGBtoHSL(COLORREF rgb, float *H, float *S, float *L); +void RGBtoHSV(COLORREF rgb, float *H, float *S, float *V); +COLORREF HSLtoRGB(float H, float S, float L); +COLORREF HSVtoRGB(float H, float S, float V); + + +// ͼ + +COLORREF getpixel(int x, int y); // ȡɫ +void putpixel(int x, int y, COLORREF color); // + +void moveto(int x, int y); // ƶǰ() +void moverel(int dx, int dy); // ƶǰ() + +void line(int x1, int y1, int x2, int y2); // +void linerel(int dx, int dy); // () +void lineto(int x, int y); // () + +void rectangle (int left, int top, int right, int bottom); // +void fillrectangle (int left, int top, int right, int bottom); // (б߿) +void solidrectangle(int left, int top, int right, int bottom); // (ޱ߿) +void clearrectangle(int left, int top, int right, int bottom); // վ + +void circle (int x, int y, int radius); // Բ +void fillcircle (int x, int y, int radius); // Բ(б߿) +void solidcircle(int x, int y, int radius); // Բ(ޱ߿) +void clearcircle(int x, int y, int radius); // Բ + +void ellipse (int left, int top, int right, int bottom); // Բ +void fillellipse (int left, int top, int right, int bottom); // Բ(б߿) +void solidellipse(int left, int top, int right, int bottom); // Բ(ޱ߿) +void clearellipse(int left, int top, int right, int bottom); // Բ + +void roundrect (int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ +void fillroundrect (int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ(б߿) +void solidroundrect(int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ(ޱ߿) +void clearroundrect(int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ + +void arc (int left, int top, int right, int bottom, double stangle, double endangle); // Բ(ʼǶȺֹǶΪ) +void pie (int left, int top, int right, int bottom, double stangle, double endangle); // Բ(ʼǶȺֹǶΪ) +void fillpie (int left, int top, int right, int bottom, double stangle, double endangle); // Բ(б߿) +void solidpie(int left, int top, int right, int bottom, double stangle, double endangle); // Բ(ޱ߿) +void clearpie(int left, int top, int right, int bottom, double stangle, double endangle); // Բ + +void polyline (const POINT *points, int num); // +void polygon (const POINT *points, int num); // +void fillpolygon (const POINT *points, int num); // Ķ(б߿) +void solidpolygon(const POINT *points, int num); // Ķ(ޱ߿) +void clearpolygon(const POINT *points, int num); // ն + +void floodfill(int x, int y, int border); // + + + +// غ + +void outtext(LPCTSTR str); // ڵǰλַ +void outtext(TCHAR c); // ڵǰλַ +void outtextxy(int x, int y, LPCTSTR str); // ָλַ +void outtextxy(int x, int y, TCHAR c); // ָλַ +int textwidth(LPCTSTR str); // ȡַռõؿ +int textwidth(TCHAR c); // ȡַռõؿ +int textheight(LPCTSTR str); // ȡַռõظ +int textheight(TCHAR c); // ȡַռõظ +int drawtext(LPCTSTR str, RECT* pRect, UINT uFormat); // ָָʽַ +int drawtext(TCHAR c, RECT* pRect, UINT uFormat); // ָָʽַ + +// õǰʽ() +// nHeight: ַƽ߶ȣ +// nWidth: ַƽ(0 ʾӦ) +// lpszFace: ƣ +// nEscapement: ַдǶ(λ 0.1 ) +// nOrientation: ÿַдǶ(λ 0.1 ) +// nWeight: ַıʻϸ(0 ʾĬϴϸ) +// bItalic: Ƿб壻 +// bUnderline: Ƿ»ߣ +// bStrikeOut: Ƿɾߣ +// fbCharSet: ַָ +// fbOutPrecision: ֵָȣ +// fbClipPrecision: ֵָļȣ +// fbQuality: ֵָ +// fbPitchAndFamily: ָԳ淽ʽϵС +void settextstyle(int nHeight, int nWidth, LPCTSTR lpszFace); +void settextstyle(int nHeight, int nWidth, LPCTSTR lpszFace, int nEscapement, int nOrientation, int nWeight, bool bItalic, bool bUnderline, bool bStrikeOut); +void settextstyle(int nHeight, int nWidth, LPCTSTR lpszFace, int nEscapement, int nOrientation, int nWeight, bool bItalic, bool bUnderline, bool bStrikeOut, BYTE fbCharSet, BYTE fbOutPrecision, BYTE fbClipPrecision, BYTE fbQuality, BYTE fbPitchAndFamily); +void settextstyle(const LOGFONT *font); // õǰʽ +void gettextstyle(LOGFONT *font); // ȡǰʽ + + + +// ͼ +void loadimage(IMAGE *pDstImg, LPCTSTR pImgFile, int nWidth = 0, int nHeight = 0, bool bResize = false); // ͼƬļȡͼ(bmp/jpg/gif/emf/wmf) +void loadimage(IMAGE *pDstImg, LPCTSTR pResType, LPCTSTR pResName, int nWidth = 0, int nHeight = 0, bool bResize = false); // Դļȡͼ(bmp/jpg/gif/emf/wmf) +void saveimage(LPCTSTR pImgFile, IMAGE* pImg = NULL); // ͼ +void getimage(IMAGE *pDstImg, int srcX, int srcY, int srcWidth, int srcHeight); // ӵǰͼ豸ȡͼ +void putimage(int dstX, int dstY, const IMAGE *pSrcImg, DWORD dwRop = SRCCOPY); // ͼĻ +void putimage(int dstX, int dstY, int dstWidth, int dstHeight, const IMAGE *pSrcImg, int srcX, int srcY, DWORD dwRop = SRCCOPY); // ͼĻ(ָ) +void rotateimage(IMAGE *dstimg, IMAGE *srcimg, double radian, COLORREF bkcolor = BLACK, bool autosize = false, bool highquality = true);// תͼ +void Resize(IMAGE* pImg, int width, int height); // ͼ豸ĴС +DWORD* GetImageBuffer(IMAGE* pImg = NULL); // ȡͼ豸Դָ +IMAGE* GetWorkingImage(); // ȡǰͼ豸 +void SetWorkingImage(IMAGE* pImg = NULL); // õǰͼ豸 +HDC GetImageHDC(IMAGE* pImg = NULL); // ȡͼ豸(HDC) + + +// + +int getwidth(); // ȡͼ +int getheight(); // ȡͼ߶ +int getx(); // ȡǰ x +int gety(); // ȡǰ y + +void BeginBatchDraw(); // ʼ +void FlushBatchDraw(); // ִδɵĻ +void FlushBatchDraw(int left, int top, int right, int bottom); // ִָδɵĻ +void EndBatchDraw(); // ƣִδɵĻ +void EndBatchDraw(int left, int top, int right, int bottom); // ƣִָδɵĻ + +HWND GetHWnd(); // ȡͼھ(HWND) +TCHAR* GetEasyXVer(); // ȡ EasyX ǰ汾 + +// ȡû +bool InputBox(LPTSTR pString, int nMaxCount, LPCTSTR pPrompt = NULL, LPCTSTR pTitle = NULL, LPCTSTR pDefault = NULL, int width = 0, int height = 0, bool bOnlyOK = true); + + + +// Ϣ +// ֧Ϣ +// WM_MOUSEMOVE ƶ +// WM_MOUSEWHEEL ֲ +// WM_LBUTTONDOWN +// WM_LBUTTONUP +// WM_LBUTTONDBLCLK ˫ +// WM_MBUTTONDOWN м +// WM_MBUTTONUP м +// WM_MBUTTONDBLCLK м˫ +// WM_RBUTTONDOWN Ҽ +// WM_RBUTTONUP Ҽ +// WM_RBUTTONDBLCLK Ҽ˫ +struct MOUSEMSG +{ + UINT uMsg; // ǰϢ + bool mkCtrl; // Ctrl Ƿ + bool mkShift; // Shift Ƿ + bool mkLButton; // Ƿ + bool mkMButton; // мǷ + bool mkRButton; // ҼǷ + short x; // ǰ x + short y; // ǰ y + short wheel; // ֵֹ (120 ı) +}; + +bool MouseHit(); // ǷϢ +MOUSEMSG GetMouseMsg(); // ȡһϢûУ͵ȴ +void FlushMouseMsgBuffer(); // Ϣ diff --git a/Easy2D/EasyX/x86/EasyXa.lib b/Easy2D/EasyX/x86/EasyXa.lib new file mode 100644 index 00000000..db14e5bf Binary files /dev/null and b/Easy2D/EasyX/x86/EasyXa.lib differ diff --git a/Easy2D/EasyX/x86/EasyXw.lib b/Easy2D/EasyX/x86/EasyXw.lib new file mode 100644 index 00000000..c2f75141 Binary files /dev/null and b/Easy2D/EasyX/x86/EasyXw.lib differ diff --git a/Easy2D/FreePool.cpp b/Easy2D/FreePool.cpp new file mode 100644 index 00000000..f177c2d5 --- /dev/null +++ b/Easy2D/FreePool.cpp @@ -0,0 +1,39 @@ +#include "easy2d.h" + +// FreePool ͷųصʵֻƣ +/// Object еüm_nRefüָ֤ʹðȫ +/// ¼˶ʹõĴΪ 0 ʱFreePool Զͷ +/// е Object Ӧڱʹʱ Text ӵ˳У +/// retain ֤ö󲻱ɾڲʹʱ release +/// Զͷ + +// ͷų +static std::vector pool; + +void FreePool::__flush() +{ + // + std::vector::iterator iter; + // ѭеж + for (iter = pool.begin(); iter != pool.end();) + { + // õļΪ 0 + if ((*iter)->m_nRef == 0) + { + // ͷŸö + delete (*iter); + // ͷųɾö + iter = pool.erase(iter); + } + else + { + iter++; // ƶ + } + } +} + +void FreePool::add(Object * nptr) +{ + // һͷų + pool.push_back(nptr); +} diff --git a/Easy2D/Msg/KeyMsg.cpp b/Easy2D/Msg/KeyMsg.cpp new file mode 100644 index 00000000..6ed05471 --- /dev/null +++ b/Easy2D/Msg/KeyMsg.cpp @@ -0,0 +1,172 @@ +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" +#include + +// ص +static std::vector s_vKeyMsg; + +// ֵ +static std::vector s_vKeys = { + KeyMsg::A, KeyMsg::B, KeyMsg::C, KeyMsg::D, KeyMsg::E, KeyMsg::F, KeyMsg::G, KeyMsg::H, KeyMsg::I, KeyMsg::J, + KeyMsg::K, KeyMsg::L, KeyMsg::M, KeyMsg::N, KeyMsg::O, KeyMsg::P, KeyMsg::Q, KeyMsg::R, KeyMsg::S, KeyMsg::T, + KeyMsg::U, KeyMsg::V, KeyMsg::W, KeyMsg::X, KeyMsg::Y, KeyMsg::Z, + KeyMsg::NUM_1, KeyMsg::NUM_2, KeyMsg::NUM_3, KeyMsg::NUM_4, KeyMsg::NUM_5, + KeyMsg::NUM_6, KeyMsg::NUM_7, KeyMsg::NUM_8, KeyMsg::NUM_9, KeyMsg::NUM_0, + KeyMsg::NUMPAD_1, KeyMsg::NUMPAD_2, KeyMsg::NUMPAD_3, KeyMsg::NUMPAD_4, KeyMsg::NUMPAD_5, + KeyMsg::NUMPAD_6, KeyMsg::NUMPAD_7, KeyMsg::NUMPAD_8, KeyMsg::NUMPAD_9, KeyMsg::NUMPAD_0, + KeyMsg::Enter, KeyMsg::Space, KeyMsg::Up, KeyMsg::Down, KeyMsg::Left, KeyMsg::Right, KeyMsg::Esc, + KeyMsg::Decimal, KeyMsg::Shift, KeyMsg::LShift, KeyMsg::RShift, KeyMsg::Ctrl, KeyMsg::LCtrl, KeyMsg::RCtrl, + KeyMsg::F1, KeyMsg::F2, KeyMsg::F3, KeyMsg::F4, KeyMsg::F5, KeyMsg::F6, + KeyMsg::F7, KeyMsg::F8, KeyMsg::F9, KeyMsg::F10, KeyMsg::F11, KeyMsg::F12 +}; + +// ֵĶ +const VK_KEY KeyMsg::A = 'A'; +const VK_KEY KeyMsg::B = 'B'; +const VK_KEY KeyMsg::C = 'C'; +const VK_KEY KeyMsg::D = 'D'; +const VK_KEY KeyMsg::E = 'E'; +const VK_KEY KeyMsg::F = 'F'; +const VK_KEY KeyMsg::G = 'G'; +const VK_KEY KeyMsg::H = 'H'; +const VK_KEY KeyMsg::I = 'I'; +const VK_KEY KeyMsg::J = 'J'; +const VK_KEY KeyMsg::K = 'K'; +const VK_KEY KeyMsg::L = 'L'; +const VK_KEY KeyMsg::M = 'M'; +const VK_KEY KeyMsg::N = 'N'; +const VK_KEY KeyMsg::O = 'O'; +const VK_KEY KeyMsg::P = 'P'; +const VK_KEY KeyMsg::Q = 'Q'; +const VK_KEY KeyMsg::R = 'R'; +const VK_KEY KeyMsg::S = 'S'; +const VK_KEY KeyMsg::T = 'T'; +const VK_KEY KeyMsg::U = 'U'; +const VK_KEY KeyMsg::V = 'V'; +const VK_KEY KeyMsg::W = 'W'; +const VK_KEY KeyMsg::X = 'X'; +const VK_KEY KeyMsg::Y = 'Y'; +const VK_KEY KeyMsg::Z = 'Z'; +const VK_KEY KeyMsg::NUM_0 = '0'; +const VK_KEY KeyMsg::NUM_1 = '1'; +const VK_KEY KeyMsg::NUM_2 = '2'; +const VK_KEY KeyMsg::NUM_3 = '3'; +const VK_KEY KeyMsg::NUM_4 = '4'; +const VK_KEY KeyMsg::NUM_5 = '5'; +const VK_KEY KeyMsg::NUM_6 = '6'; +const VK_KEY KeyMsg::NUM_7 = '7'; +const VK_KEY KeyMsg::NUM_8 = '8'; +const VK_KEY KeyMsg::NUM_9 = '9'; +const VK_KEY KeyMsg::NUMPAD_0 = VK_NUMPAD0; +const VK_KEY KeyMsg::NUMPAD_1 = VK_NUMPAD1; +const VK_KEY KeyMsg::NUMPAD_2 = VK_NUMPAD2; +const VK_KEY KeyMsg::NUMPAD_3 = VK_NUMPAD3; +const VK_KEY KeyMsg::NUMPAD_4 = VK_NUMPAD4; +const VK_KEY KeyMsg::NUMPAD_5 = VK_NUMPAD5; +const VK_KEY KeyMsg::NUMPAD_6 = VK_NUMPAD6; +const VK_KEY KeyMsg::NUMPAD_7 = VK_NUMPAD7; +const VK_KEY KeyMsg::NUMPAD_8 = VK_NUMPAD8; +const VK_KEY KeyMsg::NUMPAD_9 = VK_NUMPAD9; +const VK_KEY KeyMsg::Enter = VK_RETURN; +const VK_KEY KeyMsg::Space = VK_SPACE; +const VK_KEY KeyMsg::Decimal = VK_DECIMAL; +const VK_KEY KeyMsg::Ctrl = VK_CONTROL; +const VK_KEY KeyMsg::LCtrl = VK_LCONTROL; +const VK_KEY KeyMsg::RCtrl = VK_RCONTROL; +const VK_KEY KeyMsg::Shift = VK_SHIFT; +const VK_KEY KeyMsg::LShift = VK_LSHIFT; +const VK_KEY KeyMsg::RShift = VK_RSHIFT; +const VK_KEY KeyMsg::Up = VK_UP; +const VK_KEY KeyMsg::Down = VK_DOWN; +const VK_KEY KeyMsg::Left = VK_LEFT; +const VK_KEY KeyMsg::Right = VK_RIGHT; +const VK_KEY KeyMsg::Esc = VK_ESCAPE; +const VK_KEY KeyMsg::F1 = VK_F1; +const VK_KEY KeyMsg::F2 = VK_F2; +const VK_KEY KeyMsg::F3 = VK_F3; +const VK_KEY KeyMsg::F4 = VK_F4; +const VK_KEY KeyMsg::F5 = VK_F5; +const VK_KEY KeyMsg::F6 = VK_F6; +const VK_KEY KeyMsg::F7 = VK_F7; +const VK_KEY KeyMsg::F8 = VK_F8; +const VK_KEY KeyMsg::F9 = VK_F9; +const VK_KEY KeyMsg::F10 = VK_F10; +const VK_KEY KeyMsg::F11 = VK_F11; +const VK_KEY KeyMsg::F12 = VK_F12; + +KeyMsg::KeyMsg(tstring name, const KEY_CALLBACK & callback) +{ + m_sName = name; + m_callback = callback; +} + +KeyMsg::~KeyMsg() +{ +} + +void KeyMsg::onKbHit(VK_KEY key) +{ + m_callback(key); +} + +void KeyMsg::__exec() +{ + if (_kbhit()) // ȡϢ + { + for (VK_KEY key : s_vKeys) // ѭеֵ + { + if (GetAsyncKeyState(key) & 0x8000) // жϸüǷ + { + for (auto k : s_vKeyMsg) // ַðϢ + { + k->onKbHit(key); // ִаص + } + } + } + } +} + +void KeyMsg::addListener(tstring name, const KEY_CALLBACK & callback) +{ + // µļ + auto key = new KeyMsg(name, callback); + // µİص + s_vKeyMsg.push_back(key); +} + +bool easy2d::KeyMsg::delListener(tstring name) +{ + // + std::vector::iterator iter; + // ѭм + for (iter = s_vKeyMsg.begin(); iter != s_vKeyMsg.end(); iter++) + { + // ͬƵļ + if ((*iter)->m_sName == name) + { + // ɾöʱ + delete (*iter); + s_vKeyMsg.erase(iter); + return true; + } + } + // δҵͬƵļ false + return false; +} + +void easy2d::KeyMsg::clearAllListener() +{ + // ɾм + for (auto t : s_vKeyMsg) + { + delete t; + } + // + s_vKeyMsg.clear(); +} + +bool KeyMsg::isKeyDown(VK_KEY key) +{ + // ȡ key İ + return (GetAsyncKeyState(key) & 0x8000); +} \ No newline at end of file diff --git a/Easy2D/Msg/MouseMsg.cpp b/Easy2D/Msg/MouseMsg.cpp new file mode 100644 index 00000000..8b725f25 --- /dev/null +++ b/Easy2D/Msg/MouseMsg.cpp @@ -0,0 +1,130 @@ +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" + +// Ϣ +static MouseMsg s_mouseMsg = MouseMsg(); + +// EasyX MOUSEMSG תΪ MouseMsg +static void ConvertMsg(MOUSEMSG msg); + +void easy2d::MouseMsg::__exec() +{ + // ȡϢ + while (MouseHit()) + { + // תϢ + ConvertMsg(GetMouseMsg()); + // ִг + Application::get()->getCurrentScene()->_exec(); + } +} + +MouseMsg MouseMsg::getMsg() +{ + return s_mouseMsg; // ȡǰϢ +} + +bool MouseMsg::getLButtonDown() +{ + return s_mouseMsg.mkLButton; +} + +bool MouseMsg::getRButtonDown() +{ + return s_mouseMsg.mkRButton; +} + +bool MouseMsg::getMButtonDown() +{ + return s_mouseMsg.mkMButton; +} + +int MouseMsg::getMouseX() +{ + return s_mouseMsg.x; +} + +int MouseMsg::getMouseY() +{ + return s_mouseMsg.y; +} + +int MouseMsg::getMouseWheel() +{ + return s_mouseMsg.wheel; +} + +bool MouseMsg::getMouseMovedMsg() +{ + return s_mouseMsg.uMsg == WM_MOUSEMOVE; +} + +bool MouseMsg::getLButtonDBClickedMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONDBLCLK; +} + +bool MouseMsg::getLButtonDownMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONDOWN; +} + +bool MouseMsg::getLButtonUpMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONUP; +} + +bool MouseMsg::getRButtonDBClicked() +{ + return s_mouseMsg.uMsg == WM_RBUTTONDBLCLK; +} + +bool MouseMsg::getRButtonDownMsg() +{ + return s_mouseMsg.uMsg == WM_RBUTTONDOWN; +} + +bool MouseMsg::getRButtonUpMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONUP; +} + +bool MouseMsg::getMButtonDBClicked() +{ + return s_mouseMsg.uMsg == WM_MBUTTONDBLCLK; +} + +bool MouseMsg::getMButtonDownMsg() +{ + return s_mouseMsg.uMsg == WM_MBUTTONDOWN; +} + +bool MouseMsg::getMButtonUpMsg() +{ + return s_mouseMsg.uMsg == WM_MBUTTONUP; +} + +bool MouseMsg::getWheelMsg() +{ + return s_mouseMsg.uMsg == WM_MOUSEWHEEL; +} + +void MouseMsg::resetMouseMsg() +{ + s_mouseMsg.uMsg = 0; +} + +void ConvertMsg(MOUSEMSG msg) +{ + // MOUSEMSG תΪ MouseMsg + /// Ȼ MOUSEMSG MouseMsg һ + /// Ϊʵ Easy2D EasyX Ը룬Զµ MouseMsg + /// Msg ϢĴͳһ WinAPIʵ֣ EasyX ĺ + s_mouseMsg.uMsg = msg.uMsg; + s_mouseMsg.mkLButton = msg.mkLButton; + s_mouseMsg.mkMButton = msg.mkMButton; + s_mouseMsg.mkRButton = msg.mkRButton; + s_mouseMsg.wheel = msg.wheel; + s_mouseMsg.x = msg.x; + s_mouseMsg.y = msg.y; +} diff --git a/Easy2D/Node/BatchNode.cpp b/Easy2D/Node/BatchNode.cpp new file mode 100644 index 00000000..57f507e0 --- /dev/null +++ b/Easy2D/Node/BatchNode.cpp @@ -0,0 +1,115 @@ +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" +#include + +BatchNode::BatchNode() +{ +} + + +BatchNode::~BatchNode() +{ + clearAllChildren(); +} + +bool BatchNode::_exec(bool active) +{ + // ڵǷʾ + if (!m_bDisplay) + { + return false; + } + // ӽڵ + for (int i = int(m_vChildren.size() - 1); i >= 0; i--) + { + assert(m_vChildren[i]); + if (m_vChildren[i]->_exec(active)) + { + active = false; + } + } + // ӽڵȡ˻潹㣬ýڵҲȡ˽ + return !active; +} + +void BatchNode::_onDraw() +{ + // ڵǷʾ + if (!m_bDisplay) + { + return; + } + + // λûӽڵ + Application::setOrigin(Application::getOriginX() + m_nX, Application::getOriginY() + m_nY); + for (auto child : m_vChildren) + { + assert(child); + child->_onDraw(); + } + Application::setOrigin(Application::getOriginX() - m_nX, Application::getOriginY() - m_nY); +} + +void BatchNode::add(Node * child, int z_Order) +{ + // ӵĽڵǿ + assert(child); + // ýڵĸ + child->setParentScene(this->getParentScene()); + // ýڵڵе z ˳ + child->setZOrder(z_Order); + // üһ + child->retain(); + + // z ˳ڵ + size_t size = m_vChildren.size(); + for (unsigned i = 0; i <= size; i++) + { + if (i != size) + { + if (z_Order < m_vChildren.at(i)->getZOrder()) + { + m_vChildren.insert(m_vChildren.begin() + i, child); + break; + } + } + else + { + m_vChildren.push_back(child); + break; + } + } +} + +bool BatchNode::del(Node * child) +{ + // Խڵǿ + assert(child); + + // ѰǷͬڵ + std::vector::iterator iter; + for (iter = m_vChildren.begin(); iter != m_vChildren.end(); iter++) + { + // ҵͬڵ + if ((*iter) == child) + { + // üһ + (*iter)->release(); + // ȥýڵ + m_vChildren.erase(iter); + return true; + } + } + return false; +} + +void BatchNode::clearAllChildren() +{ + // нڵüһ + for (auto child : m_vChildren) + { + child->release(); + } + // մڵ + m_vChildren.clear(); +} diff --git a/Easy2D/Node/Button/Button.cpp b/Easy2D/Node/Button/Button.cpp new file mode 100644 index 00000000..256166a6 --- /dev/null +++ b/Easy2D/Node/Button/Button.cpp @@ -0,0 +1,65 @@ +#include "..\..\Easy2d.h" +#include "..\..\EasyX\easyx.h" + + +Button::Button() : + m_bEnable(true) +{ +} + +Button::~Button() +{ +} + +bool Button::_exec(bool active) +{ + // ťǷ + if (!m_bEnable || !m_bDisplay) + { + return false; + } + return MouseNode::_exec(active); +} + +void Button::_onDraw() +{ + // ťǷ + if (!m_bEnable) + { + // δʱ Disable ״̬ + _onDisable(); + return; + } + MouseNode::_onDraw(); +} + +void Button::_judge() +{ + // жϰťǰ״̬ + // λڰťڵľ + if (MouseMsg::getMsg().x >= m_nX && MouseMsg::getMsg().x <= m_nX + m_nWidth && + MouseMsg::getMsg().y >= m_nY && MouseMsg::getMsg().y <= m_nY + m_nHeight) + { + _setMouseIn(); + + // ڰťϣ + if (MouseMsg::getLButtonDownMsg()) + { + _setSelected(); + } + } + else + { + _setNormal(); + } +} + +bool Button::isEnable() +{ + return m_bEnable; +} + +void Button::setEnable(bool enable) +{ + m_bEnable = enable; +} diff --git a/Easy2D/Node/Button/ImageButton.cpp b/Easy2D/Node/Button/ImageButton.cpp new file mode 100644 index 00000000..79733a98 --- /dev/null +++ b/Easy2D/Node/Button/ImageButton.cpp @@ -0,0 +1,167 @@ +#include "..\..\Easy2d.h" + + +ImageButton::ImageButton() : + m_pNormalImage(nullptr), + m_pMouseInImage(nullptr), + m_pSelectedImage(nullptr), + m_pUnableImage(nullptr) +{ + m_nWidth = 0; + m_nHeight = 0; +} + +ImageButton::ImageButton(Image * image) : + ImageButton() +{ + setNormalImage(image); // ðť״̬ʱͼƬ +} + +ImageButton::~ImageButton() +{ + // ͼƬüһ + SAFE_RELEASE(m_pNormalImage); + SAFE_RELEASE(m_pMouseInImage); + SAFE_RELEASE(m_pSelectedImage); + SAFE_RELEASE(m_pUnableImage); +} + +void ImageButton::_onNormal() +{ + if (m_pNormalImage) + { + m_pNormalImage->_onDraw(); + } +} + +void ImageButton::_onMouseIn() +{ + if (m_pMouseInImage) + { + m_pMouseInImage->_onDraw(); + } + else + { + _onNormal(); + } +} + +void ImageButton::_onSelected() +{ + if (m_pSelectedImage) + { + m_pSelectedImage->_onDraw(); + } + else + { + _onNormal(); + } +} + +void ImageButton::_onDisable() +{ + if (m_pUnableImage) + { + m_pUnableImage->_onDraw(); + } + else + { + _onNormal(); + } +} + +void ImageButton::setNormalImage(Image * image) +{ + if (image) + { + // ԭͼƬüһ + SAFE_RELEASE(m_pNormalImage); + // ޸ͼƬ + m_pNormalImage = image; + // ͼƬüһ + m_pNormalImage->retain(); + // ¼ͼƬλ + resetImagePosition(); + } +} + +void ImageButton::setMouseInImage(Image * image) +{ + if (image) + { + SAFE_RELEASE(m_pMouseInImage); + m_pMouseInImage = image; + m_pMouseInImage->retain(); + resetImagePosition(); + } +} + +void ImageButton::setSelectedImage(Image * image) +{ + if (image) + { + SAFE_RELEASE(m_pSelectedImage); + m_pSelectedImage = image; + m_pSelectedImage->retain(); + resetImagePosition(); + } +} + +void ImageButton::setUnableImage(Image * image) +{ + if (image) + { + SAFE_RELEASE(m_pUnableImage); + m_pUnableImage = image; + m_pUnableImage->retain(); + resetImagePosition(); + } +} + +void ImageButton::setX(int x) +{ + Node::setX(x); + resetImagePosition(); +} + +void ImageButton::setY(int y) +{ + Node::setY(y); + resetImagePosition(); +} + +void ImageButton::setPos(int x, int y) +{ + Node::setPos(x, y); + resetImagePosition(); +} + +void ImageButton::resetImagePosition() +{ + if (m_pNormalImage) + { + // ͼƬ趨ťС + m_nWidth = m_pNormalImage->getWidth(); + m_nHeight = m_pNormalImage->getHeight(); + // ݰťλúͼƬͼƬλþʾ + m_pNormalImage->setPos(m_nX, m_nY); + } + if (m_pMouseInImage) + { + m_pMouseInImage->setPos( + m_nX + (m_nWidth - m_pMouseInImage->getWidth()) / 2, + m_nY + (m_nHeight - m_pMouseInImage->getHeight()) / 2); + } + if (m_pSelectedImage) + { + m_pSelectedImage->setPos( + m_nX + (m_nWidth - m_pSelectedImage->getWidth()) / 2, + m_nY + (m_nHeight - m_pSelectedImage->getHeight()) / 2); + } + if (m_pUnableImage) + { + m_pUnableImage->setPos( + m_nX + (m_nWidth - m_pUnableImage->getWidth()) / 2, + m_nY + (m_nHeight - m_pUnableImage->getHeight()) / 2); + } +} diff --git a/Easy2D/Node/Button/TextButton.cpp b/Easy2D/Node/Button/TextButton.cpp new file mode 100644 index 00000000..fb6ce9d9 --- /dev/null +++ b/Easy2D/Node/Button/TextButton.cpp @@ -0,0 +1,167 @@ +#include "..\..\Easy2d.h" + + +TextButton::TextButton() : + m_pNormalText(nullptr), + m_pMouseInText(nullptr), + m_pSelectedText(nullptr), + m_pUnableText(nullptr) +{ + m_nWidth = 0; + m_nHeight = 0; +} + +TextButton::TextButton(Text * text) : + TextButton() +{ + setNormalText(text); // ðť״̬ʱ +} + +TextButton::~TextButton() +{ + // ıüһ + SAFE_RELEASE(m_pNormalText); + SAFE_RELEASE(m_pMouseInText); + SAFE_RELEASE(m_pSelectedText); + SAFE_RELEASE(m_pUnableText); +} + +void TextButton::_onNormal() +{ + if (m_pNormalText) + { + m_pNormalText->_onDraw(); + } +} + +void TextButton::_onMouseIn() +{ + if (m_pMouseInText) + { + m_pMouseInText->_onDraw(); + } + else + { + _onNormal(); + } +} + +void TextButton::_onSelected() +{ + if (m_pSelectedText) + { + m_pSelectedText->_onDraw(); + } + else + { + _onNormal(); + } +} + +void TextButton::_onDisable() +{ + if (m_pUnableText) + { + m_pUnableText->_onDraw(); + } + else + { + _onNormal(); + } +} + +void TextButton::setNormalText(Text * text) +{ + if (text) + { + // ԭıüһ + SAFE_RELEASE(m_pNormalText); + // ޸ı + m_pNormalText = text; + // ıüһ + m_pNormalText->retain(); + // ¼ıλ + resetTextPosition(); + } +} + +void TextButton::setMouseInText(Text * text) +{ + if (text) + { + SAFE_RELEASE(m_pMouseInText); + m_pMouseInText = text; + m_pMouseInText->retain(); + resetTextPosition(); + } +} + +void TextButton::setSelectedText(Text * text) +{ + if (text) + { + SAFE_RELEASE(m_pSelectedText); + m_pSelectedText = text; + m_pSelectedText->retain(); + resetTextPosition(); + } +} + +void TextButton::setUnableText(Text * text) +{ + if (text) + { + SAFE_RELEASE(m_pUnableText); + m_pUnableText = text; + m_pUnableText->retain(); + resetTextPosition(); + } +} + +void TextButton::setX(int x) +{ + Node::setX(x); + resetTextPosition(); +} + +void TextButton::setY(int y) +{ + Node::setY(y); + resetTextPosition(); +} + +void TextButton::setPos(int x, int y) +{ + Node::setPos(x, y); + resetTextPosition(); +} + +void TextButton::resetTextPosition() +{ + if (m_pNormalText) + { + // ֿ趨ťС + m_nWidth = m_pNormalText->getWidth(); + m_nHeight = m_pNormalText->getHeight(); + // ݰťλúֿλþʾ + m_pNormalText->setPos(m_nX , m_nY); + } + if (m_pMouseInText) + { + m_pMouseInText->setPos( + m_nX + (m_nWidth - m_pMouseInText->getWidth()) / 2, + m_nY + (m_nHeight - m_pMouseInText->getHeight()) / 2); + } + if (m_pSelectedText) + { + m_pSelectedText->setPos( + m_nX + (m_nWidth - m_pSelectedText->getWidth()) / 2, + m_nY + (m_nHeight - m_pSelectedText->getHeight()) / 2); + } + if (m_pUnableText) + { + m_pUnableText->setPos( + m_nX + (m_nWidth - m_pUnableText->getWidth()) / 2, + m_nY + (m_nHeight - m_pUnableText->getHeight()) / 2); + } +} diff --git a/Easy2D/Node/Image.cpp b/Easy2D/Node/Image.cpp new file mode 100644 index 00000000..bc9f84db --- /dev/null +++ b/Easy2D/Node/Image.cpp @@ -0,0 +1,181 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" + +// PNG ͼת +static void CrossImage(CImage &img); + +Image::Image() : + m_fScaleX(1), + m_fScaleY(1) +{ +} + +Image::Image(LPCTSTR ImageFile, int x, int y, int width, int height) : + m_fScaleX(1), + m_fScaleY(1) +{ + setImageFile(ImageFile, x, y, width, height); // ͼƬԴͲüС +} + +Image::~Image() +{ +} + +void Image::_onDraw() +{ + // display Ϊ falseδͼƬԴʱƸͼƬ + if (!m_bDisplay || m_Image.IsNull()) + { + return; + } + // ͼƬ + m_Image.Draw(GetImageHDC(), m_rDest, m_rSrc); +} + +int Image::getWidth() const +{ + return m_rDest.Width(); // ĿεĿ +} + +int Image::getHeight() const +{ + return m_rDest.Height(); // Ŀεĸ߶ +} + +float Image::getScaleX() const +{ + return m_fScaleX; +} + +float Image::getScaleY() const +{ + return m_fScaleY; +} + +void Image::setImageFile(LPCTSTR ImageFile, int x, int y, int width, int height) +{ + // ͼƬ + m_Image.Load(ImageFile); + // ȡչ PNG ͼƬ⴦ + if (_T(".png") == FileUtils::getFileExtension(ImageFile)) + { + // ת + CrossImage(m_Image); + // Alpha ͨ + m_Image.AlphaBlend(GetImageHDC(), 15, 30); + } + // ĿΣƵڵλúʹС + m_rDest.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); + // üͼƬС + crop(x, y, width, height); +} + +void Image::setImageRes(LPCTSTR pResName, int x, int y, int width, int height) +{ + // ԴͼƬ֧ PNG + m_Image.LoadFromResource(GetModuleHandle(NULL), pResName); + // + m_fScaleX = 0, m_fScaleY = 0; + // ĿΣƵڵλúʹС + m_rDest.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); + // üͼƬС + crop(x, y, width, height); +} + +void Image::crop(int x, int y, int width, int height) +{ + // ԴελúʹСڲü + m_rSrc.SetRect( + x, y, + x + (width ? width : m_Image.GetWidth() - x), + y + (height ? height : m_Image.GetHeight() - y)); + // ĿΣƵڵλúʹС + m_rDest.SetRect( + m_nX, m_nY, + m_nX + (width ? width : int(m_rSrc.Width() * m_fScaleX)), + m_nY + (height ? height : int(m_rSrc.Height() * m_fScaleY))); +} + +void Image::stretch(int width, int height) +{ + // ĿελúʹСƵڵλúʹСͼƬ + m_rDest.SetRect( + m_nX, m_nY, + m_nX + (width ? width : m_Image.GetWidth()), + m_nY + (height ? height : m_Image.GetHeight())); +} + +void Image::scale(float scaleX, float scaleY) +{ + m_fScaleX = min(max(scaleX, 0), 1.0f); + m_fScaleY = min(max(scaleY, 0), 1.0f); + m_rDest.SetRect( + m_nX, m_nY, + m_nX + int(m_Image.GetWidth() * scaleX), + m_nY + int(m_Image.GetHeight() * scaleY)); +} + +void Image::setPos(int x, int y) +{ + // ƶĿ + m_rDest.MoveToXY(x, y); + m_nX = x; + m_nY = y; +} + +void Image::move(int x, int y) +{ + // ƶĿ + m_rDest.OffsetRect(x, y); + m_nX += x; + m_nY += y; +} + +void Image::setX(int x) +{ + // ƶĿ + m_rDest.MoveToX(x); + m_nX = x; +} + +void Image::setY(int y) +{ + // ƶĿ + m_rDest.MoveToY(y); + m_nY = y; +} + +void Image::setTransparentColor(COLORREF value) +{ + // ͸ɫ + m_Image.SetTransparentColor(value); +} + +void Image::screenshot() +{ + tstring savePath; + // ȡλ + if (FileUtils::getSaveFilePath(savePath, _T("ͼ浽"), _T("jpg"))) + { + // 洰ڽͼ + IMAGE image; + getimage(&image, 0, 0, Application::get()->getWidth(), Application::get()->getHeight()); + saveimage(savePath.c_str(), &image); + } +} + + +// PNG ͼת +void CrossImage(CImage &img) +{ + for (int i = 0; i < img.GetWidth(); i++) + { + for (int j = 0; j < img.GetHeight(); j++) + { + UCHAR *cr = (UCHAR*)img.GetPixelAddress(i, j); + cr[0] = cr[0] * cr[3] / 255; + cr[1] = cr[1] * cr[3] / 255; + cr[2] = cr[2] * cr[3] / 255; + } + } +} \ No newline at end of file diff --git a/Easy2D/Node/MouseNode.cpp b/Easy2D/Node/MouseNode.cpp new file mode 100644 index 00000000..089b7ec6 --- /dev/null +++ b/Easy2D/Node/MouseNode.cpp @@ -0,0 +1,109 @@ +#include "..\easy2d.h" + + +MouseNode::MouseNode() : + m_bBlock(true), + m_bTarget(false), + m_callback([]() {}) +{ +} + +MouseNode::~MouseNode() +{ +} + +bool MouseNode::_exec(bool active) +{ + // ȡý㣬 display Ϊ false˳ + if (!active || !m_bDisplay) + { + return false; + } + // жϽڵ״̬ + _judge(); + // ڽڵϣѡʱҲڽڵϣ + if (m_eStatus == MOUSEIN || m_eStatus == SELECTED) + { + // ڵ㱻ѡУ̧ + if (m_bTarget && MouseMsg::getLButtonUpMsg()) + { + onClicked(); // ִлص + } + // ڵ㲻Ϣȡû潹 + if (!m_bBlock) return true; + } + return false; +} + +void MouseNode::_onDraw() +{ + // ڵǷʾ + if (!m_bDisplay) + { + return; + } + // ڵǷѡ + if (m_eStatus == SELECTED) + { + _onSelected(); + } + else + { + // Ƿڽڵ + if (m_eStatus == MOUSEIN) + { + _onMouseIn(); + } + else + { + _onNormal(); + } + } +} + +void MouseNode::_setNormal() +{ + m_bTarget = false; // ʧȥ + m_eStatus = NORMAL; +} + +void MouseNode::_setMouseIn() +{ + m_eStatus = MOUSEIN; +} + +void MouseNode::_setSelected() +{ + m_bTarget = true; // ȡý + m_eStatus = SELECTED; +} + +void MouseNode::onClicked() +{ + m_callback(); +} + +bool MouseNode::isMouseIn() +{ + return m_eStatus == MOUSEIN || m_eStatus == SELECTED; +} + +bool MouseNode::isSelected() +{ + return m_eStatus == SELECTED; +} + +void MouseNode::setOnMouseClicked(const CLICK_CALLBACK & callback) +{ + m_callback = callback; +} + +void MouseNode::reset() +{ + m_eStatus = NORMAL; +} + +void MouseNode::setBlock(bool block) +{ + m_bBlock = block; +} diff --git a/Easy2D/Node/Node.cpp b/Easy2D/Node/Node.cpp new file mode 100644 index 00000000..3f8ea475 --- /dev/null +++ b/Easy2D/Node/Node.cpp @@ -0,0 +1,92 @@ +#include "..\Easy2d.h" + +Node::Node() : + m_nZOrder(0), + m_bDisplay(true), + m_nX(0), + m_nY(0) +{ +} + +Node::Node(int x, int y) : + m_nZOrder(0), + m_bDisplay(true), + m_nX(x), + m_nY(y) +{ +} + +Node::~Node() +{ +} + +bool Node::_exec(bool active) +{ + return false; +} + +void Node::_onDraw() +{ +} + +const int Node::getX() const +{ + return m_nX; +} + +const int Node::getY() const +{ + return m_nY; +} + +void Node::setX(int x) +{ + m_nX = x; +} + +void Node::setY(int y) +{ + m_nY = y; +} + +void Node::setPos(int x, int y) +{ + m_nX = x; + m_nY = y; +} + +void Node::move(int x, int y) +{ + m_nX += x; + m_nY += y; +} + +int Node::getZOrder() const +{ + return m_nZOrder; +} + +void Node::setZOrder(int z) +{ + m_nZOrder = z; +} + +Scene * Node::getParentScene() +{ + return m_pScene; +} + +void Node::setParentScene(Scene * scene) +{ + m_pScene = scene; +} + +void Node::setDisplay(bool value) +{ + m_bDisplay = value; +} + +bool Node::display() const +{ + return m_bDisplay; +} \ No newline at end of file diff --git a/Easy2D/Node/Shape/Circle.cpp b/Easy2D/Node/Shape/Circle.cpp new file mode 100644 index 00000000..0e5af186 --- /dev/null +++ b/Easy2D/Node/Shape/Circle.cpp @@ -0,0 +1,43 @@ +#include "..\..\easy2d.h" +#include "..\..\EasyX\easyx.h" + + +Circle::Circle() : + m_nRadius(0) +{ +} + +Circle::Circle(int x, int y, int radius) : + Node(x, y), + m_nRadius(radius) +{ +} + +Circle::~Circle() +{ +} + +void Circle::solidShape() +{ + solidcircle(m_nX, m_nY, m_nRadius); +} + +void Circle::fillShape() +{ + fillcircle(m_nX, m_nY, m_nRadius); +} + +void Circle::roundShape() +{ + circle(m_nX, m_nY, m_nRadius); +} + +int Circle::getRadius() const +{ + return m_nRadius; +} + +void Circle::setRadius(int r) +{ + m_nRadius = r; +} \ No newline at end of file diff --git a/Easy2D/Node/Shape/Rectangle.cpp b/Easy2D/Node/Shape/Rectangle.cpp new file mode 100644 index 00000000..4c7517a4 --- /dev/null +++ b/Easy2D/Node/Shape/Rectangle.cpp @@ -0,0 +1,61 @@ +#include "..\..\easy2d.h" +#include "..\..\EasyX\easyx.h" + + +Rect::Rect() : + m_nWidth(0), + m_nHeight(0) +{ +} + +Rect::Rect(int x, int y, int width, int height) : + Node(x, y), + m_nWidth(width), + m_nHeight(height) +{ +} + +Rect::~Rect() +{ +} + +void Rect::solidShape() +{ + solidrectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); +} + +void Rect::fillShape() +{ + fillrectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); +} + +void Rect::roundShape() +{ + rectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); +} + +int Rect::getWidth() const +{ + return m_nWidth; +} + +int Rect::getHeight() const +{ + return m_nHeight; +} + +void Rect::setWidth(int width) +{ + m_nWidth = width; +} + +void Rect::setHeight(int height) +{ + m_nHeight = height; +} + +void Rect::setSize(int width, int height) +{ + m_nWidth = width; + m_nHeight = height; +} \ No newline at end of file diff --git a/Easy2D/Node/Shape/Shape.cpp b/Easy2D/Node/Shape/Shape.cpp new file mode 100644 index 00000000..7258439d --- /dev/null +++ b/Easy2D/Node/Shape/Shape.cpp @@ -0,0 +1,56 @@ +#include "..\..\Easy2d.h" +#include "..\..\EasyX\easyx.h" + +Shape::Shape() +{ +} + +Shape::~Shape() +{ +} + +void Shape::_onDraw() +{ + // ״Ƿʾ + if (!m_bDisplay) + { + return; + } + // ɫ + setlinecolor(lineColor); + setfillcolor(fillColor); + + // ״ʽвͬĻ + if (_style == Shape::STYLE::round) + { + roundShape(); + } + else if (_style == Shape::STYLE::solid) + { + solidShape(); + } + else if (_style == Shape::STYLE::fill) + { + fillShape(); + } +} + +inline COLORREF Shape::getFillColor() const +{ + return fillColor; +} + +inline COLORREF Shape::getLineColor() const +{ + return lineColor; +} + +void Shape::setFillColor(COLORREF color) +{ + fillColor = color; +} + +void Shape::setLineColor(COLORREF color) +{ + lineColor = color; +} diff --git a/Easy2D/Node/Sprite/Sprite.cpp b/Easy2D/Node/Sprite/Sprite.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Easy2D/Node/Sprite/SpriteFrame.cpp b/Easy2D/Node/Sprite/SpriteFrame.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Easy2D/Node/Text.cpp b/Easy2D/Node/Text.cpp new file mode 100644 index 00000000..cbef6dbd --- /dev/null +++ b/Easy2D/Node/Text.cpp @@ -0,0 +1,99 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" + + +Text::Text() : + m_sText(_T("")), + m_color(Color::white), + m_pFontStyle(FontStyle::getDefault()) +{ + m_pFontStyle->retain(); // üһ +} + +Text::Text(tstring text, COLORREF color, FontStyle * font) : + m_sText(text), + m_color(color), + m_pFontStyle(font) +{ + m_pFontStyle->retain(); // üһ +} + +Text::Text(int x, int y, tstring text, COLORREF color, FontStyle * font) : + Node(x, y), + m_sText(text), + m_color(color), + m_pFontStyle(font) +{ + m_pFontStyle->retain(); // üһ +} + +Text::~Text() +{ + SAFE_RELEASE(m_pFontStyle); // üһ +} + +void Text::_onDraw() +{ + // display Ϊ falseı + if (!m_bDisplay) + { + return; + } + // + settextstyle(&m_pFontStyle->m_font); + // ıɫ + settextcolor(m_color); + // + outtextxy(m_nX, m_nY, m_sText.c_str()); +} + +COLORREF Text::getColor() const +{ + return m_color; +} + +tstring Text::getText() const +{ + return m_sText; +} + +FontStyle * Text::getFontStyle() +{ + return m_pFontStyle; +} + +int Text::getWidth() +{ + // 壬ȻȡıڸµĿ + settextstyle(&m_pFontStyle->m_font); + return textwidth(getText().c_str()); +} + +int Text::getHeight() +{ + // 壬Ȼȡıڸµĸ߶ + settextstyle(&m_pFontStyle->m_font); + return textheight(getText().c_str()); +} + +bool Text::isEmpty() const +{ + return m_sText.empty(); // ıǷΪ +} + +void Text::setText(tstring text) +{ + m_sText = text; +} + +void Text::setColor(COLORREF color) +{ + m_color = color; +} + +void Text::setFontStyle(FontStyle * style) +{ + SAFE_RELEASE(m_pFontStyle); // ԭüһ + m_pFontStyle = style; // ޸ + m_pFontStyle->retain(); // üһ +} diff --git a/Easy2D/Object.cpp b/Easy2D/Object.cpp new file mode 100644 index 00000000..08ca53aa --- /dev/null +++ b/Easy2D/Object.cpp @@ -0,0 +1,21 @@ +#include "easy2d.h" + +Object::Object() : + m_nRef(0) +{ + FreePool::add(this); // öͷų +} + +Object::~Object() +{ +} + +void Object::retain() +{ + m_nRef++; // üһ +} + +void Object::release() +{ + m_nRef--; // üһ +} diff --git a/Easy2D/Scene.cpp b/Easy2D/Scene.cpp new file mode 100644 index 00000000..93099331 --- /dev/null +++ b/Easy2D/Scene.cpp @@ -0,0 +1,102 @@ +#include "easy2d.h" +#include + +Scene::Scene() +{ +} + +Scene::~Scene() +{ + clearAllChildren(); +} + +void Scene::_exec() +{ + // active ־Ƿȡý + bool active = true; + // ִУƵĽڵ㣨λڻϷȱ + for (int i = int(m_vChildren.size()) - 1; i >= 0; i--) + { + assert(m_vChildren[i]); + if (m_vChildren[i]->_exec(active)) // ִнڵ + { + active = false; // ӽڵȡý㣬־ false + } + } +} + +void Scene::_onDraw() +{ + // нڵ + for (auto child : m_vChildren) + { + assert(child); + child->_onDraw(); + } +} + +void Scene::add(Node * child, int zOrder) +{ + // ӵĽڵǿ + assert(child); + // ýڵĸ + child->setParentScene(this); + // z ˳ + child->setZOrder(zOrder); + // üһ + child->retain(); + + // z ˳ڵ + size_t size = m_vChildren.size(); + for (unsigned i = 0; i <= size; i++) + { + if (i == size) + { + m_vChildren.push_back(child); + break; + } + else + { + auto temp = m_vChildren.at(i); + if (temp->getZOrder() > zOrder) + { + m_vChildren.insert(m_vChildren.begin() + i, child); + break; + } + } + } +} + +bool Scene::del(Node * child) +{ + // Խڵǿ + assert(child); + + // ѰǷͬڵ + std::vector::iterator iter; + for (iter = m_vChildren.begin(); iter != m_vChildren.end(); iter++) + { + // ҵͬڵ + if (*iter == child) + { + // üһ + (*iter)->release(); + // ȥýڵ + m_vChildren.erase(iter); + return true; + } + } + // δҵýڵ㷵 false + return false; +} + +void Scene::clearAllChildren() +{ + // нڵüһ + for (auto child : m_vChildren) + { + child->release(); + } + // մڵ + m_vChildren.clear(); +} \ No newline at end of file diff --git a/Easy2D/Style/Color.cpp b/Easy2D/Style/Color.cpp new file mode 100644 index 00000000..5daa3584 --- /dev/null +++ b/Easy2D/Style/Color.cpp @@ -0,0 +1,56 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" + +// ɫֵĶ +const COLORREF Color::black = BLACK; +const COLORREF Color::blue = BLUE; +const COLORREF Color::green = GREEN; +const COLORREF Color::cyan = CYAN; +const COLORREF Color::red = RED; +const COLORREF Color::magenta = MAGENTA; +const COLORREF Color::brown = BROWN; +const COLORREF Color::lightgray = LIGHTGRAY; +const COLORREF Color::darkgray = DARKGRAY; +const COLORREF Color::lightblue = LIGHTBLUE; +const COLORREF Color::lightgreen = LIGHTGREEN; +const COLORREF Color::lightcyan = LIGHTCYAN; +const COLORREF Color::lightred = LIGHTRED; +const COLORREF Color::lightmagenta = LIGHTMAGENTA; +const COLORREF Color::yellow = YELLOW; +const COLORREF Color::white = WHITE; + + +COLORREF Color::getFromRGB(BYTE r, BYTE g, BYTE b) +{ + return RGB(r, g, b); // (r, g, b) ɫֵתΪɫ +} + +COLORREF Color::getFromHSL(float H, float S, float L) +{ + return HSLtoRGB(H, S, L); +} + +COLORREF Color::getFromHSV(float H, float S, float V) +{ + return HSVtoRGB(H, S, V); +} + +BYTE Color::getRValue(COLORREF color) +{ + return GetRValue(color); // ɫеĺɫֵ +} + +BYTE Color::getGValue(COLORREF color) +{ + return GetGValue(color); // ɫеɫֵ +} + +BYTE Color::getBValue(COLORREF color) +{ + return GetBValue(color); // ɫеɫֵ +} + +COLORREF Color::getGray(COLORREF color) +{ + return RGBtoGRAY(color); // ȡɫеĻҶֵ +} diff --git a/Easy2D/Style/FillStyle.cpp b/Easy2D/Style/FillStyle.cpp new file mode 100644 index 00000000..498580d5 --- /dev/null +++ b/Easy2D/Style/FillStyle.cpp @@ -0,0 +1 @@ +/* FillStyle EasyX е࣬Ŀǰδʵ */ \ No newline at end of file diff --git a/Easy2D/Style/FontStyle.cpp b/Easy2D/Style/FontStyle.cpp new file mode 100644 index 00000000..6d9b6921 --- /dev/null +++ b/Easy2D/Style/FontStyle.cpp @@ -0,0 +1,97 @@ +#include "..\Easy2d.h" + +// ϸֵĶ +const LONG FontWeight::dontcare = 0; +const LONG FontWeight::thin = 100; +const LONG FontWeight::extraLight = 200; +const LONG FontWeight::light = 300; +const LONG FontWeight::normal = 400; +const LONG FontWeight::regular = 400; +const LONG FontWeight::medium = 500; +const LONG FontWeight::demiBlod = 600; +const LONG FontWeight::blod = 700; +const LONG FontWeight::extraBold = 800; +const LONG FontWeight::black = 900; +const LONG FontWeight::heavy = 900; + +// Ĭ +static const FontStyle s_defaultFont(_T(""), 18, FontWeight::normal); + + +FontStyle::FontStyle() +{ + m_font = s_defaultFont.m_font; +} + +FontStyle::FontStyle(LPCTSTR fontfamily, LONG height, LONG weight, LONG width, bool italic, bool underline, bool strikeout, LONG escapement, LONG orientation, bool quality) +{ + setFontFamily(fontfamily); + m_font.lfWeight = weight; + m_font.lfHeight = height; + m_font.lfWidth = width; + m_font.lfItalic = italic; + m_font.lfUnderline = underline; + m_font.lfStrikeOut = strikeout; + m_font.lfEscapement = escapement; + m_font.lfOrientation = orientation; + setQuality(quality); +} + +FontStyle::~FontStyle() +{ +} + +FontStyle * FontStyle::getDefault() +{ + return new FontStyle(s_defaultFont); +} + +void FontStyle::setHeight(LONG value) +{ + m_font.lfHeight = value; +} + +void FontStyle::setWidth(LONG value) +{ + m_font.lfWidth = value; +} + +void FontStyle::setFontFamily(LPCTSTR value) +{ + _tcscpy_s(m_font.lfFaceName, 32, value); +} + +void FontStyle::setEscapement(LONG value) +{ + m_font.lfEscapement = value; +} + +void FontStyle::setOrientation(LONG value) +{ + m_font.lfOrientation = value; +} + +void FontStyle::setQuality(bool value) +{ + m_font.lfQuality = value ? ANTIALIASED_QUALITY : DEFAULT_QUALITY; +} + +void FontStyle::setWeight(LONG value) +{ + m_font.lfWeight = value; +} + +void FontStyle::setItalic(bool value) +{ + m_font.lfItalic = value; +} + +void FontStyle::setUnderline(bool value) +{ + m_font.lfUnderline = value; +} + +void FontStyle::setStrikeOut(bool value) +{ + m_font.lfStrikeOut = value; +} \ No newline at end of file diff --git a/Easy2D/Style/LineStyle.cpp b/Easy2D/Style/LineStyle.cpp new file mode 100644 index 00000000..1b613360 --- /dev/null +++ b/Easy2D/Style/LineStyle.cpp @@ -0,0 +1 @@ +/* LineStyle EasyX е࣬Ŀǰδʵ */ \ No newline at end of file diff --git a/Easy2D/Tool/FileUtils.cpp b/Easy2D/Tool/FileUtils.cpp new file mode 100644 index 00000000..067cca17 --- /dev/null +++ b/Easy2D/Tool/FileUtils.cpp @@ -0,0 +1,45 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" +#include + + +tstring FileUtils::getFileExtension(const tstring & filePath) +{ + tstring fileExtension; + // ҵļеһ '.' λ + size_t pos = filePath.find_last_of('.'); + // ж pos ǷǸЧλ + if (pos != tstring::npos) + { + // ȡչ + fileExtension = filePath.substr(pos, filePath.length()); + // תΪСдĸ + std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); + } + + return fileExtension; +} + +bool FileUtils::getSaveFilePath(tstring& path, LPCTSTR title, LPCTSTR defExt) +{ + // Ի + OPENFILENAME ofn = { 0 }; + TCHAR strFilename[MAX_PATH] = { 0 }; // ڽļ + ofn.lStructSize = sizeof(OPENFILENAME); // ṹС + ofn.hwndOwner = GetHWnd(); // ӵŴھNULL ʾԻǷģ̬ + ofn.lpstrFilter = _T("ļ\0*.*\0\0"); // ù + ofn.nFilterIndex = 1; // + ofn.lpstrFile = strFilename; // շصļ·ļ + ofn.nMaxFile = sizeof(strFilename); // + ofn.lpstrInitialDir = NULL; // ʼĿ¼ΪĬ + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;// Ŀ¼ڣļǰ + ofn.lpstrTitle = title; // ʹϵͳĬϱռ + ofn.lpstrDefExt = defExt; // Ĭ׷ӵչ + + if (GetSaveFileName(&ofn)) + { + path = strFilename; + return true; + } + return false; +} diff --git a/Easy2D/Tool/MusicUtils.cpp b/Easy2D/Tool/MusicUtils.cpp new file mode 100644 index 00000000..e5575f35 --- /dev/null +++ b/Easy2D/Tool/MusicUtils.cpp @@ -0,0 +1,458 @@ +#include "..\Easy2d.h" + + +/* עMusicUtils ȫ Cocos2dx е SimpleAudioEngine ʵ */ + +#include +#pragma comment(lib , "winmm.lib") +#include + +//////////////////////////////////////////////////////////////////// +// MciPlayer +//////////////////////////////////////////////////////////////////// + +class MciPlayer +{ +public: + MciPlayer(); + ~MciPlayer(); + + void Close(); + void Open(tstring pFileName, UINT uId); + void Play(UINT uTimes = 1); + void Pause(); + void Resume(); + void Stop(); + void Rewind(); + bool IsPlaying(); + UINT GetSoundID(); + +private: + friend LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + + void _SendGenericCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0); + + HWND _wnd; + MCIDEVICEID _dev; + UINT _soundID; + UINT _times; + bool _playing; + tstring strExt; +}; + + + +#define WIN_CLASS_NAME "Easy2dCallbackWnd" + +static HINSTANCE s_hInstance; +static MCIERROR s_mciError; + +LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + +MciPlayer::MciPlayer() + : _wnd(NULL) + , _dev(0L) + , _soundID(0) + , _times(0) + , _playing(false) + , strExt(_T("")) +{ + if (!s_hInstance) + { + s_hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window + + WNDCLASS wc; // Windows Class Structure + + // Redraw On Size, And Own DC For Window. + wc.style = 0; + wc.lpfnWndProc = _SoundPlayProc; // WndProc Handles Messages + wc.cbClsExtra = 0; // No Extra Window Data + wc.cbWndExtra = 0; // No Extra Window Data + wc.hInstance = s_hInstance; // Set The Instance + wc.hIcon = 0; // Load The Default Icon + wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer + wc.hbrBackground = NULL; // No Background Required For GL + wc.lpszMenuName = NULL; // We Don't Want A Menu + wc.lpszClassName = _T(WIN_CLASS_NAME); // Set The Class Name + + if (!RegisterClass(&wc) // Register Our Class + && GetLastError() != 1410) // Class is Already Existent + { + return; + } + } + + _wnd = CreateWindowEx( + WS_EX_APPWINDOW, // Extended Style For The Window + _T(WIN_CLASS_NAME), // Class Name + NULL, // Window Title + WS_POPUPWINDOW, // Defined Window Style + 0, 0, // Window Position + 0, 0, // Window Width And Height + NULL, // No Parent Window + NULL, // No Menu + s_hInstance, // Instance + NULL); // No Param + + if (_wnd) + { + SetWindowLongPtr(_wnd, GWLP_USERDATA, (LONG_PTR)this); + } +} + +MciPlayer::~MciPlayer() +{ + Close(); + DestroyWindow(_wnd); +} + +void MciPlayer::Open(tstring pFileName, UINT uId) +{ + if (pFileName.empty() || !_wnd) return; + int nLen = (int)pFileName.size(); + if (!nLen) return; + + strExt = FileUtils::getFileExtension(pFileName); + + Close(); + + MCI_OPEN_PARMS mciOpen = { 0 }; + MCIERROR mciError; + mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID; + mciOpen.lpstrElementName = pFileName.c_str(); + + mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast(&mciOpen)); + if (mciError) return; + + _dev = mciOpen.wDeviceID; + _soundID = uId; + _playing = false; +} + +void MciPlayer::Play(UINT uTimes /* = 1 */) +{ + if (!_dev) + { + return; + } + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(_wnd); + s_mciError = mciSendCommand(_dev, MCI_PLAY, MCI_FROM | MCI_NOTIFY, reinterpret_cast(&mciPlay)); + if (!s_mciError) + { + _playing = true; + _times = uTimes; + } +} + +void MciPlayer::Close() +{ + if (_playing) + { + Stop(); + } + if (_dev) + { + _SendGenericCommand(MCI_CLOSE); + } + _dev = 0; + _playing = false; +} + +void MciPlayer::Pause() +{ + _SendGenericCommand(MCI_PAUSE); + _playing = false; +} + +void MciPlayer::Resume() +{ + if (strExt == _T(".mid")) + { + // midi not support MCI_RESUME, should get the position and use MCI_FROM + MCI_STATUS_PARMS mciStatusParms; + MCI_PLAY_PARMS mciPlayParms; + mciStatusParms.dwItem = MCI_STATUS_POSITION; + _SendGenericCommand(MCI_STATUS, MCI_STATUS_ITEM, reinterpret_cast(&mciStatusParms)); // MCI_STATUS + mciPlayParms.dwFrom = mciStatusParms.dwReturn; // get position + _SendGenericCommand(MCI_PLAY, MCI_FROM, reinterpret_cast(&mciPlayParms)); // MCI_FROM + } + else + { + _SendGenericCommand(MCI_RESUME); + _playing = true; + } +} + +void MciPlayer::Stop() +{ + _SendGenericCommand(MCI_STOP); + _playing = false; + _times = 0; +} + +void MciPlayer::Rewind() +{ + if (!_dev) + { + return; + } + mciSendCommand(_dev, MCI_SEEK, MCI_SEEK_TO_START, 0); + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(_wnd); + _playing = mciSendCommand(_dev, MCI_PLAY, MCI_NOTIFY, reinterpret_cast(&mciPlay)) ? false : true; +} + +bool MciPlayer::IsPlaying() +{ + return _playing; +} + +UINT MciPlayer::GetSoundID() +{ + return _soundID; +} + +void MciPlayer::_SendGenericCommand(int nCommand, DWORD_PTR param1 /*= 0*/, DWORD_PTR parma2 /*= 0*/) +{ + if (!_dev) + { + return; + } + mciSendCommand(_dev, nCommand, param1, parma2); +} + + + + +//////////////////////////////////////////////////////////////////// +// MusicUtils +//////////////////////////////////////////////////////////////////// + + +typedef std::map MusicList; +typedef std::pair Music; + + +static unsigned int _Hash(tstring key); + + +static MusicList& sharedList() +{ + static MusicList s_List; + return s_List; +} + +static MciPlayer& sharedMusic() +{ + static MciPlayer s_Music; + return s_Music; +} + +void MusicUtils::end() +{ + sharedMusic().Close(); + + for (auto& iter : sharedList()) + { + SAFE_DELETE(iter.second); + } + sharedList().clear(); + return; +} + +////////////////////////////////////////////////////////////////////////// +// BackgroundMusic +////////////////////////////////////////////////////////////////////////// + +void MusicUtils::playBackgroundMusic(tstring pszFilePath, bool bLoop) +{ + if (pszFilePath.empty()) + { + return; + } + + sharedMusic().Open(pszFilePath, ::_Hash(pszFilePath)); + sharedMusic().Play((bLoop) ? -1 : 1); +} + +void MusicUtils::stopBackgroundMusic(bool bReleaseData) +{ + if (bReleaseData) + { + sharedMusic().Close(); + } + else + { + sharedMusic().Stop(); + } +} + +void MusicUtils::pauseBackgroundMusic() +{ + sharedMusic().Pause(); +} + +void MusicUtils::resumeBackgroundMusic() +{ + sharedMusic().Resume(); +} + +void MusicUtils::rewindBackgroundMusic() +{ + sharedMusic().Rewind(); +} + +bool MusicUtils::isBackgroundMusicPlaying() +{ + return sharedMusic().IsPlaying(); +} + +////////////////////////////////////////////////////////////////////////// +// effect function +////////////////////////////////////////////////////////////////////////// + +unsigned int MusicUtils::playMusic(tstring pszFilePath, bool bLoop) +{ + unsigned int nRet = ::_Hash(pszFilePath); + + preloadMusic(pszFilePath); + + MusicList::iterator p = sharedList().find(nRet); + if (p != sharedList().end()) + { + p->second->Play((bLoop) ? -1 : 1); + } + return nRet; +} + +void MusicUtils::stopMusic(unsigned int nSoundId) +{ + MusicList::iterator p = sharedList().find(nSoundId); + if (p != sharedList().end()) + { + p->second->Stop(); + } +} + +void MusicUtils::preloadMusic(tstring pszFilePath) +{ + if (pszFilePath.empty()) return; + + int nRet = ::_Hash(pszFilePath); + + if (sharedList().end() != sharedList().find(nRet)) return; + + sharedList().insert(Music(nRet, new MciPlayer())); + MciPlayer * pPlayer = sharedList()[nRet]; + pPlayer->Open(pszFilePath, nRet); + + if (nRet == pPlayer->GetSoundID()) return; + + delete pPlayer; + sharedList().erase(nRet); + nRet = 0; +} + +void MusicUtils::pauseMusic(unsigned int nSoundId) +{ + MusicList::iterator p = sharedList().find(nSoundId); + if (p != sharedList().end()) + { + p->second->Pause(); + } +} + +void MusicUtils::pauseAllMusics() +{ + for (auto& iter : sharedList()) + { + iter.second->Pause(); + } +} + +void MusicUtils::resumeMusic(unsigned int nSoundId) +{ + MusicList::iterator p = sharedList().find(nSoundId); + if (p != sharedList().end()) + { + p->second->Resume(); + } +} + +void MusicUtils::resumeAllMusics() +{ + for (auto& iter : sharedList()) + { + iter.second->Resume(); + } +} + +void MusicUtils::stopAllMusics() +{ + for (auto& iter : sharedList()) + { + iter.second->Stop(); + } +} + +void MusicUtils::unloadMusic(LPCTSTR pszFilePath) +{ + unsigned int nID = ::_Hash(pszFilePath); + + MusicList::iterator p = sharedList().find(nID); + if (p != sharedList().end()) + { + SAFE_DELETE(p->second); + sharedList().erase(nID); + } +} + + + +////////////////////////////////////////////////////////////////////////// +// static function +////////////////////////////////////////////////////////////////////////// + +LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + MciPlayer * pPlayer = NULL; + if (MM_MCINOTIFY == Msg + && MCI_NOTIFY_SUCCESSFUL == wParam + && (pPlayer = (MciPlayer *)GetWindowLongPtr(hWnd, GWLP_USERDATA))) + { + if (pPlayer->_times) + { + --pPlayer->_times; + } + + if (pPlayer->_times) + { + mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0); + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(hWnd); + mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast(&mciPlay)); + } + else + { + pPlayer->_playing = false; + } + return 0; + } + return DefWindowProc(hWnd, Msg, wParam, lParam); +} + +unsigned int _Hash(tstring key) +{ + unsigned int len = unsigned(key.size()); + unsigned int hash = 0; + + for (unsigned i = 0; i < len; i++) + { + hash *= 16777619; + hash ^= (unsigned int)(unsigned char)toupper(key[i]); + } + return (hash); +} \ No newline at end of file diff --git a/Easy2D/Tool/Timer.cpp b/Easy2D/Tool/Timer.cpp new file mode 100644 index 00000000..aa62ff90 --- /dev/null +++ b/Easy2D/Tool/Timer.cpp @@ -0,0 +1,183 @@ +#include "..\Easy2d.h" + +// жʱ +static std::vector s_nTimers; + +Timer::Timer(tstring name, UINT ms, const TIMER_CALLBACK & callback) : + m_sName(name), + m_bRunning(false), + m_callback(callback) +{ + setInterval(ms); // öʱʱ +} + +Timer::~Timer() +{ +} + +void Timer::start() +{ + // ־öʱ + this->m_bRunning = true; + // ¼ǰʱ + QueryPerformanceCounter(&m_nLast); +} + +void Timer::stop() +{ + this->m_bRunning = false; // ־öʱֹͣ +} + +bool Timer::isRunning() +{ + return m_bRunning; // ȡöʱ״̬ +} + +void Timer::setInterval(UINT ms) +{ + // öʱʱ + LARGE_INTEGER nFreq; + QueryPerformanceFrequency(&nFreq); + m_nAnimationInterval.QuadPart = (LONGLONG)(ms / 1000.0 * nFreq.QuadPart); + // ʱʱ + this->m_nMilliSeconds = ms; +} + +void Timer::setCallback(const TIMER_CALLBACK & callback) +{ + m_callback = callback; // ص +} + +void Timer::setName(tstring name) +{ + m_sName = name; // ޸Ķʱ +} + +UINT Timer::getInterval() const +{ + return m_nMilliSeconds; // ȡʱʱ +} + +tstring Timer::getName() const +{ + return m_sName; // ȡʱ +} + +void Timer::__exec() +{ + // ʱΪ + if (!s_nTimers.size()) + { + return; + } + // ȡǰʱ + static LARGE_INTEGER nNow; + QueryPerformanceCounter(&nNow); + // ѭеĶʱ + for (auto timer : s_nTimers) + { + // ʱδУʱ + if (!timer->m_bRunning) + { + continue; + } + // жʱǷ㹻 + if (nNow.QuadPart - timer->m_nLast.QuadPart > timer->m_nAnimationInterval.QuadPart) + { + // ķ¼¼ʱ + timer->m_nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % timer->m_nAnimationInterval.QuadPart); + // лص + timer->m_callback(); + } + } +} + +void Timer::addTimer(Timer * timer) +{ + // ʱ + timer->start(); + // öʱ + s_nTimers.push_back(timer); +} + +void Timer::addTimer(tstring name, UINT ms, const TIMER_CALLBACK & callback) +{ + // ʱ + auto timer = new Timer(name, ms, callback); + // Ӷʱ + addTimer(timer); +} + +Timer * Timer::getTimer(tstring name) +{ + // ǷͬƵĶʱ + for (auto timer : s_nTimers) + { + if (timer->m_sName == name) + { + // ҵظöʱָ + return timer; + } + } + // δҵؿָ + return nullptr; +} + +bool Timer::startTimer(tstring name) +{ + // ָƵĶʱҵöʱ + auto t = getTimer(name); + if (t) + { + // ʱ + t->start(); + return true; + } + // δҵͬƵĶʱ false + return false; +} + +bool Timer::stopTimer(tstring name) +{ + // ָֹͣƵĶʱҵöʱ + auto t = getTimer(name); + if (t) + { + // ֹͣʱ + t->stop(); + return true; + } + // δҵͬƵĶʱ false + return false; +} + +bool Timer::deleteTimer(tstring name) +{ + // + std::vector::iterator iter; + // ѭжʱ + for (iter = s_nTimers.begin(); iter != s_nTimers.end(); iter++) + { + // ͬƵĶʱ + if ((*iter)->m_sName == name) + { + // ɾöʱ + delete (*iter); + s_nTimers.erase(iter); + return true; + } + } + // δҵͬƵĶʱ false + return false; +} + +void Timer::clearAllTimers() +{ + // ɾжʱ + for (auto t : s_nTimers) + { + delete t; + } + // + s_nTimers.clear(); +} diff --git a/Easy2D/easy2d.h b/Easy2D/easy2d.h new file mode 100644 index 00000000..e3471e81 --- /dev/null +++ b/Easy2D/easy2d.h @@ -0,0 +1,946 @@ +/****************************************************** +* Easy2D Game Engine (v1.0.0) +* http://www.easy2d.cn +* +* Depends on EasyX (Ver:20170827(beta)) +******************************************************/ + +#pragma once + +#ifndef __cplusplus + #error Easy2D is only for C++ +#endif + + +// String macros + +#ifdef UNICODE + #define tstring std::wstring +#else + #define tstring std::string +#endif + + +// Safe macros + +#define SAFE_DELETE(p) { delete (p); (p) = nullptr; } +#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = nullptr; } } +#define SAFE_RELEASE(p) { if (p) p->release(); } + + +#include +#include +#include +#include +#include +#include + + +#if defined(UNICODE) && (_DEBUG) + #pragma comment(lib,"Easy2Ddw.lib") +#elif !defined(UNICODE) && (_DEBUG) + #pragma comment(lib,"Easy2Dd.lib") +#elif defined(UNICODE) + #pragma comment(lib,"Easy2Dw.lib") +#elif !defined(UNICODE) + #pragma comment(lib,"Easy2D.lib") +#endif + + +// Class Declare + +namespace easy2d { + +// +class Application; +class Scene; +class KeyMsg; +class MouseMsg; +class FreePool; +// ʽ +class Color; +class FontStyle; +// +class Timer; +class MusicUtils; +class FileUtils; +// +class Object; +class Node; +class BatchNode; +class MouseNode; +class Image; +class Text; +class Shape; +class Rect; +class Circle; +class Button; +class TextButton; +class ImageButton; + + +typedef unsigned int VK_KEY; +typedef std::function CLICK_CALLBACK; +typedef std::function TIMER_CALLBACK; +typedef std::function KEY_CALLBACK; + + +class Application +{ +protected: + tstring m_sTitle; + Scene* m_currentScene; + Scene* m_nextScene; + std::stack m_sceneStack; + LARGE_INTEGER m_nAnimationInterval; + int m_nWidth; + int m_nHeight; + int m_nWindowMode; + bool m_bRunning; + bool m_bPause; + bool m_bSaveScene; + +protected: + void _initGraph(); + void _mainLoop(); + void _enterNextScene(); + +public: + Application(); + ~Application(); + + // ڿѡģʽ + enum { SHOW_CONSOLE = 1, NO_CLOSE = 2, NO_MINI_MIZE = 4 }; + // ȡʵ + static Application * get(); + // ԭ + static void setOrigin(int originX, int originY); + // ȡԭ + static int getOriginX(); + // ȡԭ + static int getOriginY(); + // + int run(); + // ͣ + void pause(); + // ֹ + void quit(); + // ֹ + void end(); + // ͼ + void createWindow(int width, int height, int mode = 0); + // ͼ + void createWindow(tstring title, int width, int height, int mode = 0); + // ޸ĴڴС + void setWindowSize(int width, int height); + // ôڱ + void setWindowText(tstring title); + // رմ + void close(); + // ȡڿ + int getWidth() const; + // ȡڸ߶ + int getHeight() const; + // л + void enterScene(Scene *scene, bool save = true); + // һ + void backScene(); + // ϷǷ + bool isRunning(); + // ֡ + void setFPS(DWORD fps); + // ûͼʽΪĬֵ + void reset(); + // ͷڴԴ + void free(); + // ٸö + void destory(); + // ȡǰ + Scene * getCurrentScene(); + // ȡ Easy2D 汾 + LPCTSTR getVersion(); +}; + +class FreePool +{ + friend class Application; + +private: + static void __flush(); + +public: + // һڵͷų + static void add(Object * nptr); +}; + +class Scene +{ + friend class Application; + friend class MouseMsg; + +protected: + std::vector m_vChildren; + +protected: + void _exec(); + void _onDraw(); + +public: + Scene(); + ~Scene(); + + // ӳԱ + void add(Node * child, int zOrder = 0); + // ɾӳԱ + bool del(Node * child); + // ӳԱ + void clearAllChildren(); +}; + + +class MouseMsg +{ + friend class Application; + +private: + static void __exec(); + +public: + UINT uMsg; // ǰϢ + bool mkLButton; // Ƿ + bool mkMButton; // мǷ + bool mkRButton; // ҼǷ + short x; // ǰ x + short y; // ǰ y + short wheel; // ֵֹ (120 ı) + +public: + // ȡǰϢ + static MouseMsg getMsg(); + // Ƿ + static bool getLButtonDown(); + // ҼǷ + static bool getRButtonDown(); + // мǷ + static bool getMButtonDown(); + // ȡX + static int getMouseX(); + // ȡY + static int getMouseY(); + // ȡֵ + static int getMouseWheel(); + // ƶϢ + static bool getMouseMovedMsg(); + // ˫Ϣ + static bool getLButtonDBClickedMsg(); + // ҼϢ + static bool getLButtonDownMsg(); + // Ϣ + static bool getLButtonUpMsg(); + // Ҽ˫Ϣ + static bool getRButtonDBClicked(); + // ҼϢ + static bool getRButtonDownMsg(); + // ҼϢ + static bool getRButtonUpMsg(); + // м˫Ϣ + static bool getMButtonDBClicked(); + // мϢ + static bool getMButtonDownMsg(); + // мϢ + static bool getMButtonUpMsg(); + // ֲϢ + static bool getWheelMsg(); + // Ϣ + static void resetMouseMsg(); +}; + + +class KeyMsg +{ + friend class Application; + +public: + // ĸֵ + static const VK_KEY A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; + // ֵּ + static const VK_KEY NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, NUM_0; + // Сֵּ + static const VK_KEY NUMPAD_1, NUMPAD_2, NUMPAD_3, NUMPAD_4, NUMPAD_5, NUMPAD_6, NUMPAD_7, NUMPAD_8, NUMPAD_9, NUMPAD_0, Decimal; + // Ƽֵ + static const VK_KEY Enter, Space, Up, Down, Left, Right, Esc, Shift, LShift, RShift, Ctrl, LCtrl, RCtrl; + // F ֵ + static const VK_KEY F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12; + +private: + static void __exec(); + +protected: + tstring m_sName; + KEY_CALLBACK m_callback; + +public: + KeyMsg(tstring name, const KEY_CALLBACK& callback); + ~KeyMsg(); + + // ִлص + void onKbHit(VK_KEY key); + + // Ӽ̼ + static void addListener(tstring name, const KEY_CALLBACK& callback); + // ɾ̼ + static bool delListener(tstring name); + // ɾм̼ + static void clearAllListener(); + // жϼǷ񱻰£·true + static bool isKeyDown(VK_KEY key); +}; + + +class FileUtils +{ +public: + // õļչСд + static tstring getFileExtension(const tstring& filePath); + /** + * 򿪱ļԻ򣬵õЧ· true + * ļ·ַڱ⣬չˣĬչ + */ + static bool getSaveFilePath(tstring& path, LPCTSTR title = _T("浽"), LPCTSTR defExt = NULL); +}; + + +class MusicUtils +{ +public: + // ű + static void playBackgroundMusic(tstring pszFilePath, bool bLoop = false); + // ֹͣ + static void stopBackgroundMusic(bool bReleaseData = false); + // ͣ + static void pauseBackgroundMusic(); + // ű + static void resumeBackgroundMusic(); + // ͷű + static void rewindBackgroundMusic(); + // Ƿڲ + static bool isBackgroundMusicPlaying(); + + // Ч + static unsigned int playMusic(tstring pszFilePath, bool loop = false); + // ֹͣЧ + static void stopMusic(unsigned int nSoundId); + // ԤЧ + static void preloadMusic(tstring pszFilePath); + // ͣЧ + static void pauseMusic(unsigned int nSoundId); + // Ч + static void resumeMusic(unsigned int nSoundId); + // жЧ + static void unloadMusic(LPCTSTR pszFilePath); + + // ͣ + static void pauseAllMusics(); + // + static void resumeAllMusics(); + // ֹͣ + static void stopAllMusics(); + // ֹ֣ͣͷڴ + static void end(); +}; + + +class Timer +{ + friend class Application; + +protected: + bool m_bRunning; + tstring m_sName; + TIMER_CALLBACK m_callback; + LARGE_INTEGER m_nLast; + LARGE_INTEGER m_nAnimationInterval; + UINT m_nMilliSeconds; + +private: + static void __exec(); + +public: + Timer(tstring name, UINT ms, const TIMER_CALLBACK & callback); + ~Timer(); + + // ʱ + void start(); + // ֹͣʱ + void stop(); + // ʱǷ + bool isRunning(); + // üʱ + void setInterval(UINT ms); + // ûص + void setCallback(const TIMER_CALLBACK& callback); + // öʱ + void setName(tstring name); + + // ȡʱʱ + UINT getInterval() const; + // ȡʱ + tstring getName() const; + + // Ӷʱ + static void addTimer(Timer * timer); + // Ӷʱ + static void addTimer(tstring name, UINT ms, const TIMER_CALLBACK & callback); + // ƻȡʱ + static Timer * getTimer(tstring name); + // ضʱ + static bool startTimer(tstring name); + // ֹͣضʱ + static bool stopTimer(tstring name); + // ɾضʱ + static bool deleteTimer(tstring name); + // ɾжʱ + static void clearAllTimers(); +}; + + +class Color +{ +public: + static const COLORREF black; // ɫ + static const COLORREF blue; // ɫ + static const COLORREF green; // ɫ + static const COLORREF cyan; // ɫ + static const COLORREF red; // ɫ + static const COLORREF magenta; // ɫ + static const COLORREF brown; // ɫ + static const COLORREF lightgray; // ɫ + static const COLORREF darkgray; // ɫ + static const COLORREF lightblue; // ɫ + static const COLORREF lightgreen; // ɫ + static const COLORREF lightcyan; // ɫ + static const COLORREF lightred; // ɫ + static const COLORREF lightmagenta; // ɫ + static const COLORREF yellow; // ɫ + static const COLORREF white; // ɫ + + // ͨ졢̡ɫϳɫ + static COLORREF getFromRGB(BYTE r, BYTE g, BYTE b); + // ͨɫࡢͶȡȺϳɫ + static COLORREF getFromHSL(float H, float S, float L); + // ͨɫࡢͶȡȺϳɫ + static COLORREF getFromHSV(float H, float S, float V); + + // ָɫеĺɫֵ + static BYTE getRValue(COLORREF color); + // ָɫеɫֵ + static BYTE getGValue(COLORREF color); + // ָɫеɫֵ + static BYTE getBValue(COLORREF color); + // ָɫӦĻҶֵɫ + static COLORREF getGray(COLORREF color); +}; + + +class Object +{ + friend class FreePool; + +protected: + int m_nRef; + +public: + Object(); + virtual ~Object(); + + void retain(); + void release(); +}; + + +class FontStyle : + public virtual Object +{ + friend class Text; + +protected: + LOGFONT m_font; + +public: + FontStyle(); + /** + * ʹ [ơֺšϸֿб塢»ߡɾߡַдǶȡ + * ÿַдǶȡ] Դʽ + */ + FontStyle(LPCTSTR fontfamily, LONG height = 18, LONG weight = 0, LONG width = 0, + bool italic = 0, bool underline = 0, bool strikeout = 0, LONG escapement = 0, + LONG orientation = 0, bool quality = true); + virtual ~FontStyle(); + + // ȡĬ + static FontStyle * getDefault(); + // ַƽ߶ + void setHeight(LONG value); + // ַƽȣ0ʾӦ + void setWidth(LONG value); + // + void setFontFamily(LPCTSTR value); + // ַʻϸΧ0~1000ĬΪ0 + void setWeight(LONG value); + // б + void setItalic(bool value); + // » + void setUnderline(bool value); + // ɾ + void setStrikeOut(bool value); + // ַдǶȣλ0.1ȣĬΪ0 + void setEscapement(LONG value); + // ÿַдǶȣλ0.1ȣĬΪ0 + void setOrientation(LONG value); + // 忹ݣĬΪtrue + void setQuality(bool value); +}; + + +class FontWeight +{ +public: + static const LONG dontcare; // ϸֵ 0 + static const LONG thin; // ϸֵ 100 + static const LONG extraLight; // ϸֵ 200 + static const LONG light; // ϸֵ 300 + static const LONG normal; // ϸֵ 400 + static const LONG regular; // ϸֵ 400 + static const LONG medium; // ϸֵ 500 + static const LONG demiBlod; // ϸֵ 600 + static const LONG blod; // ϸֵ 700 + static const LONG extraBold; // ϸֵ 800 + static const LONG black; // ϸֵ 900 + static const LONG heavy; // ϸֵ 900 +}; + + +class Node : + public virtual Object +{ + friend class Scene; + friend class Layer; + friend class BatchNode; + +protected: + int m_nZOrder; + bool m_bDisplay; + Scene* m_pScene; + int m_nX; + int m_nY; + +protected: + virtual bool _exec(bool active); + virtual void _onDraw() = 0; + void setParentScene(Scene * scene); + +public: + Node(); + Node(int x, int y); + virtual ~Node(); + + // ȡڵ + const int getX() const; + // ȡڵ + const int getY() const; + // ýڵ + virtual void setX(int x); + // ýڵ + virtual void setY(int y); + // ýڵ + virtual void setPos(int x, int y); + // ƶڵ + virtual void move(int x, int y); + // ڵǷʾ + bool display() const; + // ýڵǷʾ + void setDisplay(bool value); + // ȡڵͼ˳ + virtual int getZOrder() const; + // ýڵͼ˳0ΪȻƣʾײ㣩 + virtual void setZOrder(int z); + // ȡڵڳ + Scene * getParentScene(); +}; + + +class BatchNode : + public virtual Node +{ +protected: + std::vector m_vChildren; + +protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + +public: + BatchNode(); + virtual ~BatchNode(); + + // ӽڵ + void add(Node *child, int z_Order = 0); + // ɾӽڵ + bool del(Node * child); + // ӽڵ + void clearAllChildren(); +}; + + +class Image : + public virtual Node +{ + friend class ImageButton; + +protected: + CImage m_Image; + CRect m_rDest; + CRect m_rSrc; + float m_fScaleX; + float m_fScaleY; + +protected: + virtual void _onDraw() override; + +public: + Image(); + /** + * ͼƬļȡͼ(png/bmp/jpg/gif/emf/wmf/ico) + * ͼƬļͼƬü꣬ͼƬüȺ͸߶ + */ + Image(LPCTSTR ImageFile, int x = 0, int y = 0, int width = 0, int height = 0); + virtual ~Image(); + + // ȡͼ + int getWidth() const; + // ȡͼ߶ + int getHeight() const; + // ȡ + float getScaleX() const; + // ȡ + float getScaleY() const; + + /** + * ͼƬļȡͼ(png/bmp/jpg/gif/emf/wmf/ico) + * ͼƬļͼƬü꣬ͼƬüȺ͸߶ + */ + void setImageFile(LPCTSTR ImageFile, int x = 0, int y = 0, int width = 0, int height = 0); + /** + * Դļȡͼ񣬲֧ png (bmp/jpg/gif/emf/wmf/ico) + * ԴƣͼƬü꣬ͼƬüȺ͸߶ + */ + void setImageRes(LPCTSTR pResName, int x = 0, int y = 0, int width = 0, int height = 0); + // üͼƬüָ stretch 죩 + void crop(int x = 0, int y = 0, int width = 0, int height = 0); + // ͼƬ쵽̶ + void stretch(int width = 0, int height = 0); + // ͼƬ0 ~ 1.0f + void scale(float scaleX, float scaleY); + // ͼƬλ + void setPos(int x, int y) override; + // ƶͼƬ + void move(int x, int y) override; + // ͼƬ + void setX(int x) override; + // ͼƬ + void setY(int y) override; + // ͸ɫ + void setTransparentColor(COLORREF value); + // 浽ͼ + static void screenshot(); +}; + + +class Text : + public virtual Node +{ + friend class TextButton; + +protected: + tstring m_sText; + COLORREF m_color; + FontStyle * m_pFontStyle; + +protected: + virtual void _onDraw() override; + +public: + Text(); + // ַɫ崴 + Text(tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); + // ݺꡢַɫ崴 + Text(int x, int y, tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); + virtual ~Text(); + + // ȡǰɫ + COLORREF getColor() const; + // ȡǰ + tstring getText() const; + // ȡǰ + FontStyle * getFontStyle(); + // ȡֿ + int getWidth(); + // ȡָ߶ + int getHeight(); + // ıǷΪ + bool isEmpty() const; + + // + void setText(tstring text); + // ɫ + void setColor(COLORREF color); + // + void setFontStyle(FontStyle * style); +}; + + +class MouseNode : + public virtual Node +{ +private: + bool m_bTarget; + bool m_bBlock; + enum { NORMAL, MOUSEIN, SELECTED } m_eStatus; + CLICK_CALLBACK m_callback; + +protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + + void _setNormal(); + void _setMouseIn(); + void _setSelected(); + + // дúʵλõж + virtual void _judge() = 0; + // ״̬ + virtual void _onNormal() = 0; + // ʱ + virtual void _onMouseIn() = 0; + // ѡʱ + virtual void _onSelected() = 0; + +public: + MouseNode(); + virtual ~MouseNode(); + + // ʱ + virtual void onClicked(); + // Ƿ + virtual bool isMouseIn(); + // Ƿѡ + virtual bool isSelected(); + // ûص + virtual void setOnMouseClicked(const CLICK_CALLBACK & callback); + // ״̬ + virtual void reset(); + // ýڵǷϢ + void setBlock(bool block); +}; + + +class Button : + public virtual MouseNode +{ +protected: + int m_nWidth; + int m_nHeight; + bool m_bEnable; + +protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + virtual void _judge() override; + + virtual void _onNormal() = 0; + virtual void _onMouseIn() = 0; + virtual void _onSelected() = 0; + virtual void _onDisable() = 0; + +public: + Button(); + virtual ~Button(); + + // ťǷ + virtual bool isEnable(); + // Ƿ + virtual void setEnable(bool enable); +}; + + + +class TextButton : + public virtual Button +{ +protected: + Text * m_pNormalText; + Text * m_pMouseInText; + Text * m_pSelectedText; + Text * m_pUnableText; + +protected: + // λãʾ + void resetTextPosition(); + + virtual void _onNormal() override; + virtual void _onMouseIn() override; + virtual void _onSelected() override; + virtual void _onDisable() override; + +public: + TextButton(); + TextButton(Text * text); + virtual ~TextButton(); + + // ðť + void setNormalText(Text * text); + // ʱİť + void setMouseInText(Text * text); + // ѡʱİť + void setSelectedText(Text * text); + // ðťʱİť + void setUnableText(Text * text); + + // ðť + virtual void setX(int x) override; + // ðť + virtual void setY(int y) override; + // ðť + virtual void setPos(int x, int y) override; +}; + + + +class ImageButton : + public virtual Button +{ +protected: + Image * m_pNormalImage; + Image * m_pMouseInImage; + Image * m_pSelectedImage; + Image * m_pUnableImage; + +protected: + // ͼƬλãʾ + void resetImagePosition(); + + virtual void _onNormal() override; + virtual void _onMouseIn() override; + virtual void _onSelected() override; + virtual void _onDisable() override; + +public: + ImageButton(); + ImageButton(Image * image); + virtual ~ImageButton(); + + // ðťͼƬ + void setNormalImage(Image * image); + // ʱİťͼƬ + void setMouseInImage(Image * image); + // ѡʱİťͼƬ + void setSelectedImage(Image * image); + // ðťʱİťͼƬ + void setUnableImage(Image * image); + + // ðť + virtual void setX(int x) override; + // ðť + virtual void setY(int y) override; + // ðť + virtual void setPos(int x, int y) override; +}; + + +class Shape : + public virtual Node +{ +protected: + enum STYLE { round, solid, fill }; // ״ʽ + STYLE _style; + COLORREF fillColor = 0; + COLORREF lineColor = 0; + +protected: + virtual void _onDraw() override; + virtual void solidShape() = 0; + virtual void fillShape() = 0; + virtual void roundShape() = 0; + +public: + Shape(); + virtual ~Shape(); + + // ȡ״ɫ + COLORREF getFillColor() const; + // ȡ״ɫ + COLORREF getLineColor() const; + // ɫ + void setFillColor(COLORREF color); + // ɫ + void setLineColor(COLORREF color); +}; + + +class Rect : + public virtual Shape +{ +protected: + int m_nWidth; + int m_nHeight; + +protected: + virtual void solidShape() override; + virtual void fillShape() override; + virtual void roundShape() override; + +public: + Rect(); + Rect(int x, int y, int width, int height); + virtual ~Rect(); + + // ȡο + int getWidth() const; + // ȡθ߶ + int getHeight() const; + // þο + void setWidth(int width); + // þθ߶ + void setHeight(int height); + // þδС + void setSize(int width, int height); +}; + + +class Circle : + public virtual Shape +{ +protected: + int m_nRadius; + +protected: + virtual void solidShape() override; + virtual void fillShape() override; + virtual void roundShape() override; + +public: + Circle(); + Circle(int x, int y, int radius); + virtual ~Circle(); + + // ȡԲΰ뾶 + int getRadius() const; + // Բΰ뾶 + void setRadius(int m_nRadius); +}; + +} // End of easy2d namespace + + +// Ĭʹ easy2d ռ +using namespace easy2d; \ No newline at end of file