R语言游戏框架设计.docx

上传人:b****4 文档编号:3808502 上传时间:2023-05-06 格式:DOCX 页数:14 大小:95.63KB
下载 相关 举报
R语言游戏框架设计.docx_第1页
第1页 / 共14页
R语言游戏框架设计.docx_第2页
第2页 / 共14页
R语言游戏框架设计.docx_第3页
第3页 / 共14页
R语言游戏框架设计.docx_第4页
第4页 / 共14页
R语言游戏框架设计.docx_第5页
第5页 / 共14页
R语言游戏框架设计.docx_第6页
第6页 / 共14页
R语言游戏框架设计.docx_第7页
第7页 / 共14页
R语言游戏框架设计.docx_第8页
第8页 / 共14页
R语言游戏框架设计.docx_第9页
第9页 / 共14页
R语言游戏框架设计.docx_第10页
第10页 / 共14页
R语言游戏框架设计.docx_第11页
第11页 / 共14页
R语言游戏框架设计.docx_第12页
第12页 / 共14页
R语言游戏框架设计.docx_第13页
第13页 / 共14页
R语言游戏框架设计.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

R语言游戏框架设计.docx

《R语言游戏框架设计.docx》由会员分享,可在线阅读,更多相关《R语言游戏框架设计.docx(14页珍藏版)》请在冰点文库上搜索。

R语言游戏框架设计.docx

R语言游戏框架设计

R语言游戏框架设计

目录

1.贪食蛇的面向对象改造

2.游戏框架定义

3.在框架中重新实现贪食蛇游戏

1.贪食蛇的面向对象改造

我们可以利用面向对象的方法论,对贪食蛇游戏进行抽象整理,并实现代码的面向对象的改造。

R语言支持3种面向对象的编程实现方式,我选择基于RC的面向对象编程,关于RC详细使用请参考文章:

R语言基于RC的面向对象编程。

由于我们之前的代码都是通过函数来封装的,所以代码重构还是比较简单的,只要把Snake对象的属性和方法定义清楚就行了。

1.1定义Snake类

定义Snake类,画出类图,包括属性和方法。

属性解释:

∙name:

游戏的名字

∙stage:

当前的游戏场景

∙e:

游戏中的变量,environment类型

∙m:

游戏地图矩阵

∙width:

矩阵的宽

∙height:

矩阵的高

方法解释:

∙initialize():

构建函数,用于RC类的初始化

∙init():

给stage1场景初始化游戏变量

∙fail():

失败查询

∙furit():

判断并生成水果坐标

∙head():

生成蛇头移动坐标。

∙body():

生成蛇尾移动坐标。

∙drawTable():

绘制游戏背景。

∙drawMatrix():

绘制游戏矩阵。

∙stage0():

创建开机场景,可视化输出。

∙stage1():

创建游戏场景,stage1()函数内部,封装了游戏场景运行时的函数,并进行调用。

∙stage2():

创建结束场景,可视化输出

∙keydown():

监听键盘事件。

∙run():

启动函数

1.2全局函数调用顺序图

接下来,根据UML规范画出顺序图,主要包括全局函数调用和stage1场景游戏环境调用。

全局函数调用关系。

1.通过run()函数启动游戏,进入stage0场景,注册键盘事件。

2.在stage0场景按任意键切换到stage1场景。

3.init()出始化stage1场景的游戏变量。

4.stage1()运行游戏

5.当游戏失败fail()或按q键

6.游戏进行stage2场景,显示游戏结束画面,

7.按空格键回到stage0重新开始,按q键退出程序。

1.3stage1场景游戏环境函数调用顺序图

stage1场景游戏环境函数调用关系。

1.游戏进入stage1场景,按上下左右(up,down,left,right)方向键操作蛇头的前进路线。

2.furit()函数检查,如果地图上水果被吃掉,生成一个新水果,记录到矩阵中。

3.head()函数,通过上下左边键的操作,进行蛇头的移动,记录到矩阵中。

4.fail()函数失败检查,no未失败继续,yes失败进行stage2场景。

5.body()函数,蛇身体移动,记录到矩阵中。

6.drawTable()函数,画出游戏背景画布。

7.drawMatrix()函数,画出游戏矩阵。

利用UML的方法,通过类图和顺序图的描述,我们就把贪食蛇的游戏程序进行了面向对象的设计改造。

不用着急去写代码,我们再想想如何进行游戏框架的提取。

2.游戏框架定义

要设计一个完整、易用、有良好扩展的游戏框架是比难的,但我们可以基于贪食蛇的游戏,一步一步来做抽象。

抽象过程就是把程序对象化,上面的我们已经做了;第二步再把公用的属性和方法提取封装,可以统一把公用的部分提取到一个Game的父类里面,让Snake类继承Game类,从而实现游戏框架定义。

我们画出Game类和Snake类的类图。

