在此之前,我们通过自定义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);
}
});
}
}
在方向盘的角度回调里设置一下方向就可以了。最终结果
可以稍加改一下,给头用一张图片来显示,记住要随方向旋转诺。