安卓2048源码解析
目录
安卓2048源码解析
安卓2048源码解析 |
2014年4月24日 联系商易上海电子商务网站建设,了解更多 |
2048游戏比来很火,想看下源码,却不会JavaScript。网上搜了搜安卓版的源码,测验测验下来进修。 uberspot 在https://github.com/uberspot/2048-android 上方发了然一个安卓版的2048代码,于是筹办浏览。却发明源文件中只有一个Java类,MainActivity.java。打开大致看了一下: // If there is a previous instance restore it in the webview if (savedInstanceState != null) { mWebView.restoreState(savedInstanceState); } else { mWebView.loadUrl("file:///android_asset/2048/index.html"); } 本来是用一个 webview 对底本的 JavaScript 进行了封装,应用安卓内部 webkit 浏览器进行了加载。相当于用浏览器玩网页版的游戏,只能再搜刮了。 极客学院 别的找到一个极客学院版本的源码,在网站上方还有视频教程。本文解析的首要内容就是极客学院版本的源代码了,作者是 ime。 源码链接:https://github.com/plter/Android2048GameLesson 解析的目标为 code\ide\ADT\Game2048Publish 目次中的源码版本 1 界面 界面斗劲简单了,打开 activity_main.xml 看看,几个 TextView,一个按钮,还有三个自定义的控件 GameView,AnimLayer,Card。游戏的截图如下: image 标准控件就不介绍了,介绍一系三个自定义的控件。 1.1 Card(后文混用 Card 卡片 方块三个词语) 类 Card 持续了 FrameLayout,目标是作为游戏中的卡片。卡片数字和样式的实现: public void setNum(int num) { this.num = num; if (num<=0) { label.setText(""); }else{ label.setText(num+""); } switch (num) { case 0: label.setBackgroundColor(0 x00000000);//透明色 break; case 2: label.setBackgroundColor(0 xffeee4da); break; case 4: label.setBackgroundColor(0 xffede0c8); break; case 8: label.setBackgroundColor(0 xfff2b179); break; case 16: label.setBackgroundColor(0 xfff59563); break; …… default: label.setBackgroundColor(0 xff3c3a32); break; } } num<=0 注解是空白方格。当前地位上若是没有 card,则应用 num<=0 的 card 进行调换。card 0 没有 label,同时底色为透明。除了 card 0 之外,card 2 之后的卡片都有对应的色彩和数字。 1.2 AnimLayer 类 AnimLayer 持续了 FramLayout,用于动画显现。在极客学院安卓 2048 最首要由两个动画:卡片移动和卡片呈现。 a) 对于卡片呈现动画: //目标卡片 public void createScaleTo1(Card target){ //缩放 ScaleAnimation sa = new ScaleAnimation(0.1f, 1, 0.1f, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(100); target.setAnimation(null); target.getLabel().startAnimation(sa); } b) 对于卡片移动动画: java 应用 ArrayList<Card> cards 用于经管姑且卡片的创建和收受接管(避免每次创建姑且卡片时创建新的对象) java 创建一个姑且卡片,从卡片移动到卡片 to,当完成动画之后将姑且卡片设为不成见,并应用 cards 收受接管该卡片。 java 创建卡片: private Card getCard(int num){ Card c; if (cards.size()>0) { c = cards.remove(0); }else{ c = new Card(getContext()); addView(c); } c.setVisibility(View.VISIBLE); c.setNum(num); return c; } 创建卡片时,若是 cards 不为空,则从 cards 队首取出一张姑且卡片。(这里认为应用 LinkedListprivate void recycleCard(Card c){ c.setVisibility(View.INVISIBLE); c.setAnimation(null); cards.add(c); } 收受接管卡片将当前卡片设为不成见,并参加到 cards 中。 卡片移动: public void createMoveAnim(final Card ,final Card to,int X,int toX,int Y,int toY){ //姑且卡片 final Card c = getCard(.getNum()); //设置布局 LayoutParams lp = new LayoutParams(Config.CARD_WIDTH, Config.CARD_WIDTH); lp.leftMargin = X*Config.CARD_WIDTH; lp.topMargin = Y*Config.CARD_WIDTH; c.setLayoutParams(lp); if (to.getNum()<=0) { to.getLabel().setVisibility(View.INVISIBLE); } //从卡片地位移动到to卡片 TranslateAnimation ta = new TranslateAnimation(0, Config.CARD_WIDTH*(toX-X), 0, Config.CARD_WIDTH*(toY-Y)); ta.setDuration(25); ta.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} //动画停止,将姑且卡片收受接管 @Override public void onAnimationEnd(Animation animation) { to.getLabel().setVisibility(View.VISIBLE); recycleCard(c); } }); c.startAnimation(ta); } 1.3 GameView GameView 持续了 GridLayout,包含了界面和游戏逻辑两个项目组。这里介绍界面。 界面中斗劲首要的内容就是手势辨认,用于操控格子的移动: private void initGameView(){ setColumnCount(Config.LINES); setBackgroundColor(0 xffbbada0); 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) { swipeLeft(); }else if (offsetX>5) { swipeRight(); } }else{ if (offsetY<-5) { swipeUp(); }else if (offsetY>5) { swipeDown(); } } break; } return true;//listener已经处理惩罚了事务 } }); } 应用了View.OnTouchListener来侦听触摸事务:策画按下和抬起来时offsetX和offsetY,猜测手势的移动。 2 游戏逻辑 上一节介绍了根蒂根基的界面显现,本节介绍营业逻辑,即游戏实现道理。 2.1 游戏初始化 调用函数initGameView()完成游戏初始化: private void initGameView(){ setColumnCount(Config.LINES);//设置行数量 setBackgroundColor(0 xffbbada0); setOnTouchListener(new View.OnTouchListener() { } }); } 设置控件的方格数量,随后设置了控件北京,最后注册了刚才解析过的触摸事务器。此时游戏已经筹办好了,正式开端。 2.2 开端游戏 函数 startGame();正式开端游戏,起首向方格内随机写入两个方块: public void startGame(){ MainActivity aty = MainActivity.getMainActivity(); aty.clearScore(); aty.showBestScore(aty.getBestScore()); for (int y = 0; y < Config.LINES; y++) { for (int x = 0; x < Config.LINES; x++) { cardsMap[x][y].setNum(0); } } addRandomNum(); addRandomNum(); } 这个函数 addRandomNum()向游戏面板内随机参加两个方块,开端游戏: private void addRandomNum(){ //private List<Point> emptyPoints = new ArrayList<Point>(); emptyPoints.clear(); //将所有空格子汇集起来 for (int y = 0; y < Config.LINES; y++) { for (int x = 0; x < Config.LINES; x++) { if (cardsMap[x][y].getNum()<=0) { emptyPoints.add(new Point(x, y)); } } } if (emptyPoints.size()>0) { //随机地位生成一个card Point p = emptyPoints.remove((int)(Math.random()*emptyPoints.size())); int num = Math.random()>0.1?2:4; cardsMap[p.x][p.y].setNum(num); MainActivity.getMainActivity().getAnimLayer().createScaleTo1(cardsMap[p.x][p.y]); } } 函数 addRandomNum()向面板中空的格子中随机生成一个卡片。起首汇集面板中所有空的地位,汇集到一个 List 中,最后生成随机数,随机生成一个数字,并完成天活泼画。 2.3 移动 2048 游戏经由过程游戏中所有的方格朝某个标的目标移动,归并雷同数字的方块。有四个函数负责移动,分别是高低阁下,这里只解析一个标的目标。 ``` private void swipeLeft(){ boolean merge = false;//是否归并卡片, 1空卡片和已有卡片归并 2两个数字雷同的卡片归并 for (int y = 0; y < Config.LINES; y++) {//对所有列 for (int x = 0; x < Config.LINES; x++) { //搜检当前点的右侧是否有非空卡片(非空:num>=2) for (int x1 = x+1; x1 < Config.LINES; x1++) { if (cardsMap[x1][y].getNum()>0) {//若是右边有非空卡片 if (cardsMap[x][y].getNum()<=0) {//当前坐标上没有格子(空卡片和已有卡片归并) MainActivity.getMainActivity().getAnimLayer().createMoveAnim(cardsMap[x1][y],cardsMap[x][y], x1, x, y, y); cardsMap[x][y].setNum(cardsMap[x1][y].getNum()); cardsMap[x1][y].setNum(0); x–;//和空卡片归并,还须要从当前地位策画(不然: |