5.游戏滑动上下左右相加的逻辑

下面我们将来分析一下游戏2048滑动上下左右相加逻辑的实现。要实现这一功能,首先我们得监听触碰事件。本游戏中,我们是在 GameGroup 实现滑动事件的处理。

(1)

  1. public GameGroup(GameScene pGameScene) {

  2.                 super(0, 0, 435, 435, pGameScene);

  3.                 // 设置可以监听触碰事件

  4.                 this.setIgnoreTouch(false);

  5.                 this.mGameScene = pGameScene;

  6.                 initView();

  7.         }

复制代码


如上面的代码,记得把 GameGroup 设置可以监听触碰事件即:this.setIgnoreTouch(false);

接下来重写它的 onAreaTouched 方法。


根据监听按下ActionDown以及松开ActionUp时的滑动情况实现判断是向哪个方向滑动


其中FLING_MIN_DISTANCE 为一常量值:

/**手指滑动的最小响应距离**/

        private final static int FLING_MIN_DISTANCE =10;

具体代码如下:


  1. private boolean mGrabbed = false;

  2.         private float startX, startY, offsetX, offsetY;

  3.         @Override

  4.         public boolean onAreaTouched(TouchEvent pSceneTouchEvent,

  5.                         float pTouchAreaLocalX, float pTouchAreaLocalY) {


  6.                 if (pSceneTouchEvent.isActionDown()) {

  7.                         mGrabbed = true;

  8.                         startX = pSceneTouchEvent.getX();

  9.                         startY = pSceneTouchEvent.getY();


  10.                 } else if (pSceneTouchEvent.isActionUp()) {

  11.                         if (mGrabbed) {

  12.                                 mGrabbed = false;

  13.                                 offsetX = pSceneTouchEvent.getX() - startX;

  14.                                 offsetY = pSceneTouchEvent.getY() - startY;


  15.                                 if (Math.abs(offsetX) > Math.abs(offsetY)) {

  16.                                         if (offsetX < -FLING_MIN_DISTANCE) {

  17.                                                 // 向左滑

  18.                                                 toLeft();

  19.                                         } else if (offsetX > FLING_MIN_DISTANCE) {

  20.                                                 // 向右滑

  21.                                                 toRight();

  22.                                         }

  23.                                 } else {

  24.                                         if (offsetY < -FLING_MIN_DISTANCE) {

  25.                                                 // 向上滑

  26.                                                 toUp();

  27.                                         } else if (offsetY > FLING_MIN_DISTANCE) {

  28.                                                 // 向下滑

  29.                                                 toDown();

  30.                                         }

  31.                                 }

  32.                         }


  33.                 }

  34.                 return true;

  35.         }

复制代码


(2)向左滑动函数的逻辑代码:

  1. private void toLeft() {

  2.                 LogUtil.d("左移");

  3.                 SoundRes.playSound(ConstantUtil.SOUND_SELECT);

  4.                 boolean mMerge = false;


  5.                 for (int x = 0; x < mCount; x++) {

  6.                         for (int y = 0; y < mCount; y++) {


  7.                                 for (int y1 = y + 1; y1 < mCount; y1++) {

  8.                                         if (cardArrays[x][y1].getNumber() > 0) {

  9.                                                 if (cardArrays[x][y].getNumber() <= 0) {

  10.                                                         cardArrays[x][y].setNumber(cardArrays[x][y1]

  11.                                                                         .getNumber());

  12.                                                         cardArrays[x][y1].setNumber(0);


  13.                                                         mMerge = true;

  14.                                                         y--;

  15.                                                 } else if (cardArrays[x][y].equals(cardArrays[x][y1])) {

  16.                                                         cardArrays[x][y].setNumber(cardArrays[x][y]

  17.                                                                         .getNumber() * 2);

  18.                                                         mergeAction(cardArrays[x][y]);

  19.                                                         cardArrays[x][y1].setNumber(0);

  20.                                                         mGameScene.addCurrScore(cardArrays[x][y].getNumber());

  21.                                                         mMerge = true;

  22.                                                 }

  23.                                                 break;

  24.                                         }

  25.                                 }

  26.                         }

  27.                 }


  28.                 if (mMerge) {

  29.                         addRandomNum();

  30.                         checkComplete();

  31.                 }

  32.         }

复制代码


