Android手机游戏开发知识点总结
更新时间:2024-01-30 00:03:01 阅读量: 教育文库 文档下载
Android手机游戏知识点总结
Android手机游戏开发学习笔记
第一部分 其实游戏就是让状态机不断的让Canvas在View上画你想要的东西。这个状态机包括内部的执行,还包括外部的输入。 Android开发的MVC模式
1,通过View和SurfaceView来显示界面的视图。(处理界面与用户的交互事件,如,触笔点击,用户按键等。可通过View类的onKeyDown,onKeyUp,onTouchEvent等)。 2,用Activity来控制游戏的整体结构。 3,设计一个逻辑类,用来处理逻辑运算。
Android中任何一个View类都只有重写onDraw方法来实现界面显示。 Android中提供了
onKeyUp,onKeyDown,onKeyMultiple,onKeyPreIme,onTouchEvent,onTrackballEvent等方法。可以用来处理游戏中的事件消息。所以继承View时,需要重载这些方法。
Android中提供了invalidate来刷新界面,但invalidate不能直接在线程中调用,违背单线程模型。
因此Android中最常用的方法是利用Handler来时更新UI界面。
第一部分 View 类
每个View类都有一个绘画的画布,在游戏中可以自定义视图View,任何一个View类都只需要重写onDraw方法来实现界面显示,可以是3D,也可以是文本。 游戏的核心就是不断的绘图和刷新,图我们可以通过onDraw方法绘制,刷新Android中可以用invalidate方法来刷新界面,注意:invalidate不能直接在线程中调用,因其违背了
违背单线程模型。因此Android中最常用的方法是利用Handler来时更新UI界面。下面这个例子中包含了两个刷新方法。
public class Game extends Activity{ public static final int REFRESH = 1; public GameView gameView;
public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);
this.gameView = new GameView(this);//实例化GameView
setContentView(gameView);
new Thread(new GameThread()).start(); }
// Handler handler = new Handler(){//注释掉的为实例化Handler对象并重写handleMessage方法实现一个消息接受器,然后在线程中通过sendMessage方法发送更新界面的消息,
当接收器收到更新界面的消息时,便执行invalidate方法更新屏幕显示。 // public void handleMessage(Message msg){//接受消息 // switch (msg.what){ // case Game.REFRESH:
// gameView.invalidate();//更新界面 // break; // }
// super.handleMessage(msg); // } // };
public boolean onTouchEvent (MotionEvent event){ return true; }
public boolean onKeyDown(int keyCode,KeyEvent event){ return true; }
public boolean onKeyUp(int keyCode,KeyEvent event){ switch (keyCode){
case KeyEvent.KEYCODE_DPAD_DOWN: gameView.y+=6; break;
case KeyEvent.KEYCODE_DPAD_UP: gameView.y-=6; break; }
return true; }
public boolean onKeyMultiple(int keyCode,int repeatCount,KeyEvent event){ return true;
}
// public class GameThread implements Runnable{//创建更新线程 // @Override // public void run() {
// while(!Thread.currentThread().isInterrupted()){ // Message message = new Message(); // message.what = Game.REFRESH;
// Game.this.handler.sendMessage(message);//发送消息 // try{
// Thread.sleep(100);
// }catch(InterruptedException e){ // Thread.currentThread().interrupt(); // } // } // } // }
public class GameThread implements Runnable{ public void run(){
while(!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(100);
}catch(InterruptedException e){ Thread.currentThread().interrupt(); }
gameView.postInvalidate();//使用PostInvalidate可以直接在线程中更新界面 不需要Handler来传递消息 } } } }
public class GameView extends View{ public int count = 0; public int y =0;
public GameView(Context context) { super(context); }
public void onDraw(Canvas canvas){ if(count<8){ count++; }else{ count=0; }
Paint paint= new Paint(); switch(count%4){ case 0:
paint.setColor(Color.BLACK); break; case 1:
paint.setColor(Color.RED); break; case 2:
paint.setColor(Color.YELLOW); break; case 3:
paint.setColor(Color.GREEN); break; }
canvas.drawRect(y,y,y+40,y+40, paint);//绘制矩形 } }
第二部分 SurfaceView类
1,开发复杂游戏,而且对程序的执行效率要求更高时用此类,因本身就是双缓冲机制的。
2,SurfaceView可以直接访问一个画布。
3,SurfaceView是提供给需要直接画像素而不是使用窗体部件的应用而使用的。 4,View即其子类(如TextVie,Button)要画在Surface上。每个Surface创建一个Canvas对象(属性时常改变)用来管理View在Surface上绘制操作。 5,使用SurfaceView绘图时,一般都是出现在最顶层。在使用时要对其创建,
销毁,情况改变进行监视,这就需要实现SurfaceHolder.Callback接口, 如果要对被绘制的画布进行裁剪,控制其大小时都需要使用SurfaceHolder来完成处理。
6,在程序中,SurfaceHolder对象需要通过getHolder方法来获得,同时还需要addCallback方法来添加“回调函数”。
7,SurfaceView与View不同之处,在于SurfaceView不需要通过线程来更新视图,在绘制前必须使用lockCanvas方法锁定画布,并得到画布,然后在画布上绘制
绘制完成后,使用unlockCanvasAndPost方法来解锁画布。 8,addCallback:给SurfaceView添加一个回调函数; removeCallback:从SurfaceView移除回调函数;
public class GameView2 extends SurfaceView implements SurfaceHolder.Callback, Runnable{
SurfaceHolder surfaceHolder = null;//定义对象 public boolean loop = false; public int count = 1;
public GameView2(Context context) { super(context);
surfaceHolder = this.getHolder();//实例化SurfaceHolder对象 surfaceHolder.addCallback(this);//添加回调函数 loop = true;
this.setFocusable(true);//不知道这句什么意思? }
private void Draw() {
Canvas canvas = surfaceHolder.lockCanvas();//锁定画布 if(surfaceHolder ==null||canvas ==null){ return ; }
if(count<100){ count++; }else{ count= 0; }
Paint paint = new Paint();//创建画笔 paint.setAntiAlias(true);//设置抗锯齿
paint.setColor(Color.GREEN);//设置画笔颜色 canvas.drawRect(0,0,320,480, paint);//绘制矩形 switch(count%4){ case 0:
paint.setColor(Color.BLUE); break; case 1:
paint.setColor(Color.YELLOW); break; case 2:
paint.setColor(Color.RED); break; case 3:
paint.setColor(Color.CYAN); break; default:
paint.setColor(Color.WHITE); break; }
canvas.drawCircle(130, 240, 500, paint);
surfaceHolder.unlockCanvasAndPost(canvas);//绘制后解锁,绘制后必须解锁才能显示 }
@Override//在Surface大小发生改变时激发
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
// TODO Auto-generated method stub }
@Override//在Surface创建时激发
public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub new Thread(this).start(); }
@Override//在Surface销毁时调用
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub loop=false; }
public void run(){ while(loop){ try{
Thread.sleep(200);
synchronized (surfaceHolder) { Draw(); }
}catch(Exception e){ } } } }
第三部分 Paint类和Color类
在Android中通过graphic类来显示2D图形。graphic包括Canvas类(画布),Paint(画笔),Color(颜色),Bitmap(图像),2D几何图形等常用类。 package graphics; Paint类常用的一些方法: setAntiAlias 设置画笔的锯齿效果 setColor 设置画笔颜色
setARGB 设置画笔的a,r,g,b值。 setAlpha 设置透明度 setTextSize 设置字体大小 setStyle 设置画笔风格 空心或实心 setStrokeWidth设置空心的边框宽度 getColor 得到画笔的颜色 getAlpha 得到画笔的透明度 Color类中定义了一些颜色常量
Color.rgb方法将整型的颜色转换成Color类型。如Color.red方法可提取出红色的值。 /**
* 注意:在绘制时按从上到下的顺序绘制的 ,后面的如果和前面的重合的话会
将前面的覆盖掉 */
public class Graphics_Paint_Color extends View implements Runnable { public Paint paint; private String TAG=\你好\
public Graphics_Paint_Color(Context context) { super(context);
paint = new Paint();//创建画笔 new Thread(this).start();//开启线程 }
public void onDraw(Canvas canvas){ super.onDraw(canvas);
paint.setAntiAlias(true);//设置抗锯齿 paint.setColor(Color.RED);//设置画笔颜色
paint.setColor(Color.rgb(12, 234, 34));//设置画笔颜色 其中参数分别为red,green,blue三种颜色的值
Color.red(23);//提取颜色? Color.blue(234);
paint.setARGB(255, 23,234,49);//设置Paint的颜色和Alpha值
paint.setAlpha(200);//设置透明度
//paint.set(new PAINT());//设置另外一个Paint对象 paint.setTextSize(14);//设置字体的尺寸
//得到Paint的一些属性
Log.i(TAG, \的颜色\Log.i(TAG,\的Alpha\
paint.setStyle(Paint.Style.STROKE);//设置Paint为空心 paint.setStrokeWidth(5);//设置空心的外框宽度 canvas.drawRect(0,0,50,60, paint);//绘制空心矩形
paint.setStyle(Paint.Style.FILL);//设置Paint为实心 canvas.drawRect(60,70,120,140, paint);//绘制实心的矩形 }
public void run() {
while(!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(200); }catch(Exception e){ e.printStackTrace();
Thread.currentThread().interrupt(); }
postInvalidate();//使用postInvalidate可以直接在线程中更新界面 } }
}在View或SurfaceView中绘制图形后,需要在Activtiy中通过setContentView()来让其显示出来
第四部分 Canvas类和ShadeDrawable类 Canvas方法:
Canvas() 创建画布,可以用setBitmap()方法设置绘制具体画布 Canvas(Bitmap bitmap) 以bitmap对象创建一个画布,则将内容都绘制在bitmap上,所以bitmap不得为null
Canvas(GL gl) 绘制3D效果时使用,与OpenGL drawColor 设置画布背景色 setBitmap 设置具体画布
clipRect 设置显示区域,即设置裁剪区 isOpaque 检测是否支持透明
rotate 旋转画布 在游戏中我们需要对精灵旋转,缩放或其它操作就可以通过旋转画布来实现,但在旋转画布时会旋转画布上所以对象,而我们只需要旋转其中一个。这个时候
我们就需要用save方法来锁定需要操作的对象,在操作后通过restore方法来解锁。(例子有此方法的运用) setViewport 设置画布中显示窗口 skew 设置便宜量
绘制几何图形的方法
drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawLine 绘制直线 drawPoint 绘制点
public class CanvasView extends View implements Runnable{ private Paint paint ;
public ShapeDrawableView shapeDrawableView; public CanvasView(Context context) { super(context); paint = new Paint();
shapeDrawableView= new ShapeDrawableView(context);//得到对象 new Thread(this).start(); }
public void onDraw(Canvas canvas){ super.onDraw(canvas);
canvas.drawColor(Color.BLACK);//设置画布颜色 paint.setAntiAlias(true);//取消抗锯齿效果 //canvas.clipRect(20,20,80,80);//设置裁剪区域
canvas.save();//锁定画布 //canvas.rotate(45.0f);//旋转画布
paint.setColor(Color.RED);//设置颜色及绘制矩形 canvas.drawRect(new Rect(10,10,80,80), paint); canvas.restore();//解锁画布
paint.setStyle(Paint.Style.STROKE);{//设置为空心画笔 Rect rect = new Rect(); rect.left =85; rect.bottom=80; rect.right=150; rect.top = 10;
paint.setColor(Color.BLUE);
canvas.drawRect(rect, paint);//绘制矩形
canvas.drawCircle(60,60,50,paint);//绘制圆形
RectF rectF = new RectF();//绘制椭圆 rectF.bottom=80; rectF.left=160; rectF.right= 300; rectF.top = 10;
canvas.drawOval(rectF, paint);
Path path = new Path();//绘制多边形 path.moveTo(10, 90); path.lineTo(80, 100); path.lineTo(70,150); path.lineTo(10, 200); path.close();//封闭多边形 canvas.drawPath(path, paint);
paint.setStrokeWidth(5);
canvas.drawLine(50,50,300,200, paint); }
paint.setStyle(Paint.Style.FILL);{//设置画笔为实心 paint.setColor(Color.YELLOW);
canvas.drawRect(20,250,300,300, paint); }
shapeDrawableView.DrawShape(canvas);//绘制另一View里的图形到本View中来 }
public void run() {
while(!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(200); }catch(Exception e){
Thread.currentThread().interrupt(); }
postInvalidate();//直接在线程中更新
} } } /**
*Android中可以通过ShapeDrawable来绘制图像。可以通过getPaint方法得到Paint对象,
setBounds 此方法可设置图形显示的区域
通过ShapeDrawable的Draw方法将图形画到屏幕上 */
public class ShapeDrawableView extends View{ ShapeDrawable shapeDrawable; Paint paint;
public ShapeDrawableView(Context context) { super(context); }
public void DrawShape(Canvas canvas){
shapeDrawable = new ShapeDrawable();//------用ShapeDrawable绘图必须要实例化对象
paint=shapeDrawable.getPaint();//得到画笔 paint.setColor(Color.GREEN);//设置画笔颜色 Rect bounds =new Rect(10,310,80,390);//绘制矩形
shapeDrawable.setBounds(bounds);//------用ShapeDrawable绘图必须要使用SetBounds显示区域
shapeDrawable.draw(canvas);//--------用ShapeDrawable绘图必须要使用draw()使图像显示到屏幕上 //另一种写法
/* 实例化ShapeDrawable对象并说明是绘制一个椭圆 */ shapeDrawable = new ShapeDrawable(new OvalShape()); //得到画笔paint对象并设置其颜色
shapeDrawable.getPaint().setColor(Color.GREEN); /* 设置图像显示的区域 */
shapeDrawable.setBounds(70, 250, 150, 280); /* 绘制图像 */
shapeDrawable.draw(canvas);
//以下为绘制多边形 Path path1 = new Path(); /*设置多边形的点*/
path1.moveTo(150+5, 80+80-50); path1.lineTo(150+45, 80+80-50); path1.lineTo(150+30, 80+120-50); path1.lineTo(150+20, 80+120-50); /* 使这些点构成封闭的多边形 */ path1.close();
//PathShape后面两个参数分别是宽度和高度
shapeDrawable = new ShapeDrawable(new PathShape(path1,150,150)); //得到画笔paint对象并设置其颜色
shapeDrawable.getPaint().setColor(Color.BLUE); /* 设置图像显示的区域 */
shapeDrawable.setBounds(100, 170, 200, 280); /* 绘制图像 */
shapeDrawable.draw(canvas); } }
第五部分 字符串绘制
Android中提供了drawText方法来绘制字符串,在绘制执法串之前需要设置画笔对象,包括字符串的尺寸,颜色等属性。使用FontMetrics来规划字体属性 可以用getFontMetrics方法来获得系统字体的相关内容。 setTextSize 设置字符串的尺寸 setARGB 设置颜色
getTextWidths 取得字符串宽度
setFlags(Paint.ANTI_ALIAS_FLAG) 消除锯齿 measureText 得到字符串宽度 得到字符串高度可用:
FontMetrics fontMetrics = paint.getFontMetrics();
textselfHeight = (int)Math.ceil(fontMetrics.descent - fontMetrics.top)+2;//得到文字的高度
textPageLineNum = textHeight/textselfHeight;//每一页的行数 = 绘制区域的高度/文字本身的高度
下例实现了文本翻页,换行。
* 实现文字自动换行 * 自动翻页
public class TextUtil{
int m_iTextPosX; //绘制的x点 int m_iTextPosY; //绘制的y点 int m_iTextWidth; //绘制宽度 int m_iTextHeight; //绘制高度 int m_iFontHeight; //字体高度
int m_ipageLineNum; //每一页显示的行数 int m_iTextBGColor; // 背景颜色 int m_iTextColor; // 字体颜色 int m_iAlpha; //Alpha值
int m_iRealLine; // 字符串真实的行数 int m_iCurLine; //当前行
String m_strText; Vector m_String; Paint m_paint; int m_iTextSize; public TextUtil(){ m_paint = new Paint(); m_String = new Vector(); }
public TextUtil(String strText, int x, int y, int w, int h, int bgcolor, int txetcolor, int a, int iTextSize){ m_paint = new Paint(); m_String = new Vector();
m_strText = strText; m_iTextPosX = x; m_iTextPosY = y; m_iTextWidth = w; m_iTextHeight = h;
m_iTextBGColor = bgcolor; m_iTextColor = txetcolor; m_iTextSize = iTextSize; m_iAlpha = a; } /** * 初始化
* @param strText 要显示的字符串 * @param x x * @param y y * @param w w * @param h h
* @param bgcolor 背景颜色 * @param txetcolor 文字的颜色 * @param a Alpha
* @param iTextSize 字体大小 */
public void InitText(String strText, int x, int y, int w, int h, int bgcolor, int txetcolor, int a, int iTextSize){ m_iCurLine = 0; m_ipageLineNum = 0; m_iRealLine = 0; m_strText = \m_iTextPosX = 0; m_iTextPosY = 0; m_iTextWidth = 0; m_iTextHeight = 0; m_iTextBGColor = 0; m_iTextColor = 0; m_iTextSize = 0; m_iAlpha = 0; m_String.clear();
SetText(strText); SetRect(x, y, w, h); SetBGColor(bgcolor); SetTextColor(txetcolor); SetFontSize(iTextSize); SetAlpha(a); SetPaint(); GetTextIfon(); } /**
* 设置Alpha * @param a Alpha值 */
public void SetAlpha(int a){ m_iAlpha = a; } /**
* 对Paint属性的设置 */
public void SetPaint(){
m_paint.setARGB(m_iAlpha, Color.red(m_iTextColor), Color.green(m_iTextColor), Color.blue(m_iTextColor)); m_paint.setTextSize(m_iTextSize); } /**
* 设置字体尺寸 * @param iTextSize */
public void SetFontSize(int iTextSize){ m_iTextSize = iTextSize; } /**
* 设置显示文本的区域 * @param x * @param y
* @param w * @param h */
public void SetRect(int x, int y, int w, int h){ m_iTextPosX = x; m_iTextPosY = y; m_iTextWidth = w; m_iTextHeight = h; } /**
* 设置背景颜色 * @param bgcolor */
public void SetBGColor(int bgcolor){ m_iTextBGColor = bgcolor; } /**
* 设置字体颜色 * @param txetcolor */
public void SetTextColor(int txetcolor){ m_iTextColor = txetcolor; } /**
* 色绘制要显示的字符串 * @param strText */
public void SetText(String strText){ m_strText = strText; } /**
* 得到字符串的信息 * 包括:行数、页数等信息 * 内部调用 */
public void GetTextIfon(){ char ch; int w = 0; int istart = 0;
FontMetrics fm = m_paint.getFontMetrics();
m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + 2; m_ipageLineNum = m_iTextHeight / m_iFontHeight; for (int i = 0; i < m_strText.length(); i++){ ch = m_strText.charAt(i); float[] widths = new float[1]; String srt = String.valueOf(ch); m_paint.getTextWidths(srt, widths); if (ch == '\\n'){ m_iRealLine++;
m_String.addElement(m_strText.substring(istart, i)); istart = i + 1; w = 0; }else{
w += (int) (Math.ceil(widths[0])); if (w > m_iTextWidth){ m_iRealLine++;
m_String.addElement(m_strText.substring(istart, i)); istart = i; i--; w = 0; }else{
if (i == (m_strText.length() - 1)){ m_iRealLine++;
m_String.addElement(m_strText.substring(istart, m_strText.length())); } } } } } /**
* 绘制字符串 * @param canvas */
public void DrawText(Canvas canvas){
for (int i = m_iCurLine, j = 0; i < m_iRealLine; i++, j++){ if (j > m_ipageLineNum){ break; }
canvas.drawText((String) (m_String.elementAt(i)), m_iTextPosX, m_iTextPosY + m_iFontHeight * j, m_paint); } } /**
* 翻页等按键处理 * @param keyCode * @param event * @return */
public boolean KeyDown(int keyCode, KeyEvent event){ if (keyCode == KeyEvent.KEYCODE_DPAD_UP){ if (m_iCurLine > 0){ m_iCurLine--; }
}else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN){ if ((m_iCurLine + m_ipageLineNum) < (m_iRealLine - 1)){ m_iCurLine++; } }
return false; } }
public class GameView extends View implements Runnable{ /* 声明Paint对象 */ private Paint mPaint = null; private int mICount = 0;
/* 声明TextUtil对象 */ private TextUtil mTextUtil = null; public GameView(Context context){ super(context); /* 构建对象 */ mPaint = new Paint();
String string = \测试自动换行\\n\\n设置文字自动换行abcdefgh\\niklmnopqrst换行123347465\\n43756245Android\\n设置文字自动换行abcdefgh\\n iklmnopqrst换行123347465\\n43756245Android\ /* 实例化TextUtil */
mTextUtil = new TextUtil(string,5,50,300,80,0x0,0xffffff,255,16); /* 初始化TextUtil */
mTextUtil.InitText(string,5,150,300,80,0x0,0xffffff,255,16); /* 开启线程 */
new Thread(this).start(); }
public void onDraw(Canvas canvas){ super.onDraw(canvas); /* 设置背景颜色 */
canvas.drawColor(Color.BLACK); mPaint.setAntiAlias(true); if ( mICount < 100 ){ mICount++; }
mPaint.setColor(Color.RED);
canvas.drawText(\装在进度:\/* 绘制TextUtil:实现自动换行 */ mTextUtil.DrawText(canvas); }
// 触笔事件
public boolean onTouchEvent(MotionEvent event){ return true; }
// 按键按下事件
public boolean onKeyDown(int keyCode, KeyEvent event){
return mTextUtil.KeyDown(keyCode, event); }
// 按键弹起事件
public boolean onKeyUp(int keyCode, KeyEvent event){ return false; }
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event){ return true; } /** * 线程处理 */
public void run(){
while (!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(100);
}catch (InterruptedException e){ Thread.currentThread().interrupt(); }
//使用postInvalidate可以直接在线程中更新界面 postInvalidate(); } } }
public class Activity01 extends Activity{ private GameView mGameView = null;
public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); mGameView = new GameView(this); setContentView(mGameView); }
// 按键弹起事件
public boolean onKeyUp(int keyCode, KeyEvent event){ return super.onKeyUp(keyCode, event);
}
// 按键按下事件
public boolean onKeyDown(int keyCode, KeyEvent event){ mGameView.onKeyDown(keyCode, event); return true; } }
第六部分 图像的绘制 旋转 缩放
1.((BitmapDrawable) getResource().getDrawable(资源索引)).getBitmap() 加载资源
2.canvas.drawBitmap(bitmap,x,y,null);将bitmap绘制在屏幕的(x,y)位置 3.getHeight() ,getWidth() 获得图片的高度好宽度
4.Android中通过Matrix旋转图片。Matrix没有结果体,它必须被实例化,可通过reset方法或set方法来实现。 setRotate方法来设置旋转角度
createBitmap 创建一个经过旋转等处理的Bitmap对象
5.Matrix的postScale(x,y)方法来设置缩放的倍数 分别在x,y方法缩放的倍数。 public class Draw_Bitmap extends Activity{ public DrawBitmap drawBitmap;
public void onCreate(Bundle savedInstanceState){ drawBitmap = new DrawBitmap(this); super.onCreate(savedInstanceState); setContentView(drawBitmap); }
public boolean onKeyDown(int keyCode,KeyEvent event){ if(drawBitmap == null){ return false;
}else if(keyCode ==KeyEvent.KEYCODE_BACK){ this.finish(); return true; }
return drawBitmap.onKeyDown(keyCode, event); } }
public class DrawBitmap extends View implements Runnable{ private static Paint paint1=null; public static Bitmap dog1=null; public Bitmap tb1=null; public int dog1width = 0; public int dog1height = 0; public float rotate=0.0f; public float scale = 1.0f;
Matrix matrix = new Matrix();//构建Matrix对象 Matrix用于旋转图片 public DrawBitmap(Context context) { super(context); paint1 = new Paint(); //从资源中装载图片 dog1 =
((BitmapDrawable)getResources().getDrawable(R.drawable.dog)).getBitmap(); tb1 =
((BitmapDrawable)getResources().getDrawable(R.drawable.tb)).getBitmap();
dog1width = dog1.getWidth();//得到图像的宽度 dog1height =dog1.getHeight();//得到图像的高度
new Thread(this).start();//创建,开启线程 }
public void onDraw(Canvas canvas){ super.onDraw(canvas); canvas.drawColor(Color.BLUE);
canvas.drawBitmap(dog1,10,240,paint1);
matrix.reset();//重置matrix得到Matrix的方法体 matrix.setRotate(rotate);//设置旋转
matrix.postScale(scale, scale);//设置缩放分别为(x,y)方法的缩放 Bitmap dog1rotate =
Bitmap.createBitmap(dog1,0,0,dog1width,dog1height,matrix,true);//按Matrix
的旋转构建新的Bitmap
DrawBitmap.drawImage(canvas,dog1rotate,130,240);//绘制旋转后的图片
dog1rotate= null;//这里难道是释放资源
DrawBitmap.drawImage(canvas,dog1,0,0);//在屏幕的(0,0)处绘制图片 DrawBitmap.drawImage2(canvas,tb1,10,dog1.getHeight(),142,100,150,178);//在指定位置按指定的裁决区域进行绘制 } /**
* i---屏幕上的x坐标 * height---屏幕上的y坐标 * j---要绘制图片的宽度 *k---要绘制图片的高度 *l---图片上的x坐标 *m---图片上的Y坐标 */
private static void drawImage2(Canvas canvas, Bitmap tb12, int i, int height, int j, int k, int l, int m) {
Rect rect1 = new Rect();//图片上裁剪区域 rect1.left = l; rect1.top =m; rect1.right=l+j; rect1.bottom = m+k;
Rect rect2 = new Rect();//屏幕上的裁剪区域 rect2.left = i; rect2.top = height; rect2.right =i+j;
rect2.bottom = height+k;
canvas.drawBitmap(tb12, rect1,rect2, null); }
private static void drawImage(Canvas canvas, Bitmap dog12, int i, int j){ canvas.drawBitmap(dog12,i,j,null); }
public boolean onKeyDown(int keyCode,KeyEvent event){ if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){ rotate+=10;
}else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){ rotate--;
}else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){ if(scale>0.3){//注意:scale必须大于0,否则会报错 scale-=0.1; }
}else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){ if(scale<2.0){ scale+=0.1; } }
return true; }
public boolean onKeyUp(int keyCode,KeyEvent event){ return false; }
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event){ return true; }
@Override public void run() {
while(!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(100); }catch(Exception e){
Thread.currentThread().interrupt(); }
postInvalidate(); } } }
第七部分 图像像素的操作
Android中Bitmap提供了操作像素的方法,可通过getPixels方法获得图像像素并放到一个数组中去。我们处理这个数组就可以了,最后通过setPixels设置这个像素数组到Bitmap中去。
Android中,每一个图像像素通过4字节整数来展现:最高位字节用作Alpha通道。即用来实现透明与不透明控制,255代表完全透明,0为完全不透明;接下来的一个字节是Red红色通道。
255代表完全是红色。依次类推,接下来的两个字节相应地实现绿色和蓝色通道。 下例为通过图像像素的操作来模拟水纹效果。
public class GameView extends View implements Runnable{ int BACKWIDTH; int BACKHEIGHT; short[] buf2; short[] buf1; int[] Bitmap2; int[] Bitmap1;
public GameView(Context context){ super(context); Bitmap image =
BitmapFactory.decodeResource(this.getResources(),R.drawable.qq);//装载图片
BACKWIDTH = image.getWidth(); BACKHEIGHT = image.getHeight();
buf2 = new short[BACKWIDTH * BACKHEIGHT]; buf1 = new short[BACKWIDTH * BACKHEIGHT]; Bitmap2 = new int[BACKWIDTH * BACKHEIGHT]; Bitmap1 = new int[BACKWIDTH * BACKHEIGHT];
image.getPixels(Bitmap1, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT);//加载图片的像素到数组中 new Thread(this).start(); }
public void DropStone(
int x, // x坐标 int y, // y坐标
int stonesize, // 波源半径 int stoneweight){ // 波源能量
for (int posx = x - stonesize; posx < x + stonesize; posx++) for (int posy = y - stonesize; posy < y + stonesize; posy++)
if ((posx - x) * (posx - x) + (posy - y) * (posy - y) < stonesize * stonesize) buf1[BACKWIDTH * posy + posx] = (short) -stoneweight; }
public void RippleSpread(){
for (int i = BACKWIDTH; i < BACKWIDTH * BACKHEIGHT - BACKWIDTH; i++){
buf2[i] = (short) (((buf1[i - 1] + buf1[i + 1] + buf1[i - BACKWIDTH] + buf1[i + BACKWIDTH]) >> 1) - buf2[i]);// 波能扩散 buf2[i] -= buf2[i] >> 5;// 波能衰减 }
// 交换波能数据缓冲区 short[] ptmp = buf1; buf1 = buf2; buf2 = ptmp; }
public void render(){//渲染你水纹效果 int xoff, yoff; int k = BACKWIDTH;
for (int i = 1; i < BACKHEIGHT - 1; i++){ for (int j = 0; j < BACKWIDTH; j++){ // 计算偏移量
xoff = buf1[k - 1] - buf1[k + 1];
yoff = buf1[k - BACKWIDTH] - buf1[k + BACKWIDTH]; // 判断坐标是否在窗口范围内 if ((i + yoff) < 0){ k++; continue; }
if ((i + yoff) > BACKHEIGHT){
k++; continue; }
if ((j + xoff) < 0){ k++; continue; }
if ((j + xoff) > BACKWIDTH){ k++; continue; }
// 计算出偏移象素和原始象素的内存地址偏移量 int pos1, pos2;
pos1 = BACKWIDTH * (i + yoff) + (j + xoff); pos2 = BACKWIDTH * i + j;
Bitmap2[pos2++] = Bitmap1[pos1++]; k++; } } }
public void onDraw(Canvas canvas){ super.onDraw(canvas);
canvas.drawBitmap(Bitmap2, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT, false, null);//绘制经过处理的图片效果 }
public boolean onTouchEvent(MotionEvent event){// 触笔事件 return true; }
public boolean onKeyDown(int keyCode, KeyEvent event){// 按键按下事件 return true; }
public boolean onKeyUp(int keyCode, KeyEvent event){// 按键弹起事件 DropStone(BACKWIDTH/2, BACKHEIGHT/2, 10, 30); return false; }
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event){ return true; }
public void run(){//线程处理
while (!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(50);
}catch (InterruptedException e){ Thread.currentThread().interrupt(); }
RippleSpread(); render();
//使用postInvalidate可以直接在线程中更新界面 postInvalidate(); } } }
第八部分 Shader类 图片的渲染 /**
* 所谓的渲染就是对画笔的设置 本人是这样理解的。Shader类的使用,都需要先构建Shader对象,然后通过Paint的setShader方法来设置渲染对象,然后在绘制时使用Paint
对象。当然用不同的渲染需要构建不同的对象(即相当于创建不同的画笔)。 */
public class Shader01 extends View{ Bitmap qq2 = null; int qq2width = 0; int qq2height = 0; Paint paint = null;
Shader bitmapShaper = null;//Bitmap渲染 Shader linearGradient = null;//线性渲染 Shader radialGradient = null;//环形渲染 Shader sweepGradient = null;//梯度渲染
Shader composeShaper = null;//混合渲染
ShapeDrawable shapeDrawable = null;
public Shader01(Context context) { super(context);
qq2 = ((BitmapDrawable)
getResources().getDrawable(R.drawable.qq)).getBitmap();//装载资源
qq2width = qq2.getWidth();//得到图片的宽度 qq2height = qq2.getHeight();//得到图片的高度
//创建BitmapShader对象 bitmapShaper = new
BitmapShader(qq2,Shader.TileMode.REPEAT,Shader.TileMode.MIRROR);//要想裁剪需要使用BitmapShader类来裁剪,得到图片的宽度和高度
//创建linearGradient对象并设置变化的颜色数组 linearGradient = new LinearGradient(10, 0, 50, 100, new int []{Color.RED,Color.YELLOW,Color.BLACK}, null, Shader.TileMode.MIRROR);
//混合渲染
composeShaper =new ComposeShader(linearGradient, bitmapShaper, PorterDuff.Mode.DARKEN);//也可选用其他的混合
//环形渲染
radialGradient = new RadialGradient(50, 200, 50, new int[]{Color.GREEN,Color.RED,Color.BLUE}, null, Shader.TileMode.REPEAT);
//梯度渲染
sweepGradient = new SweepGradient(30, 30, new int[]{Color.GREEN,Color.RED,Color.BLUE}, null); paint = new Paint();//创建画笔
}
public void onDraw(Canvas canvas){ super.onDraw(canvas);
shapeDrawable = new ShapeDrawable(new OvalShape());//设置绘制椭圆 shapeDrawable.getPaint().setShader(bitmapShaper);//设置要绘制的椭圆形的图片
shapeDrawable.setBounds(0,0,qq2width,qq2height);//设置要显示的区域 shapeDrawable.draw(canvas);//绘制图片
paint.setShader(linearGradient);//绘制线性渲染 canvas.drawRect(200,0,320,50, paint);
paint.setShader(composeShaper);//绘制混合渲染 canvas.drawRect(200,55,320,105, paint);
paint.setShader(radialGradient);//绘制环形渲染 canvas.drawRect(200,200,320,250, paint);
paint.setShader(sweepGradient);//绘制梯度渲染 canvas.drawRect(200,110,320,160, paint); } }
================================================================================================================================================= 第九部分 双缓冲技术
原理:当一个动画争先显示时,程序又在改变它,前面的还没画完,程序又请求重新绘制,这时就会出现闪屏。为避免这种情况,可以使用双缓冲技术,将要处理好的的图片
在内存中处理好之后,再将其显示到屏幕上。Android中SurfaceView类本身就是一个双缓冲机制,所以游戏开发中用SurfaceView用得更多,效率也更高。下例是针对View类实现 双缓冲技术的例子。
public class BufferView extends View implements Runnable{-----------???
Bitmap bitmap1= null;
Bitmap bufferBitmap = null;//创建缓冲区
Canvas canvas1 = null; Paint paint = null;
public BufferView(Context context) { super(context); bitmap1 =
((BitmapDrawable)getResources().getDrawable(R.drawable.qq)).getBitmap();//装载资源
bufferBitmap = Bitmap.createBitmap(320,480,Config.ARGB_8888);//创建屏幕大小的缓冲区
canvas1 = new Canvas();//创建画布(程序中出现了两块画布) paint = new Paint();
canvas1.setBitmap(bufferBitmap);//将内容绘制在bufferBitmap缓冲区上,可理解为将缓冲区作为画布。
canvas1.drawBitmap(bitmap1, 0,0, paint);//将图片绘制到缓冲区上
new Thread(this).start(); }
public void onDraw(Canvas canvas){ super.onDraw(canvas);
canvas.drawBitmap(bufferBitmap, 0,0, paint);//将bufferBitmap缓冲区上画布绘制到屏幕上去 }
@Override public void run() {
while(!Thread.currentThread().isInterrupted()){ try{
Thread.sleep(200); }catch(Exception e){
Thread.currentThread().interrupt(); }
postInvalidate(); } } }
================================================================================================================================================= 第十部分 全屏显示及获取屏幕属性
如果想像G1游戏那样,当我们把手机屏幕横放时,应用程序会自动变为横屏模式。其实可以通过下面两个方法实现这个功能。
法一:双击AndroidManifest.xml文件,选择Application选项卡,选中Activity类,再找到Screen orientation选项 ,选择 senor 最后保存即可。在真机上就能看到效果
法二:在AndroidManifest.xml文件中设计如下中加入android:screenOrientation=\即可。如下:
public class FullScreen extends Activity{
public TextView textView_FullScreen;//定义一个TextView来显示屏幕属性 public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//通过requestWindowFeature方法来设置为无标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//通过setFlags方法设置为全屏模式
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//通过setRequestedOrientation方法来设置为横屏 setContentView(R.layout.fullscreen);
textView_FullScreen =
(TextView)this.findViewById(R.id.textView_FullScreen);//得到TextView对象
DisplayMetrics displayMetrics = new DisplayMetrics();//定义DisplayMetrics对象,DisplayMetrics定义了屏幕的一些属性
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);//通过getMetrics方法来取得窗口属性
int screenWidth = displayMetrics.widthPixels;//得到窗口宽度 int screenHeight = displayMetrics.heightPixels;//得到窗口高度
textView_FullScreen.setText(\屏幕宽度:\屏幕高度:\} }
第十一部分 Tween动画 第一种方法 在代码中设计
public class AnimationView extends View{ public Animation animationAlpha = null; public Animation animationScale = null; public Animation animationTranslate = null; public Animation animationRotate = null;
Bitmap bitmap1 = null;
public AnimationView(Context context) { super(context); bitmap1 =
((BitmapDrawable)getResources().getDrawable(R.drawable.dog)).getBitmap();//加载资源 }
public void onDraw(Canvas canvas){ canvas.drawBitmap(bitmap1, 50,100, null); }
public boolean onKeyUp(int keyCode,KeyEvent event){ switch(keyCode){ /*
* Alpha透明度动画效果。其属性设置格式为: * AlphaAnimation(float fromAlpha,float toAlpha) * fromAlpha---为动画起始时透明度
* toAlpha---动画结束时透明度(0.0表示完全透明,1.0表示完全不透明) *
* setDuration(long durationMillis);设置动画显示的时间 单位为毫秒 * startAnimation(Animation animation);开始播放动画 */
case KeyEvent.KEYCODE_DPAD_UP:
animationAlpha = new AlphaAnimation(0.0f, 1.0f);//创建Alpha动画 animationAlpha.setDuration(3000);//动画持续时间 this.startAnimation(animationAlpha);//开始播放动画 break; /*
* Scale伸缩动画效果.。其属性设置如下:
* ScaleAnimation(fromX, toX, fromY, toY, pivotXType, pivotXValue, pivotYType, pivotYValue)
* fromX,toX 为起始和结束时x坐标上的伸缩尺寸 * fromY,toY 为起始和结束时y坐标上的伸缩尺寸 * pivotXType,pivotYType 分别为x,y的伸缩模式
* pivotXVale,pivotYVale 分别为伸缩动画相对于x,y的坐标开始位置 */
case KeyEvent.KEYCODE_DPAD_DOWN:
animationScale = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);//创建Scale动画 animationScale.setDuration(500);//动画持续的时间 this.startAnimation(animationScale);//开始播放动画 /*
* Translate移动动画效果。其属性设置如下:
* TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta) * fromXDelta ,fromYDelta 分别为起始x,y坐标
* toXDelta,toYDelta 分别为终点时x,y坐标 */
case KeyEvent.KEYCODE_DPAD_LEFT:
animationTranslate = new TranslateAnimation(10, 100, 10, 100);//创建Translate动画
animationTranslate.setDuration(1000);//动画持续时间 this.startAnimation(animationTranslate);//开始播放动画 break; /*
* Rotate旋转动画效果
* RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue) * fromDegrees 开始角度 * toDegrees 结束角度
* pivotXValue , pivotYValue 伸缩动画相对于x,y的坐标坐标开始位置 * pivotXType,pivotYType 分别为x,y的伸缩模式 */
case KeyEvent.KEYCODE_DPAD_RIGHT: animationRotate = new RotateAnimation(0.0f, 360f, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);//创建Rotate动画 animationRotate.setDuration(1000);//动画持续时间 this.startAnimation(animationRotate);//动画播放 }
return true; }
} 需在Activity种实例化
------------------------------------------------------------------------------------------------------- 第二种方法 xml设计 aipha.xml
android:toAlpha=\android:duration=\/>
rotate.xml
android:interpolator=\ android:fromDegrees=\ android:toDegrees=\ android:pivotX=\ android:pivotY=\ android:duration=\
android:interpolator=\ android:fromXScale=\android:toXScale=\ android:fromYScale=\android:toYScale=\ android:pivotX=\android:pivotY=\ android:fillAfter=\android:duration=\
public class GameView extends View{
private Animation mAnimationAlpha = null;//定义Alpha动画 private Animation mAnimationScale = null;//定义Scale动画 private Animation mAnimationTranslate = null;//定义Translate动画 private Animation mAnimationRotate = null;//定义Rotate动画
Bitmap mBitQQ = null;//定义Bitmap对象 Context mContext = null;
public GameView(Context context){ super(context); mContext = context;
mBitQQ = ((BitmapDrawable)
getResources().getDrawable(R.drawable.qq)).getBitmap();//装载资源 }
public void onDraw(Canvas canvas){ super.onDraw(canvas);
canvas.drawBitmap(mBitQQ, 0, 0, null);//绘制图片 }
public boolean onKeyUp(int keyCode, KeyEvent event){ switch ( keyCode ){
case KeyEvent.KEYCODE_DPAD_UP:
mAnimationAlpha = AnimationUtils.loadAnimation(mContext,R.layout.alpha);//装载动画布局
this.startAnimation(mAnimationAlpha);//开始播放动画 break;
case KeyEvent.KEYCODE_DPAD_DOWN:
mAnimationScale = AnimationUtils.loadAnimation(mContext,R.layout.scale);//装载动画布局
this.startAnimation(mAnimationScale);//开始播放动画 break;
case KeyEvent.KEYCODE_DPAD_LEFT: mAnimationTranslate =
AnimationUtils.loadAnimation(mContext,R.layout.translate);//装载动画布局 this.startAnimation(mAnimationTranslate);//开始播放动画 break;
case KeyEvent.KEYCODE_DPAD_RIGHT: mAnimationRotate =
AnimationUtils.loadAnimation(mContext,R.layout.rotate);//装载动画布局 this.startAnimation(mAnimationRotate);//开始播放动画 break; }
return true; } }
=================================================================================================================================== Framed动画
第一种方法 在代码中设计
public class GameView extends View{
private AnimationDrawable animationDrawable = null;//定义AnimationDrawable装载动画 Context mContext = null;
Drawable mBitAnimation = null;//定义一个Drawable对象 public GameView(Context context){ super(context); mContext = context;
animationDrawable = new AnimationDrawable();//实例化AnimationDrawable对象
for (int i = 1; i <= 15; i++){//利用循环装载所有名字类似的资源(图片命名时是有规律的 所以才能用此循环)
int id = getResources().getIdentifier(\mContext.getPackageName());------------------------需要深入 mBitAnimation = getResources().getDrawable(id);
animationDrawable.addFrame(mBitAnimation, 500);//通过addFrame方法把每一帧添加进去,每一帧显示的时间为500毫秒 }
animationDrawable.setOneShot( false );//利用setOneShot方法设置播放模式是否循环false表示循环而true表示不循环
this.setBackgroundDrawable(animationDrawable);// 加载本类将要显示这个动画 }
public void onDraw(Canvas canvas){ super.onDraw(canvas); }
public boolean onKeyUp(int keyCode, KeyEvent event){ switch ( keyCode ){
case KeyEvent.KEYCODE_DPAD_UP:
animationDrawable.start();//最后通过start方法播放动画 break; }
return true; }
} 要想显示Frame动画,还要在Activity中添加GameView对象 ------------------------------------------------------------------------------ 第二种方法:在XML文件中的设计 frameanimation.xml
public class GameView extends View{ private AnimationDrawable frameAnimation = null; Context mContext = null; public GameView(Context context){ super(context); mContext = context; ImageView img = new ImageView(mContext);//定义一个ImageView用来显示动画 img.setBackgroundResource(R.anim.frameanimation);//装载动画布局文件 frameAnimation = (AnimationDrawable) img.getBackground();//构建动画 frameAnimation.setOneShot( false ); //设置是否循环 this.setBackgroundDrawable(frameAnimation);//设置该类显示的动画 } public void onDraw(Canvas canvas){ super.onDraw(canvas); } public boolean onKeyUp(int keyCode, KeyEvent event){ switch ( keyCode ){ case KeyEvent.KEYCODE_DPAD_UP: frameAnimation.start();//开始播放动画 break; } return true; } } 还许要在Acitivity类中实例化GameView对象才能显示。 =================================================================================================================================================== GIF动画播放 其原理:首先需要对GIF动画图像进行解码,然后将GIF中的每一帧分别提取出来保存到一个容器中,然后根据需要绘制每一帧,这样就可以轻松地实现GIF动画的播放了。 下面有个例子,可以在工作中直接使用。 public class GifDecoder{ private int E0; private int E1[]; private int E2; private int E6; private boolean E7; private int E8[]; private int width; private int height; private int ED; private boolean EE; private boolean EF; private int F0[]; private int F1; private boolean F2; private int F3; private long F4; private int F5; private static final int F6[] = { 8, 8, 4, 2 }; private static final int F8[] = { 0, 4, 2, 1 }; int curFrame; int poolsize; int FA; byte C2[]; int FB; int FC; int FD; public GifDecoder(byte abyte0[]){ E0 = -1; E1 = new int[280]; E2 = -1; E6 = 0; E7 = false; E8 = null; width = 0; height = 0; ED = 0; EE = false; EF = false; F0 = null; F1 = 0; F5 = 0; curFrame = 0; C2 = abyte0; poolsize = C2.length; FA = 0; } public boolean moreFrames(){ return poolsize - FA >= 16; } public void nextFrame(){ curFrame++; } public Bitmap decodeImage(){ return decodeImage(curFrame); } public Bitmap decodeImage(int i){ if (i <= E0){ return null; } if (E0 < 0){ if (!E3()){ return null; } if (!E4()){ return null; } } do{ if (!E9(1)){ return null; } int j = E1[0]; if (j == 59){ return null; } if (j == 33){ if (!E7()){ return null; } } else if (j == 44){ if (!E5()){ return null; } Bitmap image = createImage(); E0++; if (E0 < i){ image = null; }else{ return image; } } } while (true); } public void clear(){ C2 = null; E1 = null; E8 = null; F0 = null; } private Bitmap createImage(){ int i = width; int j = height; int j1 = 0; int k1 = 0; int ai[] = new int[4096]; int ai1[] = new int[4096]; int ai2[] = new int[8192]; if (!E9(1)){ return null; } int k = E1[0]; int[] image = new int[width * height]; int ai3[] = E8; if (EE){ ai3 = F0; } if (E2 >= 0){ ai3[E2] = 0xffffff; } int l2 = 1 << k; int j3 = l2 + 1; int k2 = k + 1; int l3 = l2 + 2; int k3 = -1; int j4 = -1; for (int l1 = 0; l1 < l2; l1++){ ai1[l1] = l1; } int j2 = 0; E2(); j1 = 0; label0: for (int i2 = 0; i2 < j; i2++){ int i1 = 0; do{ if (i1 >= i){ break; } if (j2 == 0){ int i4 = E1(k2); if (i4 < 0){ return Bitmap.createBitmap(image, width, height, Config.RGB_565); } if (i4 > l3 || i4 == j3){ return Bitmap.createBitmap(image, width, height, Config.RGB_565); } if (i4 == l2){ k2 = k + 1; l3 = l2 + 2; k3 = -1; continue; } if (k3 == -1){ ai2[j2++] = ai1[i4]; k3 = i4; j4 = i4; continue; } int i3 = i4; if (i4 == l3){ ai2[j2++] = j4; i4 = k3; } for (; i4 > l2; i4 = ai[i4]){ ai2[j2++] = ai1[i4]; } j4 = ai1[i4]; if (l3 >= 4096){ return Bitmap.createBitmap(image, width, height, Config.RGB_565); } ai2[j2++] = j4; ai[l3] = k3; ai1[l3] = j4; if (++l3 >= 1 << k2 && l3 < 4096){ k2++; } k3 = i3; } int l = ai2[--j2]; if (l < 0){ return Bitmap.createBitmap(image, width, height, Config.RGB_565); } if (i1 == 0){ FC = 0; FB = ai3[l]; FD = 0; }else if (FB != ai3[l]){ for (int mm = FD; mm <= FD + FC; mm++){ image[j1 * width + mm] = FB; } FC = 0; FB = ai3[l]; FD = i1; if (i1 == i - 1){ image[j1 * width + i1] = ai3[l]; } }else{ FC++; if (i1 == i - 1){ for (int mm = FD; mm <= FD + FC; mm++){ image[j1 * width + mm] = FB; } } } i1++; } while (true); if (EF){ j1 += F6[k1]; do{ if (j1 < j){ continue label0; } if (++k1 > 3){ return Bitmap.createBitmap(image, width, height, Config.RGB_565); } j1 = F8[k1]; } while (true); } j1++; } return Bitmap.createBitmap(image, width, height, Config.RGB_565); } private int E1(int i){ while (F5 < i){ if (F2){ return -1; } if (F1 == 0){ F1 = E8(); F3 = 0; if (F1 <= 0){ F2 = true; break; } } F4 += E1[F3] << F5; F3++; F5 += 8; F1--; } int j = (int) F4 & (1 << i) - 1; F4 >>= i; F5 -= i; return j; } private void E2(){ F5 = 0; F1 = 0; F4 = 0L; F2 = false; F3 = -1; } private boolean E3(){ if (!E9(6)){ return false; } return E1[0] == 71 && E1[1] == 73 && E1[2] == 70 && E1[3] == 56 && (E1[4] == 55 || E1[4] == 57) && E1[5] == 97; } private boolean E4(){ if (!E9(7)){ return false; } int i = E1[4]; E6 = 2 << (i & 7); E7 = EB(i, 128); E8 = null; return !E7 || E6(E6, true); } private boolean E5(){ if (!E9(9)){ return false; } width = EA(E1[4], E1[5]); height = EA(E1[6], E1[7]); int i = E1[8]; EE = EB(i, 128); ED = 2 << (i & 7); EF = EB(i, 64); F0 = null; return !EE || E6(ED, false); } private boolean E6(int i, boolean flag){ int ai[] = new int[i]; for (int j = 0; j < i; j++){ if (!E9(3)){ return false; } ai[j] = E1[0] << 16 | E1[1] << 8 | E1[2] | 0xff000000; } if (flag){ E8 = ai; }else{ F0 = ai; }
正在阅读:
Android手机游戏开发知识点总结01-30
低年级作文指导06-07
酒店餐饮部培训资料 - 图文01-31
电子时钟的设计01-15
浙江省2018届高三预测金卷文科综合试题及答案 精品 - 图文12-21
XX年县发改局副局长述职报告05-07
HXN5型内燃机车“油水互窜”故障浅析12-21
霍兰德职业倾向测验量表05-26
影视制作-招标书08-08
()论文写作要点01-08
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 知识点
- 手机游戏
- Android
- 总结
- 开发
- 电教教师岗位安全工作责任书
- 安全管理台帐 - 图文
- 高考英语冲刺模拟题
- 2017年高三历史组复习计划
- 《基础会计学》教案
- 旅游公关与策划课件
- 中国数字化仪行业调查投资研究报告目录
- 西安交通大学理论力学小组大作业报告 - 图文
- 人教版八年级数学练习试题第一章第二章,难题,好题
- 2016上海应届毕业生进沪就业申请户籍办法
- 六年级思品下册测试题
- 物理人教版选修3-2同步练习专题1楞次定律的推广及应用
- 简述朱熹的教育思想
- linux php开发环境配置
- 结训典礼主持词
- 国际贸易考试试题及答案
- 《机械制图》会考复习题集(修改)
- 2012年北京燕山区中考二模英语试卷及答案
- 机械基础练习题(练习题库) - 图文
- 河南省公路工程施工招标固定标价随机抽取法实施办法