用SurfaceView制作简单的android游戏 : 重力小球(2)制作重力感应小球

1.紧接第一篇,创建一些类

Vec.java (用来表示速度的)

View Code
public class Vec {

    public Float _x, _y;
    
    Vec(){
        _x = _y = 0.f;
    }
    
    Vec(float x, float y){
        _x = x;
        _y = y;
    }
    
    float getAngle(){
        return (float)Math.atan2(_x, _y);
    }
    
    //坐标系内任意一点到原点的距离
    float getLength(){
        return (float)Math.sqrt(_x *_x + _y * _y);
    }
}

Circle.java (表示玩家各项参数属性的)

View Code
public class Circle {

        public float _x, _y, _r;

        Circle(){
                _x = _y = _r = 0;
        }
//座标x,y, 半径r        
        Circle(float x, float y, float r){
                _x = x;
                _y = y;
                _r = r;
        }
        
}

 

Player.java (表示玩家)

View Code
public class Player extends Task {
        private final static float SIZE = 20;           //半径
        private Circle _cir = null;             //表示自身的圆
        private Paint _paint = new Paint();     //画笔
        private Vec _vec = new Vec();           //速度
        
        public Player(){
                _cir = new Circle( 240, 0, SIZE );//在(240,0)生成玩家
                _paint.setColor(Color.BLUE);      //颜色
                _paint.setAntiAlias(true);        //抗锯齿
                _vec._y = 2;                      //设置初始的方向
        }

        @Override
        public boolean onUpdate(){
                _cir._x += _vec._x;     //更新玩家的移动
                _cir._y += _vec._y;             
                return true;
        }

        @Override
        public void onDraw( Canvas c ){
                c.drawCircle(_cir._x, _cir._y, _cir._r, _paint);
        }

}

AcSensor.java (重力感应器,写法网上一搜一大堆,要注意在activity暂停时注销感应器,不然会多次注册出错)

View Code
public class AcSensor implements SensorEventListener {

    private SensorManager _sensorManager = null;
    private float _x, _y, _z;

    public void onCreate(Context c) {
        // 获取系统sensorManager
        _sensorManager = (SensorManager) c
                .getSystemService(Context.SENSOR_SERVICE);
        onResume();
    }

    public void onResume() {
        // 获取sensor
        Sensor sensor = _sensorManager
                .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        // 注册sensor
        _sensorManager.registerListener(this, sensor,
                SensorManager.SENSOR_DELAY_FASTEST);
    }

    public void onPause() {
        if (_sensorManager == null) {
            return;
        }
        _sensorManager.unregisterListener(this);
    }

    //当感应器数值改变时
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            _x = event.values[SensorManager.DATA_X];
            _y = event.values[SensorManager.DATA_Y];
            _z = event.values[SensorManager.DATA_Z];
        }
    }

    public float getX() {
        return _x;
    }

    public float getY() {
        return _y;
    }

    public float getZ() {
        return _z;
    }

    // 频率改变时调用,也就是SensorManager.SENSOR_DELAY_FASTEST改变时
    //这里暂时用不上
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    //singleton单例模式
    private static AcSensor _instance = new AcSensor();

    private AcSensor() {
        _x = _y = _z = 0;
    }

    public static AcSensor Inst() {
        return _instance;
    }

}

记得把player添加到tasklist中,

GameMgr.java中的_taskList.add( new FpsController() );前添加_taskList.add( new Player() );

让玩家与感应器连接起来,在Player.java的update方法中加入

 //从传感器获取数据
float x = -AcSensor.Inst().getX();
float y = AcSensor.Inst().getY();

还记得重力感应器用了单例模式么?

IrairaBarActivity.java代码如下

View Code
public class IrairaBarActivity extends Activity implements
        GestureDetector.OnGestureListener {

    GameSurfaceView _view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // 设置全屏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // 去除标题
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 确保屏幕不会自动关闭
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        super.onCreate(savedInstanceState);

        _view = new GameSurfaceView(this);
        setContentView(_view);

        // sensor的初始化
        AcSensor.Inst().onCreate(this);

    }

    @Override
    protected void onResume() {
        super.onResume();
        // 游戏重开时使感应器也重开
        AcSensor.Inst().onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 游戏暂停时感应器也暂停
        AcSensor.Inst().onPause();
    }
}

 

 

2.为小球的移动加上惯性吧

Vec.java加入两个方法

View Code
//限制最大速度
    void setLengthCap( float maxLength ){
            float len = getLength();
            if( maxLength == 0 ){
                    return; 
            }
            if( len > maxLength ){
                    float rate =len/maxLength;
                    _x /= rate;
                    _y /= rate;
            }
    }
    
     //速度变化快慢
    void blend( Vec vec, float rate ){
            float w = vec._x - _x;
            float h = vec._y - _y;
            _x += w*rate;
            _y += h*rate;
    }

 

最后的Player.java更新如下

View Code
public class Player extends Task {

    private final static float SIZE = 10; // 自身大小
    private Circle _cir = null; // 自身
    private Paint _paint = new Paint(); // 画出自己所需要的画笔
    private Vec _vec = new Vec(); // 自身的移动方向

    private Vec _sensorVec = new Vec(); // 传感器的速度
    private final static float MAX_SPEED = 10; // 小球最大速度

    public Player() {
        _cir = new Circle(160, 50, SIZE);// 初始化玩家位置
        _paint.setColor(Color.BLUE); // 设置为蓝色
        _paint.setAntiAlias(true); // 抗锯齿
        _vec._y = 0.1f; // 初始化方向
    }

    //设置小球方向速度
    private void setVec() {
        float x = -AcSensor.Inst().getX(); //从传感器获取数据
        float y = AcSensor.Inst().getY();
        _sensorVec._x = x < 0 ? -x * x : x * x; //用平方可以让速度的变化幅度加大
        _sensorVec._y = y < 0 ? -y * y : y * y; 
        _sensorVec.setLengthCap(MAX_SPEED); //设置最大速度
        _vec.blend(_sensorVec, 0.05f); // 速度变化的快慢
    }

    private void Move() {
        // 把数据赋值给小圆球
        _cir._x += _vec._x;
        _cir._y += _vec._y;
    }
    
    //取得自身圆
    public final Circle getPt(){
            return _cir;
    }

    @Override
    public boolean onUpdate() {
        setVec();
        Move();
        return true;
    }

    @Override
    public void onDraw(Canvas c) {
        c.drawCircle(_cir._x, _cir._y, _cir._r, _paint);
    }

}

至此可以到真机上测试一下,正常的话可以得到一个重力感应球 

 

 

 

 

 

原文地址:https://www.cnblogs.com/tomboy/p/2683511.html