很简单的实现,作为软件专业大二在校生,接触安卓还没两个月,没事写着玩练练手,请大神们莫要嘲讽
重力小球主要参考了http://www.xuanyusong.com/archives/337这篇文章,我写出来的代码风格都完全一样,惭愧惭愧
(我的第一篇CSDN博客,值得纪念一手,蛤蛤蛤
package com.example.a29205.myapp10;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
final static String TAG="MainActivity";
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 全屏显示窗口
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//强制横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// 显示自定义的游戏View
mysuferView mysuferView=new mysuferView(this);
setContentView(mysuferView);
}
@Override
protected void onPause() {
super.onPause();
}
}
然后就是自定义的suferView
package com.example.a29205.myapp10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import static android.content.Context.SENSOR_SERVICE;
/**
* Created by 29205 on 2018/4/29.
*/
public class mysuferView extends SurfaceView implements SurfaceHolder.Callback,Runnable,SensorEventListener{
final static String TAG="mysuferView";
SensorManager mSensorManager;//SensorManager 是系统所有传感器的管理器,获得一个sensormanager的实例
Sensor mSensor_of_orientation;//传感器sensor实例
//永远记得确保当你不需要的时候,特别是Activity暂定的时候,要关闭感应器。
SensorEventListener mSensorEventListener;//对传感器输出的信号进行监听
float GX=0;
float GY=0;
float GZ;
//重力加速度g在设备的x,y,z轴三个方向的分量
double AX;
double AY=0;////大地垂直坐标系与设备Y轴之间的弧度,由该弧度的大小决定赋予小球加速度的大小
double AZ;
//设备的x,y,z轴与大地方向(即重力加速度方向)的夹角
double g;
//重力加速度
double acceleation;//小球被赋予的加速度,由屏幕旋转的角度赋予
double weiyi;
/**每30帧刷新一次屏幕**/
public static final int TIME_IN_FRAME = 30;
Paint mPaint = null;
Paint mLinePaint = null;
/**小球资源文件**/
private Bitmap mbitmapBall;
/**游戏背景文件**/
private Bitmap mbitmapBackground;
SurfaceHolder mSurfaceHolder = null;
/** 控制游戏更新循环 **/
boolean mRunning = false; // 子线程标志位
private Canvas mCanvas=null;// 用于绘图的Canvas
/**手机屏幕宽高**/
int mphoneScreenWidth = 0;
int mphoneScreenHeight = 0;
/**小球越界区域**/
private int mBallWidth_zuo = 0;
private int mBallHeight_shang = 0;
private int mBallWidth_you=0;
private int mBallHeight_xia= 0;
private int r_of_bianjie=500;
// 在屏幕内,坐标都是正值,屏幕范围内最小是0
/**小球的坐标位置**/
private float mPosX =500;
private float mPosY =300;
/* 不管横屏是由竖屏顺时针旋转90度,或者 逆时针旋转90度得到,
都是以左上角为原点。是视觉上的左上角 ,不是空间上的左上角。
*/
boolean is_chujie=false;
public void initView(Context context){//自定义的初始化方法
// 所谓焦点就是被选中的意思,或者说是“当前正在操作的组件”的意思。
// 如果一个组件被选中,或者正在被操作者,就是得到了焦点,而相反的,
// 一个组件没有被选中或者失去操作,就是被转移了焦点,焦点已经到别的组件上去了。
this.setFocusable(true);
//设置当前View可以拥有控制焦点
/** 设置当前View拥有触摸事件 **/
this.setFocusableInTouchMode(true);
/** 拿到SurfaceHolder对象 **/
mSurfaceHolder = this.getHolder();
/** 将mSurfaceHolder添加到Callback回调函数中 **/
mSurfaceHolder.addCallback(this);
/** 创建画布 **/
mCanvas = new Canvas();
mCanvas.drawColor(Color.YELLOW);
/** 创建画笔 ,分别用来画小球和杆**/
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mLinePaint=new Paint();
mLinePaint.setColor(Color.WHITE);
mLinePaint.setTextSize(30);
/**加载游戏背景**/
mbitmapBackground = BitmapFactory.decodeResource(this.getResources(), R.drawable.bg);
/**加载小球资源**/
mbitmapBall = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball);
mSensorManager= (SensorManager)context.getSystemService(SENSOR_SERVICE);//获取到 SensorManager 的实例
mSensor_of_orientation=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//获取重力传感器
mSensorManager.registerListener(this, mSensor_of_orientation, SensorManager.SENSOR_DELAY_GAME);//注册传感器
}
private void Draw() {//绘制方法
Log.e(TAG,mPosX+"mPosX ");
Log.e(TAG,mPosY+" mPosY");
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mCanvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mPosX+=0.5*GY*(TIME_IN_FRAME*TIME_IN_FRAME/80);
mPosY+=0.5*GX*(TIME_IN_FRAME*TIME_IN_FRAME/80);
/**绘制游戏背景**/
mCanvas.drawBitmap(mbitmapBackground,0,0, mPaint);
Paint linshipaint=new Paint();
linshipaint.setColor(Color.RED);
linshipaint.setTextSize(50);
if(is_chujie==true){
mCanvas.drawText("小球已出界",0,140,linshipaint);}
else{
mCanvas.drawText("小球未出界",0,140,linshipaint);}
mCanvas.drawText(GX+" X轴上的重力加速度",0,30,mLinePaint);
mCanvas.drawText(GY+" Y轴上的重力加速度",0,80,mLinePaint);
mCanvas.drawCircle(mphoneScreenWidth/2,mphoneScreenHeight/2 ,r_of_bianjie,mPaint);
/**绘制小球**/
mCanvas.drawBitmap(mbitmapBall, mPosX,mPosY, mPaint);
}
public mysuferView(Context context) {
super(context);
initView(context);
}
public mysuferView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public mysuferView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
//对于SurfaceHolder.Callback方法,需要实现如下方法,其实就是SurfaceView的生命周期:
@Override
public void surfaceCreated(SurfaceHolder holder) {
/**开始游戏主循环线程**/
mRunning = true;
/**得到当前屏幕宽高**/
mphoneScreenWidth = this.getWidth();
mphoneScreenHeight = this.getHeight();
Log.e(TAG,mphoneScreenWidth+"当前屏幕宽");
Log.e(TAG,mphoneScreenHeight+"当前屏幕的高");
/**得到小球越界区域**/
mBallWidth_you = (mphoneScreenWidth/2) +r_of_bianjie;
mBallWidth_zuo=(mphoneScreenWidth/2)-r_of_bianjie;
mBallHeight_shang=mphoneScreenHeight/2+r_of_bianjie;
mBallHeight_xia=mphoneScreenHeight/2-r_of_bianjie;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mRunning = false;
mSensorManager.unregisterListener(mSensorEventListener);//要调用 unregisterListener ()方法将使用的资源释放掉
}
//对于Runnable接口,需要实现run()方法
@Override
public void run() {
while (mRunning) {
/** 取得更新游戏之前的时间 **/
long startTime = System.currentTimeMillis();
/** 在这里加上线程安全锁 **/
synchronized (mSurfaceHolder) {
/** 拿到当前画布 然后锁定 **/
mCanvas = mSurfaceHolder.lockCanvas();
Draw();
/** 绘制结束后解锁显示在屏幕上 **/
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
/** 取得更新游戏结束的时间 **/
long endTime = System.currentTimeMillis();
/** 计算出游戏一次更新的毫秒数 **/
int diffTime = (int) (endTime - startTime);
/** 确保每次更新时间为30帧 **/
while (diffTime <= TIME_IN_FRAME) {
diffTime = (int) (System.currentTimeMillis() - startTime);
/** 线程等待 **/
Thread.yield();
}
}
}
@Override
public void onSensorChanged(SensorEvent event) {
// onSensorChanged()方法中传入了一个 SensorEvent 参数,
// 这个参数里又包含了一个 values 数组,所有传感器输出的信息都是存放在这里的
// //获取传感器的数据
GZ=event.values[SensorManager.DATA_Z];
GX=event.values[SensorManager.DATA_X];
GY=event.values[SensorManager.DATA_Y];
// g= Math.sqrt(GX*GX+GY*GY+GZ*GZ);//重力加速度,约为9.8
//
// AX= Math.acos((GX/g));
// AY= Math.acos((GY/g));//大地垂直坐标系与设备Y轴之间的弧度
// AZ= Math.acos((GZ/g));
//// Log.e(TAG,g+" "+AY+" 想要的Y弧度");
//// Log.d(TAG,g+" "+AX+" X的弧度");
//// Log.d(TAG,g+" "+AZ+" Z的弧度");
// double shuzhi_chuizhi;
// if(AY>Math.PI/2.0) {
// shuzhi_chuizhi=(Math.PI / 2.0 )- (Math.PI - AY);
// Log.d(TAG,shuzhi_chuizhi+"数值垂直夹角");
// acceleation=g*Math.sin(shuzhi_chuizhi)*5;
// Log.e(TAG,acceleation+"看一下加速度");
//
//
//
//
// }else{
// acceleation=g*Math.sin(AY)*5;
// Log.e(TAG,acceleation+"看一下加速度");
//
// }
Log.d(TAG," "+GX+" X轴上的重力加速度");
Log.d(TAG," "+GY+" Y轴上的重力加速度 ");
is_chujie=false;
//检测小球是否超出边界
if (mPosX <520) {
is_chujie=true;
} else if (mPosX > 1200) {
is_chujie=true;
}
if (mPosY <=0 ) {
mPosY = 0;
is_chujie=true;
} else if (mPosY > (mphoneScreenHeight-20)) {
mPosY = mphoneScreenHeight;
is_chujie=true;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}