(3)向右滑动函数的逻辑代码:

  1. private void toRight() {

  2.                 LogUtil.d("右移");

  3.                 SoundRes.playSound(ConstantUtil.SOUND_SELECT);

  4.                 boolean mMerge = false;


  5.                 for (int x = 0; x < mCount; x++) {

  6.                         for (int y = mCount - 1; y >= 0; y--) {


  7.                                 for (int y1 = y - 1; y1 >= 0; y1--) {

  8.                                         if (cardArrays[x][y1].getNumber() > 0) {

  9.                                                 if (cardArrays[x][y].getNumber() <= 0) {


  10.                                                         cardArrays[x][y].setNumber(cardArrays[x][y1]

  11.                                                                         .getNumber());

  12.                                                         cardArrays[x][y1].setNumber(0);


  13.                                                         mMerge = true;

  14.                                                         y++;

  15.                                                 } else if (cardArrays[x][y].equals(cardArrays[x][y1])) {

  16.                                                         cardArrays[x][y].setNumber(cardArrays[x][y]

  17.                                                                         .getNumber() * 2);

  18.                                                         mergeAction(cardArrays[x][y]);

  19.                                                         cardArrays[x][y1].setNumber(0);

  20.                                                         mGameScene.addCurrScore(cardArrays[x][y].getNumber());

  21.                                                         mMerge = true;

  22.                                                 }

  23.                                                 break;

  24.                                         }

  25.                                 }

  26.                         }

  27.                 }


  28.                 if (mMerge) {

  29.                         addRandomNum();

  30.                         checkComplete();

  31.                 }

  32.         }

复制代码


(4)向上滑动函数的逻辑代码:

  1.         private void toUp() {

  2.                 LogUtil.d("上移");

  3.                 SoundRes.playSound(ConstantUtil.SOUND_SELECT);

  4.                 boolean mMerge = false;

  5.                 for (int y = 0; y < mCount; y++) {

  6.                         for (int x = 0; x < mCount; x++) {


  7.                                 for (int x1 = x + 1; x1 < mCount; x1++) {

  8.                                         if (cardArrays[x1][y].getNumber() > 0) {

  9.                                                 if (cardArrays[x][y].getNumber() <= 0) {

  10.                                                         cardArrays[x][y].setNumber(cardArrays[x1][y]

  11.                                                                         .getNumber());

  12.                                                         cardArrays[x1][y].setNumber(0);

  13.                                                         mMerge = true;

  14.                                                         x--;

  15.                                                 } else if (cardArrays[x][y].equals(cardArrays[x1][y])) {

  16.                                                         cardArrays[x][y].setNumber(cardArrays[x][y]

  17.                                                                         .getNumber() * 2);

  18.                                                         mergeAction(cardArrays[x][y]);

  19.                                                         cardArrays[x1][y].setNumber(0);

  20.                                                         mGameScene.addCurrScore(cardArrays[x][y].getNumber());

  21.                                                         mMerge = true;

  22.                                                 }

  23.                                                 break;

  24.                                         }

  25.                                 }

  26.                         }

  27.                 }


  28.                 if (mMerge) {

  29.                         addRandomNum();

  30.                         checkComplete();

  31.                 }

  32.         }

复制代码


(5)向下滑动函数的逻辑代码:

  1.         private void toDown() {

  2.                 LogUtil.d("下移");

  3.                 SoundRes.playSound(ConstantUtil.SOUND_SELECT);

  4.                 boolean mMerge = false;


  5.                 for (int y = 0; y < mCount; y++) {

  6.                         for (int x = mCount - 1; x >= 0; x--) {


  7.                                 for (int x1 = x - 1; x1 >= 0; x1--) {

  8.                                         if (cardArrays[x1][y].getNumber() > 0) {

  9.                                                 if (cardArrays[x][y].getNumber() <= 0) {

  10.                                                         cardArrays[x][y].setNumber(cardArrays[x1][y]

  11.                                                                         .getNumber());

  12.                                                         cardArrays[x1][y].setNumber(0);

  13.                                                         mMerge = true;

  14.                                                         x++;

  15.                                                 } else if (cardArrays[x][y].equals(cardArrays[x1][y])) {

  16.                                                         cardArrays[x][y].setNumber(cardArrays[x][y]

  17.                                                                         .getNumber() * 2);

  18.                                                         mergeAction(cardArrays[x][y]);

  19.                                                         cardArrays[x1][y].setNumber(0);

  20.                                                         mGameScene.addCurrScore(cardArrays[x][y].getNumber());

  21.                                                         mMerge = true;

  22.                                                 }

  23.                                                 break;

  24.                                         }

  25.                                 }

  26.                         }

  27.                 }


  28.                 if (mMerge) {

  29.                         addRandomNum();

  30.                         checkComplete();

  31.                 }

  32.         }

