程序运行效果图:
代码实现:
1、MainActivity
package com.njupt.surface; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends Activity implements OnClickListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MySurfaceView(this)); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View v) { } @Override public boolean dispatchTouchEvent(MotionEvent ev) { GameData.clickX = (int) ev.getX(); GameData.clickY = (int) ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: GameData.clickType = GameData.DOWN; break; case MotionEvent.ACTION_MOVE: GameData.clickType = GameData.MOVE; break; case MotionEvent.ACTION_UP: GameData.clickType = GameData.UP; break; default: break; } return super.dispatchTouchEvent(ev); } /** * 根据当前activity加载的view的大小有关 */ @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub return super.onTouchEvent(event); } }
2、MySurfaceView
package com.njupt.surface; import java.util.ArrayList; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * ①展现游戏界面 * ②控制游戏界面 */ public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{ private SurfaceHolder sh;//SurfaceView的管理器,不直接和SurfaceView打交道 private boolean isDestroy = false; private Canvas canvas;//画纸 private Paint paint;//画笔 private int sW = 0; private int sH = 0; private ArrayList<Smile> list = new ArrayList<Smile>(); private Resources res; /** * ①绘制灰色背景 * ②绘制fps,帧率:每秒钟屏幕刷新的次数 * ③绘制按钮 * ④绘制小人,实现按钮的业务 * ⑤绘制笑脸 * */ public MySurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MySurfaceView(Context context) { super(context); res = context.getResources(); init(); sh = this.getHolder();//获取当前view管理者 sh.addCallback(this); paint = new Paint(); paint.setTextSize(30); paint.setAntiAlias(true);//设置抗锯齿 } private Bitmap[] bm = new Bitmap[10]; private int w1 = 0; private int h1 = 0; private int w2 = 0; private int h2 = 0; /** * 加载图片资源 */ private void init() { //加载drable下的资源可以使用BitmapFactory bm[0] = BitmapFactory.decodeResource(res, R.drawable.left01); bm[1] = BitmapFactory.decodeResource(res, R.drawable.left02); bm[2] = BitmapFactory.decodeResource(res, R.drawable.top); bm[3] = BitmapFactory.decodeResource(res, R.drawable.top2); bm[4] = BitmapFactory.decodeResource(res, R.drawable.right01); bm[5] = BitmapFactory.decodeResource(res, R.drawable.right02); bm[6] = BitmapFactory.decodeResource(res, R.drawable.bottom); bm[7] = BitmapFactory.decodeResource(res, R.drawable.bottom2); bm[8] = BitmapFactory.decodeResource(res, R.drawable.avatar_boy);//人物 bm[9] = BitmapFactory.decodeResource(res, R.drawable.rating_small);//笑脸 w1 = bm[0].getWidth(); h1 = bm[0].getHeight(); w2 = bm[2].getWidth(); h2 = bm[2].getHeight(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { sW = this.getWidth();//不要在surfaceCreate()方法中那这两个值,因为那时view可能还没完全生成... sH = this.getHeight(); GameData.screenX = sW; GameData.screenY = sH; } @Override public void surfaceCreated(SurfaceHolder holder) { new Thread(this).start(); fpsThread(); } private int fps = 0; private int count = 0;//计数,屏幕每刷新一次+1 private void fpsThread() { new Thread(new Runnable() { @Override public void run() { while(!isDestroy){ fps = count; count = 0; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { isDestroy = true; } @Override public void run() { while(!isDestroy){ canvas = sh.lockCanvas();//锁定画布,得到画布 draw(); count++; sh.unlockCanvasAndPost(canvas);//提交画好的画布,显示到屏幕 } } /** * 小人的初始位置... */ private int px = 10; private int py = 30; private int space = 5;//小人移动的距离 /** * 游戏界面的绘制 */ private void draw() { // canvas.drawColor(Color.GRAY); paint.setColor(Color.GRAY); canvas.drawRect(0,0,sW,sH, paint); paint.setColor(Color.GREEN); canvas.drawText(String.valueOf(fps), 10, sH - 20, paint); tickBtn();//应付事件,做相应处理 drawBtn(); canvas.drawBitmap(bm[8], px,py, null);//绘制小人 drawSmile();//绘制笑脸... } /** * 绘制笑脸... */ private void drawSmile() { for(int i = list.size() - 1 ; i >= 0 ; --i){ Smile smile = list.get(i); if(smile.isDestroy()){ list.remove(i); } } for(int i = 0 ; i < list.size() ; ++i){ Smile smile = list.get(i); smile.draw(canvas); } } private void tickBtn() { switch (GameData.clickType) { case GameData.DOWN: if(!btn()){ createSmile(); GameData.clickType = 0;//防止笑脸一直创建... } break; case GameData.MOVE://用于处理手指一开始不在按钮上,但是滑到了按钮上的情况... btn(); break; case GameData.UP: left = 0; top = 0; right = 0; bottom = 0; break; default: break; } } private void createSmile() { Smile smile = new Smile(bm[9],new Point(px+50,py+50),new Point(GameData.clickX,GameData.clickY),0.02f); list.add(smile); } /** * 用于点击按钮时,将按钮的图片换掉... * 使用boolean作为返回值是为了解决点击按钮时也产生笑脸的bug。。。 */ private boolean btn() { int x = GameData.clickX; int y = GameData.clickY; //判断是否点击了左边按钮 if(10 < x && x < 10+w1 && sH-100 < y && y < sH-100+h1){ left = 1;//用于将图片切换掉... px -= space;//用于改变小人的位置 return true; } //判断是否点击了上边按钮 if(60 < x && x < 60+w2 && sH-150 < y && y < sH-150+h2){ top = 1; py -= space; return true; } if(110 < x && x < 100+w1 && sH-100 < y && y < sH-100+h1){ right = 1; px += space; return true; } if(60 < x && x < 60+w2 && sH-60 < y && y < sH-60+h2){ bottom = 1; py += space; return true; } return false; } private int left = 0; private int top = 0; private int right = 0; private int bottom = 0; private void drawBtn() { canvas.drawBitmap(bm[0 + left], 10,sH-100 ,null);//绘制左边按钮 canvas.drawBitmap(bm[2 + top], 60,sH-150 ,null); canvas.drawBitmap(bm[4 + right], 110,sH-100 ,null); canvas.drawBitmap(bm[6 + bottom], 60,sH-60 ,null); } }
3、GameData
package com.njupt.surface; public class GameData { public static int clickX = 0; public static int clickY = 0; public static int clickType = 0;//记录当前和屏幕交换的状态 public final static int DOWN = 1; public final static int MOVE = 2; public final static int UP = 3; public static int screenX = 0; public static int screenY = 0; }
4、Smile
package com.njupt.surface; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; public class Smile { private Bitmap bm; private Point sp;//笑脸的起点 private Point ep;//笑脸的终点 private float space; public Smile(Bitmap bm, Point sp, Point ep, float space) { super(); this.bm = bm; this.sp = sp; this.ep = ep; this.space = space; px = sp.x; py = sp.y; } private int px = 0; private int py = 0; public void draw(Canvas canvas){ canvas.drawBitmap(bm, px, py,null); tick(); if(GameData.screenX < px || px < -bm.getWidth() || py < - bm.getHeight() || py > GameData.screenY){ isDestroy = true; } } /** * 用于改变笑脸的位置 */ private void tick() { if(ep.x > sp.x){ px += (ep.x - sp.x)*space; }else if(sp.x > ep.x){ px -= (sp.x - ep.x)*space; } if(ep.y > sp.y){ py += (ep.y - sp.y)*space; }else{ py -= (sp.y - ep.y)*space; } } private boolean isDestroy = false; public boolean isDestroy(){ return isDestroy; } }