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模型的载入与绘制

raylib 2d动画教程(4)raylib-drawing库
在教程(1)中,我们介绍了使用raylib制作2d动画的基本框架。完整看过这篇教程的读者应该发现了,raylib的2d绘图功能非常弱。这是因为,raylib是一个以制作游戏为主要目标的库,而游戏中一般都是直接从预先制作好的图片文件中读入图片,不需要用程序的方式来绘制图片。因此,raylib现有的2d绘图函数对于绝大多数游戏制作来说是够用的。

但如果我们在C/C++语言教学过程中需要让学生尝试自行制作一些几何图形的动画,raylib的功能就不够用了。在Windows下我们可以用ege、EasyX等库来制作这类动画;但在国产深度操作系统等非Windows系统下,就很困难了。为了解决这个问题,笔者在raylib的基础上开发了raylib-drawing扩展库,可以绘制2d图形。从小熊猫C++ 1.1版本开始,发行版自带的编译器中已经集成了raylib和raylib-drawing库和相应的自动链接设置,直接单文件编译(不使用项目),或者使用预带的raylib 2d项目模板创建新项目均可。

函数列表
raylib-drawing中的rdrawing.h中包含了若干颜色常量定义,和下列2d绘图函数:
函数作用
ImageDrawPointEx使用指定的大小,在Image对象中画一个点
ImageDrawArcEx使用指定的线宽和颜色,在Image对象中画一段椭圆弧
ImageDrawLineEx使用指定的线宽和颜色,在Image对象中画一条线段
ImageDrawPolylineEx使用指定的线宽和颜色,在Image对象中画一条多叉线(polyline)
ImageDrawRectangleEx使用指定的线宽和颜色,在Image对象中画一个矩形(仅轮廓线)
ImageDrawRoundRectEx使用指定的线宽和颜色,在Image对象中画一个圆角矩形(仅轮廓线)
ImageDrawCircleEx使用指定的线宽和颜色,在Image对象中画一个圆(仅轮廓线)
ImageDrawEllipseEx使用指定的线宽和颜色,在Image对象中画一个椭圆(仅轮廓线)
ImageDrawPolygonEx使用指定的线宽和颜色,在Image对象中画一个多边形(仅轮廓线)
ImageFillCircleEx使用指定的颜色,绘制一个填充的圆
ImageFillEllipseEx使用指定的颜色,绘制一个填充的椭圆
ImageFillTriangleEx使用指定的颜色,绘制一个填充的三角形
ImageFillRectangleEx使用指定的颜色,绘制一个填充的矩形
ImageFillRoundRectEx使用指定的颜色,绘制一个填充的圆角矩形
ImageFillPolygonEx使用指定的颜色,绘制一个填充的多边形
ImageFillSectorEx使用指定的颜色,绘制一个填充的扇形
ImageFloodFill泛洪填充(当遇到颜色为border color的像素时停止)
示例程序 下面的程序使用rdrawing.h中提供的绘制函数画了一个哆啦A梦: #include <raylib.h> #include <rdrawing.h> #include <time.h> #define SHRINK_FRAMES 2 Image genBodyImage(); int main() { InitWindow(800,600,"Doraemon"); SetTraceLogLevel(LOG_WARNING); SetTargetFPS(30); Image img=genBodyImage(); Texture texture = LoadTextureFromImage(img); while(!WindowShouldClose()) { BeginDrawing(); ClearBackground(WHITE); DrawTexture(texture,0,0,WHITE); EndDrawing(); } //Clean up UnloadTexture(texture); UnloadImage(img); CloseWindow(); } Image genBodyImage(){ Image img=GenImageColor(800,600,WHITE); //画头 Color fillColor = (Color){7,190,234,255}; Color color=BLACK; ImageFillRoundRectEx(&img,265, 94, 270, 260, 124, 124,fillColor); ImageDrawRoundRectEx(&img,265, 94, 270, 260, 124, 124,1,color); fillColor = WHITE;//脸 ImageFillEllipseEx(&img, 400, 256, 115, 95, fillColor); ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);//右眼 ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color); ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);//左眼 ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color); fillColor = BLACK; ImageFillCircleEx(&img,384,184,6, fillColor);//右眼球 ImageFillCircleEx(&img,416,184,6, fillColor);//左眼球 fillColor = (Color){201, 62, 0, 255};//鼻子 ImageFillCircleEx(&img, 400, 208, 15, fillColor); ImageDrawLineEx(&img,400,223,400,296,1,color);//人中 ImageDrawArcEx(&img,400, 192, 108, 108, PI * 5 / 4, PI * 7 / 4,1,color);//嘴 ImageDrawLineEx(&img,358, 227, 310, 209,1,color);//胡子 ImageDrawLineEx(&img,442, 227, 490, 209,1,color); ImageDrawLineEx(&img,359, 235, 308, 235,1,color); ImageDrawLineEx(&img,441, 235, 492, 235,1,color); ImageDrawLineEx(&img,358, 243, 310, 261,1,color); ImageDrawLineEx(&img,442, 243, 490, 261,1,color); //画身体 ImageDrawLineEx(&img, 319, 332, 262, 372,1,color);//手臂(上) ImageDrawLineEx(&img, 481, 332, 538, 372,1,color); ImageDrawLineEx(&img, 304, 396, 284, 410,1,color);//手臂(下) ImageDrawLineEx(&img, 496, 396, 516, 410,1,color); ImageDrawLineEx(&img, 304, 385, 304, 478,1,color);//腿外侧 ImageDrawLineEx(&img, 496, 385, 496, 478,1,color); ImageDrawArcEx(&img, 400, 479, 15,11,0,PI,1,color);//腿内侧 fillColor=WHITE;//手 ImageFillCircleEx(&img, 260,399,27, fillColor); ImageDrawCircleEx(&img, 260,399,27, 1, color); ImageFillCircleEx(&img, 540,399,27, fillColor); ImageDrawCircleEx(&img, 540,399,27, 1, color); ImageFillRoundRectEx(&img,288,478,110,27,12,12,fillColor);//脚 ImageDrawRoundRectEx(&img,288,478,110,27,12,12,1,color); ImageFillRoundRectEx(&img,402,478,110,27,12,12,fillColor); ImageDrawRoundRectEx(&img,402,478,110,27,12,12,1,color); fillColor=(Color){7,190,234,255};//身体填充蓝色 ImageFloodFill(&img,400,400,BLACK,fillColor); fillColor=WHITE;//肚皮 ImageFillCircleEx(&img,400,381,75,fillColor); ImageFillRectangleEx(&img,340,304,120,20,fillColor);//用白色矩形擦掉多余的肚皮 ImageDrawSectorEx(&img,400,381,58, 58,PI,2*PI,1,color);//口袋 //画铃铛 fillColor=(Color){169, 38, 0,255};//绳子 ImageFillRoundRectEx(&img,300,323,200,19,12,12,fillColor); fillColor=(Color){245, 237, 38,255};//铃铛外形 ImageFillCircleEx(&img,400,349,19,fillColor); fillColor=BLACK;//铃铛上的洞 ImageFillEllipseEx(&img,400,354,4,4,fillColor); ImageDrawLineEx(&img,400,357,400,368,3,color); ImageDrawLineEx(&img,384,340,416,340,1,color);//铃铛上的纹路 ImageDrawLineEx(&img,384,344,418,344,1,color); return img; } Image genShrinkImage0() { Image img = GenImageColor(800,600, BLANK); Color fillColor=WHITE; Color color=BLACK; ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);//右眼 ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);//左眼 ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color); ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color); fillColor = BLACK; ImageFillCircleEx(&img,384,184,6, fillColor);//右眼球 ImageFillCircleEx(&img,416,184,6, fillColor);//左眼球 fillColor = (Color){201, 62, 0, 255};//鼻子 ImageFillCircleEx(&img, 400, 208, 15, fillColor); return img; } Image genShrinkImage1() { Image img = GenImageColor(800,600, BLANK); Color fillColor=WHITE; Color color=BLACK; ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);//右眼 ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);//左眼 ImageDrawRoundRectEx(&img,337, 150, 63, 37, 28, 28, 1, color); ImageDrawRoundRectEx(&img,400, 150, 63, 37, 28, 28, 1, color); ImageFillRectangleEx(&img,337,168,63,19,fillColor); ImageFillRectangleEx(&img,400,168,63,19,fillColor); ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color); ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color); fillColor = BLACK; ImageFillCircleEx(&img,384,184,6, fillColor);//右眼球 ImageFillCircleEx(&img,416,184,6, fillColor);//左眼球 fillColor = (Color){201, 62, 0, 255};//鼻子 ImageFillCircleEx(&img, 400, 208, 15, fillColor); return img; } Image genShrinkImage2() { Image img=GenImageColor(800,600,BLANK); Color fillColor=WHITE; Color color=BLACK; ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);//右眼 ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);//左眼 ImageDrawLineEx(&img,337,168,399,168,1,color); ImageDrawLineEx(&img,400,168,462,168,1,color); ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color); ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color); fillColor = (Color){201, 62, 0, 255};//鼻子 ImageFillCircleEx(&img, 400, 208, 15, fillColor); return img; } Image genShrinkImage3(){ Image img=GenImageColor(800,600,BLANK); Color fillColor=WHITE; Color color=BLACK; ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);//右眼 ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);//左眼 ImageDrawRoundRectEx(&img,337, 150, 63, 37, 28, 28, 1, color); ImageDrawRoundRectEx(&img,400, 150, 63, 37, 28, 28, 1, color); ImageFillRectangleEx(&img,337,150,63,19,fillColor); ImageFillRectangleEx(&img,400,150,63,19,fillColor); ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color); ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color); fillColor = (Color){201, 62, 0, 255};//鼻子 ImageFillCircleEx(&img, 400, 208, 15, fillColor); return img; } Image genShrinkImage4() { Image img=GenImageColor(800,600,BLANK); Color fillColor=WHITE; Color color=BLACK; ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);//右眼 ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);//左眼 ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color); ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color); fillColor = (Color){201, 62, 0, 255};//鼻子 ImageFillCircleEx(&img, 400, 208, 15, fillColor); return img; }