
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import com.chengqi.drysister.R;
import android.os.Handler;
import android.widget.TextView;
import androidx.annotation.NonNull;
import org.w3c.dom.Text;
import java.lang.ref.PhantomReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.linkedList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.jar.Attributes;
public class MyImageView extends androidx.appcompat.widget.AppCompatImageView {
private final Bitmap snake;
private final Bitmap food;
//适配后的bitmap对象
//每一个单位长度的蛇身体
private Bitmap mSnakeBitmap;
private Bitmap mFoodBitmap;
private int screenWidth;
private int screenHeight;
private static int speed = 4;
private static int length = 0;
private static int mController = 0;
int[] foodPoint = new int[2];
private boolean initFlag = false;
private final Context mContext;
//在蛇尾部增加长度,使用arraylist
private ArrayList snakeBody = new ArrayList<>();
private static MoveHandler moveHandler ;
private static final class MoveHandler extends Handler{
WeakReference myImageViewWeakReference;
Timer timer = new Timer();
int R;
public MoveHandler(MyImageView myImageView){
myImageViewWeakReference = new WeakReference<>(myImageView);
}
@Override
public void handleMessage(@NonNull Message msg) {
MyImageView myImageView = myImageViewWeakReference.get();
//物体有效面积半径
R = myImageView.screenWidth/100;
double lastX,lastY,thisX,thisY;
lastX=myImageView.snakeBody.get(0).snakeBodyX;
lastY=myImageView.snakeBody.get(0).snakeBodyY;
//手机最左上角是坐标原点,因此x轴向右是正,y轴向下为正
switch (msg.what){
case 1 :
//如果到头了,将y坐标直接设置为最大值,从下边界出来(无边界模式)
if (myImageView.snakeBody.get(0).snakeBodyY<0) {
myImageView.snakeBody.get(0).snakeBodyY = myImageView.screenHeight;
} else {
//如果没到头,就向上增加speed个坐标
myImageView.snakeBody.get(0).snakeBodyY -= speed;
}
break;
case 2 :
//如果到底了,将y坐标设置为0,从上边界出来
if (myImageView.snakeBody.get(0).snakeBodyY>myImageView.screenHeight) {
myImageView.snakeBody.get(0).snakeBodyY = 0;
} else {
//如果没到底,就减少speed个坐标
myImageView.snakeBody.get(0).snakeBodyY += speed;
}
break;
case 3 :
//如果到最左边了,将x坐标设置为最大值,从右边界出来
if (myImageView.snakeBody.get(0).snakeBodyX<0) {
myImageView.snakeBody.get(0).snakeBodyX = myImageView.screenWidth;
} else {
//如果没到底,就减少speed个坐标
myImageView.snakeBody.get(0).snakeBodyX -= speed;
}
break;
case 4 :
//如果到最右边了,将x坐标设置为0,从左边界出来
if (myImageView.snakeBody.get(0).snakeBodyX>myImageView.screenWidth) {
myImageView.snakeBody.get(0).snakeBodyX = 0;
} else {
//如果没到底,就增加speed个坐标
myImageView.snakeBody.get(0).snakeBodyX += speed;
}
break;
}
//如果foodPoint没有初始化完成,蛇头没有碰到豆子,则不会创建新的豆子
if (myImageView.initFlag){
//在某一瞬间,豆子和蛇头产生交集时,刷新豆子
//以蛇头为中心点,蛇头宽为半径,豆子为中心点,豆子宽为半径,作为两个物体的有效面积
//当蛇头和豆子中心点的距离小于两者半径之和时,代表两者有交集
//两者中心点的距离可用勾股定理计算
double distance = Math.sqrt(Math.pow((myImageView.foodPoint[0]-myImageView.snakeBody.get(0).snakeBodyX),2)+
Math.pow((myImageView.foodPoint[1]-myImageView.snakeBody.get(0).snakeBodyY),2));
if (distance<(double) myImageView.screenWidth/100+(double) myImageView.screenWidth/100){
//吃掉豆子后,创建新的豆子
myImageView.foodPoint = myImageView.createFood();
//一个豆子十分,发送广播,长度加一
length++;
myImageView.mContext.sendBroadcast(new Intent("GET_SCORE"));
//每个单位长度都要遵循前一个单位行动的轨迹,每次吃到一个豆子,增加一个单位长度
//增加在蛇的末端
myImageView.snakeBody.add(new SnakeBodyObject(myImageView.snakeBody.get(myImageView.snakeBody.size()-1).snakeBodyX,
myImageView.snakeBody.get(myImageView.snakeBody.size()-1).snakeBodyY,myImageView.mSnakeBitmap));
}
}
//将除头结点以外的结点依次覆盖下一个结点的位置
for (int i = 1; i < myImageView.snakeBody.size(); i++) {
thisX =myImageView.snakeBody.get(i).snakeBodyX;
thisY =myImageView.snakeBody.get(i).snakeBodyY;
myImageView.snakeBody.get(i).snakeBodyX=lastX;
myImageView.snakeBody.get(i).snakeBodyY=lastY;
lastX = thisX;
lastY = thisY;
}
if (isDead()){
stopTimer();
//弹出消息,游戏结束
}
myImageView.invalidate();//将坐标更新后,重绘。会调用onDraw()方法
}
//每次吃一个豆子,蛇长增加speed个单位,由于蛇身体有效面积半径单位长度是screenWidth/100
//因此,再第screenWidth/100*speed个豆子后,对蛇咬自己进行判断
//和蛇咬豆子一个机制,只要对所有单位的身体中心点进行距离判断,如果小于两者半径之和则视为蛇咬了自己
public boolean isDead(){
if (length>R/speed){
//等有时间再做,暂时搁置
return true;
}else {
return false;
}
}
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (mController!=0)
sendEmptyMessage(mController);
}
};
public void startMove(){
timer.schedule(timerTask,0 , 10);
}
public void stopTimer(){
timerTask.cancel();
timer.cancel();
}
}
public MyImageView(Context context, AttributeSet attributeSet){
super(context,attributeSet);
//获取贪吃蛇图片实例,从项目资源文件中加载一个Bitmap对象
snake = BitmapFactory.decodeResource(context.getResources(), R.drawable.black);
//获取豆子图片实例
food = BitmapFactory.decodeResource(context.getResources(),R.drawable.red);
//先开启线程,监听mController是否改变
moveHandler = new MoveHandler(this);
moveHandler.startMove();
mContext = context;
}
//初始蛇的位置放在中心点
public void initPoint(){
//初始化豆子
foodPoint[0] = new Random().nextInt(screenWidth);
foodPoint[1] = new Random().nextInt(screenHeight);
//初始化贪吃蛇,放置在中间位置
snakeBody.add(new SnakeBodyObject(screenWidth/2.0,screenHeight/2.0,mSnakeBitmap));
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// canvas.drawBitmap(mSnakeBitmap,(float)startX,(float)startY,null);
for (int i = 0; i < snakeBody.size(); i++) {
canvas.drawBitmap(snakeBody.get(i).snakeBody,(float)snakeBody.get(i).snakeBodyX,
(float)snakeBody.get(i).snakeBodyY,null);
}
//如果没有开始控制,不显示豆子
if (mController!=0) {
canvas.drawBitmap(mFoodBitmap,(float)foodPoint[0],(float)foodPoint[1],null);
}
}
public static void changeState(int state){
//不能180度转向,不能0度转向
if (state != mController){
if (mController==0){
mController = state;
}else if (mController+state!=3 && mController+state!= 7){
mController = state;
}
}
}
//在xml渲染完成后调用这个方法
@Override
protected void onFinishInflate() {
super.onFinishInflate();
this.getViewTreeObserver().addonGlobalLayoutListener(new ViewTreeObserver.onGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
MyImageView.this.getViewTreeObserver().removeonGlobalLayoutListener(this);
//获取渲染完成后imageView的宽高值
screenWidth = MyImageView.this.getMeasuredWidth();
screenHeight = MyImageView.this.getMeasuredHeight();
//图片按控件比例缩小
mSnakeBitmap = Bitmap.createScaledBitmap(snake,screenWidth/50,screenHeight/50,true);
mFoodBitmap = Bitmap.createScaledBitmap(food,screenWidth/50,screenHeight/50,true);
//初始化蛇,豆子的位置
initPoint();
initFlag = true;
}
});
}
public int[] createFood(){
return new int[]{new Random().nextInt(screenWidth),new Random().nextInt(screenHeight)};
}
public static void stop(){
moveHandler.stopTimer();
mController = 0;
}
}
android 菜鸟 ,新手上路~ = w =
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)