android游戏---贪吃蛇

时间:2022-02-28 15:23:28

android游戏---贪吃蛇  android游戏---贪吃蛇android游戏---贪吃蛇

先看看运行的效果

 

最顶层的是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();
}
});
}

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="vertical" >

<Button
android:id="@+id/resume"
android:text
="继续游戏"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
/>
<Button
android:id="@+id/reStart"
android:text
="重新开始"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
/>
<Button
android:id="@+id/stop"
android:text
="结束游戏"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
/>

</LinearLayout>

 

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();
}
});
}
}

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="vertical" >


<Button
android:id="@+id/reStart"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="重新开始"/>
<Button
android:id="@+id/stop"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="结束游戏"/>

</LinearLayout>

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package
="com.example.worm"
android:versionCode
="1"
android:versionName
="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion
="15" />

<application
android:icon="@drawable/ic_launcher"
android:label
="@string/app_name"
android:theme
="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:theme
="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:label
="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".reStartActivity"
android:theme
="@android:style/Theme.Dialog">
</activity>

<activity
android:name=".onStopActivity"
android:theme
="@android:style/Theme.Dialog">
</activity>


</application>

</manifest>