APP下载

基于Android的动态壁纸的设计

2019-12-09王晓东

智富时代 2019年10期
关键词:设计

【摘 要】本文介绍了手机动态壁纸的设计方法,以及实现的过程。运行的目标平台为Android,使用OpenGL ES3.0渲染技术。

【关键词】Android;动态壁纸;设计

一、引言

随着移动互联网的快速发展,单一的图片壁纸已经不能满足用户的需求,动态壁纸用动态的影像替换了原始古板的静态壁纸,并且不影响图标的显示和应用程序的使用。通过动态壁纸让桌面显得更加酷炫、个性,增加手机的魅力。本项目采用的动态壁纸为3D水族馆,在该壁纸中有许多自由游动的鱼,地面有不断一张一合的珍珠贝和不断闪烁的珍珠。还有几处不断冒出气泡,并且这些气泡随高度增加而不断变大。用户可以单击地面给鱼喂食,也可以左右滑动屏幕,使壁纸跟随滑动。使用3ds Max对模型进行设计与贴图,所有相关图片资源统一放在一个项目文件夹中。采用OpenGL ES3.0渲染技术,使得场景中有很强的立体感,以及非常逼真的光影效果。

二、类的设计

在水族馆壁纸的制作中设计了很多类,主要有以下五个方面。(1)壁纸实现类,具体又有壁纸服务类和自定义场景渲染器类。前者是水族馆壁纸的基础类,通过继承GLWallpaperService类,重写onCreateEngine方法等来实现壁纸功能;后者是水族馆壁纸的核心类,在本类中首先设置使用渲染技术,然后创建需要绘制的所有对象,设置绘制方式,加载各类物体模型以及所需纹理,设置摄像机位置,使用投影矩阵,初始化光源位置等。

(2)绘制类,具体包括群鱼控制类、单条鱼类、单个鱼群类、喂食类、鱼食类、气泡控制类以及珍珠贝类等。群鱼控制类定义了群鱼列表,存放所有的单条鱼对象,创建并启动鱼的移动线程,最后遍历列表对鱼进行绘制。单条鱼类定义了鱼的所有属性,包括位置、速度、外力、质量以及旋转角度等,单个鱼群类定义了鱼群中每条鱼的所有相关属性。喂食类是食物的控制类,其中的startFeed方法由摄像机与触控点确定一条与场景地面高度交叉的拾取射线,并计算出交点的坐标。鱼食类的作用是创建并启动线程,绘制鱼食。

(3)线程类,具体包括群鱼游动线程类、鱼食移动线程类和气泡移动线程类等。群鱼游动线程类的作用是通过遍历群鱼列表判断两条鱼之间的距离,若距离小于阈值,则两条鱼之间产生力的作用。还可以进行碰撞检测,修改外力、速度和位置等属性值。鱼食移动线程类的主要作用是判断鱼群中的鱼与相对位置的距离,若大于阈值就会对该鱼产生向心力,并对鱼群进行碰撞检测。气泡移动线程类的作用是遍历气泡列表,判断气泡移动方向,然后调用气泡对象中的bubbleMove方法,实现气泡的移动。

(4)工具常量类,具体包括常量类、向量类、屏幕拾取类和存储矩阵状态类等。常量类是整个壁纸中用到的所有静态常量的集合,向量类包含了相关向量算法、获取力的大小等方法。屏幕拾取类通过拾取计算获得触控点在摄像机坐标系中的坐标,再乘以摄像机矩阵的逆矩阵,即可得到该点在世界坐标系中的坐標。

(5)辅助绘制类,具体包括背景图辅助绘制类、气泡辅助绘制类和珍珠贝辅助绘制类等。以背景图辅助绘制类为例,它给出背景图的顶点坐标和纹理坐标,并生成缓冲送进渲染管线,用来绘制背景图。

三、类的实现

以自定义场景渲染器类为例,介绍动态壁纸相关类的实现。首先清除深度缓冲与颜色缓冲,进行现场保护,依次绘制背景图、鱼食、单条鱼鱼群以及珍珠贝。相关代码如下:

GLE30.glClear(GLES30.GL_DEPTH_BUFFER_BIT| GLES30.GL_COLOR_BUFFER_BIT);

if(bg!=null){bg.drawSelf(back);}

if(singlefood!=null){singlefood.drawSelf();}

if(fishControl!=null){fishControl.drawSelf();}

…………

重写onSurfaceChanged方法,设置视窗的尺寸和位置,计算宽高比,产生投影矩阵以及摄像机参数位置矩阵。相关代码如下:

GLES30.glViewport(0,0,width,height);

float ratio=(float)width/height;

…………

重写onSurfaceCreated方法,初始化光源位置,加载纹理,加载BNModel模型,创建鱼群、珍珠贝等对象,开启深度检测等。相关代码如下:

MatrixState.setInitStack();

MatrixState.setLightLocation(0,9,13);

dpm=initTexture(MySurfaceView,this,getResources(),”dpm.png”);

back=initTexture(MySurfaceView,this,getResources(),”background.png”);

…………

重写initTexture方法,通过输入流从assets中加载图片,生成纹理ID,设置纹理的拉伸方式,设置纹理采样方式,最后释放Bitmap。相关代码如下:

GLES30.glGenTextures(1,textures,0);

int textureId=textures[0];

GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,textureId);

back=initTexture(MySurfaceView,this,getResources(),”background.png”);

…………

bitmapTmp.recycle();

四、结语

在软件设计过程中,重点是着色器的应用,以及鱼游动过程中鱼与鱼之间作用力的变化规律等。动态壁纸的界面和风格还可以继续改进,使其更加完美。例如水族馆背景壁纸、鱼的骨骼动画及纹理图、珍珠贝的纹理图都可以进一步完善,从而达到更加理想的效果。本项目将明暗纹理和法向量的计算放在了片元着色器上进行,这样的处理方式占用资源过多。可以考虑将片元着色器中这部分计算任务转移到顶点着色器中进行,预期会显著减少壁纸在运行时对手机GPU资源的消耗。

【参考文献】

[1] 吴亚峰. Android应用案例开发大全(第4版)[M].北京:人民邮电出版社, 2018.

作者简介:王晓东(1971—),男,汉族,湖北十堰人,副教授,主要研究方向:软件开发。

猜你喜欢

设计
何为设计的守护之道?
瞒天过海——仿生设计萌到家
设计秀
有种设计叫而专
设计之味