∙Game类公共属性,包括了所有的Snake类的属性,这是因为这些属性都是全局的,其他的游戏也会用到,而且每个游戏中的属性,可以在e中进行定义。

∙Game类公共方法,包括了游戏全局调用的方法,但不包括Snake游戏stage1场景中运行的方法。

在Game类的方法中,我们主要实现的都是开发的辅助功能。

∙Snake类方法,同样还有Game类的方法,这是用到方法的重写技术。

子类的方法,先调用父类的同名方法,然后再执行子类方法里的程序。

这样我们就简单地分离了游戏框架Game类和游戏实现Snake类,下面我们要做的就是把代码按照设计进行实现,看看我们的设计是否是合理的。

3.在框架中重新实现贪食蛇游戏

Game类的代码实现,用R语言的RC面向对象编程进行代码编写。

Game<-setRefClass('Game',

         

  fields=list(

   #系统变量

   name="character",#名字

   debug='logical', #调试状态

   width='numeric', #矩阵宽

   height='numeric',#矩阵高

   

   #应用变量

   stage='numeric', #场景

   e='environment', #环境空间变量

   m='matrix',   #数据矩阵

   isFail='logical' #游戏失败

  ),

         

  methods=list(

   

   #构造函数

   initialize=function(name,width,height,debug){

    name<<-"RGameFramework"

    debug<<-FALSE

    width<<-height<<-20 #矩阵宽高

   },

   

   #初始化变量

   init=function(){

    e<<-new.env() #环境空间

    m<<-matrix(rep(0,width*height),nrow=width) #数据矩阵

    isFail<<-FALSE

   },

   

   #开机画图

   stage0=function(){

    stage<<-0

    init()

   },

   

   #结束画图

   stage2=function(){

    stage<<-2

   },

   

   #游戏中

   stage1=function(default=FALSE){

    stage<<-1

    if(FALSE){ #默认游戏中界面

     plot(0,0,xlim=c(0,1),ylim=c(0,1),type='n',xaxs="i",yaxs="i")

     text(0.5,0.7,label="Playing",cex=5) 

    }

   },

   

   #矩阵工具

   index=function(col){

    return(which(m==col))

   },

   

   #失败操作

   fail=function(msg){

    print(paste("GameOver",msg))

    isFail<<-TRUE

    keydown('q')

    return(NULL)

   },

   

   #键盘事件,控制场景切换

   keydown=function(K){

    if(stage==0){#开机画面

     stage1()

     return(NULL)

    } 

    

    if(stage==2){#结束画面

     if(K=="q")q()

     elseif(K=='')stage0() 

     return(NULL)

    }

   },

   

   #启动程序

   run=function(){

    par(mai=rep(0,4),oma=rep(0,4))

    stage0()

    getGraphicsEvent(prompt="SnakeGame",onKeybd=function(K){

     if(debug)print(paste("keydown",K)) 

     return(keydown(K))

    })

   }

  )         

Snake类的代码实现,继承Game类,并实现贪食蛇游戏的私有方法。

#引用game.r文件

source(file="game.r")

#Snake类,继承Game类

Snake<-setRefClass("Snake",contains="Game",

         

 methods=list(

  

  #构造函数

  initialize=function(name,width,height,debug){

   callSuper(name,width,height,debug)#调父类

   

   name<<-"SnakeGame"

  },

  

  #初始化变量

  init=function(){

   callSuper() #调父类

   

   e$step<<-1/width#步长

   e$dir<<-e$lastd<<-'up'#移动方向

   e$head<<-c(2,2)#初始蛇头坐标

   e$lastx<<-e$lasty<<-2#蛇头上一个点坐标

   e$tail<<-data.frame(x=c(),y=c())#初始蛇尾坐标

   

   e$col_furit<<-2#水果颜色

   e$col_head<<-4#蛇头颜色

   e$col_tail<<-8#蛇尾颜色

   e$col_path<<-0#路颜色

   e$col_barrier<<-1#障碍颜色

  },

  

  #失败检查

  lose=function(){

   #head出边界

   if(length(which(e$head<1))>0|length(which(e$head>width))>0){

    fail("Outofledge.")

    return(NULL)

   }

   

   #head碰到tail

   if(m[e$head[1],e$head[2]]==e$col_tail){

    fail("headhittail.")

    return(NULL)

   }

  },

  

  #随机的水果点

  furit=function(){

   if(length(index(e$col_furit))<=0){#不存在水果

    idx<-sample(index(e$col_path),1)

    

    fx<-ifelse(idx%%width==0,10,idx%%width)

    fy<-ceiling(idx/height)

    m[fx,fy]<<-e$col_furit

    

    if(debug){

     print(paste("furitidx",idx))

     print(paste("furitaxis:

",fx,fy))

    }

   }

  },

  

  #snakehead

  head=function(){

   e$lastx<<-e$head[1]

   e$lasty<<-e$head[2]

   

   #方向操作

   if(e$dir=='up')e$head[2]<<-e$head[2]+1

   if(e$dir=='down')e$head[2]<<-e$head[2]-1

   if(e$dir=='left')e$head[1]<<-e$head[1]-1

   if(e$dir=='right')e$head[1]<<-e$head[1]+1

  },

  

  #snakebody

  body=function(){

   if(isFail)return(NULL)

   

   m[e$lastx,e$lasty]<<-e$col_path

   m[e$head[1],e$head[2]]<<-e$col_head#snake

   if(length(index(e$col_furit))<=0){#不存在水果

    e$tail<<-rbind(e$tail,data.frame(x=e$lastx,y=e$lasty))

   }

   

   if(nrow(e$tail)>0){#如果有尾巴

    e$tail<<-rbind(e$tail,data.frame(x=e$lastx,y=e$lasty))

    m[e$tail[1,]$x,e$tail[1,]$y]<<-e$col_path

    e$tail<<-e$tail[-1,]

    m[e$lastx,e$lasty]<<-e$col_tail

   }

   

   if(debug){

    print(paste("snakeidx",index(e$col_head)))

    print(paste("snakeaxis:

",e$head[1],e$head[2])) 

   }

  },

  

  #画布背景

  drawTable=function(){

   if(isFail)return(NULL)

   

   plot(0,0,xlim=c(0,1),ylim=c(0,1),type='n',xaxs="i",yaxs="i")

   

   if(debug){

    #显示背景表格

    abline(h=seq(0,1,e$step),col="gray60")#水平线

    abline(v=seq(0,1,e$step),col="gray60")#垂直线

    #显示矩阵

    df<-data.frame(x=rep(seq(0,0.95,e$step),width),y=rep(seq(0,0.95,e$step),each=height),lab=seq(1,width*height))

    text(df$x+e$step/2,df$y+e$step/2,label=df$lab)

   }

  },

  

  #根据矩阵画数据

  drawMatrix=function(){

   if(isFail)return(NULL)

   

   idx<-which(m>0)

   px<-(ifelse(idx%%width==0,width,idx%%width)-1)/width+e$step/2

   py<-(ceiling(idx/height)-1)/height+e$step/2

   pxy<-data.frame(x=px,y=py,col=m[idx])

   points(pxy$x,pxy$y,col=pxy$col,pch=15,cex=4.4)

  },

  

  #游戏场景

  stage1=function(){

   callSuper()

   

   furit()

   head()

   lose()

   body()

   drawTable()

   drawMatrix() 

  },

  

  #开机画图

  stage0=function(){

   callSuper()

   plot(0,0,xlim=c(0,1),ylim=c(0,1),type='n',xaxs="i",yaxs="i")

   text(0.5,0.7,label=name,cex=5)

   text(0.5,0.4,label="Anykeyboardtostart",cex=2,col=4)

   text(0.5,0.3,label="Up,Down,Left,Rigthtocontroldirection",cex=2,col=2)

   text(0.2,0.05,label="Author:

DanZhang",cex=1)

   text(0.5,0.05,label="http:

//blog.fens.me",cex=1)

  },

  

  #结束画图

  stage2=function(){

   callSuper()

   info<-paste("Congratulations!

Youhaveeat",nrow(e$tail),"fruits!

")

   print(info)

   

   plot(0,0,xlim=c(0,1),ylim=c(0,1),type='n',xaxs="i",yaxs="i")

   text(0.5,0.7,label="GameOver",cex=5)

   text(0.5,0.4,label="Spacetorestart,qtoquit.",cex=2,col=4)

   text(0.5,0.3,label=info,cex=2,col=2)

   text(0.2,0.05,label="Author:

DanZhang",cex=1)

   text(0.5,0.05,label="http:

//blog.fens.me",cex=1)

  },

  

  #键盘事件,控制场景切换

  keydown=function(K){

   callSuper(K)

   

   if(stage==1){#游戏中

    if(K=="q")stage2()

    else{

     if(tolower(K)%in%c("up","down","left","right")){

      e$lastd<<-e$dir

      e$dir<<-tolower(K)

      stage1() 

     }

    }

    return(NULL)

   }

   return(NULL)

  }

 )         

snake<-function(){

 game<-Snake$new()

 game$initFields(debug=TRUE)

 game$run()

}

snake()

最后,我们运行snake.r的程序,就完成了整个贪食蛇游戏。

游戏运行效果,可以查看上一篇文章,R语言游戏之旅贪食蛇入门 的游戏截图和动画。

对于贪食蛇游戏的开发,我们已经完成了,虽然界面还是比较土,而且没有时间维度的操作。

那么我们换一个角度思考,如果不太要求画面效果,而且不需要时间维度的游戏,是不是R语言会表现的更好呢?

当然,这类游戏也有很多,比如最近流行的2048。

那么接下来,就用我们的游戏框架,再来做一个2048的游戏吧,试试在100行之内实现。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2