5.游戏滑动上下左右相加的逻辑
下面我们将来分析一下游戏2048滑动上下左右相加逻辑的实现。要实现这一功能,首先我们得监听触碰事件。本游戏中,我们是在 GameGroup 实现滑动事件的处理。
(1)
public GameGroup(GameScene pGameScene) {
super(0, 0, 435, 435, pGameScene);
// 设置可以监听触碰事件
this.setIgnoreTouch(false);
this.mGameScene = pGameScene;
initView();
}
复制代码
如上面的代码,记得把 GameGroup 设置可以监听触碰事件即:this.setIgnoreTouch(false);
接下来重写它的 onAreaTouched 方法。
根据监听按下ActionDown以及松开ActionUp时的滑动情况实现判断是向哪个方向滑动
其中FLING_MIN_DISTANCE 为一常量值:
/**手指滑动的最小响应距离**/
private final static int FLING_MIN_DISTANCE =10;
具体代码如下:
private boolean mGrabbed = false;
private float startX, startY, offsetX, offsetY;
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionDown()) {
mGrabbed = true;
startX = pSceneTouchEvent.getX();
startY = pSceneTouchEvent.getY();
} else if (pSceneTouchEvent.isActionUp()) {
if (mGrabbed) {
mGrabbed = false;
offsetX = pSceneTouchEvent.getX() - startX;
offsetY = pSceneTouchEvent.getY() - startY;
if (Math.abs(offsetX) > Math.abs(offsetY)) {
if (offsetX < -FLING_MIN_DISTANCE) {
// 向左滑
toLeft();
} else if (offsetX > FLING_MIN_DISTANCE) {
// 向右滑
toRight();
}
} else {
if (offsetY < -FLING_MIN_DISTANCE) {
// 向上滑
toUp();
} else if (offsetY > FLING_MIN_DISTANCE) {
// 向下滑
toDown();
}
}
}
}
return true;
}
复制代码
(2)向左滑动函数的逻辑代码:
private void toLeft() {
LogUtil.d("左移");
SoundRes.playSound(ConstantUtil.SOUND_SELECT);
boolean mMerge = false;
for (int x = 0; x < mCount; x++) {
for (int y = 0; y < mCount; y++) {
for (int y1 = y + 1; y1 < mCount; y1++) {
if (cardArrays[x][y1].getNumber() > 0) {
if (cardArrays[x][y].getNumber() <= 0) {
cardArrays[x][y].setNumber(cardArrays[x][y1]
.getNumber());
cardArrays[x][y1].setNumber(0);
mMerge = true;
y--;
} else if (cardArrays[x][y].equals(cardArrays[x][y1])) {
cardArrays[x][y].setNumber(cardArrays[x][y]
.getNumber() * 2);
mergeAction(cardArrays[x][y]);
cardArrays[x][y1].setNumber(0);
mGameScene.addCurrScore(cardArrays[x][y].getNumber());
mMerge = true;
}
break;
}
}
}
}
if (mMerge) {
addRandomNum();
checkComplete();
}
}
复制代码
(3)向右滑动函数的逻辑代码:
private void toRight() {
LogUtil.d("右移");
SoundRes.playSound(ConstantUtil.SOUND_SELECT);
boolean mMerge = false;
for (int x = 0; x < mCount; x++) {
for (int y = mCount - 1; y >= 0; y--) {
for (int y1 = y - 1; y1 >= 0; y1--) {
if (cardArrays[x][y1].getNumber() > 0) {
if (cardArrays[x][y].getNumber() <= 0) {
cardArrays[x][y].setNumber(cardArrays[x][y1]
.getNumber());
cardArrays[x][y1].setNumber(0);
mMerge = true;
y++;
} else if (cardArrays[x][y].equals(cardArrays[x][y1])) {
cardArrays[x][y].setNumber(cardArrays[x][y]
.getNumber() * 2);
mergeAction(cardArrays[x][y]);
cardArrays[x][y1].setNumber(0);
mGameScene.addCurrScore(cardArrays[x][y].getNumber());
mMerge = true;
}
break;
}
}
}
}
if (mMerge) {
addRandomNum();
checkComplete();
}
}
复制代码
(4)向上滑动函数的逻辑代码:
private void toUp() {
LogUtil.d("上移");
SoundRes.playSound(ConstantUtil.SOUND_SELECT);
boolean mMerge = false;
for (int y = 0; y < mCount; y++) {
for (int x = 0; x < mCount; x++) {
for (int x1 = x + 1; x1 < mCount; x1++) {
if (cardArrays[x1][y].getNumber() > 0) {
if (cardArrays[x][y].getNumber() <= 0) {
cardArrays[x][y].setNumber(cardArrays[x1][y]
.getNumber());
cardArrays[x1][y].setNumber(0);
mMerge = true;
x--;
} else if (cardArrays[x][y].equals(cardArrays[x1][y])) {
cardArrays[x][y].setNumber(cardArrays[x][y]
.getNumber() * 2);
mergeAction(cardArrays[x][y]);
cardArrays[x1][y].setNumber(0);
mGameScene.addCurrScore(cardArrays[x][y].getNumber());
mMerge = true;
}
break;
}
}
}
}
if (mMerge) {
addRandomNum();
checkComplete();
}
}
复制代码
(5)向下滑动函数的逻辑代码:
private void toDown() {
LogUtil.d("下移");
SoundRes.playSound(ConstantUtil.SOUND_SELECT);
boolean mMerge = false;
for (int y = 0; y < mCount; y++) {
for (int x = mCount - 1; x >= 0; x--) {
for (int x1 = x - 1; x1 >= 0; x1--) {
if (cardArrays[x1][y].getNumber() > 0) {
if (cardArrays[x][y].getNumber() <= 0) {
cardArrays[x][y].setNumber(cardArrays[x1][y]
.getNumber());
cardArrays[x1][y].setNumber(0);
mMerge = true;
x++;
} else if (cardArrays[x][y].equals(cardArrays[x1][y])) {
cardArrays[x][y].setNumber(cardArrays[x][y]
.getNumber() * 2);
mergeAction(cardArrays[x][y]);
cardArrays[x1][y].setNumber(0);
mGameScene.addCurrScore(cardArrays[x][y].getNumber());
mMerge = true;
}
break;
}
}
}
}
if (mMerge) {
addRandomNum();
checkComplete();
}
}
复制代码
(6)为合并的卡片添加动画效果
/**
* 合并时的动作效果
* @param entity
*/
private void mergeAction(IEntity entity){
ScaleModifier scaleModifier1 = new ScaleModifier(0.1f, 0.8f, 1.2f, EaseBounceInOut.getInstance());
ScaleModifier scaleModifier2 = new ScaleModifier(0.1f, 1.2f, 1.0f);
SequenceEntityModifier sequenceEntityModifier = new SequenceEntityModifier(scaleModifier1,scaleModifier2);
entity.registerEntityModifier(sequenceEntityModifier);
}
复制代码
6. 检查游戏是否要结束了checkComplete()
(1)成功拼成2048胜利结束,全盘填满并且不能再合并时失败结束。
判断游戏是否还能够继续条件:
① 是否有其中一个卡片的数字为 2048,如果有则胜利结束,弹出胜利界面。
② 利用五个条件判断失败结束:1.还有空卡片 2.还可以向左滑 3.还可以向右滑 4.还可以向上滑 5.还可以向下滑。
只要以上条件满足一个,游戏就可以再继续。
否则,游戏就不能够再继续了,弹出失败界面。
/**
* 检测是否游戏结束
*/
private void checkComplete() {
for (int i = 0; i < mCount; i++) {
for (int j = 0; j < mCount; j++) {
if(cardArrays[i][j].getNumber()==2048){
// 拼出2048,胜利完成,弹出胜利对话框
showDialog(true);
return;
}
}
}
for (int y = 0; y < mCount; y++) {
for (int x = 0; x < mCount; x++) {
if (cardArrays[x][y].getNumber() <= 0
|| (x > 0 && cardArrays[x][y]
.equals(cardArrays[x - 1][y]))
|| (x < mCount - 1 && cardArrays[x][y]
.equals(cardArrays[x + 1][y]))
|| (y > 0 && cardArrays[x][y]
.equals(cardArrays[x][y - 1]))
|| (y < mCount - 1 && cardArrays
.equals(cardArrays[x][y + 1]))) {
return;
}
}
}
// 全盘填满并且不能再合并时失败结束,弹出失败对话框
showDialog(false);
}
复制代码
(2)在上下左右每一步滑动后,都添加该函数,详情请看上面的第5点。例如:
private void toLeft() {
......
if (mMerge) {
addRandomNum();
checkComplete();
}
}
复制代码
7.添加游戏分数模块
(1)在游戏场景GameScene中处理
① 声明有关最佳分数和当前分数的变量、精灵、文本实体。
// 当前分数
private int currScore = 0;
// 最佳得分背景
private AnimatedSprite bestScoreBg;
// 最佳得分文本
private Text tBestScore;
// 当前得分背景
private AnimatedSprite currScoreBg;
// 当前分数文本
private Text tCurrScore;
复制代码
②加入最佳分数背景、文本实体,当前分数背景、文本实体。
// 最佳得分背景
bestScoreBg = new AnimatedSprite(0, 20, Res.GAME_SCORE_BG_BEST,
getVertexBufferObjectManager());
// 设置bestScoreBg右边x坐标的位置在镜头的右边减20的位置
bestScoreBg.setRightPositionX(this.getCameraRightX() - 20);
this.attachChild(bestScoreBg);
// 最佳得分文本
tBestScore = new Text(0, bestScoreBg.getY() + 50,
FontRes.getFont(ConstantUtil.FONT_SCORE_NUM),
SharedUtil.getBestScore(getActivity()) + "", 4,
getVertexBufferObjectManager());
// 设置 tBestScore 的X坐标上的中点在bestScoreBg的X坐标中点上
tBestScore.setCentrePositionX(bestScoreBg.getCentreX());
this.attachChild(tBestScore);
// 当前得分背景
currScoreBg = new AnimatedSprite(0, bestScoreBg.getY(),
Res.GAME_SCORE_BG_NOW, getVertexBufferObjectManager());
// 设置currScoreBg的右边X坐标点在bestScoreBg左边的X坐标减20的位置上
currScoreBg.setRightPositionX(bestScoreBg.getLeftX() - 20);
this.attachChild(currScoreBg);
// 当前得分文本
tCurrScore = new Text(0, currScoreBg.getY() + 50,
FontRes.getFont(ConstantUtil.FONT_SCORE_NUM), "0", 4,
getVertexBufferObjectManager());
tCurrScore.setCentrePositionX(currScoreBg.getCentreX());
this.attachChild(tCurrScore);
复制代码
③创建一个SharedUtil类,用于把游戏中的最佳分数数据保存到SharedPreferences里面。
public class SharedUtil {
private static final String Shared_System = "Shared_og";
private static final String BEST_SCORE = "best_score";
public static void setBestScore(Context pContext, int pBestScore) {
Editor edit = pContext.getSharedPreferences(Shared_System,
Context.MODE_PRIVATE).edit();
edit.putInt(BEST_SCORE, pBestScore);
edit.commit();
}
public static int getBestScore(Context context) {
return context
.getSharedPreferences(Shared_System, Context.MODE_PRIVATE)
.getInt(BEST_SCORE, 0);
}
}
复制代码
④更新最佳分数和当前分数的方法实现
/**
* 更新最高纪录
*
* @param pBestScore
*/
private void updateBestScore(int pBestScore) {
tBestScore.setText(pBestScore + "");
// 设置相对bestScoreBgX坐标居中
tBestScore.setCentrePositionX(bestScoreBg.getCentreX());
}
复制代码
// 增加当前分数
public void addCurrScore(int pAddScore) {
if (pAddScore != 0) {
// 播放音效
SoundRes.playSound(ConstantUtil.SOUND_MERGE);
}
currScore += pAddScore;
tCurrScore.setText(currScore + "");
tCurrScore.setCentrePositionX(currScoreBg.getCentreX());
// 当前分数大于所保存的最佳分数时,更新最佳分数
if (currScore > SharedUtil.getBestScore(getActivity())) {
SharedUtil.setBestScore(getActivity(), currScore);
updateBestScore(currScore);
}
}
复制代码
③ 完成卡片合并的时候,要添加分数;在前面的上下左右滑动方法内调用,例如:
for (int x = 0; x < mCount; x++) {
for (int y = 0; y < mCount; y++) {
for (int y1 = y + 1; y1 < mCount; y1++) {
if (cardArrays[x][y1].getNumber() > 0) {
if (cardArrays[x][y].getNumber() <= 0) {
cardArrays[x][y].setNumber(cardArrays[x][y1]
.getNumber());
cardArrays[x][y1].setNumber(0);
mMerge = true;
y--;
} else if (cardArrays[x][y].equals(cardArrays[x][y1])) {
cardArrays[x][y].setNumber(cardArrays[x][y]
.getNumber() * 2);
mergeAction(cardArrays[x][y]);
cardArrays[x][y1].setNumber(0);
// 添加当前分数
mGameScene.addCurrScore(cardArrays[x][y].getNumber());
mMerge = true;
}
break;
}
}
}
}
复制代码
http://www.eoeandroid.com/forum-863-1.html
2048游戏完整源代码揭秘和下载 (二),布布扣,bubuko.com
原文:http://9165326.blog.51cto.com/9155326/1439333