Android自定义View画贪吃蛇游戏

在此之前,我们通过自定义View实现了方向轮盘的制作,用来控制贪吃蛇的方向。《Android自定义View游戏方向轮盘转向盘方向盘》
现在我们再自定义一个View来实现贪吃蛇,使用LinkedList集合来作为蛇的身体。


public class ShakeView extends View {
    public ShakeView(Context context) {
        super(context);
    }

    public ShakeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
}

写一个蛇身体类,(蛇由很多个这样的身体节点组成)

  private class ShakeBody {
        float x;
        float y;

        public ShakeBody() {
        }

        public ShakeBody(float x, float y) {
            this.x = x;
            this.y = y;
        }
        public void set(float x,float y){
            this.x = x;
            this.y = y;
        }

        public float getX() {
            return x;
        }

        public void setX(float x) {
            this.x = x;
        }

        public float getY() {
            return y;
        }

        public void setY(float y) {
            this.y = y;
        }
    }

最终的ShakeView类如下(贪吃蛇View):


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.LinkedList;
import java.util.Random;

public class ShakeView extends View {
    int body = 20;//蛇身半径
    LinkedList<ShakeBody> shakeList;//蛇
    Paint pShake,pFood;//画蛇的笔,画食物的笔

    ShakeBody food;//食物
    Random random;
    int width;
    int height;

    int moveSpeed = 100;//移动速度
    float direction = 0;//方向0-360度的角度值

    private void init() {
        shakeList = new LinkedList<>();

        pShake = new Paint();
        pShake.setAntiAlias(true);
        pShake.setColor(Color.parseColor("#FF7C12"));

        pFood = new Paint();
        pFood.setAntiAlias(true);
        pFood.setColor(Color.parseColor("#FF6B6B"));

        for (int i = 0; i < 3; i++) {
            shakeList.add(new ShakeBody(100+i*body,100));
        }
        random = new Random();
        food = new ShakeBody();
    }

    public void setDirection(float direction) {
        this.direction = direction;
    }

    public ShakeView(Context context) {
        super(context);
        init();
    }

    public ShakeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawShake(canvas);//画蛇

        canvas.drawCircle(food.x,food.y,body,pFood);//画食物

        move(direction);//移动

        postInvalidateDelayed(moveSpeed);//刷新
    }

    //画蛇
    private void drawShake(Canvas canvas) {
        for (ShakeBody node : shakeList) {
            canvas.drawCircle(node.x,node.y,body,pShake);
        }
    }


    //移动
    //移动原理:头加尾巴减(给移动反向前面加一个头,删除尾巴,如果吃到食物则不删除尾巴就实现变长)
    private void move(float direction){//角度
        //计算新的头在坐标
        ShakeBody newHead = new ShakeBody();
        float x = (float) (shakeList.getLast().x + Math.cos(Math.toRadians(direction))*body);//cos的参数是弧度
        float y = (float) (shakeList.getLast().y - Math.sin(Math.toRadians(direction))*body);//sin的参数是弧度

        //边界处理
        if (x > width)x = 0;
        if (x < 0 )x = width;
        if (y > height)y = 0;
        if (y < 0)y = height;

        newHead.set(x,y);//设置新头的坐标

        shakeList.add(newHead);//把新的头添加到蛇身上

        if ((Math.pow(x-food.x,2) + Math.pow(y-food.y,2) < body*body)) {//吃到食物重新制作食物
            makeFood();
        }else{//没吃到则删除尾巴
            shakeList.removeFirst();
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = right - left;
        height = bottom - top;
        makeFood();//初始食物
    }

    private void makeFood() {
        food.set(random.nextInt(width-body)+body,random.nextInt(height-body)+body);
    }

    private class ShakeBody {
        float x;
        float y;

        public ShakeBody() {
        }

        public ShakeBody(float x, float y) {
            this.x = x;
            this.y = y;
        }
        public void set(float x,float y){
            this.x = x;
            this.y = y;
        }

        public float getX() {
            return x;
        }

        public void setX(float x) {
            this.x = x;
        }

        public float getY() {
            return y;
        }

        public void setY(float y) {
            this.y = y;
        }
    }
}

layout布局:



    <com.hongying.shakegame.ShakeView
        android:id="@+id/shake"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.hongying.shakegame.SteerView
        android:id="@+id/steer"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.9" />

其中SteerView是我们自定义的方向盘
MainActivity里:


import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    SteerView steerView;
    ShakeView shakeView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        shakeView = findViewById(R.id.shake);
        steerView = findViewById(R.id.steer);
        steerView.setAngleCallback(new SteerView.AngleCallback() {
            @Override
            public void onEvent(float angle) {
                shakeView.setDirection(angle);
            }
        });
    }
     
}

在方向盘的角度回调里设置一下方向就可以了。最终结果
在这里插入图片描述
可以稍加改一下,给头用一张图片来显示,记住要随方向旋转诺。

  • 15
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dear Mr. Ma

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值