平衡球小游戏
在手机硬件还不够发达的早些时候,简易的"体感游戏"成为了手机游戏中的一个大头。
利用设备上自带的动态传感器,通过摇晃手机等方式,移动游戏物体来游玩的游戏。
为了成功理解陀螺仪的使用,我试着还原了一个类似的小游戏。
可以在这里获取我的游戏demo.
首先是…球?
为了尽可能简单地去体现陀螺仪的本质,整个游戏本身我仅使用了常规的布局组件来完成。
- 一个ConstraintLayout作为棋盘
- 一个重写过的View子类customDrawableView作为"球体"
- 一个继承于Drawable的Ball类,作为球的外观,放在"球体"上
constraintLayout = new ConstraintLayout(this);constraintLayout.addView(customDrawableView);setContentView(constraintLayout);
public class Ball extends Drawable {private final Paint redPaint;public Ball() {redPaint = new Paint();redPaint.setARGB(255, 255, 0, 0);}@Overridepublic void draw(Canvas canvas) {int width = getBounds().width();int height = getBounds().height();float radius = Math.min(width, height) / 2;//绘制一个红色的实心圆canvas.drawCircle(width/2, height/2, radius, redPaint);}//...省略了其他必须继承的空方法}
效果如下
很简陋对吧,而接下来则是重点
再然后是…让牛顿现身?
传感器有分许多种,而调用传感器的方式非常简单
private SensorManager sensorManager;//传感管理器实例
private Sensor sensor;//传感器实例
...
//获取实例并从管理器实例中获取传感器实例
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//X为传感器类别
sensor = sensorManager.getDefaultSensor(Sensor.X);
常用的有
TYPE_GRAVITY 三轴重力
TYPE_GYROSCOPE 三轴旋转加速度
TYPE_ACCELEROMETER 三轴加速度
这里直接选择Sensor.TYPE_ACCELEROMETER就行
为了让牛顿大叔能够感受到变化,就得整个监听器。
sensorManager.registerListener(new SensorEventListener() {//核心方法,当传感器变化时会立刻调用这个函数@Overridepublic void onSensorChanged(SensorEvent event) {double x = event.values[0];double y = event.values[1];double z = event.values[2];customDrawableView.speed_x += -x;//球的横轴速度customDrawableView.speed_y += y;//球的纵轴速度}//监听精度变化,在这里暂时用不到@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}},sensor,SensorManager.SENSOR_DELAY_NORMAL);
最后是…会动的球?
要让球动起来,只要不断让球通过速度属性进行运动就行了,这里我通过额外建立了一个新线程,让该线程不断循环根据球的速度属性进行view的移动
public class MoveThread extends Thread {private Thread t;private CustomDrawableView view;MoveThread(CustomDrawableView c){view = c;}public void run() {while(true){//第一遍球在高速移动的时候卡卡的,所以这里做了一个高速优化if(Math.sqrt(view.speed_x*view.speed_x+view.speed_y*view.speed_y)>10){try{Thread.sleep(10);}catch (Exception e){}view.moveView((int)view.speed_x/10,(int)view.speed_y/10);}else {try{Thread.sleep(100);}catch (Exception e){}view.moveView((int)view.speed_x,(int)view.speed_y);}}}public void start () {if (t == null) {t = new Thread (this);t.start ();}}
}
//MainActivity
MoveThread mt = new MoveThread(customDrawableView);mt.start();
然后再加上防止球滚出棋盘等等小细节…搞定!
实机调试后有点上头
是不是哪里不对?
确实有一个地方没搞清楚,为了防止球滚出屏幕外,我使用的是
DisplayMetrics metrics = this.getResources().getDisplayMetrics();
来获取设备屏幕长宽
但是由于不同设备有着不同的组件大小,屏幕尺寸≠constrainlayout尺寸
我试着使用constrainlayout的getwidth()与getheight()获取尺寸,但是发现结果是0*0
查阅了一下文档可能是因为constrainlayout默认使用的是"match_parent",在查看了很多博客之后没能解决这个问题最后选择了偷懒
希望有人能解答如何获取属性为"match_parent"的组件的尺寸
邮箱:774244276@qq.com
参考文档
安卓官方文档
作者 方昉
原文地址