The earliest release version

This commit is contained in:
werelone 2017-09-10 23:56:52 +08:00
parent 849298b242
commit 183c7bfcea
35 changed files with 4645 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# ignore all files in the /Easy2D/** directory
Easy2D/Win32/
Easy2D/x64/

43
Easy2D.sln Normal file
View File

@ -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

368
Easy2D/Application.cpp Normal file
View File

@ -0,0 +1,368 @@
#include "easy2d.h"
#include "EasyX\easyx.h"
#include <time.h>
#include <assert.h>
#include <imm.h>
#pragma comment(lib, "imm32.lib")
#include <mmsystem.h>
#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;
}

374
Easy2D/Easy2D.vcxproj Normal file
View File

@ -0,0 +1,374 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugW|Win32">
<Configuration>DebugW</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="DebugW|x64">
<Configuration>DebugW</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseW|Win32">
<Configuration>ReleaseW</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseW|x64">
<Configuration>ReleaseW</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Easy2D</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>Easy2Dd</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>Easy2Ddw</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>Easy2Dd</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>Easy2Ddw</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>Easy2D</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>Easy2Dw</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>Easy2D</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>Easy2Dw</TargetName>
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ProjectReference>
<LinkLibraryDependencies>false</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalDependencies>EasyXa.lib;GdiPlus.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>EasyX\x86</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>EasyXw.lib;GdiPlus.lib</AdditionalDependencies>
<IgnoreAllDefaultLibraries>
</IgnoreAllDefaultLibraries>
<AdditionalLibraryDirectories>EasyX\x86</AdditionalLibraryDirectories>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>false</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalLibraryDirectories>EasyX\x64</AdditionalLibraryDirectories>
<AdditionalDependencies>EasyXa.lib;GdiPlus.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugW|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>EasyXw.lib;GdiPlus.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>EasyX\x64</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalLibraryDirectories>EasyX\x86</AdditionalLibraryDirectories>
<AdditionalDependencies>EasyXa.lib;GdiPlus.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>EasyXw.lib;GdiPlus.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>EasyX\x86</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalLibraryDirectories>EasyX\x64</AdditionalLibraryDirectories>
<AdditionalDependencies>EasyXa.lib;GdiPlus.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseW|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>EasyXw.lib;GdiPlus.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>EasyX\x64</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Application.cpp" />
<ClCompile Include="FreePool.cpp" />
<ClCompile Include="Msg\KeyMsg.cpp" />
<ClCompile Include="Msg\MouseMsg.cpp" />
<ClCompile Include="Node\BatchNode.cpp" />
<ClCompile Include="Node\Button\Button.cpp" />
<ClCompile Include="Node\Button\ImageButton.cpp" />
<ClCompile Include="Node\Button\TextButton.cpp" />
<ClCompile Include="Node\Image.cpp" />
<ClCompile Include="Node\MouseNode.cpp" />
<ClCompile Include="Node\Node.cpp" />
<ClCompile Include="Node\Shape\Circle.cpp" />
<ClCompile Include="Node\Shape\Rectangle.cpp" />
<ClCompile Include="Node\Shape\Shape.cpp" />
<ClCompile Include="Node\Sprite\Sprite.cpp" />
<ClCompile Include="Node\Sprite\SpriteFrame.cpp" />
<ClCompile Include="Node\Text.cpp" />
<ClCompile Include="Object.cpp" />
<ClCompile Include="Scene.cpp" />
<ClCompile Include="Style\Color.cpp" />
<ClCompile Include="Style\FillStyle.cpp" />
<ClCompile Include="Style\FontStyle.cpp" />
<ClCompile Include="Style\LineStyle.cpp" />
<ClCompile Include="Tool\FileUtils.cpp" />
<ClCompile Include="Tool\MusicUtils.cpp" />
<ClCompile Include="Tool\Timer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="easy2d.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="源文件\Style">
<UniqueIdentifier>{18e7fd5c-0935-47bb-9a2e-38da40377f7d}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Tool">
<UniqueIdentifier>{682a1a3c-39d8-4ac9-ba03-fa90c089c9ab}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Node">
<UniqueIdentifier>{d6778635-8947-4f9b-9388-dd088642b5b2}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Node\Sprite">
<UniqueIdentifier>{e5ec6183-113b-4140-8285-18b18ea37d15}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Node\Button">
<UniqueIdentifier>{051f9343-e5a5-4491-8110-f13fc27c3827}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Node\Shape">
<UniqueIdentifier>{065a3244-7169-4a45-bc9f-f2a80d8a9759}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Msg">
<UniqueIdentifier>{72dbabab-8278-4ee4-917f-bfffb474a51b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Application.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Scene.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Style\Color.cpp">
<Filter>源文件\Style</Filter>
</ClCompile>
<ClCompile Include="Tool\Timer.cpp">
<Filter>源文件\Tool</Filter>
</ClCompile>
<ClCompile Include="Tool\MusicUtils.cpp">
<Filter>源文件\Tool</Filter>
</ClCompile>
<ClCompile Include="Tool\FileUtils.cpp">
<Filter>源文件\Tool</Filter>
</ClCompile>
<ClCompile Include="Style\FontStyle.cpp">
<Filter>源文件\Style</Filter>
</ClCompile>
<ClCompile Include="Node\BatchNode.cpp">
<Filter>源文件\Node</Filter>
</ClCompile>
<ClCompile Include="Node\Image.cpp">
<Filter>源文件\Node</Filter>
</ClCompile>
<ClCompile Include="Node\Node.cpp">
<Filter>源文件\Node</Filter>
</ClCompile>
<ClCompile Include="Node\Text.cpp">
<Filter>源文件\Node</Filter>
</ClCompile>
<ClCompile Include="Node\Sprite\Sprite.cpp">
<Filter>源文件\Node\Sprite</Filter>
</ClCompile>
<ClCompile Include="Node\Sprite\SpriteFrame.cpp">
<Filter>源文件\Node\Sprite</Filter>
</ClCompile>
<ClCompile Include="Node\Shape\Circle.cpp">
<Filter>源文件\Node\Shape</Filter>
</ClCompile>
<ClCompile Include="Node\Shape\Rectangle.cpp">
<Filter>源文件\Node\Shape</Filter>
</ClCompile>
<ClCompile Include="Node\Shape\Shape.cpp">
<Filter>源文件\Node\Shape</Filter>
</ClCompile>
<ClCompile Include="Node\Button\Button.cpp">
<Filter>源文件\Node\Button</Filter>
</ClCompile>
<ClCompile Include="Node\MouseNode.cpp">
<Filter>源文件\Node</Filter>
</ClCompile>
<ClCompile Include="Node\Button\TextButton.cpp">
<Filter>源文件\Node\Button</Filter>
</ClCompile>
<ClCompile Include="Node\Button\ImageButton.cpp">
<Filter>源文件\Node\Button</Filter>
</ClCompile>
<ClCompile Include="Style\LineStyle.cpp">
<Filter>源文件\Style</Filter>
</ClCompile>
<ClCompile Include="FreePool.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Object.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Style\FillStyle.cpp">
<Filter>源文件\Style</Filter>
</ClCompile>
<ClCompile Include="Msg\MouseMsg.cpp">
<Filter>源文件\Msg</Filter>
</ClCompile>
<ClCompile Include="Msg\KeyMsg.cpp">
<Filter>源文件\Msg</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="easy2d.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

321
Easy2D/EasyX/easyx.h Normal file
View File

@ -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 <windows.h>
#include <tchar.h>
// 绘图窗口初始化参数
#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); // 设置当前绘图设备的裁剪区
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(); // 清空鼠标消息缓冲区

BIN
Easy2D/EasyX/x86/EasyXa.lib Normal file

Binary file not shown.

BIN
Easy2D/EasyX/x86/EasyXw.lib Normal file

Binary file not shown.

39
Easy2D/FreePool.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "easy2d.h"
// FreePool 释放池的实现机制:
/// Object 类中的引用计数m_nRef引用计数保证了指针的使用安全
/// 它记录了对象被使用的次数,当计数为 0 时FreePool 会自动释放这个对象
/// 所有的 Object 对象都应在被使用时(例如 Text 添加到了场景中)
/// 调用 retain 函数保证该对象不被删除,并在不再使用时调用 release 函数
/// 让其自动释放
// 释放池容器
static std::vector<Object*> pool;
void FreePool::__flush()
{
// 创建迭代器
std::vector<Object*>::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);
}

