raylib绘图库--瞿华
2022.7.1
知乎 1、raylib绘图库简介
知乎 2、raylib 2d动画/游戏教程(1)动画基本原理
知乎 3、raylib 2d动画/游戏教程(2)坐标系与颜色系统
知乎 4、raylib 2d动画/游戏教程(3)图像文件与图层
知乎 5、raylib 2d动画/游戏教程(4)raylib-drawing库
知乎 6、raylib 2d动画/游戏教程(5)键盘与鼠标输入
知乎 7、raylib 2d动画/游戏教程(6)游戏手柄输入
知乎 8、raylib 2d动画/游戏教程(7)音乐和音效
知乎 9、raylib绘制中文内容
知乎 10、使用raygui绘制控件
知乎 11、raylib 3d绘图基础教程(1)坐标系和摄像机
知乎 12、raylib 3d绘图基础教程(2)网格(Mesh)
知乎 13、raylib 3d绘图基础教程(3)几何变换
知乎 14、raylib 3d绘图基础教程(4)3d模型的载入与绘制
使用raygui绘制控件
1 raygui简介
raygui是基于raylib开发的实时UI库,可以配合raylib使用,为动画/游戏提供交互界面。它提供了按钮、下拉框、输入框等多种组件。从1.1.2版本开始,小熊猫C++在发行版自带的编译器中集成了raygui。
注意:
对于小熊猫C++1.1.4版本以前自带的raygui,请使用
#include
由于raylib字体占用显存的问题,raygui的文本框不太适合用于接收中文输入内容。
raygui.h是一个只有头文件的库,通过RAYGUI_IMPLEMENTATION宏来控制raygui.h是否同时包含函数的实现。如果一个项目中有多个文件包含raygui.h,则必须保证有且仅有一个文件在包含raygui.h前定义了RAYGUI_IMPLEMENTATION宏。否则,要么会在链接时出现函数重复实现的错误(多个文件定义了RAYGUI_IMPLEMENTATION宏);要么会在链接时出现找不到相关函数实现的错误(没有文件定义RAYGUI_IMPLEMENTATION)。
raygui控件的实际绘制在EndDrawing()时完成,因此BeginDrawing()/EndDrawing()内的绘制的内容会显示在控件后面。
2 按钮示例
下面的例子演示了raygui按钮的使用方法,以及如何让raygui的控件显示中文提示。
注意,因为控件上的文字内容很少且基本不变,所以我们直接在绘制循环外载入字体,以方便处理。
#include
#include
//raygui的函数实现也都在raygui.h文件中,如果一个项目中有多个文件
//包含raygui.h,那么只能有一个文件定义RAYGUI_IMPLEMENTATION,否则
//会导致链接时出错。
#define RAYGUI_IMPLEMENTATION
#include
int main() {
InitWindow(800,600,"RAYGUI示例");
SetTraceLogLevel(LOG_WARNING);
SetTargetFPS(30);
//读取字体文件
char sWordNeed[]="太阳月亮您选择了:!";
//将字符串中的字符逐一转换成Unicode码点,得到码点表
int nCode;
int *pCodeNeed=LoadCodepoints(sWordNeed,&nCode);
//读取仅含码点表中各字符的字体
Font fontNeed = LoadFontEx("simhei.ttf",64,pCodeNeed,nCode);
//释放码点表
UnloadCodepoints(pCodeNeed);
//设置GUI控件的字体和大小
GuiSetFont(fontNeed);
GuiSetStyle(DEFAULT,TEXT_SIZE,20);
int btnClick = 0;
while(!WindowShouldClose()) {
if (btnClick==0) {
if (GuiButton((Rectangle){ 120, 150, 150, 30 },"太阳"))btnClick = 1;
if (GuiButton((Rectangle){ 120, 250,150,30},"月亮"))btnClick = 2;
}
BeginDrawing();
ClearBackground(WHITE);
if (btnClick==0){EndDrawing();continue;}
switch(btnClick) {
case 1:
DrawTextEx(fontNeed,"您选择了太阳!",Vector2{200,200},64,1,RED);
break;
case 2:
DrawTextEx(fontNeed,"您选择了月亮!",Vector2{200,200},64,1,RED);
break;
}
EndDrawing();
}
//释放字体
UnloadFont(fontNeed);
CloseWindow();
}
3 外旋螺线示例
下面这个例子演示了raygui的按钮、调节钮、颜色选择等控件的使用。注意本例中使用了rdrawing.h用于绘制2d图形。
#include
#include
#include
//raygui的函数实现也都在raygui.h文件中,如果一个项目中有多个文件
//包含raygui.h,那么只能有一个文件定义RAYGUI_IMPLEMENTATION,否则
//会导致链接时出错。
#define RAYGUI_IMPLEMENTATION
#include
#define SCREEN_W 1000
#define SCREEN_H 700
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 = SCREEN_H/2;
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=1;//内圆半径
int outerL=3;//外圆半径
int pointL=2;//动点半径
int baseR,outerR,pointR;
int cx=SCREEN_H/2,cy=SCREEN_H/2;
int speed = 1;
Color trackColor = BLUE;
//计算外旋轮、基圆和动点的实际半径,以保证不超出图像范围
updateRadius(baseL, outerL, pointL, &baseR, &outerR, & pointR);
InitWindow(SCREEN_W,SCREEN_H,"外旋螺线");
SetTraceLogLevel(LOG_WARNING);
SetTargetFPS(60);
//读取字体文件
char sWordNeed[]="外旋轮基圆动点半径速度颜色清除: 0123456789x";
//将字符串中的字符逐一转换成Unicode码点,得到码点表
int nCode;
int *pCodeNeed=LoadCodepoints(sWordNeed,&nCode);
//读取仅含码点表中各字符的字体
Font fontNeed = LoadFontEx("simhei.ttf",20,pCodeNeed,nCode);
//释放码点表
UnloadCodepoints(pCodeNeed);
//设置GUI控件的字体和大小
GuiSetFont(fontNeed);
GuiSetStyle(DEFAULT,TEXT_SIZE,20);
Image trackImage=GenImageColor(SCREEN_W-100,SCREEN_W-100,WHITE);
//border
ImageFillRectangleEx(&trackImage,0,0,SCREEN_W-100,SCREEN_W-100,LIGHTGRAY);
ImageFillRectangleEx(&trackImage,5,5,SCREEN_W-110,SCREEN_W-110,WHITE);
Image circlesImage = GenImageColor(SCREEN_W-100,SCREEN_W-100,BLANK);
float r=0;
int lastx,lasty;
lasty=cy;
lastx=cx+(baseR+outerR-pointR);
int frameCount = 0;
#define BAR_W 50
#define BAR_H 30
while(!WindowShouldClose()) {
int newOuterL = GuiSliderBar((Rectangle){ 120, 20,BAR_W,BAR_H },"外旋轮半径",TextFormat("%i", (int)outerL), outerL, 1, 50);
int newBaseL = GuiSliderBar((Rectangle){ 120, 60,BAR_W,BAR_H },"基圆半径",TextFormat("%i", (int)baseL), baseL, 1, 50);
int newPointL = GuiSliderBar((Rectangle){ 120, 100,BAR_W,BAR_H },"动点半径",TextFormat("%i", (int)pointL), pointL, 1, 50);
speed = GuiSliderBar((Rectangle){ 120, 150,BAR_W,BAR_H },"速度",TextFormat("%i", (int)speed), speed, 1, 50);
GuiLabel((Rectangle){ 20, 220,BAR_W,BAR_H },TextFormat("颜色: 0x%X%X%X ",(int)(trackColor.r), (int)(trackColor.g),(int)(trackColor.b)));
trackColor= GuiColorPicker((Rectangle){ 50, 250, BAR_W*2,BAR_H*2 }, NULL, trackColor);
int doClear = GuiButton((Rectangle){ 120, SCREEN_H-100, BAR_W,BAR_H },"清除");
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,SCREEN_W-100,SCREEN_W-100,LIGHTGRAY);
ImageFillRectangleEx(&trackImage,5,5,SCREEN_W-110,SCREEN_W-110,WHITE);
} else if (doClear) {
ImageClearBackground(&trackImage,WHITE);
ImageFillRectangleEx(&trackImage,0,0,SCREEN_W-100,SCREEN_W-100,LIGHTGRAY);
ImageFillRectangleEx(&trackImage,5,5,SCREEN_W-110,SCREEN_W-110,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));
//update image (in CPU)
//ImageClearBackground(&trackImage,WHITE);
ImageDrawLineEx(&trackImage,lastx,lasty,x,y,3,trackColor);
frameCount++;
if (frameCount>=speed) {
ImageClearBackground(&circlesImage,BLANK);
//base circle
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);
//Drawing in GPU
Texture trackTexture = LoadTextureFromImage(trackImage);
Texture circlesTexture = LoadTextureFromImage(circlesImage);
BeginDrawing();
ClearBackground(WHITE);
DrawTexture(trackTexture,200,0,WHITE);
DrawTexture(circlesTexture,200,0,WHITE);
EndDrawing();
UnloadTexture(circlesTexture);
UnloadTexture(trackTexture);
frameCount=0;
}
lastx=x;
lasty=y;
}
//Clean up
UnloadImage(circlesImage);
UnloadImage(trackImage);
//释放字体
UnloadFont(fontNeed);
CloseWindow();
}
