博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android游戏---贪吃蛇
阅读量:5307 次
发布时间:2019-06-14

本文共 20622 字,大约阅读时间需要 68 分钟。

 

先看看运行的效果

 

最顶层的是wall类,生成和绘制外墙  代码如下:

package com.example.worm;import android.content.Context;import android.util.DisplayMetrics;import android.view.View;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Bitmap;public class wall extends View{    private Context mContext;    private int width;    private int height;    private int widthNum;                           // 方格20 * 20 保存方格行列数;    private int heightNum;    private Bitmap bm;        public wall(Context context)    {        super(context);        mContext = context;                DisplayMetrics dm = new DisplayMetrics();        dm = context.getResources().getDisplayMetrics();                width = dm.widthPixels;        height = dm.heightPixels;            widthNum = width / 20;        heightNum = height / 20;                bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.wall);    }        private void drawTableForm (Canvas canvas)             //绘制表格白线    {        Paint paint = new Paint ();                paint.setStrokeWidth(1);        paint.setStyle(Paint.Style.STROKE);        paint.setColor(Color.WHITE);                for (int i = 0; i <= widthNum; i++)        {            canvas.drawLine(20 * i, 0, 20 * i, height, paint);        }                for (int i = 0; i <= heightNum; i++)        {            canvas.drawLine(0, 20 * i, width, 20 * i, paint);        }            }    private void drawWall(Canvas canvas)               // 在最外层绘制棕色墙体;    {        for (int i = 0; i < widthNum; i++)        {            canvas.drawBitmap(bm, 20 * i, 0, null);            canvas.drawBitmap(bm, 20 * i, height - 20, null);        }                for (int i = 1; i < heightNum - 1; i++)        {            canvas.drawBitmap(bm, 0, 20 * i, null);            canvas.drawBitmap(bm, width - 20, 20 * i, null);        }    }        @Override     protected void onDraw (Canvas canvas)                //覆盖onDraw    {        super.onDraw(canvas);                drawTableForm (canvas);        drawWall(canvas);    }        }

 

 往上是worm类,此类包含了control层,连带左右上下控制

package com.example.worm;import android.view.View;import android.content.Context;import android.util.DisplayMetrics;import android.graphics.Canvas;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Color;import android.graphics.Matrix;import android.view.MotionEvent;import android.graphics.Paint;public class Worm extends View{    private Context mContext;    private int widthNum;                                 //行列数,方便起见,此处以减去墙体,所以  widthNum = dm.widthPixels / 20 - 2 private int heightNum;    private int[] wormX = new int[35];                    //保存蛇的 X Y坐标, wormX[0], wormY[0] 为蛇头     private int[] wormY = new int[35];    private float[] wormRotate = new float[35];          //因为蛇头,蛇身在旋转时需要图片相应转动 此处保存蛇个部位图片的旋转角度    private int length;                                  //蛇长    private Bitmap bmHead;    private Bitmap bmBody;    private Bitmap bmFood;    public int direction;                                //运动方向    private float startX;                                //此为判断控制的参数    private float startY;    private float stopX;    private float stopY;    private long startTime;    private long stopTime;    private int food[] = new int[2];                    //food[0] 为food的X坐标, food[1] 为food的Y坐标;    private int score = 0;    public long speed = 500;    private int level = 1;        private final static int LEFT = 0;    private final static int RIGHT = 1;    private final static int UP = 2;    private final static int DOWN = 3;        private OnGameOverListener listener;        public Worm (Context context)    {        super(context);        mContext = context;                DisplayMetrics dm = new DisplayMetrics();        dm = mContext.getResources().getDisplayMetrics();                widthNum = dm.widthPixels / 20 - 2;        heightNum = dm.heightPixels / 20 - 2;                bmHead = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.head);        bmBody = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.body);        bmFood = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.food);            }        public void reSet()                                                              //重置贪吃蛇,点击重新开始游戏时需要调用    {            length = 3;                 wormX[0] = 2;        wormX[1] = 1;        wormX[2] = 0;                wormY[0] = 10;        wormY[1] = 10;        wormY[2] = 10;                wormRotate[0] = 0.0f;        wormRotate[1] = 0.0f;        wormRotate[2] = 0.0f;                direction = RIGHT;                updateFood();                }        @Override    protected void onDraw(Canvas canvas)    {        drawFood(canvas);        drawWorm(canvas);        drawText(canvas);    }        private void drawWorm(Canvas canvas)                                           //绘制蛇    {        Matrix m = new Matrix();        Matrix rotateM = new Matrix();        Bitmap bm;                m.setTranslate(20 * (1 + wormX[0]), 20 * (1 + wormY[0]));                rotateM.setRotate(wormRotate[0]);        bm = Bitmap.createBitmap(bmHead, 0, 0,                                      //先得到旋转后的图片                bmHead.getWidth(), bmHead.getHeight(), rotateM, true);                        canvas.drawBitmap(bm, m, null);                                            //绘制蛇头                for (int i = 1; i < length; i++)                                           //绘制蛇身        {            m.setTranslate( 20 * (1 + wormX[i]), 20 * (1 + wormY[i]));                        rotateM.setRotate(wormRotate[i]);            bm = Bitmap.createBitmap(bmBody, 0, 0,                                //同样先得到旋转后的图片                    bmBody.getWidth(), bmBody.getHeight(), rotateM, true);                        canvas.drawBitmap(bm, m, null);        }            }            private void drawFood(Canvas canvas)                               //绘制food    {        canvas.drawBitmap(bmFood, 20 * (1 + food[0]), 20 * (1 + food[1]), null);    }        private void drawText (Canvas canvas)                              // 绘制 score和 level    {        Paint paint = new Paint();        paint.setTextSize(40);        paint.setStyle(Paint.Style.STROKE);        paint.setStrokeWidth(5);        paint.setAlpha(50);        paint.setColor(Color.GREEN);                canvas.drawText("Score: ", 100, 40, paint);                canvas.drawText("Level: ", 300, 40, paint);                paint.setTextSize(50);        paint.setColor(Color.RED);                canvas.drawText(String.valueOf(score), 210, 40, paint);                canvas.drawText(String.valueOf(level), 400, 40, paint);    }        private void upDateBody()                                           //更新蛇身  位置    {        for (int i = length - 1; i > 0; i--)        {            wormX[i] = wormX[i - 1];            wormY[i] = wormY[i - 1];                        wormRotate[i] = wormRotate[i - 1];        }    }        private boolean isAble(int dir)                       //判断蛇头的下一步是否可行    {        switch(dir)        {        case LEFT:             if (wormX[0] - 1 < 0)                return false;            break;        case RIGHT:            if (wormX[0] + 1 == widthNum)                return false;            break;        case UP:            if (wormY[0] - 1 < 0)                return false;            break;        case DOWN:            if (wormY[0] + 1 == heightNum)                return false;            break;        }        return true;    }        private void eatFood()                                          //判断是否迟到food    {        if (wormX[0] == food[0] && wormY[0] == food[1])        {            score ++;            length ++;            if (score > 30)            {                score = 0;                level ++;                speed = (long) (speed * 0.8f);                length = 3;                                wormX[0] = 2;                wormX[1] = 1;                wormX[2] = 0;                                wormY[0] = 10;                wormY[1] = 10;                wormY[2] = 10;                }            updateFood();        }    }        public void turnLeft()                                              //左转    {        if (isBody(wormX[0] - 1, wormY[0]) || !isAble(LEFT))            //下一步不可行, 这调用onGameOver()        {            listener.onGameOver();            return ;        }                upDateBody();                                                 //可行时,先更新Body位置  在更新蛇头        wormX[0]--;        wormRotate[0] = 180.0f;        direction = LEFT;                eatFood();                this.invalidate();    }            public void turnRight()    {        if (isBody(wormX[0] + 1, wormY[0]) || !isAble(RIGHT))        {            listener.onGameOver();            return ;        }        upDateBody();        wormX[0]++;        wormRotate[0] = 0.0f;        direction = RIGHT;                eatFood();                this.invalidate();    }        public void turnUp()    {        if (isBody(wormX[0], wormY[0] - 1) || !isAble(UP))        {                listener.onGameOver();            return ;        }        upDateBody();        wormY[0]--;        wormRotate[0] = -90.0f;        direction = UP;                eatFood();                this.invalidate();    }        public void turnDown()    {        if (direction == UP || !isAble(DOWN))        {            listener.onGameOver();            return ;        }                upDateBody();        wormY[0]++;        wormRotate[0] = 90.0f;        direction = DOWN;                eatFood();                this.invalidate();    }        public void setOnGameOverListener(OnGameOverListener listener)                     //自定义的一个listener    {        this.listener = listener;    }        private boolean isBody(int x, int y)                                               //判断该位置是否是蛇身    {        for (int i = 1; i < length - 1; i++)        {            if (x == wormX[i] && y == wormY[i])                return true;        }        return false;    }        private boolean isLegitFood(int x, int y)                         //判断food的位置是否合法    {        for (int i = 0; i < length; i++)        {            if (x == wormX[i] && y == wormY[i])                return false;        }        return true;    }    private void updateFood()                                          //随机生成一个food位置    {        food[0] = (int) (Math.random() * (widthNum - 1));        food[1] = (int) (Math.random() * (heightNum - 1));        while (!isLegitFood(food[0], food[1]))        {            food[0] = (int) (Math.random() * (widthNum - 1));            food[1] = (int) (Math.random() * (heightNum - 1));        }    }        @Override    public boolean onTouchEvent(MotionEvent event)                  // 控制操作    {        switch (event.getAction())        {        case MotionEvent.ACTION_DOWN:            startX = event.getX();            startY = event.getY();            startTime = event.getEventTime();            break;                    case MotionEvent.ACTION_UP:            stopX = event.getX();            stopY = event.getY();            stopTime = event.getDownTime();                        if (stopTime - startTime > 1000)                        //当按压时间超过1000ms是无效                break;                        if ((stopX - startX) > 100)                             //左右上下滑动超过100有效            {                if (direction != LEFT)                    direction = RIGHT;            }            else if ((stopX - startX) < -100)            {                if (direction != RIGHT)                    direction = LEFT;            }            else if ((stopY - startY) > 100)            {                if (direction != UP)                    direction = DOWN;            }            else if ((stopY - startY) < -100)            {                    if (direction != DOWN)                    direction = UP;            }            else if (stopTime - startTime < 150)            //滑动不够100并且时间小于150ms调用onGamePause()暂停游戏            {                listener.onGamePause();            }                        break;                    }        return true;    }        }

其中使用了自定义的一个listener   用于Main类可以相应GameOver和GamePause事件   如下:

package com.example.worm;public interface OnGameOverListener {    public void onGameOver();    public void onGamePause();}

 

下面是main类

package com.example.worm;import java.util.Timer;import java.util.TimerTask;import android.os.Bundle;import android.os.Message;import android.app.Activity;import android.view.Menu;import android.view.ViewGroup.LayoutParams;import android.os.Handler;import android.content.Intent;public class MainActivity extends Activity {    private wall mWall;    private Worm mWorm;    private Timer timer = new Timer();    private TimerTask timerTask;    private int message = 1;                              //发送messge控制游戏的进行和暂停 1为进行 2为暂停            private Handler handler = new Handler()    {        @Override         public void handleMessage(Message msg)        {            switch(msg.what)            {            case 1:                                     //当收到1时  进行游戏                switch(mWorm.direction)                 //direction是个int, 0, 1, 2, 3, 分别代表4个方向                {                case 0:                    mWorm.turnLeft();                    break;                                    case 1:                    mWorm.turnRight();                    break;                                    case 2:                    mWorm.turnUp();                    break;                                    case 3:                    mWorm.turnDown();                    break;                }                break;            case 2:                                         //收到2 时  直接退出                break;            }            sendMsg();                                     //不断的发送消息,保证游戏连续进行                        super.handleMessage(msg);        }    };        @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                mWall = new wall(this);        mWorm = new Worm(this);                 setContentView(mWall);        addContentView(mWorm,              new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));                mWorm.setOnGameOverListener(new OnGameOverListener()              // 定义一个OnGameListener 当发生GameOver 和 GamePause是main类知道怎么做        {            public void onGameOver()            {                 gameStop();            }            public void onGamePause()            {                gamePause();            }        });                sendMsg();                                                      //发送第一条消息    }        @Override    public void onStart()    {            mWorm.reSet();                                               //之所以要将reSet()放在onStart()中方便暂停重开        super.onStart();    }        @Override    public void onResume()                                           //继续游戏时 将message改回 1;    {           message = 1;               super.onResume();    }        @Override    public void onActivityResult (int requestCode, int resultCode, Intent data)    //暂停和结束都是调用了一个Acitivity 这个函数可以回收信息    {        switch(requestCode)        {        case 1:                                                         //1 为调用了pauseActivity            switch (resultCode)            {            case 0:                                                    //0 为继续游戏                this.onResume();                break;            case 1:                                                    //1 为重新开始                this.onStart();                break;            case 2:                                                    //2 为结束游戏                finish();                                         break;            }            break;                    case 2:                                                       //2 为调用stopActivity            switch (resultCode)            {            case 0:                                                   // 重新开始                this.onStart();                break;            case 1:                                                  // 结束游戏                finish();                break;            }            break;                }                super.onActivityResult(requestCode, resultCode, data);    }    @Override    public void onPause()    {        message = 2;                                                       //暂停时修改messge为 2;        super.onPause();    }        @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.activity_main, menu);        return true;    }        private void gamePause()                                                    //gamePause()调用reStartActivity    {        message = 2;        Intent intent = new Intent(this, reStartActivity.class);        startActivityForResult (intent, 1);    }        private void gameStop()                                                     //gameStop()调用onStopActivity    {        message = 2;        Intent intent = new Intent(this, onStopActivity.class);        startActivityForResult (intent, 2);    }        private void sendMsg()                                                     //发送消息    {        timerTask = new TimerTask()        {            @Override            public void run()            {                Message msg = new Message();                msg.what = message;                handler.sendMessage(msg);            }        };                timer.schedule(timerTask, mWorm.speed);                               //消息发送延迟 mWorm.speed;    }        }

就下来是两个辅助Activity和他们的layout

package com.example.worm;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class reStartActivity extends Activity{        private Button resume;    private Button reStart;    private Button stop;        @Override     public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_restart);                resume  = (Button) findViewById (R.id.resume);        reStart = (Button) findViewById (R.id.reStart);        stop    = (Button) findViewById (R.id.stop);                resume.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View v) {                // TODO Auto-generated method stub                setResult(0);                finish();            }        });                reStart.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View v) {                // TODO Auto-generated method stub                setResult(1);                finish();            }        });                stop.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View v) {                // TODO Auto-generated method stub                setResult(2);                finish();            }        });    }    }

 

package com.example.worm;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class onStopActivity extends Activity{    private Button reStart;    private Button stop;        @Override    public void onCreate (Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_onstop);                reStart = (Button) findViewById (R.id.reStart);        stop    = (Button) findViewById (R.id.stop);                        reStart.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View arg0) {                // TODO Auto-generated method stub                setResult(0);                finish();            }        });        stop.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View v) {                // TODO Auto-generated method stub                setResult(1);                finish();            }        });    }}

 

 

最后要注意的是配置文件的设置,以上两个Activity的theme要定义为theme.Dialog;

 

转载于:https://www.cnblogs.com/lky-mily/archive/2012/08/30/2663451.html

你可能感兴趣的文章
[转载] redis 的两种持久化方式及原理
查看>>
C++ 删除字符串的两种实现方式
查看>>
ORA-01502: 索引'P_ABCD.PK_WEB_BASE'或这类索引的分区处于不可用状态
查看>>
Java抽象类和接口的比较
查看>>
开发进度一
查看>>
MyBaits学习
查看>>
管道,数据共享,进程池
查看>>
CSS
查看>>
[LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming
查看>>
[Cypress] Stub a Post Request for Successful Form Submission with Cypress
查看>>
程序集的混淆及签名
查看>>
判断9X9数组是否是数独的java代码
查看>>
00-自测1. 打印沙漏
查看>>
UNITY在VS中调试
查看>>
SDUTOJ3754_黑白棋(纯模拟)
查看>>
Scala入门(1)Linux下Scala(2.12.1)安装
查看>>
如何改善下面的代码 领导说了很耗资源
查看>>
Quartus II 中常见Warning 原因及解决方法
查看>>
php中的isset和empty的用法区别
查看>>
Android ViewPager 动画效果
查看>>