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 ArrayListsnakeBody = 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条)