简单的Android贪吃蛇

初学Android,想做一个小游戏来练练手,于是选择了贪吃蛇这个既能练手,做完了自己又爱玩的游戏。

代码如下:
MainActivity.java

package com.example.simplesnack;

import android.os.Bundle;
import android.util.DisplayMetrics;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.app.Activity;
import android.graphics.Color;

public class MainActivity extends Activity {
    private GamePanel mv;
    private Button left,up,right,down;
    private Button start;
    private Button gameContinue;
    private Button gameStop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);  
        int width = metric.widthPixels;     // 屏幕宽度(像素)  
        int height = metric.heightPixels;   // 屏幕高度(像素)  
        mv = (GamePanel)findViewById(R.id.mv);
        mv.setBackgroundColor(Color.LTGRAY);
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)mv.getLayoutParams();
        params.width = width;
        params.height = width;
        mv.setLayoutParams(params);
        left=(Button)findViewById(R.id.left);
        up=(Button)findViewById(R.id.up);
        right=(Button)findViewById(R.id.right);
        down=(Button)findViewById(R.id.down);       
        left.setWidth(width/4);
        left.setHeight(width/5);
        up.setWidth(width/4);
        up.setHeight(width/5);
        right.setWidth(width/4);
        right.setHeight(width/5);
        down.setWidth(width/4);
        down.setHeight(width/5);
        left.setX(width/2-width/8-width/5);
        left.setY(width+(height-width)/3+width/10);
        up.setX(width/2-width/8);
        up.setY(width+(height-width)/3-width/20);
        right.setX(width/2-width/8+width/5);
        right.setY(width+(height-width)/3+width/10);
        down.setX(width/2-width/8);
        down.setY(width+(height-width)/3+width/5+width/20);
        start=(Button)findViewById(R.id.start);
        start.setOnTouchListener(mv);
        gameContinue=(Button)findViewById(R.id.gameContinue);
        gameContinue.setOnTouchListener(mv);
        gameStop=(Button)findViewById(R.id.gameStop);
        gameStop.setOnTouchListener(mv);
        left.setOnTouchListener(mv);
        up.setOnTouchListener(mv);
        right.setOnTouchListener(mv);
        down.setOnTouchListener(mv);
    }
    @Override
    protected void onStart() {
        super.onStart();
    }
    @Override
    protected void onStop() {
        super.onStop();
    }
    @Override
    protected void onPause() {
        super.onPause();
        mv.start=false;
    }

    @Override
    protected void onResume() {
        super.onResume();
    }
    @Override
    protected void onRestart() {
        super.onRestart();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

}

activity_main.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.example.simplesnack.GamePanel 
        android:id="@+id/mv"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

    <Button
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="←"
        android:textStyle="bold"
         />

    <Button
        android:id="@+id/up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="↑"
        android:textStyle="bold"
         />

    <Button
        android:id="@+id/right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="→"
        android:textStyle="bold"
         />

    <Button
        android:id="@+id/down"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="↓"
        android:textStyle="bold"
         />

    <Button 
        android:id="@+id/start"
        android:text="放蛇"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/mv"
        android:layout_marginLeft="0dp"
        />

    <Button 
        android:id="@+id/gameStop"
        android:text="暂停"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/mv"
        android:layout_alignRight="@id/mv"
        />

    <Button 
        android:id="@+id/gameContinue"
        android:text="继续"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/mv"
        android:layout_toRightOf="@id/start"
        />


</RelativeLayout>

MyThread.java

package com.example.simplesnack;

public class MyThread extends Thread{
    private GamePanel mv;
    public MyThread(GamePanel mv){
        this.mv=mv;
    }
    @Override
    public void run() {
        while (mv.start) {
            try {
                long before=System.currentTimeMillis();
                mv.postInvalidate();
                long after=System.currentTimeMillis();
                Thread.sleep((int)((10000/mv.speed)-(after-before)));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            switch (mv.getDirection()) {
            case 1:
                mv.move(-1, 0);
                mv.lastDirection=1;
                break;
            case 2:
                mv.move(0, -1);
                mv.lastDirection=2;
                break;
            case 3:
                mv.move(1, 0);
                mv.lastDirection=3;
                break;
            case 4:
                mv.move(0, 1);
                mv.lastDirection=4;
                break;
            default:
                break;
            }
            if(mv.hitOrBite()){
                mv.start=false;
                mv.dead();
                continue;
            }
        }
    }
}

SnackBody.java

package com.example.simplesnack;

public class SnackBody {
    private int x,y;

    public void setX(int a){
        x=a;
    }
    public void setY(int a){
        y=a;
    }
    public int getX(){
        return x;
    }
    public int getY(){
        return y;
    }
}

DirectionThread.java

package com.example.simplesnack;

public class DirectionThread extends Thread{

