移动设备应用程序开发大作业.docx
《移动设备应用程序开发大作业.docx》由会员分享,可在线阅读,更多相关《移动设备应用程序开发大作业.docx(17页珍藏版)》请在冰豆网上搜索。
![移动设备应用程序开发大作业.docx](https://file1.bdocx.com/fileroot1/2022-11/21/9c22b1dd-f523-4ef5-90b1-a20f468e5182/9c22b1dd-f523-4ef5-90b1-a20f468e51821.gif)
移动设备应用程序开发大作业
淮阴工学院
《移动设备应用程序开发》大作业
系(院):
计算机与软件工程学院
专业:
计算机科学与技术班级:
计算机3132
学生姓名:
王奇奇学号:
1131321206
任课教师:
张海艳
学年学期:
2016~2017学年第1学期
2016年12月26
基于Android平台2048游戏开发
第1章绪论
1.1游戏开发背景
Android智能手机功能非常强大,具有很高的性价比,非常深受人们的喜爱,可能正式因为如此,在2014年中,Android智能手机在全世界占据着81.5%很夸张的市场份额,一举成为使用的人数最多,市场份额占据最大的Android智能手机系统。
而Android智能手机游戏的出现正是为了娱乐心神,并且随着智能移动终端和全球移动通信网络的不断进步,Android智能手机游戏也正在经历从简单到复杂的进化过程。
从全球来看,智能移动终端的娱乐服务一直被认为是带动移动数据业务加速并快速发展的重要力量。
也是作为手机娱乐服务的重要内容之一。
近年来,一直伴随着全球移动网络和移动终端性能不断的提高和完善。
由于近几年来,Android智能手机游戏的快速发展,游戏的分类也变得越来越丰富,目前手机游戏按内容可分为:
角色扮演类(RPG)、冒险类(AVG)、格斗类(FTG)、棋牌类、电影改版类、益智类、体育竞技类、模拟类。
手机游戏种类目前已成为人类线上娱乐生活的不可或缺的最主流的载体而存在,现代人对于移动终端的休闲娱乐功能所需求越来越强大,移动终端上的游戏或已以成为了现代人们娱乐生活中不可或缺的一部分了。
1.2国内外研究现状
目前国内外的Android开发还是主要以应用开发为主,主要分成3类:
企业应用、通用应用以及游戏应用。
第一类应用的开发主要是一些大公司为了自己的品牌而开发的。
第二类的应用主要是一些创业型公司或者独立开发者为了盈利开发的应用。
第三类应用目前跟第二类应用相同[4]。
2048小游戏是一款最近风靡全球的手机游戏,简单的游戏模式和趣味的玩法,几乎游戏下载排行榜的前10名都可以看到“他的身影”。
1.3游戏开发意义
现如今,手机游戏已在我们的生活中占据一席之地,并在一步步的壮大。
可以说,随着他的迅猛发展,现今的手机游戏已经不单单是一种缓解压力的工具,而是形成了一种文化现象。
随着游戏软件在市场的一步步壮大,与其有关的文化也随之传播。
2048游戏的制作属于电子游戏中的益智类小游戏,它做到了娱乐性、趣味性、教育性相统一。
益智类的游戏即是需要去开动大脑去思考从而获得游戏的胜利。
简单的益智类游戏可以使玩家在娱乐中不断的开发大脑。
这样一来就实现了在娱乐中学习。
现有2048游戏最大的不足在于过度强调简洁,它是由数字组成的游戏,所以在长时间的游戏后就会感觉无聊,同时在熟知玩法后就会知道下一个要拼出的数字,这就缺乏神秘感,当一款游戏缺乏了神秘和趣味时就注定失败。
所以我们要勇于创新,将2048游戏开发出不同的版本,当玩家觉对拼接数字感到无聊时可以有不同的选择。
2048还有一大缺点就是当玩家拼出‘2048’时游戏就会结束,这样就会让玩家感到失落,所以我们要创作一个永无止境的游戏,让玩家去不断的超越自己。
第2章系统的需求分析和概要设计
2.1系统需求分析
2.1.1系统功能需求分析
系统主要实现以下的几个功能:
关卡选择、呈现游戏界面、重新开始游戏、当前分数和最高分数、游戏帮助等功能。
关卡选择是当玩家点击此按钮时,游戏就会从主界面跳转到关卡选择界面,当玩家选择相应的关卡时,先判断此关卡是否开启,如果没有开启此关卡就会弹出对话框提示玩家此关卡未开启,如果此关卡已经开启就会跳转到主界面同时开始此关卡。
重新开始游戏是当玩家无法满足当前进度时点击此按钮就会重新开始游戏,如果玩家处于不同关卡时重新开始游戏还是停留在此关卡。
游戏帮助是当新手玩此游戏时无法知道游戏玩法时给予相应的提示。
呈现游戏界面是游戏开始时主界面在游戏区域会生成4×4的矩阵同时在矩阵里面随机生成两个2或4的卡片。
当前分数和最高分数是显示此局玩家所获得的分数和历史最高的分数,如果当前的分数超过最高分数那么最高分显示当前的分数,如图2-1所示。
图2-1系统功能图
2.1.2游戏基本规则
在开始游戏后玩家通过滑动屏幕来操控卡片的移动方向,当卡片滑动中如果有两张卡片相同且他们的中间也没有其他卡片时,在滑动的过程中这两张卡片会合并,显示为这两张卡片之和。
在滑动之中有三张卡片相同时只会合并向滑动方向两张卡片。
在滑动中如果有两张卡片一样同时又有一张卡片的值跟这两张卡片相加的值时,滑动只会使那两张相同的卡片合并而不会接着让合并后的卡片和另一张卡片合并。
2.2系统概要设计
2.2.1系统流程的设计
游戏开始进入开始页面,能够进入游戏的主界面并开始普通开局,从主界面能够重新开始游戏、查看帮助和进入关卡选择界面。
当玩家点击重新开始按钮会弹出相应的对话框让玩家选择,如果玩家选择“是”时则重新开始游戏,如果选择“否”则返回游戏界面不做任何处理。
当玩家点击关卡按钮会跳转到关卡选择界面,关卡界面将显示所有的关卡,当玩家点击相应的关卡时后台会判断此关卡是否开启,如果已经开启将会跳转到主界面并运行此关卡,如果没有开启将给予玩家提示“此关卡未开启”对话框。
在开始界面按返回按钮时则会退出游戏。
游戏的流程图如图2-2所示:
图2-2系统流程图
2.2.2系统模块设计
算法设计
(1)当有两张卡片相同时,向它们可以碰撞的方向滑屏,卡片会移动到最底边并生成其两倍数字的卡片,并且生成一个“2”或“4”的卡片,如图2-3所示:
图2-3简单卡片合成
(2)当有两张卡片相同时,且在他相同的方向有张跟它们之和的卡片,向它们可以碰撞的方向滑屏,相同的卡片会移动到无法移动的位置并生成期两倍数字的卡片,但合成的卡片不会跟那张两倍数字的卡片合并,并且生成一个“2”或“4”的卡片,如图2-4所示:
图2-4复杂卡片合成
(3)当界面上没有空位并且两两相邻的卡片不相同时游戏结束。
如图2-5所示:
图2-5游戏结束
第3章系统实现
3.1开始界面的实现
游戏的主界面是按钮图片,只是实现了界面的跳转,当玩家点击此界面时就会调用ZuomianActivity此函数让页面跳转到游戏界面开始游戏,如图3-1所示:
publicclassZuomianActivityextendsActivity{
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main0);
}
图3-1开始界面
3.2游戏界面的实现
游戏界面主要是在MainActivity_main.xml中当前分数、最高分数、游戏区域,当跳转到游戏界面时就会调用并执行MainActivity.java函数来展示游戏界面,如图3-2所示。
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
图3-2主界面
3.3游戏滑屏卡片移动的实现
当玩家滑动屏幕时,主要是通过initGameView函数来监听玩家手指滑动的位置,先通过获取开始坐标和结束坐标,然后通过比较结束坐标跟开始坐标的差值来判断玩家是怎样滑动屏幕的。
判断出玩家的滑动轨迹后,通过调用swipeLeft、swipeRight、swipeUp、swipeDown方法来实现卡片的移动,如图3-3所示。
图3-3卡片移到
publicvoidinitGameView(){
setColumnCount(4);
setOnTouchListener(newOnTouchListener(){
privatefloatstartX,startY,offsetX,offsetY;
publicbooleanonTouch(Viewv,MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
startX=event.getX();
startY=event.getY();
break;
caseMotionEvent.ACTION_UP:
offsetX=event.getX()-startX;
offsetY=event.getY()-startY;
if(Math.abs(offsetX)>Math.abs(offsetY)){
if(offsetX<-5){
swipeLeft();
}elseif(offsetX>5){
swipeRight();
}
}else{
if(offsetY<-5){
swipeUp();
}elseif(offsetY>5){
swipeDown();
}
}
break;
}
returntrue;
}
});
}
privatevoidswipeLeft(){
booleanmerge=false;
for(inty=0;y<4;y++){
for(intx=0;x<4;x++){
for(intx1=x+1;x1<4;x1++){
if(cardsMap[x1][y].getNum()>0){
if(cardsMap[x][y].getNum()<=0){
cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
cardsMap[x1][y].setNum(0);
x--;
merge=true;
}elseif(cardsMap[x][y].equals(cardsMap[x1][y])){
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
MainActivity.getMainActivity().addScore(
cardsMap[x][y].getNum());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandomNum();
checkComplete();
}
}
privatevoidswipeRight(){
booleanmerge=false;
for(inty=0;y<4;y++){
for(intx=3;x>=0;x--){
for(intx1=x-1;x1>=0;x1--){
if(cardsMap[x1][y].getNum()>0){
if(cardsMap[x][y].getNum()<=0){
cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
cardsMap[x1][y].setNum(0);
x++;
merge=true;
}elseif(cardsMap[x][y].equals(cardsMap[x1][y])){
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
MainActivity.getMainActivity().addScore(
cardsMap[x][y].getNum());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandomNum();
checkComplete();
}
}
privatevoidswipeUp(){
booleanmerge=false;
for(intx=0;x<4;x++){
for(inty=0;y<4;y++){
for(inty1=y+1;y1<4;y1++){
if(cardsMap[x][y1].getNum()>0){
if(cardsMap[x][y].getNum()<=0){
cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
cardsMap[x][y1].setNum(0);
y--;
merge=true;
}elseif(cardsMap[x][y].equals(cardsMap[x][y1])){
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y1].setNum(0);
MainActivity.getMainActivity().addScore(
cardsMap[x][y].getNum());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandomNum();
checkComplete();
}
}
privatevoidswipeDown(){
booleanmerge=false;
for(intx=0;x<4;x++){
for(inty=3;y>=0;y--){
for(inty1=y-1;y1>=0;y1--){
if(cardsMap[x][y1].getNum()>0){
if(cardsMap[x][y].getNum()<=0){
cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
cardsMap[x][y1].setNum(0);
y++;
merge=true;
}elseif(cardsMap[x][y].equals(cardsMap[x][y1])){
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y1].setNum(0);
MainActivity.getMainActivity().addScore(
cardsMap[x][y].getNum());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandomNum();
checkComplete();
}
}
3.4重新开始游戏功能的实现
当玩家点击游戏界面的重新开始游戏时,会弹出给玩家选择的对话框,让玩家选择是否重新开始游戏。
当玩家选择“是”时游戏会重新开始,重新开始游戏会根据玩家当前所选的关卡来重置游戏,如果玩家选择“否”时,游戏将继续下去,如图3-4所示。
图3-4重新开始游戏
btnNewGame=(Button)findViewById(R.id.btnNewGame);
btnNewGame.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewv){
newAlertDialog.Builder(MainActivity.this)
.setTitle("是否重新再来!
")
.setNegativeButton("取消",newDialogInterface.OnClickListener(){
publicvoidonClick(DialogInterfacedialog,intwhich){
}
})
.setPositiveButton("确定",newDialogInterface.OnClickListener(){
publicvoidonClick(DialogInterfacedialog,intwhich){
if(getGameid()==0)
gameView.startGame();
elseif(getGameid()==1)
gameView.startGame64();
elseif(getGameid()==2)
gameView.startGame128();
elseif(getGameid()==3)
gameView.startGame256();
elseif(getGameid()==4)
gameView.startGame512();
elseif(getGameid()==5)
gameView.startGame1024();
elseif(getGameid()==6)
gameView.startGame2048();
elseif(getGameid()==7)
gameView.startGame4096();
elseif(getGameid()==8)
gameView.startGame8192();
elseif(getGameid()==9)
gameView.startGame16384();
elseif(getGameid()==10)
gameView.startGame32768();
elseif(getGameid()==11)
gameView.startGame65536();
}
}).show();
}
});
}
3.5触控交互设计
本模块主要实现用户通过手指滑动屏幕,起始位置,获得水平或垂直方向的偏移离量,以此来判断用户的意图,主要是通过调用OnTouchListener监听器来实现的,具体代码实现如下:
setOnTouchListener(newOnTouchListener(){
privatefloatstartHorizontal,startVertical;privatefloatshiftHorizontal,shiftVertical;
publicbooleanonTouch(Viewv,MotionEventevent){
//TODOAuto-generatedmethodstubswitch(event.getAction()){caseMotionEvent.ACTION_DOWN:
startHorizontal=event.getX();startVertical=event.getY();break;
caseMotionEvent.ACTION_UP:
shiftHorizontal=event.getX()-startHorizontal;shiftVertical=event.getY()-startVertical;
if(Math.abs(shiftHorizontal)>Math.abs(shiftVertical)){
if(shiftHorizontal<-4){
slipLeft();}
elseif(shiftHorizontal>4){
slipRight();}}else{
if(shiftVertical<-4){
slipUp();}
elseif(shiftVertical>4){
slipDown();}}break;}
特殊情况:
由于人的手指在滑动方向会有偏差,一般不会精准的向四个方向滑动,肯定会有偏差,所以要判断手指滑过方向的是水平方向还是垂直方向的意图,当水平方向的偏移量大于垂直方向的偏移量时,表明用户是水平滑动意图,当垂直方向的偏移量大于水平方向的偏移量,表明用户是垂直方向滑动的意图。
由于人的手指只有滑动一段距离才能表明用户的意图,不可能点一下屏幕或者稍微动一下就表示滑动意图,这显然不太符合现实情况,所以要定义偏移一定的距离才能判断用户的真正意图。
规定当水平方向的偏移距离大于或者等于水平方向的偏移距离,且当偏移小于5时,用户向上滑动,大于5使,规定向下滑动;当水平方向的偏移距离大于或者等于水平方向的偏移距离,且当偏移小于5时,规定用户向左滑动,如果大于5,用户向右滑动。
3.6在游戏中添加随机数
对于每个文本框来说,规定如果文本框的数字小于等于0,清空当前文本框的数字小于等于0的文本框的数字,把每个空的文本框存储在一个空点数组中,最后取出一个空点,然后把改所在的文本框的数字设置为0或4,并且规定0和4出现的概率为9比1。
具体实现代码如下:
privatevoidaddRadomNumber(){
emptyPoint.clear();for(inti=0;i<4.;i++){
for(intj=0;j<4;j++){
if(cardArray[j][i].getNumber()<=0){
emptyPoint.add(newPoint(j