复制代码


(6)为合并的卡片添加动画效果

  1. /**

  2.          * 合并时的动作效果

  3.          * @param entity

  4.          */

  5.         private void mergeAction(IEntity entity){

  6.                 ScaleModifier scaleModifier1 = new ScaleModifier(0.1f, 0.8f, 1.2f, EaseBounceInOut.getInstance());

  7.                 ScaleModifier scaleModifier2 = new ScaleModifier(0.1f, 1.2f, 1.0f);

  8.                 SequenceEntityModifier sequenceEntityModifier = new SequenceEntityModifier(scaleModifier1,scaleModifier2);

  9.                 entity.registerEntityModifier(sequenceEntityModifier);

  10.         }

复制代码


6. 检查游戏是否要结束了checkComplete()

(1)成功拼成2048胜利结束,全盘填满并且不能再合并时失败结束。

判断游戏是否还能够继续条件:

① 是否有其中一个卡片的数字为 2048,如果有则胜利结束,弹出胜利界面。

② 利用五个条件判断失败结束:1.还有空卡片 2.还可以向左滑 3.还可以向右滑 4.还可以向上滑 5.还可以向下滑。

只要以上条件满足一个,游戏就可以再继续。

否则,游戏就不能够再继续了,弹出失败界面。


  1.         /**

  2.          * 检测是否游戏结束

  3.          */

  4.         private void checkComplete() {


  5.                 for (int i = 0; i < mCount; i++) {

  6.                         for (int j = 0; j < mCount; j++) {        

  7.                                 if(cardArrays[i][j].getNumber()==2048){

  8.                                         // 拼出2048,胜利完成,弹出胜利对话框

  9.                                         showDialog(true);

  10.                                         return;

  11.                                 }

  12.                         }

  13.                 }

  14.                 for (int y = 0; y < mCount; y++) {

  15.                         for (int x = 0; x < mCount; x++) {

  16.                                 if (cardArrays[x][y].getNumber() <= 0

  17.                                                 || (x > 0 && cardArrays[x][y]

  18.                                                                 .equals(cardArrays[x - 1][y]))

  19.                                                 || (x < mCount - 1 && cardArrays[x][y]

  20.                                                                 .equals(cardArrays[x + 1][y]))

  21.                                                 || (y > 0 && cardArrays[x][y]

  22.                                                                 .equals(cardArrays[x][y - 1]))

  23.                                                 || (y < mCount - 1 && cardArrays

  24.                                                                 .equals(cardArrays[x][y + 1]))) {

  25.                                         return;

  26.                                 }

  27.                         }

  28.                 }

  29.                 // 全盘填满并且不能再合并时失败结束,弹出失败对话框

  30.                 showDialog(false);

  31.         }

复制代码


(2)在上下左右每一步滑动后,都添加该函数,详情请看上面的第5点。例如:

  1. private void toLeft() {

  2. ......

  3. if (mMerge) {

  4.                         addRandomNum();

  5.                         checkComplete();

  6.                 }

  7. }


复制代码


7.添加游戏分数模块

(1)在游戏场景GameScene中处理

① 声明有关最佳分数和当前分数的变量、精灵、文本实体。

  1. // 当前分数

  2.         private int currScore = 0;

  3.         // 最佳得分背景

  4.         private AnimatedSprite bestScoreBg;

  5.         // 最佳得分文本

  6.         private Text tBestScore;

  7.         // 当前得分背景

  8.         private AnimatedSprite currScoreBg;

  9.         // 当前分数文本

  10.         private Text tCurrScore;

复制代码


