为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > 手机网络游戏

手机网络游戏

2011-10-10 47页 pdf 1MB 55阅读

用户头像

is_752764

暂无简介

举报
手机网络游戏 目前手机网络游戏的迅速崛起,让游戏运营商们又发现了一个新的发展“特 区”,期待着手游能继网游之后成为新的经济增长点。手游为广大手机用户带来了 一种全新的休闲方式,他们可以随时随地利用手游放松紧张的情绪,缓解学习、工 作、生活中的种种压力。本章将介绍如何使用Java的 J2ME技术开发一款以象棋为 核心的手机网络游戏。通过阅读本章,可以学习到:  J2ME 程序开发  HTTP 协议的有状态连接  J2ME 与 Tomcat 的通信  如何绘制游戏界面  游戏信息处理  使用 Ecl...
手机网络游戏
目前手机网络游戏的迅速崛起,让游戏运营商们又发现了一个新的发展“特 区”,期待着手游能继网游之后成为新的经济增长点。手游为广大手机用户带来了 一种全新的休闲方式,他们可以随时随地利用手游放松紧张的情绪,缓解学习、工 作、生活中的种种压力。本章将介绍如何使用Java的 J2ME技术开发一款以象棋为 核心的手机网络游戏。通过阅读本章,可以学习到:  J2ME 程序开发  HTTP 的有状态连接  J2ME 与 Tomcat 的通信  如何绘制游戏界面  游戏信息处理  使用 EclipseMe 工具 手机网络游戏 (J2ME+Servlet 实现) 10第 章 Java 项目开发全程实录 10.1 开发背景 加入WTO之后,随着 3G时代的即将到来,中国手机网络游戏迅速崛起,成为继网游之后又一 新的经济增长点。×××有限公司是一家手机游戏运营商,公司已经从网络版的手机游戏运营中获取了大 量的资金,现在了玩家的反馈信息,发现游戏玩家需要一些小型的休闲类游戏,例如纸牌、象棋、 围棋和一些智利游戏等。现需要委托其他单位开发一个网络版的手机象棋游戏。 10.2 系统 10.2.1 需求分析 通过与×××有限公司的沟通和需求分析,要求系统具有以下功能。  系统操作简单,界面友好。  运行速度快,保证程序的稳定性。  支持多人操作。  支持移动网络连接。  以HTTP协议通信。 10.2.2 可行性分析 从手机游戏依托的技术平台来看,目前 Java手机游戏保持很高的增长速度。手机游戏将是未来游戏 市场的主要发展方向,只要拥有一部手机,就可以进入到全新的掌上游戏世界。游戏正成为无线增值服 务的主力军,各游戏开发商早已洞察到这一点。通信公司 2.5G和 3G通信技术的发展,给手机用户带来 了高达每秒 384K6ps的移动带宽,将语音、图像、视频有序地结合起来,给手机用户带来了更加丰富多 彩的多媒体娱乐服务。借此东风,各游戏开发商将进入全新的无线网络游戏时代,市场潜力巨大。 手机版象棋游戏采用MIDP 1.0开发,在低端手机上运行的同时,保证了高端手机的兼容性,其 市场发展空间巨大。伴随着中国移动 GPRS和中国联通 CDMA1X数据业务的开展,手机游戏将是 3G 数据业务一个重要的应用领域。 ·198· 第 10 章 手机网络游戏(J2ME+Servlet 实现) 10.3 系统设计 10.3.1 系统目标 根据需求分析的描述以及与用户的沟通,现制定系统实现目标如下。  界面设计简洁、友好、美观大方,保证直接上手便可游戏。  操作简单、快捷方便。  规则简单,方便游戏者进行游戏。  实现智能规则判断。  支持大型Web服务器,以Http协议通信。  向 PC端开发靠拢,为以后 PC与手机互联奠定基础。 10.3.2 系统功能结构 本系统的服务器端包括消息接收和桌面管理,功能结构如图 10.1 所示。客户端包括主窗体、游戏界 面、消息处理等模块,其功能结构如图 10.2 所示。 主机服务器端 消息接收 登 录 信 息 处 理 落 座 信 息 处 理 开 始 信 息 处 理 走 棋 信 息 处 理 退 出 信 息 处 理 桌面管理 更 新 单 个 桌 面 获 取 桌 面 列 表 更 新 所 有 桌 面 手机客户端 主窗体 桌 面 更 新 处 理 落 座 信 息 处 理 获 取 玩 家 列 表 落 座 消 息 处 理 退 出 信 息 处 理 游戏界面 绘 制 棋 盘 规 则 处 理 绘 制 棋 子 消息处理 消 息 发 送 图 10.1 服务器端系统功能结构 图 10.2 客户端系统功能结构 10.3.3 构建开发环境(根据语言的实际情况写) 在开发手机游戏时,分别使用了以下软、硬件环境。  硬件平台:  CPU:P 800GHzⅢ 。  内存:256MB以上。  硬盘:500MB以上空间。  显卡:32MB以上显存。 ·199· Java 项目开发全程实录  软件平台:  操作系统:Windows 2003(SP1)。  Java开发包:JDK 1.6。  J2ME开发包:Wireless Toolkit 2.5.2 for CLDC。  分辨率:最佳效果 1024×768像素。  手机分辨率:最佳效果为 240×292像素。  开发工具:Eclipse 3.2+MyEclipse 5.1+EclipseMe 1.7.7。 10.3.4 系统预览 手机版象棋游戏的界面根据具体游戏进度而变换,下面仅列出几个典型界面的预览,其他页面参 见光盘中的源程序。 游戏的开局界面如图 10.3 所示,该界面是游戏的主界面,包含游戏的规则算法、控制走棋、吃棋、 选棋、退出、开始等操作。如图 10.4 所示是游戏进行到死局的界面效果,在该界面中,红棋已经无路可 走,它被对方的“炮”和“车”将死。 ·200· 第 10 章 手机网络游戏(J2ME+Servlet 实现) 图 10.3 开局界面(光盘\…\GameCanvas.java) 图 10.4 死局界面(光盘\…\GameCanvas.java) 输棋的界面如图 10.5 所示,该界面在玩家输棋的时候提示玩家“抱歉,您失败了”。游戏胜利界 面如图 10.6 所示,该界面在玩家取得胜利的时候提示玩家“恭喜,您获胜了”。 图 10.5 输棋界面(光盘\…\GameCanvas.java) 图 10.6 胜利界面(光盘\…\GameCanvas.java)  说明:由于路径太长,因此省略了部分路径,省略的路径是“TM\10\xiangqi\src\com\lzw”。 10.3.5 文件夹组织结构 在进行系统开发之前,需要规划文件夹组织结构。也就是说,建立多个文件夹,对各个功能模块 进行划分,实现统一管理。这样做的好处在于:易于开发、管理和维护。开发本游戏时,服务器文件夹 组织结构和客户端文件夹组织结构分别如图 10.7和图 10.8 所示。 ·201· Java 项目开发全程实录 图 10.7 服务器端文件夹组织结构 图 10.8 客户端文件夹组织结构 10.4 主程序设计 手游程序的主程序,必须继承 MIDlet类,MIDlet是一个抽象类,该类是手游应用程序的入口, 这和 Java应用程序中含有main()方法的主类相似。 Game类继承了MIDlet类成为手游程序的主类,并实现了 CommandListener接口处理相应的软键 触发事件。该类在程序界面中创建了 List 列表,该列表包括游戏桌面信息和相应的操作(本实例主要 是介绍游戏的开发,游戏桌面信息使用简单的字符信息“0”和“1”代替“空座”和“落座”信息)。 简单的界面如图 10.9 所示。 ·202· 第 10 章 手机网络游戏(J2ME+Servlet 实现) 第一位数字代表桌子 号码,第二位和第三 位的 0 代表是否有玩 家落座 图 10.9 简单桌面列表信息 创建主程序的步骤如下: (1)创建 Game类,该类必须继承 MIDlet类并实现 CommandListener接口。在类中创建并初始化 程序画布类(即游戏界面)、消息处理、桌面列表、软键按钮等对象。关键代码如下: 例程 01 代码位置:光盘\TM\10\xiangqi\src\com\lzw\Game.java public class Game extends MIDlet implements CommandListener { private Client client; //声明客户端消息处理对象 public static Display display; //声明静态的设备对象 private GameCanvas canvas; //声明游戏画布对象 private List playerList; //声明列表控件对象 private int[][] desks; //声明桌面数组 private int trySeat, tryDesk; //声明落座的桌号和位置变量 private Command okCommand; //声明落座按钮控件对象 public Game() { //在构造方法中初始化所有类成员 display = Display.getDisplay(this); playerList = new List("Online player", Choice.EXCLUSIVE); Command exitCommand = new Command("退出", Command.EXIT, 0); playerList.addCommand(exitCommand); okCommand = new Command("落座", Command.OK, 0); playerList.addCommand(okCommand); playerList.setCommandListener(this); display.setCurrent(playerList); client = new Client(this); } …//省略部分代码 } (2)实现MIDlet类规定的 3个声明周期方法,其中 startApp()方法在手游程序被加载时,初始化 程序需要的数据, pauseApp()方法在手游程序被暂停或者被手机来电中断时暂存游戏数据, destroyApp()方法在退出手游程序时负责清空程序数据,释放所有资源。这些方法是父类的抽象方法, 即使不实现方法逻辑,也要编写相应的方法声明。关键代码如下: ·203· Java 项目开发全程实录 例程 02 代码位置:光盘\TM\10\xiangqi\src\com\lzw\Game.java protected void startApp() throws MIDletStateChangeException { } protected void pauseApp() { } protected void destroyApp(boolean p0) throws MIDletStateChangeException { //在程序退出时,发送 exit消息 client.sendMessage("exit"); display.setCurrent(null); } (3)实现 CommandListener接口中规定的 commandAction()方法,该方法用于处理软键的触发事 件。当玩家触发“退出”按钮时,该方法将使游戏退出并结束手游程序。当玩家触发“落座”按钮时, 该方法将获取桌面列表中选择的当前列表项,并分析该桌面的玩家信息,如果该桌面有空位置,则设 置游戏玩家的桌号和座位号,并显示游戏界面。关键代码如下: 例程 03 代码位置:光盘\TM\10\xiangqi\src\com\lzw\Game.java public void commandAction(Command c, Displayable s) { if (c.getCommandType() == Command.EXIT) { //当玩家触发退出按钮时 client.sendMessage("exit"); try { destroyApp(false); notifyDestroyed(); //退出并结束手游程序 } catch (Exception e) { e.printStackTrace(); } } else if (c == okCommand) { //当玩家触发落座按钮时 if (playerList.getSelectedIndex() >= 0) { try { String info = playerList.getString(playerList .getSelectedIndex()); //获取桌面信息 int index1 = info.indexOf("-"); int d = Integer.parseInt(info.substring(0, index1)); int index2 = info.indexOf("-", index1 + 1); int d1 = Integer.parseInt(info .substring(index1 + 1, index2)); int d2 = Integer.parseInt(info.substring(index2 + 1)); if (d1 == 0 || d2 == 0) { //如果该桌面有空的座位 if (d1 == 0) trySeat = 0; //设置玩家座位号为 0 else trySeat = 1; //或者设置玩家座位号为 1 tryDesk = d; if (canvas == null) canvas = new GameCanvas(this, client); //初始化游戏界面的画布对象 else canvas.init(); //调用游戏界面的 init()方法 client.sendMessage("take," + d + "," + trySeat); //调用 sendMessage()方法发送落座消息 ·204· 第 10 章 手机网络游戏(J2ME+Servlet 实现) } } catch (Exception exc) { System.out.println("Error parseInt"); exc.printStackTrace(); } } } } (4)编写 takeSeat()方法,该方法用于处理玩家的落座信息。当程序接收到服务器的 takeseat信息 时,将调用该方法完成程序界面的初始化、设置玩家座位、桌号,并显示游戏界面。关键代码如下: 例程 04 代码位置:光盘\TM\10\xiangqi\src\com\lzw\Game.java public void takeSeat() { //处理落座信息的方法 if (canvas == null) //如果游戏界面对象未初始化 canvas = new GameCanvas(this, client); //初始化游戏界面对象 else canvas.init(); //调用游戏界面的 init()方法 canvas.setSeatPos(trySeat); //设置玩家座位 canvas.setDeskIndex(tryDesk); //设置玩家卓号 display.setCurrent(canvas); //显示游戏界面 } (5)编写 updateDesk()方法,该方法用于更新桌面列表的单个列表项,也就是单个桌面的座位信 息。当程序接收到服务器的 updatedesk信息时,将调用该方法解析 updatedesk信息之后的桌面数据, 并更新到程序界面中。关键代码如下: 例程 05 代码位置:光盘\TM\10\xiangqi\src\com\lzw\Game.java public void updateDesk(String str) { //更新桌面 int index1 = str.indexOf(","); //解析分隔符的位置 int index2 = str.indexOf(":", index1 + 1); int index3 = str.indexOf(",", index2 + 1); try { //截取桌面数据到 desks数组中 int d = Integer.parseInt(str.substring(index1 + 1, index2)); desks[d][0] = Integer.parseInt(str.substring(index2 + 1, index3)); desks[d][1] = Integer.parseInt(str.substring(index3 + 1)); playerList.set(d, d + "-" + desks[d][0] + "-" + desks[d][1], null); //更新桌面列表 } catch (Exception exc) { } } (6)编写 setDesks()方法,该方法用于设置整个桌面列表。当程序接收到服务器的 desks信息时 (该信息包括了所有桌面信息),setDesks()方法必须解析这些信息并更新游戏主程序的所有桌面。关 键代码如下: 例程 06 代码位置:光盘\TM\10\xiangqi\src\com\lzw\Game.java public void setDesks(String string) { for (int i = 0; i < playerList.size(); i++) //清除原桌面列表 ·205· Java 项目开发全程实录 playerList.delete(i); int index1, index2, index3, index4, index0; //解析分隔符位置 index1 = string.indexOf(","); index2 = string.indexOf(":", index1 + 1); int desknum = Integer.parseInt(string.substring(index1 + 1, index2)); //解析桌面编号 desks = new int[desknum][4]; //初始化桌面数组 index0 = index2; int counter = 0; while (counter < desknum) { //解析服务器发送的桌面列表信息 index1 = string.indexOf(",", index0 + 1); index4 = string.indexOf(":", index1 + 1); desks[counter][0] = Integer.parseInt(string.substring(index0 + 1, index1)); //将解析后的数据存入数组中 if (index4 > 0) desks[counter][1] = Integer.parseInt(string.substring( index1 + 1, index4)); else { string = string.trim(); desks[counter][1] = Integer.parseInt(string .substring(index1 + 1)); } playerList.append(counter + "-" + desks[counter][0] + "-" //将数组中的数据更新到主程序界面 + desks[counter][1], null); index0 = index4; counter++; } } 10.5 公共模块设计 本系统的服务器项目空间中,有部分程序是公用的,它们被多个模块甚至整个系统重复调用完成 指定的业务逻辑,本节将这些公共的模块提出来进行单独介绍。 10.5.1 创建 Player 公共类 Player类代表玩家对象。每个玩家都有不同的属性,这些属性用来表示唯一的玩家。在现实社会中 没有完全相同的两个人物,而游戏中也应如此,否则无法保证游戏的数据安全。要做到区分不同的玩 家,就必须为每个玩家添加 IP地址和端口属性。另外,玩家会坐在不同桌子的不同座位上、有不同颜 色的棋子、独立的消息队列和开始状态等,这些都需要声明对应的属性并记录属性状态。关键代码如下: 例程 07 代码位置:光盘\TM\10\XiangQiServer\src\com\lzw\Player.java public class Player { private int ID = 1; //玩家编号 private String IP = ""; //玩家 IP地址 ·206· 第 10 章 手机网络游戏(J2ME+Servlet 实现) private int PORT = 9999; //玩家端口号 private Desk desk; //玩家所在的桌面对象 public Queue data; //消息队列 private String Color = ""; //玩家手中象棋的颜色 public boolean start = false; //开始状态 public Player(String ip, int p){ IP = ip; //初始化 IP PORT = p; //初始化端口 desk = null; data = new Queue(); //初始化消息队列 } public void setDesk(Desk d) { //设置玩家桌号的方法 desk = d; } public Desk getDesk() { //获取玩家桌号的方法 return desk; } public boolean equals(String ip) { //判断是否同一个 IP玩家的方法 if (IP.equals(ip)) return true; else return false; } public boolean equals(Player p) { //判断是否同一个玩家对象的方法 if (IP.equals(p.getIP()) && PORT == p.getPort()) return true; else return false; } public String getIP() { //获取 IP的方法 return IP; } public int getPort() { //获取端口号的方法 return PORT; } …//省略部分代码 public boolean isStart() { //判断玩家是否开始游戏的方法 return start; } public void init() { //玩家的初始化方法 start = false; //设置未开始游戏状态 data.clear(); //清除消息队列 IP=""; PORT=0; } public void reset() { //玩家复位方法 Color = ""; start = false; ·207· Java 项目开发全程实录 } public String getColor() { //获取玩家象棋颜色的方法 return Color; } public void setColor(String color) { //设置玩家象棋颜色的方法 Color = color; } } 10.5.2 创建 Queue 公共类 编写消息队列公共类 Queue,该类负责存储服务器发送给玩家的消息,当手机客户端发出请求信 息时,服务器会从该客户端对应的玩家对象的消息队列中获取消息,如果消息队列中没有消息,那么 手机客户端必须等待服务器为其分配消息。 Queue公共类遵循“先进先出”的存储结构,数据元素只能从队尾进入,从队首取出。在队列中, 数据元素可以任意增减,但数据元素的次序不会改变。每当有数据元素从队列中被取出,后面的数据 元素依次向前移动一位。所以,任何时候从队列中读到的都是队首的数据。关键代码如下: 例程 08 代码位置:光盘\TM\10\XiangQiServer\src\com\lzw\Queue.java public class Queue extends java.util.Vector { //继承向量实现集合类 public class EmptyQueueException extends java.lang.RuntimeException { //创建自定义异常类 public EmptyQueueException() { super(); //调用父类的构造方法 } } public Queue() { //Queue公共类的构造方法 super(); }  public synchronized void push(Object x) { //添加队列消息的方法 super.addElement(x); }  public synchronized Object pop() { //获取队列消息的方法 /* 队列若为空,引发 EmptyQueueException 异常 */ if (this.empty()) throw new EmptyQueueException(); //抛出异常的方法 Object x = super.elementAt(0); //获取第一个消息 super.removeElementAt(0); //从队列中移除第一个消息 return x; }  public synchronized Object front() { //读取队首消息的方法 if (this.empty()) throw new EmptyQueueException(); return super.elementAt(0); } ·208· 第 10 章 手机网络游戏(J2ME+Servlet 实现)  public boolean empty() { //判断队列消息是否为空的方法 return this.isEmpty(); }  public synchronized void clear() { //清除队列消息的方法 super.removeAllElements(); }  public int search(Object x) { //搜索消息的方法 return super.indexOf(x); } }  代码贴士  push(Objectx):向队列插入一个值为 x 的元素。  pop():从队列中取出一个元素。  front():从队列中读一个元素,但队列保持不变。  empty():判断队列是否为空,空则返回 true。  clear():清空队列。  search(x):查找距队首最近的元素的位置,若不存在,返回-1。 10.5.3 创建 Umpire 公共类 服务器端的Umpire公共类用于裁判游戏输赢、记录棋盘数据。在Desk公共类中将调用Umpire类 的moveChess()方法更新棋盘数据的记录。另外该公共类还定义了其他方法来更改棋盘数据,例如 init() 方法可以初始化棋盘数据到开局状态。关键代码如下: 例程 09 代码位置:光盘\TM\10\XiangQiServer\src\com\lzw\Umpire.java public class Umpire { private int huihe; //记录回合 private int bigID; //记录先手玩家的编号 private int score; //记录分数 protected static int i, j; //棋盘数组的下标编号 protected static int isRedWin = 1; //判断红色玩家的胜利记录 protected static int isWhiteWin = 1; //判断白色玩家的胜利记录 private int point[][]; //声明棋盘记录数组 public Umpire() { huihe = 0; //初始化回合记录 score = 0; //初始化分数记录 point = new int[][] { { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, //初始化棋盘数据记录 { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 10, 0, 0, 0, 0, 0, 11, 0 }, { 12, 0, 13, 0, 14, 0, 15, 0, 16 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 28, 0, 29, 0, 30, 0, 31, 0, 32 }, { 0, 26, 0, 0, 0, 0, 0, 27, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 17, 18, 19, 20, 21, 22, 23, 24, 25 } }; } ·209· Java 项目开发全程实录  public void checkWin() { //判断输赢的方法 isRedWin = 0; isWhiteWin = 0; for (i = 0; i < 3; i++) { //遍历“将”的活动范围 for (j = 0; j < 3; j++) { if (point[0 + i][3 + j] == 5) { //如果失去主将 isRedWin++; //则另一方胜利 } } } for (i = 0; i < 3; i++) { //遍历“帅”的活动范围 for (j = 0; j < 3; j++) { if (point[7 + i][3 + j] == 21) { //如果失去主帅 isWhiteWin++; //则对方胜利 } } } }  public void moveChess(int selectedY, int selectedX, int n, int m) { //记录走棋的方法 point[selectedY][selectedX] = point[n][m]; //更新棋盘指定位置的数据 point[n][m] = 0; //移动棋子之后,将原位置清空 checkWin(); //调用判断输赢的方法 } public void logHuihe() { //记录回合数的方法 huihe++; } public int getHuihe() { //获取回合数的方法 return huihe; }  public void init() { //初始化方法,在开始新局游戏时调用 huihe = 0; //回合归零 score = 0; //分数归零 isRedWin = 1; //初始化两方胜利记录 isWhiteWin = 1; point = new int[][] { { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, //初始化棋盘数据 { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 10, 0, 0, 0, 0, 0, 11, 0 }, { 12, 0, 13, 0, 14, 0, 15, 0, 16 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 28, 0, 29, 0, 30, 0, 31, 0, 32 }, { 0, 26, 0, 0, 0, 0, 0, 27, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 17, 18, 19, 20, 21, 22, 23, 24, 25 } }; } …//省略部分代码 }  代码贴士  checkWin():该方法分别搜索游戏双方的主将,如果有一方失去主将,则另一方胜利。 ·210· 第 10 章 手机网络游戏(J2ME+Servlet 实现) � moveChess():该方法将根据用户的操作更改棋子的位置,然后调用 checkWin()方法,判断此次走棋是否导致 另一方失败。 � init():该方法用于初始化新一局游戏。它将执行清除胜负记录、回合数、复位棋盘操作。  注意:在程序中所描述的白色象棋棋子在后期美工设计时,为使界面美观,被设计成黑色的棋子。 10.5.4 创建 Desk 公共类 服务器端的Desk公共类是游戏桌面的定义类,该类包含了游戏桌面的编号、玩家数量、游戏回合 局数等属性,另外该类还包括Umpire 对象、Player 对象、Server 对象等属性,其中 Server 对象是服务器 的主程序,它负责信息的接收、发送和处理等业务。Desk公共类的属性声明与初始化的关键代码 如 下: 例程 10 代码位置:光盘\TM\10\XiangQiServer\src\com\lzw\Desk.java public class Desk { private int ID; //桌子 ID private Player[] players; //玩家数组 private int NUM = 2; //玩家数量 private Player banker = null; //先手 private int bankerID = 0; //先手 ID private Umpire umpire; //棋盘记录 private int game = 0; //游戏局数 private int score = 0; //分数 Server server; //服务器信息处理对象 public Desk() { game = 0; //初始化游戏局数 server = new Server(); //初始化信息处理对象 umpire = new Umpire(); //初始化棋盘记录对象 players = new Player[NUM]; //初始化玩家数组 banker = null; //初始化先手 bankerID = 0; //初始化先手编号 for (int i = 0; i < NUM; i++) { players[i] = null; //初始化同一桌面的玩家 } } public void init() { //桌面的初始化方法 banker = null; bankerID = 0; game = 0; umpire.init(); //初始化棋盘记录对象 } Desk公共类将控制游戏的初始化、开始、重新开始、游戏结束、走棋等游戏中的业务逻辑,这些业务 逻辑有不同的方法实现。关键代码如下: ·211· Java 项目开发全程实录 例程 11 代码位置:光盘\TM\10\XiangQiServer\src\com\lzw\Desk.java public void reset(){ //桌面复位方法 umpire.init(); for(int i=0;i= NUM) return false; return players[pos] == null; } public int getPlayerSeat(Player p) //返回玩家座位 { for (int i = 0; i < NUM; i++) { if (players[i] == null) continue; if (players[i].equals(p)) //判断指定玩家和座位上的玩家是否为同一个玩家 return i; } return -1; } public void setPlayer(int pos, Player n) { //设定玩家 n 坐在 pos 座位上 if (pos >= NUM) return; players[pos] = n; } public void removePlayer(Player p) { //移除玩家 p for (int i = 0; i < NUM; i++) { if (players[i] == null) continue; else if (players[i].equals(p)) players[i] = null; } } Desk公共类在管理游戏进度、规则、走棋记录等操作时,需要向玩家发送通知信息,这些信息需要 分别发送给所有玩家、单个玩家和除自己以外的其他玩家。这就需要编写不同的消息发送方法。关键代 码如下: 例程 13 代码位置:光盘\TM\10\XiangQiServer\src\com\lzw\Desk.java public void sendMessageToAll(String mes) { //发送信息到所有玩家 for (int i = 0; i < NUM; i++) if (players[i] != null) sendMessage(players[i], mes); } public void sendMessageToOther(Player player, String message) { //发送信息到其他玩家 for (int i = 0; i < NUM; i++) { if (players[i] != null && !players[i].equals(player)) //判断接收信息的玩家是否是自己 ·213· Java 项目开发全程实录 sendMessage(players[i], message); } } public void sendMessage(Player p, String m) { //发送信息到单个玩家的方法 server.sendMessage(p, m); } public void sendBankerInfo() { //发送象棋先手信息 sendMessageToAll("bankerInfo:" + bankerID); } } 10.6 游戏模块设计 10.6.1 游戏模块概述 手机的游戏模块包括界面设计、规则算法、按键处理等。对于手机游戏来说,界面要根据游戏所针 对的客户群体来设计,只有使客户群体接受游戏界面,游戏产品才能拥有更好的卖点。例如,针对白 领人士,需要制作适合 30岁以上的,集稳重、智慧、精干于一体的有些类似办公的界面,界面要简洁, 不需要太多的颜色装饰。规则算法是游戏公平和完整性的保障。按键处理负责游戏中的具体操作,例如 走棋、选棋等。游戏模块的界面如图 10.10 所示。 图 10.10 游戏界面 10.6.2 游戏模块技术分析 Canvas是MIDP 提供的低级用户界面类。和高级用户界面相比,Canvas拥有更大的灵活性。由于 Canvas 不提供任何现成的可视组件,所以要在 Canvas上显示图形或者文本,都必须通过 Graphics类 ·214· 第 10 章 手机网络游戏(J2ME+Servlet 实现) 绘制出来。如果使用高级用户界面,不但界面死板无法更改,而且也缺少相应的灵活性,不能用于开 发游戏。因此,使用低级用户界面,开发人员可以获得完全的界面控制能力,并能精确地控制每一个 像素的位置,在游戏开发中这是必不可少的。Canvas类定义的常用方法如表 10.1 所示。 表 10.1 Canvas 类定义的常用方法 方 法 名 称 说 明 paint 绘图方法,用于绘制游戏界面 repaint 重新执行绘图方法 isDoubleBuffered 判断是否支持双缓存技术 getKeyCode 获取指定动作对应的按键代码 10.6.3 棋盘绘制模块实现过程 (1)游戏界面中最重要的就是棋盘界面,包括棋盘和棋子的大小、颜色、棋子布局位置等多个属 性,所以定义棋盘绘制模块的属性是首要任务。创建 GameCanvas类,该类必须继承 Canvas类成为游 戏界面的画板,游戏中的所有事务,都是在这个画板上绘制的。另外,该类还需要实现 CommandListener接口来处理软键按钮的事件处理,在该类中声明游戏中需要的各种属性。关键代码如 下: 例程 14 代码位置:光盘\TM\10\xiangqi\src\com\lzw\GameCanvas.java public class GameCanvas extends Canvas implements CommandListener { protected Game game; //游戏主类对象 String color = ""; protected int rightSpace; //屏幕右侧预留的空间 protected int x; //棋盘输出的坐标 private boolean myTurn = false; protected int gridWidth; //每个棋格的边长 protected int mapWidth, canvasW; //棋盘的宽度和画布的宽度 protected int a, b, c, d; protected int chessR; //棋子的半径 private int desknum = -1; //桌子序号 private int seatPos = -1; //座位序号 private boolean banker = false; protected int selectedX, selectedY; //选择框在棋盘格局上的 x,y位置 protected static int i, j; protected int m, n, p; //记录开始的选择框位置和在数组中的位置 protected String q;//记住word[selectedX][selectedY] protected int guard, guard1, guard2, g, g1; //标记 FIRE 被按了多少次 protected static int turnWho; //表示该谁走了 protected static int isRedWin; //红棋胜利 protected static int isWhiteWin; //白棋胜利 private Client client; //消息管理对象 ·215· Java 项目开发全程实录 protected Command exitCmd, start, ok; //软键按钮 private int point[][]; //棋子位置数组 protected String[][] chess; //棋子名称数组 private int chessSelColor; //选择棋子的颜色 private int backColor; //棋盘背景色 private int charColor; //棋子汉字颜色 private int lineColor; //棋盘线的颜色 private int borderColor; //楚河汉界的颜色 private int selBorderColor; //选择棋子的边框色 private int blackChees; //黑棋
/
本文档为【手机网络游戏】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索