    private GamePanel mv;
    private int direction;
    public boolean canRun;

    public DirectionThread(GamePanel mv,int direction){
        this.mv=mv;
        this.direction=direction;
    }

    @Override
    public void run() {
        while (canRun) {
            mv.setDirection(direction);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

GamePanel.java

package com.example.simplesnack;

import java.util.ArrayList;
import java.util.Random;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;


public class GamePanel extends View implements OnTouchListener{

    public int wid, hei;//获得此view的宽高
    public ArrayList<SnackBody> body = new ArrayList<SnackBody>();//蛇身
    public int score;//分数
    public double speed;//速度
    public boolean start;//开关标志
    private static final int MAX_Height = 20;
    private static final int MAX_Width = 20;//将活动区域分为20格
    private int rectSize;//每一格宽度
    private int snackLength;//蛇长(暂时无用)
    private int foodX, foodY;//食物坐标
    private Random random;
    private Paint paint;
    private int direction;//方向
    private int eatSign;//用于刷出下一个食物时判断是否和蛇身重叠
    private MyThread mThread;
    private DirectionThread lt = new DirectionThread(this, 1);
    private DirectionThread ut = new DirectionThread(this, 2);
    private DirectionThread rt = new DirectionThread(this, 3);
    private DirectionThread dt = new DirectionThread(this, 4);
    private int itemX, itemY; // 预判蛇头位置
    public int lastDirection; // 用于限制快速按键时出现反向吃自己的BUG

    public GamePanel(Context context) {
        super(context);
    }

    public GamePanel(Context context, AttributeSet attr) {
        super(context, attr);
    }

    public void init() {
        rectSize = wid / MAX_Width;
        score = 0;
        speed = 100;
        itemX = -1;
        itemY = -1;
        body.clear();
        snackLength = 0;
        random = new Random();
        paint = new Paint();
        paint.setAntiAlias(true);
        direction = 3;
        lastDirection = 3;
        this.setWillNotDraw(false);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (start) {
            paint.setColor(Color.RED);
            canvas.drawRect(foodX * rectSize, foodY * rectSize, foodX
                    * rectSize + rectSize, foodY * rectSize + rectSize, paint);
            if (body.size() > 0) {
                paint.setColor(Color.YELLOW);
                canvas.drawRect(body.get(0).getX() * rectSize, body.get(0)
                        .getY() * rectSize, body.get(0).getX() * rectSize
                        + rectSize, body.get(0).getY() * rectSize + rectSize,
                        paint);
                paint.setColor(Color.rgb(255, 215, 0));
                for (int i = 1; i < body.size(); i++) {
                    canvas.drawRect(body.get(i).getX() * rectSize, body.get(i)
                            .getY() * rectSize, body.get(i).getX() * rectSize
                            + rectSize, body.get(i).getY() * rectSize
                            + rectSize, paint);
                }
                paint.setColor(Color.BLACK);
                paint.setTextSize(20);
                canvas.drawText("得分:" + score, wid - 120, wid - 20, paint);
            }
        }
    }

    public void startGame() {
        init();
        start = true;
        SnackBody newBody = new SnackBody();
        newBody.setX(MAX_Width / 2);
        newBody.setY(MAX_Height / 2);
        SnackBody newBody2 = new SnackBody();
        newBody2.setX(MAX_Width / 2 - 1);
        newBody2.setY(MAX_Width / 2);
        body.add(newBody);
        body.add(newBody2);
        do {
            foodX = random.nextInt(MAX_Width - 1);
            foodY = random.nextInt(MAX_Height - 1);
        } while (foodX == newBody.getX() && foodY == newBody.getY());
        mThread = new MyThread(this);
        mThread.start();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);
        wid = w;
        hei = h;
    }

    public void move(int x, int y) {
        itemX = body.get(0).getX() + x;
        itemY = body.get(0).getY() + y;
        if (itemX == foodX && itemY == foodY) {
            eat();

            for (int i = body.size() - 2; i > 0; i--) {
                body.get(i).setX(body.get(i - 1).getX());
                body.get(i).setY(body.get(i - 1).getY());
            }

        } else {

            for (int i = body.size() - 1; i > 0; i--) {
                body.get(i).setX(body.get(i - 1).getX());
                body.get(i).setY(body.get(i - 1).getY());
            }

        }
        body.get(0).setX(body.get(0).getX() + x);
        body.get(0).setY(body.get(0).getY() + y);
    }

    public void eat() {
        score = score + 10;
        snackLength++;
        do {
            eatSign = 0;
            foodX = random.nextInt(MAX_Height - 1);
            foodY = random.nextInt(MAX_Width - 1);
            for (int i = 0; i < body.size(); i++) {
                if (foodX == body.get(i).getX() && foodY == body.get(i).getY()) {
                    eatSign++;
                }
            }
            if (foodX == itemX && foodY == itemY)
                eatSign++;
        } while (eatSign > 0);
        SnackBody growBody = new SnackBody();
        growBody.setX(body.get(body.size() - 1).getX());
        growBody.setY(body.get(body.size() - 1).getY());
        body.add(growBody);
    }

    public boolean hitOrBite() {
        if (body.get(0).getX() < 0 || body.get(0).getX() >= 20
                || body.get(0).getY() < 0 || body.get(0).getY() >= 20)
            return true;
        else {
            for (int i = body.size() - 1; i > 2; i--) {
                if (body.get(0).getX() == body.get(i).getX()
                        && body.get(0).getY() == body.get(i).getY())
                    return true;
            }
        }
        return false;
    }

    public void dead() {

    }

    public int getDirection() {
        return direction;
    }

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

    public int getScore() {
        return score;
    }

    @Override
    public boolean onTouch(View v, MotionEvent e) {
        if (v.getId() == R.id.left && e.getAction() == MotionEvent.ACTION_DOWN) {
            if (lastDirection != 3) {
                lt = new DirectionThread(this, 1);
                ut.canRun = false;
                rt.canRun = false;
                dt.canRun = false;
                lt.canRun = true;
                lt.start();
            }
        } else if (v.getId() == R.id.left
                && e.getAction() == MotionEvent.ACTION_UP) {
            lt.canRun = false;
        }
        if (v.getId() == R.id.up && e.getAction() == MotionEvent.ACTION_DOWN) {
            if (lastDirection != 4) {
                ut = new DirectionThread(this, 2);
                lt.canRun = false;
                ut.canRun = true;
                rt.canRun = false;
                dt.canRun = false;
                ut.start();
            }
        } else if (v.getId() == R.id.up
                && e.getAction() == MotionEvent.ACTION_UP) {
            ut.canRun = false;
        }
        if (v.getId() == R.id.right && e.getAction() == MotionEvent.ACTION_DOWN) {
            if (lastDirection != 1) {
                rt = new DirectionThread(this, 3);
                lt.canRun = false;
                ut.canRun = false;
                rt.canRun = true;
                dt.canRun = false;
                rt.start();
            }
        } else if (v.getId() == R.id.right
                && e.getAction() == MotionEvent.ACTION_UP) {
            rt.canRun = false;
        }
        if (v.getId() == R.id.down && e.getAction() == MotionEvent.ACTION_DOWN) {
            if (lastDirection != 2) {
                dt = new DirectionThread(this, 4);
                lt.canRun = false;
                ut.canRun = false;
                rt.canRun = false;
                dt.canRun = true;
                dt.start();
            }
        } else if (v.getId() == R.id.down
                && e.getAction() == MotionEvent.ACTION_UP) {
            dt.canRun = false;
        }
        if (v.getId() == R.id.start && e.getAction() == MotionEvent.ACTION_UP&&start==false) {
            this.startGame();
        }
        if (v.getId() == R.id.gameContinue
                && e.getAction() == MotionEvent.ACTION_UP&&start==false) {
            start = true;
            mThread = new MyThread(this);
            mThread.start();
        }
        if (v.getId() == R.id.gameStop
                && e.getAction() == MotionEvent.ACTION_UP) {
            start = false;
        }
        return false;
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.simplesnack"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/snake"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.simplesnack.MainActivity"
            android:label="@string/app_name" 
            android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

代码就这些差不多了,主要是用来给自己看,总结一些经验的,所以就不多描述了。

总结:
1.在处理多方向按键的时候,可以创建4个子线程分别对应4个方向,按下其中一个方向键的时候,开启对应子线程,并用while(标志)的循环方式不断使线程将方向设置为改按键对应方向,以达到优化手感的作用。同时,声明一个变量判断最后一次移动时的方向,用于锁定,避免回头吃自己。

2.采用预判的方式,判断蛇下一步的位置所会触发的事件,将事件处理完再绘制界面。

3.在activity的oncreate方法中使用下列语句
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels;
int height = metric.heightPixels;
获得屏幕的宽高(像素 px),同时可以使用获得的宽高来按比例设置各组件的位置和大小。有以下两点需要注意:
(1)好像自定义的view在activity的oncreate方法里不能直接设置width和height,需要用到以下代码:
RelativeLayout.LayoutParams params =(RelativeLayout.LayoutParams)mv.getLayoutParams();
params.width = width;
params.height = width;
mv.setLayoutParams(params);
(mv是自定义view的引用)
(2)在activity的oncreate方法里用setX,setY方法对各个Button设置位置,其实际位置是xml布局里的原位置坐标加上此X和Y。

  • 11
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值