阅读更多 一、开发运动体Movable类
   我们将小球视为一个可移动物体Movable对象,该类中除了包含小球图片对象之外,还包括如位置坐标、水平竖直速度等一系列用于模拟小球运动的成员变量和一些方法。具体代码如下:

package xiao.fuyan.ball;import android.graphics.Bitmap;import android.graphics.Canvas;/** * Created by xiao on 2017/2/9. */public class Movable {    //初始X,Y坐标    int startX = 0, startY = 0;    //实时X,Y坐标    int x = 0, y = 0;    //初始水平、竖直方向的速度    float startV_X = 0f;    float startV_Y = 0f;    //实时水平、竖直方向的速度    float v_x = 0f;    float v_y = 0f;    //可移动物体半径    int r;    //X,Y方向上运动的时间    double timeX, timeY;    //可移动物体的图片    Bitmap bitmap = null;    //负责小球运动的线程    BallThread bt = null;    //小球是否从木板上落下    boolean bFall = false;    //小球撞地后速度的损失系数    float impactFactor = 0.25f;    //构造器,负责初始化主要的成员变量    public Movable(int x, int y, int r, Bitmap bitmap){        this.startX = x;        this.x = x;        this.startY = y;        this.y = y;        this.r = r;        this.bitmap = bitmap;        //获取系统时间来初始化timeX        this.timeX = System.nanoTime();        this.v_x = BallView.V_MIN + (int)((BallView.V_MAX - BallView.V_MIN)*Math.random());        this.bt = new BallThread(this);        this.bt.start();    }    //将自己绘制到屏幕上    public void drawSelf(Canvas canvas){        canvas.drawBitmap(this.bitmap, x, y, null);    }}

二、开发物理引擎BallThread类
   该类继承自Thread类,在程序中,每一个Movable对象都会有一个独立的BallThread对象,其主要作用是改变小球的运动轨迹。具体代码如下:

package xiao.fuyan.ball;/** * Created by xiao on 2017/2/9. */public class BallThread extends Thread {    //Movable对象的引用    Movable father;    //线程执行标志位    boolean flag = false;    //休眠时间    int sleepSpan = 40;    //小球下落的加速度    float g = 200;    //记录当前的时间    double current;    public BallThread(Movable father){        this.father = father;        this.flag = true;    }    @Override    public void run() {        while(flag){            //获取当前时间,单位为纳秒            current = System.nanoTime();            //处理水平方向上的运动,首先获取水平运动的时间            double timeSpanX = (double) ((current - father.timeX)/1000/1000/1000);            //获取水平方向移动的距离            father.x = (int) (father.startX + father.v_x * timeSpanX);            //处理竖直方向上的运动            //判断小球是否移出挡板            if(father.bFall){                double timeSpanY = (double) ((current - father.timeY)/1000/1000/1000);                father.y = (int) (father.startY + father.startV_Y * timeSpanY + timeSpanY * timeSpanY * g/2);                //计算竖直方向速度                father.v_y = (float) (father.startV_Y + g * timeSpanY);                //判断小球是否到达最高点                if(father.startV_Y < 0 && Math.abs(father.v_y) <= BallView.UP_ZERO){                    //设置新的运动阶段竖直方向上的开始时间                    father.timeY = System.nanoTime();                    //设置新的运动阶段竖直方向上的实时速度                    father.v_y = 0;                    //设置新的运动阶段竖直方向上的初始速度                    father.startV_Y = 0;                    //设置新的运动阶段竖直方向上的初始位置                    father.startY = father.y;                }                //判断小球是否撞地                if(father.y + father.r * 2 >= BallView.GROUND_LING && father.v_y > 0){                    //衰减水平和竖直方向的速度                    father.v_x = father.v_x * (1 - father.impactFactor);                    father.v_y = 0 - father.v_y * (1 - father.impactFactor);                    if(Math.abs(father.v_y) < BallView.DOWN_ZERO){ //撞地衰减后速度太小就直接停止                        this.flag = false;                    }else{                        father.startX = father.x;                        father.timeX = System.nanoTime();                        father.startY = father.y;                        father.timeY = System.nanoTime();                        father.startV_Y = father.v_y;                    }                }            }else if(father.x + father.r/2 >= BallView.WOOD_EDGE){                father.timeY = System.nanoTime();                father.bFall = true;            }            try{                sleep(sleepSpan);            }catch (Exception e){                e.printStackTrace();            }        }    }}

三、开发视图BallView类
   这次我们介绍的是负责画面渲染的视图类BallView,其中声明了一些物理计算时需要使用静态常量,同时还声明了程序中要绘制的图片资源以及要绘制的小球对象列表。具体代码如下:

package xiao.fuyan.ball;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.view.SurfaceHolder;import android.view.SurfaceView;import java.util.ArrayList;import java.util.Random;/** * Created by xiao on 2017/2/9. */public class BallView extends SurfaceView implements SurfaceHolder.Callback {    //小球水平速度的最值    public static final int V_MAX = 65;    public static final int V_MIN = 45;    //木板右边沿的X坐标    public static final int WOOD_EDGE = 110;    //游戏中代表地面的坐标,小球到此后会弹起    public static final int GROUND_LING = 1920;    //小球上升时,如果速度小于该值就算0    public static final int UP_ZERO = 30;    //小球撞地时,如果速度小于该值就算0    public static final int DOWN_ZERO = 60;    //各种颜色形状的小球图片的引用    Bitmap[] bitmaps = new Bitmap[6];    //背景图片对象    Bitmap bmpBack;    //木板图片对象    Bitmap bmpWood;    //帧速率字符串    String fps = "FPS:N/A";    //小球数目    int ballNumber = 6;    ArrayList alMovable = new ArrayList();    //后台屏幕绘制线程    DrawThread dt;    //构造器    public BallView(Context context){        super(context);        getHolder().addCallback(this);        //初始化图片        initBitmaps(getResources());        //初始化小球        initMovables();        //初始化重绘线程        dt = new DrawThread(this, getHolder());    }    //初始化图片    public void initBitmaps(Resources r){        bitmaps[0] = BitmapFactory.decodeResource(r, R.mipmap.red_small);        bitmaps[1] = BitmapFactory.decodeResource(r, R.mipmap.red);        bitmaps[2] = BitmapFactory.decodeResource(r, R.mipmap.yellow_small);        bitmaps[3] = BitmapFactory.decodeResource(r, R.mipmap.yello);        bitmaps[4] = BitmapFactory.decodeResource(r, R.mipmap.blue_small);        bitmaps[5] = BitmapFactory.decodeResource(r, R.mipmap.blue);        bmpBack = BitmapFactory.decodeResource(r, R.mipmap.wall);        bmpWood = BitmapFactory.decodeResource(r, R.mipmap.wood);    }    public void initMovables(){        Random r = new Random();        for(int i = 0; i < ballNumber; i++){            int index = r.nextInt(32);            Bitmap tmp = null;            if(i < ballNumber/2){                tmp = bitmaps[3 + index % 3];            }else{                tmp = bitmaps[index % 3];            }            //创建Movable对象            Movable m = new Movable(0, 110 - tmp.getHeight(), tmp.getWidth()/2, tmp);            alMovable.add(m);        }    }    public void doDraw(Canvas canvas){        canvas.drawBitmap(bmpBack, 0, 0, null);        canvas.drawBitmap(bmpWood, 0, 100, null);        for(Movable m : alMovable){            m.drawSelf(canvas);        }        Paint p = new Paint();        p.setColor(Color.BLUE);        p.setTextSize(60);        p.setAntiAlias(true);        canvas.drawText(fps, 800, 80, p);    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        if(!dt.isAlive()){            dt.start();        }    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        dt.flag = false;        dt = null;    }}

四、开发绘制线程DrawThread类
   该类的弄能比较简单,主要是负责定时重绘屏幕和计算帧速率。具体代码如下:

package xiao.fuyan.ball;import android.graphics.Canvas;import android.view.SurfaceHolder;/** * Created by xiao on 2017/2/9. */public class DrawThread extends Thread {    //BallView对象的引用    BallView bv;    //SurfaceHolder对象的引用    SurfaceHolder surfaceHolder;    //线程执行标志位    boolean flag = false;    //休眠时间    int sleepSpan;    //记录开始时刻,用于计算帧速率    long start = System.nanoTime();    //记录帧数    int count = 0;    public DrawThread(BallView bv, SurfaceHolder surfaceHolder){        this.bv = bv;        this.surfaceHolder = surfaceHolder;        this.flag = true;    }    @Override    public void run() {        Canvas canvas = null;        while(flag){            try {                //获取BallView的画布                canvas = surfaceHolder.lockCanvas(null);                synchronized (surfaceHolder){                    bv.doDraw(canvas);                }            }catch (Exception e){                e.printStackTrace();            }finally {                if(canvas != null){                    surfaceHolder.unlockCanvasAndPost(canvas);                }            }            count++;            if(count == 20){                count = 0;                long tempStamp = System.nanoTime();                long span = tempStamp - start;                start = tempStamp;                double fps = Math.round(100000000000.0/span*20)/100.0;                bv.fps = "FPS:" + fps;            }            try{                sleep(sleepSpan);            }catch (Exception e){                e.printStackTrace();            }        }    }}

五、开发主Activity类
   该类用于加载界面组件。具体代码如下:

package xiao.fuyan.ball;import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity {    BallView bv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //设置不显示标题        requestWindowFeature(Window.FEATURE_NO_TITLE);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                WindowManager.LayoutParams.FLAG_FULLSCREEN);        bv = new BallView(this);        setContentView(bv);    }}

   至此整个程序代码开发完毕。该代码可直接运行。
  • ball.zip (3.3 MB)
  • 下载次数: 4

更多相关文章

  1. Android实现iPhone晃动撤销输入功能 Android仿微信摇一摇功能
  2. Androidの重力感应
  3. Android检查GPU呈现速度和过度绘制
  4. android高分段进阶攻略(1)传感器
  5. 闲鱼如何在2个月内实现Android启动速度翻倍的?
  6. Android(安卓)基础知识之 VelocityTracker使用(提供手指速度计算,
  7. [置顶] Android(安卓)自定义ViewGroup实现整个Item布局竖直跑马
  8. Androidstudio实现手机摇一摇功能
  9. Android(安卓)自定义 View 之弹球游戏

随机推荐

  1. 2021年8月6日作业:回调函数和递归函数的认
  2. php之灭绝回调函数,师太递归函数
  3. 0806-请实例演绎你对回调函数与递归函数
  4. 回调函数、递归函数
  5. 对回调函数和递归函数的理解
  6. 回调函数,递归函数
  7. 利用php循环遍历及运算法则实现重新组合
  8. 【前端 · 面试 】HTTP 总结(八)—— HTTP
  9. php编程基础0806作业
  10. php基础编程作业-0805