验证中...
你有几个邮箱呢?你是怎么分配它们的用途呢?码云账号增加多邮箱支持!
语言: Java
分类: Android 组件
最后更新于 2018-12-09 10:09
贪吃蛇游戏视图
原始数据 复制代码
package com.cnsunrun.games.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.sunrun.sunrunframwork.utils.log.Logger;
import java.util.LinkedList;
/**
* 贪食蛇-游戏视图
* Created by WQ on 2018/4/12.
*/
public class SnackGameView extends View {
/**
* 蛇头方向
*/
public final static int S_LEFT = 0;
public final static int S_TOP = 1;
public final static int S_RIGHT = 2;
public final static int S_BOTTOM = 3;
public final static int S_BASE_SPEED = 300;
int mColNum = 18;//列数
int mRowNum = 18;//列数
float mColWidth;//列宽
int mBgColor = Color.parseColor("#a7a6ab");//背景颜色
int mGridLineColor = Color.parseColor("#838692");//网格线颜色
int mSnackBodyColor = Color.WHITE;//蛇身颜色
int mSnackHeadColor = Color.WHITE;//蛇头颜色
int mFoodColor = Color.parseColor("#fcae14");//食物颜色
int mSnackDefLen = 3;//蛇身默认长度
int mDirec = S_LEFT;//蛇头方向
int mSpeed = S_BASE_SPEED;//移动速度
int mQuickSpeed = 50;//快速移动时的速度
boolean mIsQuickMove = false;//是否快速移动
boolean mGamePause = false;
Paint mPaint;
LinkedList<SnackBody> mSnackBodys = new LinkedList<>();
SnackBody mFood = new SnackBody(0, 0);
OnEatFoodListener onEatFoodListener;
OnGameOverListener onGameOverListener;
public SnackGameView(Context context) {
super(context);
initView();
}
public SnackGameView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
public SnackGameView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mPaint = new Paint();
// mPaint.setStrokeWidth(1);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
post(new Runnable() {
@Override
public void run() {
initGame();
}
});
}
public void initGame() {
mGamePause = false;
mIsQuickMove = false;
mSpeed = S_BASE_SPEED;
mSnackDefLen = 3;
mDirec = S_LEFT;
mColWidth = (float) (1f*getWidth() / mColNum );//计算格子大小
mRowNum = (int) (1f*getHeight() / mColWidth);//计算行数
//在中间放置身体
LinkedList<SnackBody> mSnackBodys = this.mSnackBodys;
mSnackBodys.clear();
for (int i = 0; i < mSnackDefLen; i++) {
mSnackBodys.addLast(new SnackBody(mColNum / 2 - (mSnackDefLen / 2 - i), mRowNum / 2));
}
randomFood();
beginGameRun();
}
Runnable runnable;
private void beginGameRun() {
removeCallbacks(runnable);
final Runnable localRun = new Runnable() {
@Override
public void run() {
int speed = mIsQuickMove ? mQuickSpeed : mSpeed;
snackMove();
invalidate();
postDelayed(runnable, speed);
}
};
postDelayed(this.runnable = localRun, mSpeed);
}
//随机食物
private void randomFood() {
LinkedList<SnackBody> mSnackBodys = this.mSnackBodys;
if (mSnackBodys.size() >= mColNum * mRowNum) {
return;//满了,这么吊的么
}
SnackBody first = mSnackBodys.getFirst();
SnackBody food = new SnackBody(0, 0);
do {
food.setPositon(random(0, mColNum), random(0, mRowNum));
} while (first.equals(food));
this.mFood = food;
}
public int random(int min, int max) {
return (int) (Math.random() * (max - min) + min);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(mBgColor);
drawFood(canvas);
drawSnack(canvas);
drawGridBg(canvas);
}
/**
* 绘制网格背景
* @param canvas
*/
private void drawGridBg(Canvas canvas) {
int colNum = this.mColNum;
int rowNum = (int) (getHeight() / mColWidth);//计算行数
//绘制网格
mPaint.setColor(mGridLineColor);
//绘制列
for (int i = 0; i <= colNum; i++) {
float startX = i * mColWidth;
canvas.drawLine(startX, 0, startX, getHeight(), mPaint);
}
//绘制行
for (int i = 0; i <= rowNum; i++) {
float startY = i * mColWidth;
canvas.drawLine(0, startY, getWidth(), startY, mPaint);
}
}
/**
* 绘制蛇
* @param canvas
*/
private void drawSnack(Canvas canvas) {
LinkedList<SnackBody> mSnackBodys = this.mSnackBodys;
for (int i = mSnackBodys.size() - 1; i >= 0; i--) {
SnackBody mSnackBody = mSnackBodys.get(i);
mPaint.setColor(i == 0 ? mSnackHeadColor : mSnackBodyColor);
float left = mSnackBody.x * mColWidth;
float top = mSnackBody.y * mColWidth;
canvas.drawRect(left, top, left + mColWidth, top + mColWidth, mPaint);
}
}
/**
* 绘制食物
* @param canvas
*/
private void drawFood(Canvas canvas) {
SnackBody mFood = this.mFood;
mPaint.setColor(mFoodColor);
float left = mFood.x * mColWidth;
float top = mFood.y * mColWidth;
canvas.drawRect(left, top, left + mColWidth, top + mColWidth, mPaint);
}
/**
* 蛇的移动
*/
private void snackMove() {
if (mGamePause) return;
LinkedList<SnackBody> mSnackBodys = this.mSnackBodys;
SnackBody nextHead = new SnackBody(0, 0);
SnackBody snackHead = mSnackBodys.getFirst();
switch (mDirec) {
case S_LEFT:
nextHead.setPositon(snackHead.x - 1, snackHead.y);
break;
case S_TOP:
nextHead.setPositon(snackHead.x, snackHead.y - 1);
break;
case S_RIGHT:
nextHead.setPositon(snackHead.x + 1, snackHead.y);
break;
case S_BOTTOM:
nextHead.setPositon(snackHead.x, snackHead.y + 1);
break;
}
mSnackBodys.addFirst(nextHead);
mSnackBodys.removeLast();
//检查是否吃到食物了,
SnackBody mFood = this.mFood;
if (nextHead.equals(mFood)) {
mSnackBodys.addFirst(mFood);
mSpeed = getSpeed();//计算新速度
if (onEatFoodListener != null) {
onEatFoodListener.eatFood(mSpeed);
}
//追加到头部,重新随机食物
randomFood();
}
checkGameEnd();
}
private void checkGameEnd() {
LinkedList<SnackBody> mSnackBodys = this.mSnackBodys;
SnackBody headBody = mSnackBodys.getFirst();
//查询头部与身体的交集
int indexOf = mSnackBodys.lastIndexOf(headBody);
int cellNum = mColNum * mRowNum;
int snackLen = mSnackBodys.size();
//边界判断,咬到自己的判断,和占满了
if (headBody.x < 0 ||
headBody.y < 0 ||
headBody.x >= mColNum ||
headBody.y >= mRowNum ||
//0 是蛇头 1是刚吃到的食物 不可能咬到脖子(第二格)
(indexOf != 0 &&indexOf != 1 && indexOf != -1)||
snackLen>=cellNum
) {
mGamePause = true;
if (onGameOverListener != null) {
onGameOverListener.gameOver(snackLen, cellNum);
}
Logger.D("游戏结束");
}
}
public void turnTo(int direc) {
switch (direc) {
case S_LEFT:
if (mDirec != S_RIGHT) {
mDirec = direc;
}
break;
case S_TOP:
if (mDirec != S_BOTTOM) {
mDirec = direc;
}
break;
case S_RIGHT:
if (mDirec != S_LEFT) {
mDirec = direc;
}
break;
case S_BOTTOM:
if (mDirec != S_TOP) {
mDirec = direc;
}
break;
}
beginGameRun();
snackMove();
invalidate();
}
public int getSpeed() {
int size = mSnackBodys.size();
float percent = 1 - size / (mColNum * mRowNum);
float newSpeed = 300 * percent;
return (int) newSpeed;
}
public void setOnEatFoodListener(OnEatFoodListener onEatFoodListener) {
this.onEatFoodListener = onEatFoodListener;
}
public void setOnGameOverListener(OnGameOverListener onGameOverListener) {
this.onGameOverListener = onGameOverListener;
}
public interface OnEatFoodListener {
void eatFood(int speed);
}
public interface OnGameOverListener {
void gameOver(int snackLen, int cellNum);
}
@Override
protected void onDetachedFromWindow() {
removeCallbacks(runnable);
super.onDetachedFromWindow();
}
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
mGamePause = visibility != VISIBLE;
}
class SnackBody {
public int x, y;//坐标
public void setPositon(int x, int y) {
this.x = x;
this.y = y;
}
public SnackBody(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SnackBody snackBody = (SnackBody) o;
if (x != snackBody.x) return false;
return y == snackBody.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
}

评论列表( 0 )

你可以在登录后,发表评论

搜索帮助