动画渲染是游戏的核心部分,游戏通过不断的绘制图片实现动画效果,此外我们也需要在游戏中绘制文字。
在Android中图形相关的类位于android.graphics包里,其中Bitmap,Canvas是实现图形绘制的核心。下面介绍图形相关的核心概念:
Bitmap:
Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。Bitmap类代表位图,而位图其实是由称作像素的单个点排列而成。每一个像素其实就是一个颜色点。
像素与颜色:
位图中的每一点即一像素,而一个像素即某种颜色的一个小点,Android中使用4个数字来表示颜色,分别是alpha、红(red)、绿(green)、蓝(blue)四个颜色值(ARGB)。每个数字取值0-255,因此一个颜色可以用一个整数来表示。
红、绿、蓝三个值是就是代表颜色的取值,而Alpha代表的是透明度。最低值为0,表示颜色完全透明,而此时RGB是什么取值都不重要了。Alpha最高可取值为255,表示颜色完全不透明。如果需要颜色透明、半透明,那么可以取值0-255中间的一些值。
为了提高效率,可以实现自己的颜色类
package com.gaofeng.game;
public class Color {
public static int convert (int r, int g, int b, int a) {
return ((a & 0xff) << 24) |
((r & 0xff) << 16) |
((g & 0xff) << 8) |
((b & 0xff));
}
//绘制完全不透明的颜色
public static int convert (int r, int g, int b) {
return ((255 & 0xff) << 24) |
((r & 0xff) << 16) |
((g & 0xff) << 8) |
((b & 0xff));
}
}
|
如你所见我们可以通过一个整数表示颜色。
Bitmap 常用方法:
public static Bitmap createBitmap (Bitmap src) |
从原位图src复制出一个新的位图
public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) |
从原始位图剪切图像,可以用Matrix(矩阵)来实现旋转,缩放,平移等功能
Bitmap source:要从中截图的原始位图
int x:起始x坐标
int y:起始y坐标
int width:要截取的图的宽度
int height: 要截取的图的宽度
Bitmap.Config config:一个枚举类型的配置,可以定义截到的新位图的质量
public static Bitmap createBitmap (int
width, int height, Bitmap.Config config)
创建指定宽度(int width)和高度(int height)的空白位图
Bitmap.Config:
表示图像的质量,其实就是每个像素点的质量,像素点就是颜色点,颜色的位数越高当然质量越好,但是内存占用就大了些
Bitmap.Config有如下取值:
Bitmap.Config ALPHA_8
Bitmap.Config ARGB_4444
Bitmap.Config ARGB_8888
Bitmap.Config RGB_565
A R G B
透明度 红色 绿色 蓝色
Bitmap.Config ARGB_4444 16 每个像素 占四位
Bitmap.Config ARGB_8888 32 每个像素 占八位
Bitmap.Config RGB_565 16 R占5位 G占6位 B占5位 没有透明度(A) |
Canvas:
画布,顾名思c绘制图形,绘制文字的地方,Canvas类主要实现了屏幕的绘制过程,其中包含了很多实用的方法,比如绘制一条路径、区域、贴图、画点、画线、渲染文本,下面是Canvas类常用的方法,当然有不同的重载版本,参数更灵活。
void drawRect(RectF rect, Paint paint) |
绘制区域,参数一为RectF一个区域
游戏开发需要使用到矩形的概念,比如一个图片的大小可以由矩形表示。
Rect类即矩形类,包含重要4个重要参数,left,top,right,bottom:
矩形的左上角的坐标(left、top)
右下角的坐标(right、bottom)
由以上两点的位置确定了矩形的高和宽
高:bottom-top
宽:right-left
RectF 用于表示浮点数矩形,即left,top,right,bottom都是浮点数
Rect 用于表示整数矩形,即left,top,right,bottom都是整数
void drawPath(Path path, Paint paint) |
绘制一个路径,参数一为Path路径对象
void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) |
绘制位图,表示从位图(Bitmap bitmap)中的指定的矩形区域(Rect
src,)绘制到画布(canvas)中的矩形区域(Rect dst)里。
参数一就是我们常规的Bitmap对象,就是需要绘制的图片
参数二是源区域,类型是Rect表示一个矩形,即可以在参数一的位图里,选取一个
矩形区域来绘制.
参数三是目标区域(是在canvas中矩形区域),
参数四是Paint画刷对象
因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint) |
在指定的位置left和top即(x,y)坐标点,画位图(bitmap),Paint画刷对象
public drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) |
用特定的矩阵matrix来画图。
Matrix能定义4种画图方式共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在Android的API里都提供了set,
post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。
例如,要将一个图片旋转30度,然后平移到(100,100)的地方,那么可以这样做:
Matrix m = new Matrix();
m.postRotate(30);
m.postTranslate(100, 100);
|
pre是前乘,参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。例如上面的例子,如果用pre方式,代码如下:
Matrix m = new Matrix();
m.setTranslate(100, 100);
m.preRotate(30);
|
旋转、缩放和倾斜都可以围绕一个中心点来进行,如果不指定,默认情况下,是围绕(0,0)点来进行。
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) |
画线
参数一起始点的x轴位置
参数二起始点的y轴位置
参数三终点的x轴水平位置
参数四y轴垂直位置
最后一个参数为Paint画刷对象。
void drawPoint(float x, float y, Paint paint) |
画点
参数一水平x轴
参数二垂直y轴
第三个参数为Paint对象。
void drawText(String text, float x, float y, Paint paint) |
渲染文本
参数一是String类型的文本
参数二x轴
参数三y轴
参数四是Paint对象。
Paint
Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设置,主要方法如下:
setAntiAlias: 设置画笔的锯齿效果。
setColor: 设置画笔颜色
setARGB: 设置画笔的a,r,p,g值。
setAlpha: 设置Alpha值
setTextSize: 设置字体尺寸。
setStyle: 设置画笔风格,空心或者实心。
setStrokeWidth: 设置空心的边框宽度。
getColor: 得到画笔的颜色
getAlpha: 得到画笔的Alpha值。
Android画布与坐标系
学习了以上基础知识后,编码实现加载一幅图view中
class RenderView extends View {
Context context;
public RenderView(Context context) {
super(context);
this.context = context;
}
protected void onDraw(Canvas canvas) {
AndroidFileIO fileio = new AndroidFileIO(this.context.getAssets());
Bitmap bitmap = fileio.getImageFromAssets("a.png");
canvas.drawBitmap(bitmap, 1, 1, null);
}
}
|
RenderView 继承自View,view是Android中各种视图的基类,其中包含的onDraw(Canvas
canvas)方法,能提供一个传入的画布(canvas)。通过AndroidFileIO类 加载了一个位图,并通过canvas.drawBitmap绘制出来。
绘制文字,设置字体
在Android SDK中使用Typeface类来定义字体,可以通过常用字体类型名称进行设置,如设置默认黑体:
Paint mp = new paint();
mp.setTypeface(Typeface.DEFAULT_BOLD)
|
常用的字体类型名称还有:
Typeface.DEFAULT //常规字体类型
Typeface.DEFAULT_BOLD //黑体字体类型
Typeface.MONOSPACE //等宽字体类型
Typeface.SANS_SERIF //sans serif字体类型
Typeface.SERIF //serif字体类型
|
除了字体类型设置之外,还可以为字体类型设置字体风格,如设置粗体:
Paint mp = new Paint();
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
p.setTypeface( font );
|
常用的字体风格名称还有:
Typeface.BOLD //粗体
Typeface.BOLD_ITALIC //粗斜体
Typeface.ITALIC //斜体
Typeface.NORMAL //常规
|
更复杂的字体设置
Paint mp = new Paint();
mp.setFakeBoldText(true); //true为粗体,false为非粗体
mp.setTextSkewX(-0.5f); //float类型参数,负数表示右斜,整数左斜
mp.setUnderlineText(true); //true为下划线,false为非下划线
mp.setStrikeThruText(true); //true为删除线,false为非删除线
|
此外还能设置字体大小,粗细等
Paint mp = new Paint();
mp.setTextSize(12);//设置字体大小,int型,如12
mp.setStrokeWidth(2.5); //设置线宽,float型,如2.5f
|
通过Canvas绘制文字关键代码:
class RenderView extends View {
Context context;
public RenderView(Context context) {
super(context);
this.context = context;
}
protected void onDraw(Canvas canvas) {
Paint mp = new Paint();
mp.setTypeface(Typeface.DEFAULT_BOLD);
mp.setTextSize(12);
mp.setARGB(255, 130, 145, 215);
canvas.drawText("我是大侠", 100, 100, mp);
}
}
|
通过Paint对象(Paint mp)设置了字体类型,大小,以及画笔的颜色,最后通过调用画布(canvas)的drawText方法,绘制文字。
总结:
在这一部分中我们学习了位图Bitmap, 颜色Color,画布Canvas,以及用于设置风格,样式,颜色,粗细等的Paint类。Canvas提供了各种方法绘制位图,图形,文字等,其中Paint类扮演画笔的角色,配合Canvas提供的各种方法,为被绘制的对象设置相应的风格。
基于封装简化的原则,我们实现了一个简化Canvas使用的工具类,代码如下:
package com.gaofeng.game;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Typeface;
public class AndroidCanvas {
Matrix matrix = new Matrix();
//构造函数需要传入一个外部的Canvas
public AndroidCanvas(Canvas canvas) {
this.canvas = canvas;
this.paint = new Paint();
}
//无参数的构造函数
public AndroidCanvas() {
this.paint = new Paint();
}
Canvas canvas;
public Canvas getCanvas() {
return canvas;
}
public void setCanvas(Canvas canvas) {
this.canvas = canvas;
}
Paint paint;
Rect srcRect = new Rect();
Rect dstRect = new Rect();
/**
*设置画布的颜色
* @color 颜色数字
* @return 无
*/
public void clear(int color) {
canvas.drawRGB((color & 0xff0000) >> 16, (color & 0xff00) >> 8,
(color & 0xff));
}
public void drawPixel(int x, int y, int color) {
paint.setColor(color);
canvas.drawPoint(x, y, paint);
}
public void drawLine(int x, int y, int x2, int y2, int color) {
paint.setColor(color);
canvas.drawLine(x, y, x2, y2, paint);
}
public void drawLine(float x, float y, float x2, float y2, int color) {
paint.setColor(color);
canvas.drawLine(x, y, x2, y2, paint);
}
public void drawRect(int x, int y, int width, int height, int color) {
paint.setColor(color);
paint.setStyle(Style.FILL);
canvas.drawRect(x, y, x + width, y + height, paint);
}
public void drawRect(float x, float y, float width, float height, int color) {
paint.setColor(color);
paint.setStyle(Style.FILL);
canvas.drawRect(x, y, x + width, y + height, paint);
}
public void drawCircle(float x, float y, float radius, int color) {
paint.setColor(color);
paint.setStyle(Style.FILL);
canvas.drawCircle(x, y, radius, paint);
}
/**绘制图片中的矩形区域
* @param bitmap 被绘制的图片
* @param x 在Canvas中绘制的坐标x
* @param y 在Canvas中绘制的坐标y
* @param srcX 绘制图片中截取矩形的left,即矩形左上角X
* @param srcY 绘制图片中截取矩形的top,即矩形左上角y
* @param srcWidth 绘制图片中截取矩形的宽度
* @param srcHeight 绘制图片中截取矩形的高度
*/
public void drawBitmap(Bitmap bitmap, int x, int y, int srcX, int srcY,
int srcWidth, int srcHeight) {
srcRect.left = srcX;
srcRect.top = srcY;
srcRect.right = srcX + srcWidth;
srcRect.bottom = srcY + srcHeight;
dstRect.left = x;
dstRect.top = y;
dstRect.right = x + srcWidth;
dstRect.bottom = y + srcHeight;
canvas.drawBitmap(bitmap, srcRect, dstRect, null);
}
/**在canvas中指定的位置x,y绘制位图bitmap
* @param bitmap
* @param x
* @param y
*/
public void drawBitmap(Bitmap bitmap, float x, float y) {
canvas.drawBitmap(bitmap, x, y, null);
}
/**图片缩放 在canvas指定的位置X,Y,按照指定的宽和高(width,height)绘制图片
* @param bitmap
* @param x
* @param y
* @param width
* @param height
*/
public void drawBitmap(Bitmap bitmap, int x, int y, int width, int height) {
srcRect.left = 0;
srcRect.top = 0;
srcRect.right = bitmap.getWidth();
srcRect.bottom = bitmap.getHeight();
dstRect.left = x;
dstRect.top = y;
dstRect.right = x + width;
dstRect.bottom = y + height;
canvas.drawBitmap(bitmap, srcRect, dstRect, null);
}
public void drawBitmap(Bitmap bitmap, float x, float y, float width,
float height) {
drawBitmap(bitmap, (int) x, (int) y, (int) width, (int) height);
}
/**根据矩阵Matrix绘制图片
* @param bitmap
* @param matrix 矩阵:用于平移,缩放,旋转等图片处理
*/
public void drawBitmap(Bitmap bitmap, Matrix matrix) {
canvas.drawBitmap(bitmap, matrix, null);
}
public void drawText(String text, int x, int y, int color, int textSize,
Typeface typeface) {
paint.setTypeface(typeface);
paint.setTextSize(textSize);
paint.setColor(color);
canvas.drawText(text, x, y, paint);
}
public void drawText(String text, int x, int y, int color, int textSize) {
paint.setTextSize(textSize);
paint.setColor(color);
canvas.drawText(text, x, y, paint);
}
public int getWidth() {
return canvas.getWidth();
}
public int getHeight() {
return canvas.getHeight();
}
}
|
AndroidCanvas是一个实现文字,图形,位图绘制的工具类,使用起来简单方便,让我们忘记细节更关注于游戏开发本身,来看看封装的力量吧。
class RenderView extends View {
Context context;
AndroidFileIO io;
AndroidCanvas androidCanvas;
Bitmap view;
public RenderView(Context context) {
super(context);
this.context = context;
io = new AndroidFileIO(context.getAssets());
view = io.getImageFromAssets("a.png");
androidCanvas = new AndroidCanvas();
}
protected void onDraw(Canvas canvas) {
//传入canvas到androidCanvas,否则没有canvas就不能绘制了。
androidCanvas.setCanvas(canvas);
//通过androidCanvas绘制位图到canvas的(x=0,y=0)坐标
androidCanvas.drawBitmap(view, 0, 0);
}
}
|
以上代码实现了通过AndroidFileIO 从assets文件夹中读取图片a.png,,并使用AndroidCanvas绘制在RenderView
的画布(canvas)中。当我们通过Activity加载RenderView(自定义视图) 时,就能看到绘制出来的图片。
|