From 637f0ce6787ead727e4a84b0dec710c5efa519ca Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 9 Mar 2023 10:36:14 +0800 Subject: [PATCH] add templates --- .../templates-win64/GAS_C/main_zh_CN.cpp | 30 ++++ .../templates-win64/GAS_C/utils_zh_CN.s | 16 ++ .../windows/templates/1-WinApp/WinApp_zh_CN.c | 66 ++++++++ .../templates/C_Embed_GAS/main_zh_CN.c | 22 +++ .../templates/GLFW/GLFW_main_zh_CN.cpp | 110 ++++++++++++ .../templates/GLFW/GLFW_shader_zh_CN.h | 98 +++++++++++ .../templates/GLFW/GLFW_shader_zh_CN.vs | 11 ++ .../templates/epitrochoid/epitrochoid_zh_CN.c | 160 ++++++++++++++++++ 8 files changed, 513 insertions(+) create mode 100644 platform/windows/templates-win64/GAS_C/main_zh_CN.cpp create mode 100644 platform/windows/templates-win64/GAS_C/utils_zh_CN.s create mode 100644 platform/windows/templates/1-WinApp/WinApp_zh_CN.c create mode 100644 platform/windows/templates/C_Embed_GAS/main_zh_CN.c create mode 100644 platform/windows/templates/GLFW/GLFW_main_zh_CN.cpp create mode 100644 platform/windows/templates/GLFW/GLFW_shader_zh_CN.h create mode 100644 platform/windows/templates/GLFW/GLFW_shader_zh_CN.vs create mode 100644 platform/windows/templates/epitrochoid/epitrochoid_zh_CN.c diff --git a/platform/windows/templates-win64/GAS_C/main_zh_CN.cpp b/platform/windows/templates-win64/GAS_C/main_zh_CN.cpp new file mode 100644 index 00000000..9f05fa5b --- /dev/null +++ b/platform/windows/templates-win64/GAS_C/main_zh_CN.cpp @@ -0,0 +1,30 @@ +#include + +#ifdef __cplusplus +#define ASM_FUNC extern "C" +#else +#define ASM_FUNC +#endif + +/* + 在cpp中使用extern "C"声明函数,以避免编译时其函数名被修饰(mangle), + 导致链接失败 +*/ +ASM_FUNC int maxofthree(int, int, int); +ASM_FUNC int add3(int, int, int); + +int main() { + printf("%d\n", add3(1, -4, -7)); + printf("%d\n", add3(1, 2, 3)); + printf("%d\n", add3(2, -6, 1)); + + printf("------\n"); + + printf("%d\n", maxofthree(1, -4, -7)); + printf("%d\n", maxofthree(2, -6, 1)); + printf("%d\n", maxofthree(2, 3, 1)); + printf("%d\n", maxofthree(-2, 4, 3)); + printf("%d\n", maxofthree(2, -6, 5)); + printf("%d\n", maxofthree(2, 4, 6)); + return 0; +} diff --git a/platform/windows/templates-win64/GAS_C/utils_zh_CN.s b/platform/windows/templates-win64/GAS_C/utils_zh_CN.s new file mode 100644 index 00000000..feb87ab4 --- /dev/null +++ b/platform/windows/templates-win64/GAS_C/utils_zh_CN.s @@ -0,0 +1,16 @@ + .text + .globl maxofthree + .globl add3 +maxofthree: + #因为参数均为32位整型(int),所以使用ecx,eax等寄存器而非rcx,rax + mov %ecx, %eax # 将参数x(在ecx中)放到函数返回值(eax)中 + cmp %edx, %eax # 比较x(eax)和y(edx) + cmovl %edx, %eax # 如果x小于y,将y设置为返回值 + cmp %r8d, %eax # 比较xy中最大值(eax)和z + cmovl %r8d, %eax # 如果比z小,将z设置为返回值 + ret # 返回eax中的结果 +add3: + mov %ecx, %eax + add %edx, %eax + add %r8d, %eax + ret diff --git a/platform/windows/templates/1-WinApp/WinApp_zh_CN.c b/platform/windows/templates/1-WinApp/WinApp_zh_CN.c new file mode 100644 index 00000000..a701ec3c --- /dev/null +++ b/platform/windows/templates/1-WinApp/WinApp_zh_CN.c @@ -0,0 +1,66 @@ +#include + +/* 在这里处理所有的窗口消息(包括输入) */ +LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { + switch(Message) { + + /* 销毁(关闭)窗口时,让主线程退出 */ + case WM_DESTROY: { + PostQuitMessage(0); + break; + } + + /* 使用默认的输出过程来处理所有其他消息 */ + default: + return DefWindowProc(hwnd, Message, wParam, lParam); + } + return 0; +} + +/* Win32 GUI程序的“main”函数:程序从这里开始执行 */ +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + WNDCLASSEX wc; /* 用于设置窗口的属性 */ + HWND hwnd; /* 我们的窗口句柄(H代表handle(句柄),WND代表windows(窗口)) */ + MSG msg; /* 用于临时保存收到的消息 */ + + /* 先将整个结构全部置零,然后再设置需要的字段 */ + memset(&wc,0,sizeof(wc)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = WndProc; /* This is where we will send messages to */ + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + + /* COLOR_WINDOWS+1为白色。Ctrl+鼠标左键点击COLOR_WINDOW可以查看它的定义 */ + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszClassName = "WindowClass"; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* 加载标准图标 */ + wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* 加载标准图标 */ + + if(!RegisterClassEx(&wc)) { + MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK); + return 0; + } + + hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, /* x */ + CW_USEDEFAULT, /* y */ + 640, /* 窗口宽度 */ + 480, /* 窗口高度 */ + NULL,NULL,hInstance,NULL); + + if(hwnd == NULL) { + MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK); + return 0; + } + + /* + 这里是我们程序的核心部分。所有的消息(包括输入)都通过这个循环 + 调用WndProc函数处理。注意GetMessage会程序暂时休眠,直到它收到 + 任意消息为止。所以这个循环不会导致过高的占用CPU。 + */ + while(GetMessage(&msg, NULL, 0, 0) > 0) { /* 如果没有发生错误,且收到了任意消息... */ + TranslateMessage(&msg); /* 将消息中的键盘码转换为对应的字符 */ + DispatchMessage(&msg); /* 调用WndProc函数处理消息 */ + } + return msg.wParam; +} diff --git a/platform/windows/templates/C_Embed_GAS/main_zh_CN.c b/platform/windows/templates/C_Embed_GAS/main_zh_CN.c new file mode 100644 index 00000000..6f790b27 --- /dev/null +++ b/platform/windows/templates/C_Embed_GAS/main_zh_CN.c @@ -0,0 +1,22 @@ +#include + +int add(int x,int y) { + int result; + asm ( + "movl %%eax, %1 \n" + "addl %%eax, %2 \n" + "movl %0, %%eax \n" + :"=r"(result) //汇编代码中使用的输出变量 + :"r"(x),"r"(y) //汇编代码中使用的输入变量 + :"eax" //汇编代码中写入的寄存器 + ); + return result; +} + +int main() { + int a,b,c; + scanf("%d,%d",&a,&b); + c=a+b; + printf("%d\n",c); + return 0; +} diff --git a/platform/windows/templates/GLFW/GLFW_main_zh_CN.cpp b/platform/windows/templates/GLFW/GLFW_main_zh_CN.cpp new file mode 100644 index 00000000..b1811753 --- /dev/null +++ b/platform/windows/templates/GLFW/GLFW_main_zh_CN.cpp @@ -0,0 +1,110 @@ +#include +// GLEW 使用静态链接,注意函数选项中的相关链接参数 +#define GLEW_STATIC +#include +// GLFW +#include + +#include "shader.h" + +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); + +// 窗口大小 +const GLuint WIDTH = 800, HEIGHT = 600; + +// main函数,程序从这里开始执行 +int main() +{ + // 初始化GLFW + glfwInit(); + // 设置GLFW必要选项 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + + // 创建GLFW窗口对象 + GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); + glfwMakeContextCurrent(window); + + // 设置必要的回调函数 + glfwSetKeyCallback(window, key_callback); + + // 让GLEW使用现代方式来获取函数指针和扩展 + glewExperimental = GL_TRUE; + // 初始化GLEW,设置OpenGL函数指针 + glewInit(); + + // 设置视图尺寸 + glViewport(0, 0, WIDTH, HEIGHT); + + + // 读取shader文件,并编译,见shader.h代码 + Shader ourShader("shader.vs", "shader.frag"); + + + // 一维数组,每六个代表一个顶点属性,前三个代表位置属性,后三个代表颜色属性 + GLfloat vertices[] = { + // Positions // Colors + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right + -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left + 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top + }; + GLuint VBO, VAO;//声明顶点缓冲,声明顶点数组用于管理顶点数据 + glGenVertexArrays(1, &VAO);//创建顶点数组,返回一个独一无二的整数,标识数组 + glGenBuffers(1, &VBO);//创建顶点缓冲,返回一个独一无二的整数,标识缓冲区 + + glBindVertexArray(VAO);//绑定顶点数组 + glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲 + //指定顶点数组的数据源为vertices,第四个参数代表显卡如何管理给定的数据,GL_STATIC_DRWA代表几乎不会改变 + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // 指定顶点属性的解析方式。即,如何从顶点缓冲获取相应的顶点属性和相应的颜色属性。或者说,顶点着色器中如何知道去哪个顶点属性分量重着色呢 + //对每一个顶点而言,属性有2种,一是位置属性,而是颜色属性,因此每六个浮点数决定了一个顶点的位置和颜色 + + //顶点着色器中使用layout(location = 0)定义了position顶点属性的位置值(Location),因此第一个参数,代表属性分量的索引 + //参数二:顶点位置属性的维度,参数三:属性向量的数据类型,参数四:是否标准化;参数五,顶点位置属性的总字节长度,参数六:在缓冲数组中的偏移量,即起始位置 + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(0);//启用属性0,因为默认是禁用的 + + // 参数一,对应顶点着色器中的layout (location = 1) in vec3 color;参数六:说明颜色属性的偏移量在三个浮点数后,与上文vertices一致 + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + glEnableVertexAttribArray(1);//启用属性1. + + //顶点数组对象(Vertex Array Object, VAO)的好处就是,当配置顶点属性指针时,你只需要将上面的代码调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。如下文循环中的绑定再解绑 + glBindVertexArray(0); // 解绑 VAO + // 游戏主循环 + while (!glfwWindowShouldClose(window)) + { + // 检查事件,调用相应的回调函数,如下文的key_callback函数 + glfwPollEvents(); + + // 渲染 + // 清除颜色缓冲区(the colorbuffer) + glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//渲染颜色到后台缓冲 + glClear(GL_COLOR_BUFFER_BIT);//清除前台缓冲 + + // 绘制三角形 + ourShader.Use();//启用着色器程序 + glBindVertexArray(VAO);//每次循环都调用,绑定函数绑定VAO + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0);//解绑 + + // 交换屏幕缓冲区(the screen buffers) + glfwSwapBuffers(window); + } + // 正确释放所有不再需要的资源 + glDeleteVertexArrays(1, &VAO); + glDeleteBuffers(1, &VBO); + // 终止GLFW,清理所有GLFW使用的资源 + glfwTerminate(); + return 0; +} + + +// 当键盘按键被按下/释放时,该函数被调用 +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + glfwSetWindowShouldClose(window, GL_TRUE); +} diff --git a/platform/windows/templates/GLFW/GLFW_shader_zh_CN.h b/platform/windows/templates/GLFW/GLFW_shader_zh_CN.h new file mode 100644 index 00000000..c311da24 --- /dev/null +++ b/platform/windows/templates/GLFW/GLFW_shader_zh_CN.h @@ -0,0 +1,98 @@ +#ifndef SHADER_H +#define SHADER_H + +#include +#include +#include +#include + +#include + +class Shader +{ +public: + GLuint Program; + + Shader(const GLchar* vertexPath, const GLchar* fragmentPath) + { + // 1. 读取顶点(vertex)/片段(fragment)源文件 + std::string vertexCode; + std::string fragmentCode; + std::ifstream vShaderFile; + std::ifstream fShaderFile; + // 确保ifstream对象能够抛出异常: + vShaderFile.exceptions(std::ifstream::badbit); + fShaderFile.exceptions(std::ifstream::badbit); + try + { + // 打开文件 + vShaderFile.open(vertexPath); + fShaderFile.open(fragmentPath); + std::stringstream vShaderStream, fShaderStream; + // 将文件内容读取成字符流 + vShaderStream << vShaderFile.rdbuf(); + fShaderStream << fShaderFile.rdbuf(); + // 关闭文件 + vShaderFile.close(); + fShaderFile.close(); + // 将字符流转换为string字符串 + vertexCode = vShaderStream.str(); + fragmentCode = fShaderStream.str(); + } + catch (std::ifstream::failure e) + { + std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; + } + const GLchar* vShaderCode = vertexCode.c_str(); + const GLchar * fShaderCode = fragmentCode.c_str(); + // 2. 编译着色器(shaders) + GLuint vertex, fragment; + GLint success; + GLchar infoLog[512]; + // 顶点着色器(Vertex Shader) + vertex = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器 + glShaderSource(vertex, 1, &vShaderCode, NULL);//指定源代码 + glCompileShader(vertex);//编译着色器 + // 输出编译错误 + glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//查看是否编译成功 + if (!success) + { + glGetShaderInfoLog(vertex, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; + } + // 片段着色器(Fragment Shader) + fragment = glCreateShader(GL_FRAGMENT_SHADER);//创建片段着色器 + glShaderSource(fragment, 1, &fShaderCode, NULL); + glCompileShader(fragment); + // 输出编译错误 + glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(fragment, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; + } + // 着色器程序(Shader Program) + this->Program = glCreateProgram();//创建着色程序 + glAttachShader(this->Program, vertex);//关联顶点着色器 + glAttachShader(this->Program, fragment);//关联片段着色器 + glLinkProgram(this->Program);//链接编译器 + // 输出链接错误 + glGetProgramiv(this->Program, GL_LINK_STATUS, &success); + if (!success) + { + glGetProgramInfoLog(this->Program, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; + } + // 链接入程序后不再需要这些着色器了,删除它们。 + glDeleteShader(vertex); + glDeleteShader(fragment); + + } + // 使用当前着色器 + void Use() + { + glUseProgram(this->Program); + } +}; + +#endif diff --git a/platform/windows/templates/GLFW/GLFW_shader_zh_CN.vs b/platform/windows/templates/GLFW/GLFW_shader_zh_CN.vs new file mode 100644 index 00000000..028c68b5 --- /dev/null +++ b/platform/windows/templates/GLFW/GLFW_shader_zh_CN.vs @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 position;//in 代表输入向量, location,与下面的顶点属性描述有关。 +layout (location = 1) in vec3 color; + +out vec3 ourColor;//out 代表输出3维向量,作为片段着色器的输入,见下文 + +void main() +{ + gl_Position = vec4(position, 1.0f); + ourColor = color; +} diff --git a/platform/windows/templates/epitrochoid/epitrochoid_zh_CN.c b/platform/windows/templates/epitrochoid/epitrochoid_zh_CN.c new file mode 100644 index 00000000..72fdd36d --- /dev/null +++ b/platform/windows/templates/epitrochoid/epitrochoid_zh_CN.c @@ -0,0 +1,160 @@ +#include +#include +#include + +#define RAYGUI_IMPLEMENTATION +#include + +/** + * @brief 计算基圆、外旋轮半径和笔尖在外旋轮中位置 + * + * @param baseL 基圆相对半径 + * @param outerL 外旋轮相对半径 + * @param pointL 笔尖在外旋轮中相对位置 + * @param pBaseR 基圆实际半径 + * @param pOuterR 外旋轮实际半径 + * @param pPointR 笔尖在滚动圆中实际位置 + */ +void updateRadius(int baseL, int outerL, int pointL, int *pBaseR, int *pOuterR, int *pPointR) { + int totalL=baseL+outerL; + if (pointL>outerL) + totalL+=pointL; + else + totalL+=outerL; + int totalR = 420; + int remainder = totalR % totalL; + if (remainder!=0) { + if (remainder < totalL / 2) { + totalR -= remainder; + } else { + totalR += ( totalL - remainder); + } + } + *pBaseR = (totalR) / totalL * baseL; + *pOuterR = (totalR) / totalL * outerL; + *pPointR = (totalR) / totalL * pointL; +} + + +int main() { + int baseL=2; //默认基圆相对半径 + int outerL=13; //默认外旋轮相对半径 + int pointL=3; //默认笔尖在滚动圆中相对位置 + int baseR,outerR,pointR; + int cx=450,cy=450; + int speed = 1; + + Color trackColor = BLUE; + updateRadius(baseL, outerL, pointL, &baseR, &outerR, & pointR); + + //初始化绘图窗口 + InitWindow(1300,900,"Epitrochoid"); + SetTraceLogLevel(LOG_WARNING); + SetTargetFPS(60); + + //读取字体文件 + char guichars[]="外旋轮基圆笔尖半径速度颜色清除: 0123456789xABCDEF"; + // 将字符串中的字符逐一转换成Unicode码点,得到码点表 + int codepointsCount; + int *codepoints=LoadCodepoints(guichars,&codepointsCount); + // 读取仅含码点表中各字符的字体 + Font font = LoadFontEx("c:\\windows\\fonts\\simhei.ttf",20,codepoints,codepointsCount); + // 释放码点表 + UnloadCodepoints(codepoints); + + + //设置GUI控件的字体和大小 + GuiSetFont(font); + GuiSetStyle(DEFAULT,TEXT_SIZE,20); + + // 轨迹图层 + Image trackImage=GenImageColor(900,900,WHITE); + // 绘制图层边框 + ImageFillRectangleEx(&trackImage,0,0,900,900,LIGHTGRAY); + ImageFillRectangleEx(&trackImage,5,5,890,890,WHITE); + + //转动圆图层 + Image circlesImage = GenImageColor(900,900,BLANK); + float r=0; + int lastx,lasty; + lasty=cy; + lastx=cx+(baseR+outerR-pointR); + int frameCount = 0; + + //主绘图循环 + while(!WindowShouldClose()) { //窗口未被关闭 + //使用raygui绘制控制面板 + int newOuterL = GuiSliderBar((Rectangle){ 90, 20, 180, 30 },"外旋轮半径",TextFormat("%i", (int)outerL), outerL, 1, 50); + int newBaseL = GuiSliderBar((Rectangle){ 90, 60, 180, 30 },"基圆半径",TextFormat("%i", (int)baseL), baseL, 1, 50); + int newPointL = GuiSliderBar((Rectangle){ 90, 100, 180, 30 },"笔尖半径",TextFormat("%i", (int)pointL), pointL, 1, 50); + speed = GuiSliderBar((Rectangle){ 90, 150, 180, 30 },"速度",TextFormat("%i", (int)speed), speed, 1, 50); + GuiLabel((Rectangle){ 20, 220, 180, 30 },TextFormat("颜色: 0x%02X%02X%02X",(int)(trackColor.r), (int)(trackColor.g),(int)(trackColor.b))); + trackColor= GuiColorPicker((Rectangle){ 50, 250, 196, 192 }, NULL, trackColor); + int doClear = GuiButton((Rectangle){ 120, 700, 80, 30 },"清除"); + if (newOuterL!=outerL || newBaseL!=baseL || newPointL!=pointL) { + //圆参数有变化,清除轨迹图层 + if (newOuterL!=outerL) + pointL=newOuterL; + else + pointL=newPointL; + outerL=newOuterL; + baseL=newBaseL; + updateRadius(baseL, outerL, pointL, &baseR, &outerR, & pointR); + lasty=cy; + lastx=cx+(baseR+outerR-pointR); + r=0; + ImageClearBackground(&trackImage,WHITE); + ImageFillRectangleEx(&trackImage,0,0,900,900,LIGHTGRAY); + ImageFillRectangleEx(&trackImage,5,5,890,890,WHITE); + } else if (doClear) { + //按下了清除按钮,清除轨迹图层 + ImageClearBackground(&trackImage,WHITE); + ImageFillRectangleEx(&trackImage,0,0,900,900,LIGHTGRAY); + ImageFillRectangleEx(&trackImage,5,5,890,890,WHITE); + } + + //更新圆位置 + r+=0.01; + float outerCX=cx+ (baseR+outerR)*cos(r); + float outerCY=cy+ (baseR+outerR)*sin(r); + float theta = r * (baseL+outerL) / outerL; + int x=round(outerCX - pointR * cos(theta)); + int y=round(outerCY - pointR * sin(theta)); + + //更新轨迹 + ImageDrawLineEx(&trackImage,lastx,lasty,x,y,3,trackColor); + + frameCount++; + if (frameCount>=speed) { + //更新转动圆图层中各圆的位置 + ImageClearBackground(&circlesImage,BLANK); + + ImageDrawCircleEx(&circlesImage,cx,cy,baseR,1,LIGHTRED); + ImageDrawCircleEx(&circlesImage,outerCX,outerCY,outerR,1,LIGHTSLATEGRAY); + ImageDrawLineEx(&circlesImage,cx,cy,outerCX,outerCY,1,LIGHTRED); + ImageDrawLineEx(&circlesImage,x,y,outerCX,outerCY,1,LIGHTSLATEGRAY); + ImageDrawPointEx(&circlesImage,x,y,7,RED); + + //将图层绘制到屏幕中(GPU绘图) + Texture trackTexture = LoadTextureFromImage(trackImage); + Texture circlesTexture = LoadTextureFromImage(circlesImage); + BeginDrawing(); + ClearBackground(WHITE); + DrawTexture(trackTexture,300,0,WHITE); + DrawTexture(circlesTexture,300,0,WHITE); + EndDrawing(); + UnloadTexture(circlesTexture); + UnloadTexture(trackTexture); + frameCount=0; + } + + lastx=x; + lasty=y; + } + + //释放图层资源 + UnloadImage(circlesImage); + UnloadImage(trackImage); + //关闭窗口 + CloseWindow(); +}