上篇(https://bbs.eeworld.com.cn/thread-1204118-1-1.html)提到lvgl中使用文字,这篇来介绍一下画线。
我们知道lvgl基于对象的,用户界面的由各种对象组合而成,例如,按钮、标签、图像、列表、图表或是文本区域等。为了节约资源,可以在运行时动态加载和删除对象。这一篇主要用到改变对象的属性来实现动画效果。
创建函数如下:
lv_obj_t * lv_ <type>_create(lv_obj_t * parent, lv_obj_t * copy);
删除函数如下,它删除对象及其所有子对象:
void lv_obj_del(lv_obj_t * obj);
如果仅仅删除子对象,可以用:
void lv_obj_clean(lv_obj_t * obj);
为了显示,首先需要一个“屏幕”对象,因为屏幕没有父对象,只能从NULL中创建,例如:
lv_obj_t * scr1 = lv_obj_create(NULL, NULL);
为了获得活动屏幕,可以使用函数 lv_scr_act()来获取。
之后需要在屏幕上显示的对象都可以用 lv_scr_act()作为父对象。
可以使用函数lv_scr_load(scr)或者lv_scr_load_anim(scr, transition_type, time, delay, auto_del)实现多屏幕切换(计划下一篇再仔细介绍,如果有的话)。
本期的目标是使用RVB2601来演绎一套宅舞,这里选择的目标是比较老一点宅舞:由みうめ・メイリア・217三人表演的《极乐净土》。在屏幕上画出舞者,并间隔刷新,达到“跳舞”的效果。
RVB2601只有一个128*64的单色屏显然不可能实现高清效果,我准备使用“火柴人”方案,也就是仅仅通过简单线条来显示人物动作,手部的细节、表情等都只能忽略掉了。传统的火柴人包括脚和腿,躯干和手臂,以及头部。在舞蹈极乐净土中,没有使用道具,每个舞者只需要6根线(line)画出,因为屏幕坐标的最大值只有128,使用uint8_t格式就够用了,一共使用了28个(14组xy对)坐标值。
受显示屏本身制约,线的属性:颜色line_color(lv_color_t)、透明度line_opa(lv_opa_t)没有意义,因为线实在太细,所以圆角line_rounded(bool)也不需要理会,有意义的属性只有线宽line_width(lv_style_int_t)。
下面是初始化函数,这里的MAX_DANCERS定义的是3,其实是为了今后团舞预留的。如上文所述,先创建线的宽度,再根据数组创建线。
接下来,正式画图,pos、pos[i+1]代表的是舞者的头部(x,y)坐标,根据头部的坐标使用line_points1用9个点画出一个封闭的圆(八角形),所用线条宽度为2,作为舞者的头;使用线宽1的线段line_points2连接颈部(pos[i+2],pos[i+3])和双腿根部的平均值((pos[i+8]+pos[i+10])/2,(pos[i+9]+pos[i+11])/2),画出躯干;双手双腿(line_points3~line_points6)也类似,只是中间加上了手肘和膝盖的坐标。
为了使舞者能够动起来,需要隔一段时间刷新一下,类似这样:
片源中只有3个舞者,因此函数draw_one_person的第一个参数分别0、1、2,全局数组pos[]间隔存储着舞者各自的动作,每两个动作直接间隔100ms,也就是1秒完成10帧的刷新,因为RVB2601内存限制,大概只能存储总共2000组动作数据,大概是三个人跳1分钟左右,尝试过减少间隔时间,由100改为40,每秒播放25帧,同时细化了pos[]的动作,使得播放的时间更短,但从屏幕上看动作的连贯性似乎没有太大改善,不确定是不是板卡性能限制导致。
舞蹈效果如下:
附上原片对应片段:
还是PS:有网友提到都是火柴人,怎么看谁是谁,可以在她们头上放一个标签(label),把名字写出来,如下:
标签可以通过lv_obj_set_pos(obj, new_x, new_y)函数根据头部坐标移动显示位置,不过抱歉,因为AI还是智能不够,名字和人对错了,哈哈。
引用: tobot 发表于 2022-5-25 21:44 说个笑话,居然有人没看过极乐净土,问我是不是圣斗士里面的AE(雅典娜惊叹),哈哈哈
感觉有被内涵到