• 用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);
        }
    
    }

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

     

     

     

     

     

  • 相关阅读:
    vim 高级使用技巧第二篇
    你所不知道的Html5那些事(一)
    linux设备驱动第三篇:如何实现一个简单的字符设备驱动
    Android Metro风格的Launcher开发系列第二篇
    「BZOJ3123」[SDOI2013]森林
    【模板】左偏树
    「luogu3157」[CQOI2011]动态逆序对
    「luogu3567」[POI2014]KUR-Couriers
    【模板】二逼平衡树
    「luogu3313」[SDOI2014]旅行
  • 原文地址:https://www.cnblogs.com/tomboy/p/2683511.html
Copyright © 2020-2023  润新知