实现基础的界面设计之后,我们来进行第二步的开发:
事件获取
获取什么事件呢?主要获取的事件其实只有一个:用户的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;
}
由于原理相同,我在这里选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();
}
}
我们在方法里还标记了一个bool的值isadd,这是为了后面判断游戏结束时方便一些。如果isadd,那就再随机生成一个数字填充在余下的空位上。
那我们就顺道来看看随机生成数字的方法,即addrandomcard()的方法实现:
为此,我们要先定义一个 List集合,参数为Point类型,这是为了记录棋盘的上的空位点。我们知道android界面上是一个Y轴向下,X轴向右的坐标轴,这就是用点来标记的原因。
private List
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);
}
OK,按这个思路,swapdown()、left、right都可以写了。写好之后我们就完成了第二步。
想要继续开发,请看我的下一篇文章:《手把手教你开发2048!〖三〗》