自定义view控件
package snake.dg.com.tanchishe;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
public class Tanchishe extends View {
private float screenHeight;
private float screenWidth;
private int WIDTH_MAX_LINE = 20;
private int HEIGHT_MAX_LINE = 33;
private float lineWidth;
private float lineHeight;
private Bitmap snakeBitmap;
private Bitmap foodBitmap;
private ArrayList<Point> snakeArray = new ArrayList<Point>();
private ArrayList<Point> foodArray = new ArrayList<Point>();
private final int MOVE_RIGHT = 1;
private final int MOVE_LEFT = 2;
private final int MOVE_UP = 3;
private final int MOVE_DOWN = 4;
private int Deirector = MOVE_RIGHT;
private int grade = 0, i = 0;//得分
private int delayTime = 300;//发送消息的延迟时间
private final int movelength = 100;//控制灵敏度
private float downX = 0, downY = 0, upX = 0, upY = 0;
//调出振动器
private Vibrator vibrator;
//处理各个方向
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (Deirector) {
case MOVE_RIGHT:
moveRight();
break;
case MOVE_LEFT:
moveLeft();
break;
case MOVE_UP:
moveUp();
break;
case MOVE_DOWN:
moveDown();
break;
}
}
};
//重玩
public void restartGame() {
snakeArray.clear();
foodArray.clear();
snakeArray.add(new Point(2, 2));
snakeArray.add(new Point(3, 2));
snakeArray.add(new Point(4, 2));
foodArray.add(new Point(0, 0));
setFood();
Deirector = MOVE_RIGHT;
grade = 0;
i = 0;
delayTime = 300;
handler.sendEmptyMessageDelayed(MOVE_RIGHT, delayTime);
Toast.makeText(getContext(), "重新开局", Toast.LENGTH_SHORT).show();
invalidate();
}
//游戏结束弹出对话框
private void popWindow(String text) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("得分情况:");
int fenshu = Integer.parseInt(text);
if (fenshu <= 2500) {
text = "好low啊," + fenshu + "分,菜鸟一只!";
} else if (fenshu > 2500 && fenshu <= 6000) {
text = "成绩不错," + fenshu + "分,继续加油!";
} else {
text = "牛掰哦," + fenshu + "分,好羡慕!";
}
builder.setMessage(text);
builder.setPositiveButton("再来一局", new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
restartGame();
dialog.dismiss();
}
});
builder.setNegativeButton("退出游戏", new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
System.exit(0);
}
});
//让对话框显示出来
builder.show();
}
private void gameOver() {
//震动0.5秒
invalidate();
vibrator.vibrate(500);
popWindow(String.valueOf(grade));
}
//自己撞到自己
private boolean me2me() {
int count = Collections.frequency(snakeArray, snakeArray.get(snakeArray.size() - 1));
if (count == 2) {
gameOver();
return true;
}
return false;
}
//蛇右移
private void moveRight() {
snakeArray.remove(0);
Point point = snakeArray.get(snakeArray.size() - 1);
Point p = new Point(point.x + 1, point.y);
snakeArray.add(p);
invalidate();
if (isEat()) {
snakeArray.add(new Point(p.x + 1, p.y));
}
if (me2me())
return;
if (p.x == WIDTH_MAX_LINE) {//靠右边墙,游戏结束
snakeArray.add(new Point(snakeArray.get(0).x - 1, snakeArray.get(0).y));
gameOver();
return;
}
handler.sendEmptyMessageDelayed(Deirector, delayTime);
}
//蛇左移
private void moveLeft() {
snakeArray.remove(0);
Point point = snakeArray.get(snakeArray.size() - 1);
Point p = new Point(point.x - 1, point.y);
snakeArray.add(p);
invalidate();
if (isEat()) {
snakeArray.add(new Point(p.x - 1, p.y));
}
if (me2me())
return;
if (p.x + 1 == 0) {//靠左边墙,游戏结束
snakeArray.add(new Point(snakeArray.get(0).x + 1, snakeArray.get(0).y));
gameOver();
return;
}
handler.sendEmptyMessageDelayed(Deirector, delayTime);
}
//蛇上移
private void moveUp() {
snakeArray.remove(0);
Point point = snakeArray.get(snakeArray.size() - 1);
Point p = new Point(point.x, point.y - 1);
snakeArray.add(p);
invalidate();
if (isEat()) {
snakeArray.add(new Point(p.x, p.y - 1));
}
if (me2me())
return;
if (p.y + 1 == 0) {//靠上边墙,游戏结束
snakeArray.add(new Point(snakeArray.get(0).x, snakeArray.get(0).y + 1));
gameOver();
return;
}
handler.sendEmptyMessageDelayed(Deirector, delayTime);
}
//蛇下移
private void moveDown() {
snakeArray.remove(0);
Point point = snakeArray.get(snakeArray.size() - 1);
Point p = new Point(point.x, point.y + 1);
snakeArray.add(p);
invalidate();
if (isEat()) {
snakeArray.add(new Point(p.x, p.y + 1));
}
if (me2me())
return;
if (p.y == HEIGHT_MAX_LINE) {//靠下边墙,游戏结束
snakeArray.add(new Point(snakeArray.get(0).x, snakeArray.get(0).y - 1));
gameOver();
return;
}
handler.sendEmptyMessageDelayed(Deirector, delayTime);
}
private boolean isEat() {
//头撞到食物
if (snakeArray.get(snakeArray.size() - 1).equals(foodArray.get(0))) {
setFood();
return true;
}
return false;
}
//让食物随机出现,不能出现在蛇身上
private void setFood() {
int randomX = (int) (Math.random() * WIDTH_MAX_LINE);
int randomY = (int) (Math.random() * HEIGHT_MAX_LINE);
foodArray.set(0, new Point(randomX, randomY));
if (delayTime>=70)
delayTime -= 8;
grade = grade + 10 * i;
i++;
}
public Tanchishe(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化蛇和食物,以及振动器
private void init() {
snakeArray.add(new Point(2, 2));
snakeArray.add(new Point(3, 2));
snakeArray.add(new Point(4, 2));
foodArray.add(new Point(0, 0));
setFood();
snakeBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bird);
foodBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cz);
handler.sendEmptyMessageDelayed(MOVE_RIGHT, delayTime);
//初始化振动器对象
vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
}
//测量view大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
}
//确定蛇和食物的大小
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenWidth = w * 1.0f;
screenHeight = h * 1.0f;
lineWidth = screenWidth / WIDTH_MAX_LINE;
lineHeight = screenHeight / HEIGHT_MAX_LINE;
snakeBitmap = Bitmap.createScaledBitmap(snakeBitmap, (int) lineWidth, (int) lineHeight, false);
foodBitmap = Bitmap.createScaledBitmap(foodBitmap, (int) lineWidth, (int) lineHeight, false);
}
//画蛇画食物
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawSnake(canvas);
drawFood(canvas);
}
//画蛇
private void drawSnake(Canvas canvas) {
for (int i = 0, n = snakeArray.size(); i < n; i++) {
Point snakePoint = snakeArray.get(i);
canvas.drawBitmap(snakeBitmap,
(snakePoint.x) * lineWidth,
(snakePoint.y) * lineHeight, null);
}
}
//画食物
private void drawFood(Canvas canvas) {
canvas.drawBitmap(foodBitmap, foodArray.get(0).x * lineWidth, foodArray.get(0).y * lineHeight, null);
}
//处理滑动事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
downX = event.getX();
downY = event.getY();
}
if (action == MotionEvent.ACTION_UP) {
upX = event.getX();
upY = event.getY();
float x_x = upX - downX;
float y_y = upY - downY;
switch (Deirector) {
case MOVE_RIGHT:
case MOVE_LEFT: {
if (y_y > movelength) {
Deirector = MOVE_DOWN;
} else if (y_y < -movelength) {
Deirector = MOVE_UP;
}
break;
}
case MOVE_UP:
case MOVE_DOWN: {
if (x_x > movelength) {
Deirector = MOVE_RIGHT;
} else if (x_x < -movelength) {
Deirector = MOVE_LEFT;
}
break;
}
}
}
return true;
}
}
MainActivity
package snake.dg.com.tanchishe;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去掉状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
//播放背景音乐,音乐可以放在res下面的raw资源文件下面
mediaPlayer = null;
mediaPlayer = MediaPlayer.create(this, R.raw.bgm);
mediaPlayer.start();
//设置循环播放
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.start();
mediaPlayer.setLooping(true);
}
});
}
//实现再按一次退出程序
private long exitTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/wg"
tools:context="snake.dg.com.tanchishe.MainActivity">
<snake.dg.com.tanchishe.Tanchishe
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="snake.dg.com.tanchishe">
<!--获取振动器需要配置的权限-->
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@drawable/title"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"><!--去掉头部-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>