文章目录
实现
MainActivity.java
/**
* 划动方向即工人移动方向
* */
class Controller implements View.OnTouchListener {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
oldX = (int) motionEvent.getX();
oldY = (int) motionEvent.getY();
return true;
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
newX = (int) motionEvent.getX();
newY = (int) motionEvent.getY();
if (newX - oldX > threshold) {
gameView.menMove(1,0); // right
} else if (oldX - newX > threshold) {
gameView.menMove(-1,0); // left
} else if (newY - oldY > threshold) {
gameView.menMove(0,1); // up
} else if (oldY - newY > threshold) {
gameView.menMove(0,-1); // down
}
gameView.invalidate();
return true;
}
return false;
}
}
GameView.java
- 因为地图大小是20*20,而示例中没有统一变量定义,所以直接使用魔法数字
- 该段代码可以拓展进行障碍物和通关检测
/**
* 移动坐标
* */
public void menMove(int menMoveX, int menMoveY) {
int testX = menX + 2 * menMoveX, testY = menY + 2 * menMoveY;
// 边缘检测
if (testY < 20 && testX < 20 && testX >= 0 && testY >= 0) {
int nextAttr = mymap[menY + menMoveY][menX + menMoveX];
// 用绿地覆盖当前工人位置(无障碍检查)
mymap[menY][menX] = 2;
// 如果下一个单位是 箱子, 则移动的再下一个位置为箱子(无障碍检查)
if (nextAttr == 3) {
mymap[menY + 2 * menMoveY][menX + 2 * menMoveX] = 3;
}
// 下一个位置为工人
menX += menMoveX;
menY += menMoveY;
mymap[menY][menX] = 5;
}
}
效果
基于示例代码修改
说明
- drawable目录:放置图标 box.gif、greenbox.gif、men.gif
- raw目录:放置map0.map
- 地图说明:2表示绿地、5表示人物、3表示箱子
地图map0.map示例
22222222222222222222222222222222222222222252222222222222222222222222222222222222222223222222222222222222222223222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
修改后MainActivity.java示例
- 需要根据屏幕大小修改绘图坐标坐标值
- 以监听自定义图形组件的划动方向,明确人物移动
public class MainActivity extends AppCompatActivity {
GameView gameView; // 自定义图形组件
int initX = 70; //绘图时第一个图像的坐标
int initY = 50;
int oldX, oldY, newX, newY, threshold = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initBitmap();
}
public void initBitmap()
{
gameView = new GameView(this);
this.setContentView(gameView);
gameView.setOnTouchListener(new Controller());
}
/**
* 划动方向即工人移动方向
* */
class Controller implements View.OnTouchListener {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
oldX = (int) motionEvent.getX();
oldY = (int) motionEvent.getY();
return true;
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
newX = (int) motionEvent.getX();
newY = (int) motionEvent.getY();
if (newX - oldX > threshold) {
gameView.menMove(1,0); // right
} else if (oldX - newX > threshold) {
gameView.menMove(-1,0); // left
} else if (newY - oldY > threshold) {
gameView.menMove(0,1); // up
} else if (oldY - newY > threshold) {
gameView.menMove(0,-1); // down
}
gameView.invalidate();
return true;
}
return false;
}
}
}
修改后GameView.java示例
- 需要根据屏幕大小修改箱子坐标值,以及该tx = 2 + 60 * j、ty = 2 + 60 * i的值(60的大小)
- 通过初始化条件initflag判断人物移动后将重绘图像,不再获取地图文件数据进行绘制
public class GameView extends View {
int[][] mymap = new int[20][20]; //存放地图文件中图片位置坐标
int[] map; //存放地图文件中的图片编号
String mapstr; //存放地图文件数据
Bitmap men; //工人
Bitmap greenBox; //草地
Bitmap box; //箱子
Paint paint;
int tx = 120; //箱子的坐标
int ty = 120;
int menX, menY; // 工人移动坐标
boolean initFlag = true;
public GameView(Context context) {
super(context);
paint = new Paint();
men = BitmapFactory.decodeResource(getResources(), R.drawable.men); //工人
greenBox = BitmapFactory.decodeResource(getResources(), R.drawable.greenbox); //草地
box = BitmapFactory.decodeResource(getResources(), R.drawable.box); //箱子
}
/**
* 移动坐标
* */
public void menMove(int menMoveX, int menMoveY) {
int testX = menX + 2 * menMoveX, testY = menY + 2 * menMoveY;
// 边缘检测
if (testY < 20 && testX < 20 && testX >= 0 && testY >= 0) {
int nextAttr = mymap[menY + menMoveY][menX + menMoveX];
// 用绿地覆盖当前工人位置(无障碍检查)
mymap[menY][menX] = 2;
// 如果下一个单位是 箱子, 则移动的再下一个位置为箱子(无障碍检查)
if (nextAttr == 3) {
mymap[menY + 2 * menMoveY][menX + 2 * menMoveX] = 3;
}
// 下一个位置为工人
menX += menMoveX;
menY += menMoveY;
mymap[menY][menX] = 5;
}
}
String map() //读取地图文件
{
String mapdata = "";
try {
InputStream in_file = getResources().openRawResource(R.raw.map0); //输入流对象读取地图文件
int length = in_file.available(); //获取数据流的字节数
byte[] buffer = new byte[length];
int bytes = in_file.read(buffer); //产生读取数据的动作
mapdata = new String(buffer, 0, bytes); //把地图文件数据转换为字符串存放到mapdata中
} catch (IOException e) {
}
return mapdata;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);//设置背景颜色
paint.setColor(Color.argb(255, 220, 220, 220)); //灰白色
this.myDraw(canvas);
}
public void myDraw(Canvas canvas) //绘制图形
{
if (initFlag) {
initFlag = false;
mapstr = map(); //获取地图文件数据
byte[] d = mapstr.getBytes(); //把字符串生成字节数组
int len = mapstr.length();
int[] map = new int[len];
for (int i = 0; i < mapstr.length(); i++) {
map[i] = d[i] - 48; //字节数组中存放的ASCII码值,转换为数字要减48
//数字0所对应的ASCII码值为48,数字1的ASCII码值为49,…………
}
int k = 0;
for (int i = 0; i < 10; i++) //将地图中的数据与图片编号对应
{
for (int j = 0; j < 20; j++) {
mymap[i][j] = map[k];
if (mymap[i][j] == 2) //草地
{
tx = 2 + 60 * j;
ty = 2 + 60 * i;
canvas.drawBitmap(greenBox, tx, ty, paint); //绘制图形
}
if (mymap[i][j] == 3) //箱子
{
tx = 2 + 60 * j;
ty = 2 + 60 * i;
canvas.drawBitmap(box, tx, ty, paint); //绘制图形
}
if (mymap[i][j] == 5) //工人
{
menX = j;
menY = i;
tx = 2 + 60 * j;
ty = 2 + 60 * i;
canvas.drawBitmap(men, tx, ty, paint); //绘制图形
}
k++;
}
}
} else {
for (int i = 0; i < 10; i++) //将地图中的数据与图片编号对应
{
for (int j = 0; j < 20; j++) {
if (mymap[i][j] == 2) //草地
{
tx = 2 + 60 * j;
ty = 2 + 60 * i;
canvas.drawBitmap(greenBox, tx, ty, paint); //绘制图形
}
if (mymap[i][j] == 3) //箱子
{
tx = 2 + 60 * j;
ty = 2 + 60 * i;
canvas.drawBitmap(box, tx, ty, paint); //绘制图形
}
if (mymap[i][j] == 5) //工人
{
menX = j;
menY = i;
tx = 2 + 60 * j;
ty = 2 + 60 * i;
canvas.drawBitmap(men, tx, ty, paint); //绘制图形
}
}
}
}
}
}