——前段时间和同学上java,在上课时提出一起写点小游戏,于是写了2048~然后自己又试着在android上重新写一个,发现挺好玩。
于是无聊想试着多接触实践Android的绘图功能,于是试着写了个安卓贪吃蛇程序。
代码不好的地方大家请原谅。
先介绍一下玩法:
1、在电脑端模拟机打开的话,可以通过 w s a d 来控制上下左右。
2、在手机端通过方向感应器,手机角度的变化来控制贪吃蛇的运动。
3、试着添加了记录排名的功能,后来觉得挺简单,但是有点冗杂,所以很粗糙的弄了个得分记录。供大家参考。
还有一点就是,蛇身的点点都是固定大小,所以分辨率高的手机看到的蛇会小很多,怪我懒,不想去改了,大家可以通过获取屏幕宽度然后按比例来设置点点的大小。
代码的大部分的地方我也尽可能的注释了,方便大家参考。觉得有时候试着编个小游戏挺能鼓励自己的~哈哈哈。
首先要创建一个类来存放坐标值:
package com.snakemy; public class xymark { private int xmark; private int ymark; public int getXmark() { return xmark; } public void setXmark(int xmark) { this.xmark = xmark; } public int getYmark() { return ymark; } public void setYmark(int ymark) { this.ymark = ymark; } }
游戏界面的代码(View):
package com.snakemy; import java.util.ArrayList; import java.util.List; import java.util.Random; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class GameView extends View { private int ranx, rany;//随机点坐标。 List<xymark> xymark = new ArrayList<xymark>();//蛇身。 // private Canvas canvasout; private Paint paint; private int tarflag = 2;//蛇运动方向标志。 private boolean randomflag = true;//创造随机点的标志。 { //初始化第一个点。 xymark firstXymark = new xymark(); firstXymark.setXmark(10);firstXymark.setYmark(10); xymark.add(firstXymark); } public GameView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public GameView(Context context, AttributeSet attrs) { super(context, attrs); } public GameView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) {// 如何在外部调用这个Canvas画布。? super.onDraw(canvas); // canvasout = canvas; 原本打算通过canvasout全局量在ondraw以外的其他函数中控制canvas的,然而发现不行,所以直接用canvas就好了。 paint = new Paint(); if (randomflag) randompoint(); paint.setColor(Color.RED); canvas.drawCircle(ranx, rany, 5, paint);//随机点。 //填充空心风格,加入矩形边框。 paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.BLUE); canvas.drawRect(5,5,this.getWidth()-5,this.getHeight()-5, paint); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.BLACK); //接触红点后,蛇身集合增长。 if ((xymark.get(0).getXmark() == ranx) &&(xymark.get(0).getYmark() == rany)) { xymark nextXYmark = new xymark(); if(xymark.size()==1)//判断是否只有一个点。 { switch (tarflag) { case 1: nextXYmark.setYmark(xymark.get(0).getYmark()+10); nextXYmark.setXmark(xymark.get(0).getXmark()); break; case 2: nextXYmark.setYmark(xymark.get(0).getYmark()-10); nextXYmark.setXmark(xymark.get(0).getXmark()); break; case 3: nextXYmark.setYmark(xymark.get(0).getYmark()); nextXYmark.setXmark(xymark.get(0).getXmark()+10); break; case 4: nextXYmark.setYmark(xymark.get(0).getYmark()); nextXYmark.setXmark(xymark.get(0).getXmark()-10); break; default: break; } }else {//大于一个点。 int lenth = xymark.size()-1; //get( 0 ~ lenth ); int x_cha = xymark.get(lenth-1).getXmark() - xymark.get(lenth).getXmark(); int y_cha = xymark.get(lenth-1).getYmark() - xymark.get(lenth).getYmark(); if (x_cha == 10) { nextXYmark.setYmark(xymark.get(lenth).getYmark()); nextXYmark.setXmark(xymark.get(lenth).getXmark() - 10); } else if (x_cha == (-10)) { nextXYmark.setYmark(xymark.get(lenth).getYmark()); nextXYmark.setXmark(xymark.get(lenth).getXmark() + 10); } if (y_cha == 10) { nextXYmark.setXmark(xymark.get(lenth).getXmark()); nextXYmark.setYmark(xymark.get(lenth).getYmark() - 10); } else if (y_cha == (-10)) { nextXYmark.setXmark(xymark.get(lenth).getXmark()); nextXYmark.setYmark(xymark.get(lenth).getYmark() + 10); } } randomflag = true; xymark.add(nextXYmark); } //绘制蛇身。 for(int m = 0;m < xymark.size();m++){ canvas.drawCircle(xymark.get(m).getXmark(),xymark.get(m).getYmark(),5, paint); } } public int getTarflag() { return tarflag; } public void setTarflag(int tarflag) { this.tarflag = tarflag; } public void randompoint() { int width = (this.getWidth()-10)/10; int height = (this.getHeight()-10)/10; Random random = new Random(); ranx = random.nextInt(width) * 10+10; rany = random.nextInt(height) * 10+10; randomflag = false; } }
主程序代码(控制部分):
package com.snakemy; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.SharedPreferences; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; @SuppressWarnings("deprecation") //强迫症。 public class MainActivity extends Activity implements SensorEventListener { // private Button changeButton; private boolean deathflag = false; private Timer timer = new Timer(); private GameView gameView; private LinearLayout layout; private TextView textView; //加入方向感应来控制(虚拟机上用wsad控制,手机上用方向感应角度控制)。 //顺便提醒一下自己。之所以不用重力感应控制,是因为,比如你在做公交或地铁时,加速度就会被影响到游戏控制。 private SensorManager mSensorManager;// private Sensor mGyroscope;//并不是用陀螺仪喔。 float[] gyroscope=new float[3]; //存入数据。 private SharedPreferences preferences; private SharedPreferences.Editor editor; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { //蛇的整体移动控制。 //#对于第二个点开始的蛇身变化调整。 for (int m = gameView.xymark.size()-1; m > 0; m--) { int x_cha = gameView.xymark.get(m).getXmark() - gameView.xymark.get(m - 1).getXmark(); int y_cha = gameView.xymark.get(m).getYmark() - gameView.xymark.get(m - 1).getYmark(); if (x_cha == 10) { gameView.xymark.get(m).setXmark(gameView.xymark.get(m).getXmark() - 10); } else if (x_cha == (-10)) { gameView.xymark.get(m).setXmark(gameView.xymark.get(m).getXmark() + 10); } if (y_cha == 10) { gameView.xymark.get(m).setYmark(gameView.xymark.get(m).getYmark() - 10); } else if (y_cha == (-10)) { gameView.xymark.get(m).setYmark(gameView.xymark.get(m).getYmark() + 10); } } //#对于第一个点的变化调整。 switch (gameView.getTarflag()) { case 1: gameView.xymark.get(0).setYmark(gameView.xymark.get(0).getYmark()-10); break; case 2:gameView.xymark.get(0).setYmark(gameView.xymark.get(0).getYmark()+10); break; case 3:gameView.xymark.get(0).setXmark(gameView.xymark.get(0).getXmark()-10); break; case 4:gameView.xymark.get(0).setXmark(gameView.xymark.get(0).getXmark()+10); break; default: break; } //先刷新界面 后判断。 gameView.invalidate(); //判断是否出界。 ifgameover(); textView.setText("蛇身长度:" + gameView.xymark.size()); super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); getgameview(); Log.e("test3", "test3"); timer.schedule(new TimerTask() { @Override public void run() { if(!deathflag) handler.sendEmptyMessage(gameView.getTarflag()); } }, 500,500); } private void init() { layout = (LinearLayout) this.findViewById(R.id.root); textView = (TextView)this.findViewById(R.id.textview); mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);//方向传感器。 mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_UI); preferences = getSharedPreferences("SaveMark", Context.MODE_PRIVATE); editor = preferences.edit(); } private void getgameview(){ gameView = new GameView(this); layout.addView(gameView); gameView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { handler.sendEmptyMessage(gameView.getTarflag());//点击屏幕时加速。 return false; } }); //为什么不能通过这里设置keydown达到点击屏幕时一直加速的目的。 // gameView.setOnKeyListener(new OnKeyListener() { // // @Override // public boolean onKey(View v, int keyCode, KeyEvent event) { // Log.e("a", "b"); // return false; // } // }); } private void ifgameover(){ //判断是否出界。 if(gameView.xymark.get(0).getXmark()>gameView.getWidth()-5|| gameView.xymark.get(0).getXmark()<5|| gameView.xymark.get(0).getYmark()>gameView.getHeight()-5|| gameView.xymark.get(0).getYmark()<5) gameover(); //判断是否撞到自己。 for(int i = 1; i< gameView.xymark.size();i++){ if(gameView.xymark.get(0).getXmark()==gameView.xymark.get(i).getXmark()&& gameView.xymark.get(0).getYmark()==gameView.xymark.get(i).getYmark())//好像不能用equal。 gameover(); } } private void gameover(){ // timer.cancel(); deathflag = true; AlertDialog.Builder builder = new Builder(MainActivity.this); builder.setCancelable(false); builder.setTitle("游戏提示" ) ; builder.setMessage("碰壁了\n"+"失败鸟~!\n"+" ——您的分数是"+gameView.xymark.size()+"分") ; builder.setPositiveButton("重新开始",new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { layout.removeView(gameView); getgameview(); deathflag = false; } } ); //查看分数排行及计入排行。(比较粗糙,因为不想花太多时间在这个处理上,这部分可以删去。) builder.setNegativeButton("进入排行", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final EditText savemark = new EditText(MainActivity.this); AlertDialog.Builder builder = new Builder(MainActivity.this); builder.setCancelable(false); builder.setTitle("分数记录:"+gameView.xymark.size()); builder.setMessage(preferences.getAll().toString().substring(1,preferences.getAll().toString().length()-2)); // builder.setIcon(R.drawable.ic_launcher); builder.setView(savemark); builder.setPositiveButton("存入记录" , new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { editor.putString(savemark.getText().toString(), gameView.xymark.size()+"分\n");//存入。 editor.commit(); layout.removeView(gameView); getgameview(); deathflag = false; } } ); builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { layout.removeView(gameView); getgameview(); deathflag = false; } }); builder.show(); } }); builder.show(); } // ww== 51 s== 47 a== 29 d== 32 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //蛇的方向控制 // Log.e("2", keyCode + ""); if(!deathflag) switch (keyCode) { case 51:if(gameView.getTarflag()!=2){ gameView.setTarflag(1);handler.sendEmptyMessage(gameView.getTarflag()); }break; case 47:if(gameView.getTarflag()!=1){ gameView.setTarflag(2);handler.sendEmptyMessage(gameView.getTarflag()); }break; case 29:if(gameView.getTarflag()!=4){ gameView.setTarflag(3);handler.sendEmptyMessage(gameView.getTarflag()); }break; case 32:if(gameView.getTarflag()!=3){ gameView.setTarflag(4);handler.sendEmptyMessage(gameView.getTarflag()); }break; default: break; } return super.onKeyDown(keyCode, event); } @Override public void onSensorChanged(SensorEvent event) { if(event.sensor.getType() == Sensor.TYPE_ORIENTATION && (!deathflag)) Fun_GYROSCOPE(event); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } //用方向感应器控制。 float axisZ; float axisY; private void Fun_GYROSCOPE(SensorEvent event) { // float axisX = event.values[0];//这个值不用,具体参考方向传感器的使用。 axisY = event.values[1]; axisZ = event.values[2]; if (axisY > 15 && gameView.getTarflag()!=2) { gameView.setTarflag(1);return; } else if (axisY < -15 && gameView.getTarflag()!=1) { gameView.setTarflag(2);return; } else if (axisZ > 15 && gameView.getTarflag()!=4) { gameView.setTarflag(3);return; } else if (axisZ < -15 && gameView.getTarflag()!=3) { gameView.setTarflag(4);return; } } }
layout文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" android:id="@+id/root" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/point" android:textSize="26sp" android:id="@+id/textview"/> </LinearLayout>
通过手机端操作的代码安全性不好,建议大家自己写手机端的控制,比如可以通过滑屏来控制,我就不去写啦~
直接复制上面的代码就可以用~
或者等我把代码包上传了再把下载地址补上给大家哈~