②加入最佳分数背景、文本实体,当前分数背景、文本实体。

  1. // 最佳得分背景

  2.                 bestScoreBg = new AnimatedSprite(0, 20, Res.GAME_SCORE_BG_BEST,

  3.                                 getVertexBufferObjectManager());

  4.                 // 设置bestScoreBg右边x坐标的位置在镜头的右边减20的位置

  5.                 bestScoreBg.setRightPositionX(this.getCameraRightX() - 20);

  6.                 this.attachChild(bestScoreBg);

  7.                 // 最佳得分文本

  8.                 tBestScore = new Text(0, bestScoreBg.getY() + 50,

  9.                                 FontRes.getFont(ConstantUtil.FONT_SCORE_NUM),

  10.                                 SharedUtil.getBestScore(getActivity()) + "", 4,

  11.                                 getVertexBufferObjectManager());

  12.                 // 设置 tBestScore 的X坐标上的中点在bestScoreBg的X坐标中点上

  13.                 tBestScore.setCentrePositionX(bestScoreBg.getCentreX());

  14.                 this.attachChild(tBestScore);

  15.                 // 当前得分背景

  16.                 currScoreBg = new AnimatedSprite(0, bestScoreBg.getY(),

  17.                                 Res.GAME_SCORE_BG_NOW, getVertexBufferObjectManager());

  18.                 // 设置currScoreBg的右边X坐标点在bestScoreBg左边的X坐标减20的位置上

  19.                 currScoreBg.setRightPositionX(bestScoreBg.getLeftX() - 20);

  20.                 this.attachChild(currScoreBg);

  21.                 // 当前得分文本

  22.                 tCurrScore = new Text(0, currScoreBg.getY() + 50,

  23.                                 FontRes.getFont(ConstantUtil.FONT_SCORE_NUM), "0", 4,

  24.                                 getVertexBufferObjectManager());

  25.                 tCurrScore.setCentrePositionX(currScoreBg.getCentreX());

  26.                 this.attachChild(tCurrScore);

复制代码


③创建一个SharedUtil类,用于把游戏中的最佳分数数据保存到SharedPreferences里面。



  1. public class SharedUtil {


  2.         private static final String Shared_System = "Shared_og";


  3.         private static final String BEST_SCORE = "best_score";


  4.         public static void setBestScore(Context pContext, int pBestScore) {

  5.                 Editor edit = pContext.getSharedPreferences(Shared_System,

  6.                                 Context.MODE_PRIVATE).edit();

  7.                 edit.putInt(BEST_SCORE, pBestScore);

  8.                 edit.commit();

  9.         }


  10.         public static int getBestScore(Context context) {

  11.                 return context

  12.                                 .getSharedPreferences(Shared_System, Context.MODE_PRIVATE)

  13.                                 .getInt(BEST_SCORE, 0);

  14.         }

  15. }


复制代码


④更新最佳分数和当前分数的方法实现

  1. /**

  2.          * 更新最高纪录

  3.          * 

  4.          * @param pBestScore

  5.          */

  6.         private void updateBestScore(int pBestScore) {

  7.                 tBestScore.setText(pBestScore + "");

  8.                 // 设置相对bestScoreBgX坐标居中

  9.                 tBestScore.setCentrePositionX(bestScoreBg.getCentreX());

  10.         }


复制代码

  1. // 增加当前分数

  2.         public void addCurrScore(int pAddScore) {

  3.                 if (pAddScore != 0) {

  4.                         // 播放音效

  5.                         SoundRes.playSound(ConstantUtil.SOUND_MERGE);

  6.                 }

  7.                 currScore += pAddScore;

  8.                 tCurrScore.setText(currScore + "");

  9.                 tCurrScore.setCentrePositionX(currScoreBg.getCentreX());


  10.                 // 当前分数大于所保存的最佳分数时,更新最佳分数

  11.                 if (currScore > SharedUtil.getBestScore(getActivity())) {

  12.                         SharedUtil.setBestScore(getActivity(), currScore);

  13.                         updateBestScore(currScore);

  14.                 }

  15.         }

复制代码


③ 完成卡片合并的时候,要添加分数;在前面的上下左右滑动方法内调用,例如:

  1.         for (int x = 0; x < mCount; x++) {

  2.                         for (int y = 0; y < mCount; y++) {


  3.                                 for (int y1 = y + 1; y1 < mCount; y1++) {

  4.                                         if (cardArrays[x][y1].getNumber() > 0) {

  5.                                                 if (cardArrays[x][y].getNumber() <= 0) {

  6.                                                         cardArrays[x][y].setNumber(cardArrays[x][y1]

  7.                                                                         .getNumber());

  8.                                                         cardArrays[x][y1].setNumber(0);


  9.                                                         mMerge = true;

  10.                                                         y--;

  11.                                                 } else if (cardArrays[x][y].equals(cardArrays[x][y1])) {

  12.                                                         cardArrays[x][y].setNumber(cardArrays[x][y]

  13.                                                                         .getNumber() * 2);

  14.                                                         mergeAction(cardArrays[x][y]);

  15.                                                         cardArrays[x][y1].setNumber(0);

  16.                                                         // 添加当前分数

  17.                                                 mGameScene.addCurrScore(cardArrays[x][y].getNumber());

  18.                                                         mMerge = true;

  19.                                                 }

  20.                                                 break;

  21.                                         }

  22.                                 }

  23.                         }

  24.                 }

复制代码

 http://www.eoeandroid.com/forum-863-1.html

www.ogengine.com