手把手教你开发2048!〖二〗

实现基础的界面设计之后,我们来进行第二步的开发:


事件获取


获取什么事件呢?主要获取的事件其实只有一个:用户的touchDown和touchUp事件。从这两个事件中我们就可以知道用户的起始位置,从而得到滑动方向。这样就能实现对游戏功能的最根本也最重要的判断。


我们现在就来实现它。为了方便,我们把这个判断写为一个叫“InitGameView”的方法。由于已经实现了继承,在方法中我们可以直接使用setOnTouchListener方法。参数直接把View.OnTouchListener() new出来,同时实现onTouch方法,我们再定义四个变量 startX, startY, offsetX, offsetY,获取开始位置和偏移位置:

private void InitGameView() {
		setColumnCount(4);//定义显示四列
		setBackgroundColor(0xffbbada0);//定义背景颜色
		setOnTouchListener(new View.OnTouchListener() {
			private float startX, startY, offsetX, offsetY;

			@Override
			public boolean onTouch(View v, MotionEvent event) {

				switch (event.getAction()) {

				case MotionEvent.ACTION_DOWN:
					startX = event.getX();
					startY = event.getY();
					break;
				case MotionEvent.ACTION_UP:
					offsetX = event.getX() - startX;
					offsetY = event.getY() - startY;
					if (Math.abs(offsetX) > Math.abs(offsetY)) {
						if (offsetX < -5) {
						
							
							swapleft();
							// Toast.makeText(getContext(), "left", 0).show();
						}
						if (offsetX > 5) {
							// Toast.makeText(getContext(), "right", 0).show();
							
							swapright();
						}

					} else {
						if (offsetY < -5) {
							// Toast.makeText(getContext(), "up", 0).show();
							
							swapup();
						}
						if (offsetY > 5) {
							
							swapdown();
						}

					}

					break;

				default:
					break;
				}
				return true;
			}
		});

	}
核心方法是MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP,这样获取出来的值用abs函数取绝对值,是为了在斜向滑动(或用户滑动出现角度)时判断真正的意图。显然大的值才是用户想要操作的。这就是最基础的算法。怎么样,是不是觉得很简单呢?

基本判断实现后,还有一些事件需要我们处理。比如非常关键的载入事件。就是girdview布局里实际上是一个一个的frameLayout布局。我们之前说了可以把它看成一个棋盘,那么棋盘位上的显示,我们也来定义为一张“牌”:

再新建一个类,card,继承FrameLayout

这样把他看成一个textview,我们实现它的构造方法,再定义get/set方法,上面的数字“2”啊或其他数字,都可以调用这个方法来显示了:

public class card extends FrameLayout {

	public card(Context context) {
		super(context);
		label = new TextView(getContext());
		label.setTextSize(28);
		label.setGravity(Gravity.CENTER);
		label.setBackgroundColor(0x33ffffff);

		LayoutParams lp = new LayoutParams(-1, -1);
		lp.setMargins(10, 10, 0, 0);
		addView(label, lp);
		setNum(0);
	}

	private int num = 0;

	public int getNum() {

		return num;
	}

	public void setNum(int num) {
		this.num = num;
		if (num <= 0) {
			label.setText("");
		} else {
			label.setText(num + "");
		}
	}

	public boolean equals(card o) {

		return getNum() == o.getNum();
	}

	private TextView label;
}


有了这个方法以后,就好办多了,再回到gameview方法,刚才我们定义的什么swapup()等四个方法,就可以进行具体的实现了。

由于原理相同,我在这里选swapup()方法来说明一下编写思路。

把girdview看成4X4的牌局后,每一张牌都是显示了数字的卡片。这样我们需要用到一个二维数组来储存它。

先定义一个card类型的二维数组 private card[][] cardmap = new card[4][4];

我们知道,当游戏中用户往上滑动时,如果每列有相同的数字,就可以进行叠加,原来的数字则清零。这实际可以用一个简单的循环判断来检查。

这样每次向上滑动的时候,我们判断邻近的取值是否相同,再用刚才定义的card类中的get和set方法来实现具体的赋值:

private void swapup() {
		

		boolean isadd = false;
		for (int x = 0; x < 4; x++) {
			for (int y = 0; y < 4; y++) {
				for (int y1 = y + 1; y1 < 4; y1++) {
					if (cardmap[x][y1].getNum() > 0) {
						if (cardmap[x][y].getNum() <= 0) {
							cardmap[x][y].setNum(cardmap[x][y1].getNum());
							cardmap[x][y1].setNum(0);
							y--;
							isadd = true;

						} else if (cardmap[x][y].equals(cardmap[x][y1])) {
							cardmap[x][y].setNum(cardmap[x][y].getNum() * 2);
							cardmap[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(
									cardmap[x][y].getNum());
							isadd = true;
						}
						break;
					}
				}
			}
		}
		if (isadd) {
			//changecolor();
			addrandomcard();
			checkcompleted();
		}
	}


我们把card上的“0”标记为空,这样移动的时候,如果那个位置的值是零,就代表可以用下面的值滑动上去填充原来的“0”。  这个实现比较关键,大家可以好好思考一下。

我们在方法里还标记了一个bool的值isadd,这是为了后面判断游戏结束时方便一些。如果isadd,那就再随机生成一个数字填充在余下的空位上。


那我们就顺道来看看随机生成数字的方法,即addrandomcard()的方法实现:

为此,我们要先定义一个 List集合,参数为Point类型,这是为了记录棋盘的上的空位点。我们知道android界面上是一个Y轴向下,X轴向右的坐标轴,这就是用点来标记的原因。

private List<Point> emptypoint = new ArrayList<>();

private void addrandomcard() {
		emptypoint.clear();
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				if (cardmap[x][y].getNum() <= 0) {
					emptypoint.add(new Point(x, y));
				}
			}
		}
		Point p = emptypoint.remove((int) (Math.random() * emptypoint.size()));
		cardmap[p.x][p.y].setNum(Math.random() > 0.1 ? 2 : 4);
	}

每次我们循环整个棋盘,如果有空位,即getNum()<=0,那么就把他标记上,这样后面使用一个随机函数来获取。这里remove的方法是有一个返回值的,就是移除的那个点对象。然后我们再用card类里的set方法赋值。一个简单的三元运算符,实现不同概率的出现“2”或“4”。


OK,按这个思路,swapdown()、left、right都可以写了。写好之后我们就完成了第二步。

想要继续开发,请看我的下一篇文章:《手把手教你开发2048!〖三〗》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值