1、游戏布局(activity_main.xml)
首先在xml文件中实现游戏的整体布局
(1)添加两个TextView用来显示分数
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/score" />
<TextView android:id="@+id/tvScore" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</LinearLayout>
(2)2048游戏界面的布局,游戏界面是通过代码来实现的,所以应该用包名加类名的方式来引用
<com.jxl.game2048.GameView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/gameView">
</com.jxl.game2048.GameView>
2、新建游戏运行的主要类(GameView.java),该类继承GridLayout
(1)在构造方法中,需要对游戏进行初始化( 调用initGameView()方法 )
initGameView()主要用来初始化游戏,该方法中需要实现OnTouchListener,通过坐标值判断用户滑动的方式,响应不同的事件
在initGameView()指定列数,设定背景:
setColumnCount(4);
setBackgroundColor(0xffbbada0);
setOnTouchListener(new OnTouchListener() {
private float startX,startY,offsetX,offsetY;
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
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){
swipeLeft();
//向右滑动
}else if(offsetX>5){
swipeRight();
}
}else{
//向上滑动
if(offsetY<-5){
swipeUp();
//向下滑动
}else if(offsetY>5){
swipeDown();
}
}
break;
default:
break;
}
return true;
}
});
3、将2048的界面看做由4*4的小方块组成,将这些方块抽象为Card类,该类继承自FrameLayout
(1)游戏进行时小方块中的数字为2、4、8、16.……初始化所有小方块,将数字设为0,即数字为0时表示这一格为空
setNum(0);
private int num = 0;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
(2)在构造方法中,需要对小方块进行初始化,为小方块添加TextView保存数字,并设置字体大小,数字对应的颜色等
private TextView label;
public Card(Context context) {
super(context);
label = new TextView(getContext());
label.setTextSize(32);
label.setGravity(Gravity.CENTER);
setNum(0);
}
public void setBGColor(int num){
switch (num) {
case 2:
label.setBackgroundColor(0xffFFF68F);
break;
case 4:
label.setBackgroundColor(0xffFFEC8B);
break;
case 8:
label.setBackgroundColor(0xffFFD700);
break;
case 16:
label.setBackgroundColor(0xffFFC125);
break;
case 32:
label.setBackgroundColor(0xffFF890F);
break;
case 64:
label.setBackgroundColor(0xffFFA500);
break;
case 128:
label.setBackgroundColor(0xffFF8C00);
break;
case 256:
label.setBackgroundColor(0xffFF7F24);
break;
case 512:
label.setBackgroundColor(0xffFF4500);
break;
case 1024:
label.setBackgroundColor(0xffFF0000);
break;
case 2048:
label.setBackgroundColor(0xff7FF00);
break;
case 4096:
label.setBackgroundColor(0xff68228B);
break;
default:
label.setBackgroundColor(0x33ffffff);
break;
}
}
(3)添加一个布局参数,宽高为-1,表示填充满整个父类容器:
LayoutParams lp = new LayoutParams(-1,-1);
//设置小方块之间的间距
lp.setMargins(10, 10, 0, 0);
//然后将label添加进布局中:
addView(label, lp)
(4)在setNum()方法中,将数字转换成字符串并添加到对应的TextView中
public void setNum(int num) {
this.num = num;
if(num<=0){
label.setText("");
}else{
label.setText(num+"");
}
}
(5)添加equals()方法判断两个卡片上的数字是否相等:
public boolean equals(Card o) {
// TODO Auto-generated method stub
return getNum()==o.getNum();
}
4、将16个方块抽象化为4*4的二维数组,并将这些小方块添加到布局中
private Card[][] cardsMap = new Card[4][4];
private void addCards(int cardWidth,int cardHeight){
Card c;
for(int y=0;y<4;y++){
for(int x=0;x<4;x++){
c = new Card(getContext());
c.setNum(0);
c.setBGColor(c.getNum());
addView(c, cardWidth, cardHeight);
cardsMap[x][y] = c;
}
}
}
5、新建emptyPoint List来存放空的小方块
private List<Point> emptyPoints = new ArrayList<Point>();
游戏中新生成的数字在这些空的小方块中随机出现
private void addRandomNum(){
emptyPoints.clear();
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
if(cardsMap[x][y].getNum()<=0){
emptyPoints.add(new Point(x,y));
}
}
}
Point p = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));
//随机产生2或4,生成2的概率大于4
cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);
cardsMap[p.x][p.y].setBGColor(cardsMap[p.x][p.y].getNum());
}
6、开始游戏,实现startGame()方法
private void startGame(){
MainActivity.getMainActivity().clearScore();
for (int y = 0; y < 4; y++) {
for(int x = 0; x < 4; x++){
cardsMap[x][y].setNum(0);
}
}
//随机生成两个数字
addRandomNum();
addRandomNum();
}
7、实现游戏中最重要的部分—用户滑动后需要调用的方法,以向左滑动为例
private void swipeLeft(){
boolean merge = false;
//从上至下的第一行开始
for (int y = 0; y < 4; y++) {
//从左至右
for(int x = 0; x < 4; x++){
for(int x1 = x+1; x1 < 4; x1++){
//当前位置上的值不为0
if(cardsMap[x1][y].getNum()>0){
//当前方块左边的方块为空,则将当前方块的值传到左边,直到左边是不为空的方块为止
if(cardsMap[x][y].getNum()<=0){
cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
cardsMap[x][y].setBGColor(cardsMap[x][y].getNum());
cardsMap[x1][y].setNum(0);
cardsMap[x1][y].setBGColor(cardsMap[x1][y].getNum());
x--;
merge = true;
//左边卡片的值不为空且与当前值当等
}else if(cardsMap[x][y].equals(cardsMap[x1][y])){
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y].setBGColor(cardsMap[x][y].getNum());
cardsMap[x1][y].setNum(0);
cardsMap[x1][y].setBGColor(cardsMap[x1][y].getNum());
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
merge = true;
}
break;
}
}
}
}
if(merge){
//完成后再添加一个随机数字
addRandomNum();
//并判断游戏是否结束
checkComplete();
}
}
private void checkComplete(){
boolean complete = true;
ALL:
for (int y = 0; y < 4; y++) {
for(int x = 0; x < 4; x++){
if(cardsMap[x][y].getNum()==0||
(x>0&&cardsMap[x][y].equals(cardsMap[x-1][y]))||
(x<3&&cardsMap[x][y].equals(cardsMap[x+1][y]))||
(y>0&&cardsMap[x][y].equals(cardsMap[x][y-1]))||
(y<3&&cardsMap[x][y].equals(cardsMap[x][y+1]))){
complete = false;
break ALL;
}
}
}
if(complete){
new AlertDialog.Builder(getContext()).setTitle("2048").
setMessage("游戏结束").setPositiveButton("重来", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
startGame();
}
}).show();
}
}
8、在GameView中重写onSizeChanged()方法,动态地计算每个方块的宽、高:
在AndroidManifest.xml中修改屏幕布局为垂直:
android:screenOrientation=”portrait”
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
//对宽、高求最小值,然后求出每一个小方块的宽度
int cardWidth = (Math.min(w,h)-10)/4;
//将小方块添加到布局中
addCards(cardWidth, cardWidth);
startGame();
}
9、在MainActivity中添加addScore()、showScore()、clearScore()方法,实现计分功能
public class MainActivity extends Activity {
private TextView tvScore;
private int score = 0;
public MainActivity(){
mainActivity = this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvScore = (TextView) findViewById(R.id.tvScore);
}
public void clearScore(){
score = 0;
showScore();
}
public void showScore(){
tvScore.setText(score+"");
}
public void addScore(int s){
score+=s;
showScore();
}
private static MainActivity mainActivity = null;
public static MainActivity getMainActivity(){
return mainActivity;
}
}
源码:
https://github.com/jiangxingling/Game2048
注:该文章根据“极客学院”中2048游戏视频教程总结而来
今天的文章学Android–实现2048小游戏分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/67690.html