赞
踩
贪吃蛇是一款经典的小游戏,游戏比较简单,实现也比较简单。
本篇博客将详细介绍我自己写的贪吃蛇的思路以及实现方式。
首先我们需要在游戏界面将游戏区域划分成无数个小方格,类似下图
画布(游戏区域)的宽为 width 高为 height ,列数 sizex=width/pointSize ,行数 sizey=height/pointSize. 由于画布的长宽不一定是pointSize的整数倍,所以为了所有的数据居中需要设置 x轴 y轴的偏移量(当前貌似偏移量可有可无,本人强迫症一定要加上),offsetX=(width - sizex*pointSize)/ 2,offsetY=(height - sizey*pointSize) / 2.
新建数组 spoints=new int[ sizex ][ sizey ] 用于保存方格矩阵 其中 spoints[x][y]==1说明该点属于当前小蛇身体的一部分, spoints[x][y]==0则表示小蛇当前未运动到此点。
新建 ArrayList<Point> points=new ArrayList<Point>(); 用于保存小蛇的身体的所有节点(points 中的 所有point的x,y对应的是 spoints数组的所有值为1的点的下标),points.get(0) 为头部坐标点,最后一个为尾部坐标点
上面两幅图片代表的意思相同,都表示小蛇的当前状态(小蛇画的比较丑,请见谅)
下面开始考虑的小蛇的移动,小蛇的移动可以看成是将小蛇的尾巴的移动到小蛇的头部(根据方向判断移动的上下左右位置),其他的节点保持不动,见图示
得到下图运动后的状态
然后修改spoints数组对应的坐标的值,新增的头部对应的值修改为 1,移除的尾部的值修改为 0. 并将对应的坐标点加入points链表的对应位置,移除尾部的坐标点
解决了小蛇的移动问题,再来解决小蛇吃食物点的问题。
当小蛇吃到食物的时候,相当于将食物的点当成新的头部,而尾部不变,这样就相当于吃了之后变长了
这样就完成了小蛇的增长。
没有代码那就是耍流氓!!下面开始贴代码
git代码下载: 贪吃蛇 https://gitee.com/wuchang0213/TCS.git
csdn下载:https://download.csdn.net/download/weixin_41191134/10832869
再提供一个数独小游戏的下载:https://download.csdn.net/download/weixin_41191134/10832903
只贴了要的游戏界面的代码
- public class TcsView extends View {
-
- private Paint paint;
- //小蛇的组成点
- private ArrayList<Point> points=new ArrayList<Point>();
- private Point pointFood=new Point();//食物点
- //游戏界面的 方格划分
- private int[][] spoints;
- //方格数组的大小
- private int sizex;
- private int sizey;
- //小蛇的头部对应在数组中的位置
- private int headerX;
- private int headerY;
- //食物的坐标点
- private int foodX;
- private int foodY;
- //偏移量
- private int offsetX=0;
- private int offsetY=0;
- //随机数
- private Random random=new Random();
- private boolean isStart=true;
- //屏幕宽高
- private int width;
- private int height;
- //小蛇方块的大小
- private int pointSize=20;
- //方向
- private int direction=0;// 0 上 -1 下 1 左 2 右
- //触摸点坐标
- private float tdx;
- private float tdy;
- private boolean isStop=false;
- private TcsScoreListener tcsScoreListener;
-
- private Handler handler=new Handler(new Handler.Callback() {
- @Override
- public boolean handleMessage(Message message) {
- switch (message.what){
- case 1:
- headerNext();
- break;
- }
- return false;
- }
- });
-
- private void headerNext(){
- if(points.size()==0||isStop||foodX==-1) return;
- //小蛇的移动控制,可以看成是小蛇的首尾发生了移动,
- // 头部根据下一次移动的方向移动到下一格,然后去掉结尾
- switch (direction){
- case 0:
- headerY--;
- break;
- case -1:
- headerY++;
- break;
- case 1:
- headerX--;
- break;
- case 2:
- headerX++;
- break;
- }
- //判断是否到达边界
- if(headerX<0||headerY<0){
- isStop=true;
- }else {
- //判断小蛇是否吃到自己
- if(spoints[headerX][headerY]==1){
- isStop=true;
- }
- points.add(0,new Point(headerX,headerY));
- spoints[headerX][headerY]=1;
- if(tcsScoreListener!=null){
- tcsScoreListener.onTCSScore(points.size());
- }
- if(headerX==foodX && headerY==foodY){
- foodX=-1;
- foodY=-1;
- initPointFood();
- }else {
- Point move=points.get(points.size()-1);
- spoints[move.x][move.y]=0;
- points.remove(points.size() - 1);
- }
- if (!isStop){
- invalidate();
- }
- }
- }
-
- public TcsView(Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- private void init() {
- paint=new Paint();
- paint.setStrokeJoin(Paint.Join.ROUND);
- paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStrokeWidth(1);
- paint.setAntiAlias(true);
- //100为时间的发生间隔,即小蛇多久移动一次,此处修改可调节小蛇的速度
- new Timer().schedule(new TimerTask() {
- @Override
- public void run() {
- handler.sendEmptyMessage(1);
- }
- },0,100);
- }
-
- public void setTcsScoreListener(TcsScoreListener tcsScoreListener) {
- this.tcsScoreListener = tcsScoreListener;
- }
-
- @SuppressLint("DrawAllocation")
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- width=getWidth();
- height=getHeight();
-
- if(isStart){
- //根据宽高以及 pointSize 将游戏区域划分成不同的矩形区块,
- sizex=width/pointSize;
- sizey=height/pointSize;
- spoints=new int[sizex][sizey];
- //计算偏移量
- offsetX=(width-(sizex*pointSize))/2;
- offsetY=(height-(sizey*pointSize))/2;
- //头部起始坐标默认在屏幕中央
- headerX=sizex/2;
- headerY=sizey/2;
- spoints[headerX][headerY]=1;
- points.add(0,new Point(headerX,headerY));
- initPointFood();
- isStart=false;
- }
- for(int i=0;i<points.size();i++){
- Point point=points.get(i);
- drawPoint(canvas,paint,point);
- }
- drawPoint(canvas,paint,pointFood);
- }
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if(!isStop) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- tdx = event.getX();
- tdy = event.getY();
- break;
- case MotionEvent.ACTION_UP:
- float dx = Math.abs(tdx - event.getX());
- float dy = Math.abs(tdy - event.getY());
- if (dx > 40 || dy > 40) {
- //判断为滑动,不是点击
- Log.d("*****onTouchEvent****", "/**/*/*//**98*8/*9*/89*898565/*** ");
- } else {
- if (direction == 0 || direction == -1) {
- if (tdx > points.get(0).x) {
- direction = 2;
- } else {
- direction = 1;
- }
- } else if (direction == 1 || direction == 2) {
- if (tdy > points.get(0).y) {
- direction = -1;
- } else {
- direction = 0;
- }
- }
- handler.sendEmptyMessage(1);
- }
- break;
- }
- }
- return super.onTouchEvent(event);
- }
-
- //根据点的左边画出对应的点
- private void drawPoint(Canvas canvas,Paint paint,Point point){
- RectF rectF=new RectF(
- offsetX+point.x*pointSize,
- offsetY+point.y*pointSize,
- offsetX+(point.x+1)*pointSize,
- offsetY+(point.y+1)*pointSize);
- canvas.drawRect(rectF,paint);
- }
-
- /**
- * 确定食物点的位置
- */
- private void initPointFood(){
- foodX=random.nextInt(sizex);//获取随机的坐标点
- foodY=random.nextInt(sizey);
- //判断当前坐标点是否在小蛇的轨迹上
- if(spoints[foodX][foodY]==1){
- initPointFood();
- }else {
- //标准化坐标位置
- pointFood.set(foodX,foodY);
- }
- }
-
- /**
- * 根据传入的参数 修改小蛇的运动方向
- * @param dire
- */
- public void changeDirection(int dire) {
- switch (dire){
- case 0:// 小蛇上下运动时 可修改为左右运动
- case -1:
- if(direction==1||direction==2){
- direction=dire;
- }
- break;
- case 1://小蛇左右运动时 可修改方向为上下运动
- case 2:
- if(direction==0||direction==-1){
- direction=dire;
- }
- break;
- }
- }
-
- /**
- * 设置重新开始
- */
- public void restart(){
- isStop=false;
- isStart=true;
- points.clear();
- invalidate();
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。