172
Easy2D/Msg/KeyMsg.cpp Normal file
View File

@ -0,0 +1,172 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
#include <conio.h>
// 按键监听回调函数的容器
static std::vector<KeyMsg*> s_vKeyMsg;
// 虚拟键值的容器
static std::vector<VK_KEY> 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<KeyMsg*>::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);
}

130
Easy2D/Msg/MouseMsg.cpp Normal file
View File

@ -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;
}

115
Easy2D/Node/BatchNode.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
#include <assert.h>
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<Node*>::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();
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

181
Easy2D/Node/Image.cpp Normal file
View File

@ -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;
}
}
}

109
Easy2D/Node/MouseNode.cpp Normal file
View File

@ -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;
}

92
Easy2D/Node/Node.cpp Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

View File

99
Easy2D/Node/Text.cpp Normal file
View File

@ -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(); // 现字体引用计数加一
}

21
Easy2D/Object.cpp Normal file
View File

@ -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--; // 引用计数减一
}

102
Easy2D/Scene.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "easy2d.h"
#include <assert.h>
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<Node*>::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();
}

56
Easy2D/Style/Color.cpp Normal file
View File

@ -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); // 获取颜色中的灰度值
}

View File

@ -0,0 +1 @@
/* FillStyle 是 EasyX 中的类,目前尚未考虑实现 */

View File

@ -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;
}

View File

@ -0,0 +1 @@
/* LineStyle 是 EasyX 中的类,目前尚未考虑实现 */

45
Easy2D/Tool/FileUtils.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "..\Easy2d.h"
#include "..\EasyX\easyx.h"
#include <algorithm>
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;
}

458
Easy2D/Tool/MusicUtils.cpp Normal file
View File

@ -0,0 +1,458 @@
#include "..\Easy2d.h"
/* 注MusicUtils 类完全仿照 Cocos2dx 中的 SimpleAudioEngine 实现 */
#include <mmsystem.h>
#pragma comment(lib , "winmm.lib")
#include <map>
////////////////////////////////////////////////////////////////////
// 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<DWORD_PTR>(&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<DWORD_PTR>(_wnd);
s_mciError = mciSendCommand(_dev, MCI_PLAY, MCI_FROM | MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&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<DWORD_PTR>(&mciStatusParms)); // MCI_STATUS
mciPlayParms.dwFrom = mciStatusParms.dwReturn; // get position
_SendGenericCommand(MCI_PLAY, MCI_FROM, reinterpret_cast<DWORD_PTR>(&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<DWORD_PTR>(_wnd);
_playing = mciSendCommand(_dev, MCI_PLAY, MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&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<unsigned int, MciPlayer *> MusicList;
typedef std::pair<unsigned int, MciPlayer *> 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<DWORD_PTR>(hWnd);
mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&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);
}

183
Easy2D/Tool/Timer.cpp Normal file
View File

@ -0,0 +1,183 @@
#include "..\Easy2d.h"
// 储存所有定时器的容器
static std::vector<Timer*> 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<Timer*>::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();
}

946
Easy2D/easy2d.h Normal file
View File

@ -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 <windows.h>
#include <tchar.h>
#include <atlimage.h>
#include <vector>
#include <stack>
#include <functional>
#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<void()> CLICK_CALLBACK;
typedef std::function<void()> TIMER_CALLBACK;
typedef std::function<void(VK_KEY)> KEY_CALLBACK;
class Application
{
protected:
tstring m_sTitle;
Scene* m_currentScene;
Scene* m_nextScene;
std::stack<Scene*> 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<Node*> 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<Node*> 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;