Game.java
继承midlet
* 游戏程序的入口
* 展示玩家列表playerList
* 初始化NetClient网络通信类
* 发送相关的命令:坐下、开始、结束等命令
* 更新玩家列表
* 启动mygameCanvas, 启动游戏的画布和逻辑处理
NetClient.java
负责:
* 手机客户端的连接通信模块
* 负责发送数据到服务端
* 接收服务端的消息
* 解析接收到的消息
* 调用相应方法进行业务处理
继承midlet
* 游戏程序的入口
* 展示玩家列表playerList
* 初始化NetClient网络通信类
* 发送相关的命令:坐下、开始、结束等命令
* 更新玩家列表
* 启动mygameCanvas, 启动游戏的画布和逻辑处理
package newclient;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
/**
*
* @author sean
* 游戏程序的入口
* 展示玩家列表playerList
* 初始化NetClient网络通信类
* 发送相关的命令:坐下、开始、结束等命令
* 更新玩家列表
* 启动mygameCanvas, 启动游戏的画布和逻辑处理
*/
public class Game extends MIDlet implements CommandListener {
private NetClient client;
public static Display display;
private MyGameCanvas canvas;
private List playerList;
private int[][] desks;
private int trySeat, tryDesk;
private Command okCommand;
public static int playerId = 0;
/**
* 构造方法
* 画出第一个界面,玩家列表
* 初始化网络通信对象
*/
public Game() {
display = Display.getDisplay(this);
playerList = new List("桌面列表", 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 NetClient(this);
}
protected void startApp() throws MIDletStateChangeException {
}
protected void pauseApp() {
}
protected void destroyApp(boolean p0) throws MIDletStateChangeException {
//玩家结束游戏,当前客户端销毁
client.sendMessage(Message.EXIT_REQ, "exit");
display.setCurrent(null);
}
/**
* 命令判断和执行
* 退出时发送退出消息,执行销毁
* 确定按键,获得具体的桌子和座位号,发送消息
*/
public void commandAction(Command c, Displayable s) {
if (c.getCommandType() == Command.EXIT) {
client.sendMessage(Message.EXIT_REQ,"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;
else
trySeat = 1;
tryDesk = d;
if (canvas == null){
canvas = new MyGameCanvas(this, client);
}
else
canvas.init();
//发送坐下命令和内容服务器端
client.sendMessage(Message.TAKE_REQ, "take," + d + "," + trySeat);
}
} catch (Exception exc) {
System.out.println("Error parseInt");
exc.printStackTrace();
}
}
}
}
public MyGameCanvas getCanvas() {
return canvas;
}
public void initialize() {
canvas = null;
}
/**
* 座位坐下动作
*/
public void takeSeat() { // 处理落座信息的方法
if( canvas == null){
canvas = new MyGameCanvas(this, client);
}
else{
canvas.init();
}
canvas.setSeatPos(trySeat);
canvas.setDeskIndex(tryDesk);
//界面切换到游戏界面,等待开始指令
display.setCurrent(canvas);
}
/**
* 解析服务器的座位信息,更新当前的座位界面
* 更新桌面
* @param str
*/
public void updateDesk(String str) { // 更新桌面
System.out.println("更新桌面: " + str);
int index1 = str.indexOf(",");
int index2 = str.indexOf(":", index1 + 1);
int index3 = str.indexOf(",", index2 + 1);
try {
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) {
}
}
/**
* 获得playerList的列表
* @return
*/
public List getPlayerList() {
return playerList;
}
/**
* 根据接收消息设置座位
*
* @param string
*/
public void setDesks(String string) {
System.out.println("setDesks: " + string);
for (int i = 0; i < playerList.size(); i++)
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++;
}
}
}
NetClient.java
负责:
* 手机客户端的连接通信模块
* 负责发送数据到服务端
* 接收服务端的消息
* 解析接收到的消息
* 调用相应方法进行业务处理
/**
*
*/
package newclient;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.io.SocketConnection;
/**
* @author sean
* 手机客户端的连接通信模块
* 负责发送数据到服务端
* 接收服务端的消息
* 解析接收到的消息
* 调用相应方法进行业务处理
*
*
*/
public class NetClient implements Runnable {
Game game;
SocketConnection conn;
public static int playerId = 0;
public static Queue inDataList = new Queue(); // 输入消息队列
public static Queue outDataList = new Queue(); // 输出消息队列
/**
* 构造函数 清空输入流队列 网络连接 发送注册消息,通知服务器客户端的连接
*
* @param game
*/
public NetClient(Game game) {
// TODO Auto-generated constructor stub
this.game = game;
// 消息输入流的初始化
inDataList.clear();
outDataList.clear();
// 连接服务器端
connect();
// TODO 此处的发送消息,有些问题,发送消息的内容需要修改, 修改为:发送空消息
sendMessage(Message.REGISTER_REQ, "");
System.out.println("发送注册数据成功");
new Thread(this).start();
}
String serverAddr = "socket://127.0.0.1:9999";
private DataInputStream dis;
private DataOutputStream dos;
/**
* 连接服务器端 获得输入输出输入流
*
* @return
*/
private boolean connect() {
// TODO Auto-generated method stub
try {
conn = (SocketConnection) Connector.open(serverAddr,
Connector.READ_WRITE);
if (conn != null) {
dis = new DataInputStream(conn.openInputStream());
dos = new DataOutputStream(conn.openOutputStream());
return true;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
int count = 0;
/**
* 负责消息的组织
* 放入outdatalist
* 1. 打包msg到输出队列
* 2. 启动线程发送队列中的数据
* 3. 线程是否会自动关闭,长时间玩下来是否导致内存溢出?
* @param cmdType
* @param msg
*/
public void sendMessage(int cmdType, String msg) {
// TODO 1. 打包msg到输出队列 2. 启动线程发送队列中的数据 3. 线程是否会自动关闭,长时间玩下来是否导致内存溢出
System.out.println(count + "client ready to send msg: " + cmdType);
Message message = new Message(cmdType,playerId, msg);
outDataList.push(message);
System.out.println(count + "client ready to send msg: " + msg);
System.out.println(count + "outDataList size: " + outDataList.size());
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
sendData();
}
}).start();
}
/**
* 发送数据到客户端
* 去除队列中的第一个元素,发送数据
*/
private void sendData() {
// TODO Auto-generated method stub
System.out.println("outdatalist size: " + outDataList.size());
if(outDataList.isEmpty()){
return;
}
int size = outDataList.size();
//循环遍历消息
for(int i=0; i<size; i++){
Message msg = (Message) outDataList.pop();
try {
dos.writeInt(msg.getCmdType());
System.out.println("发送消息cmdType: " + msg.getCmdType());
dos.writeInt(msg.getPlayerId());
System.out.println("发送消息playerId: " + msg.getPlayerId());
dos.writeInt(msg.getMessage().getBytes().length);
dos.write(msg.getMessage().getBytes());
System.out.println("发送消息: " + msg.getMessage());
System.out.println("发送消息完成************************");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 线程体
* 负责客户端数据接收
* 逻辑处理
*/
public void run() {
// TODO Auto-generated method stub
while (true) {
// 读取服务器端数据
recieveData();
// 逻辑处理
handleLogic();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 读取来自服务器的数据 首先判断是否有
*
* @return
*/
private void recieveData() {
// TODO Auto-generated method stub
if (dis == null) {
return;
}
int cmdType = 0;
try {
// 死循环,不停读取输入流的内容,分析包头,然后分发到不同方法去处理
if (dis.available() == -1) {
return;
}
// 读取数据流,打包成message对象,放入队列
cmdType = dis.readInt();
System.out.println("client: cmdType is" + cmdType);
playerId = dis.readInt();
// 读取消息的长度,构建byte[], 读取消息内容
int len = dis.readInt();
byte[] tempData = new byte[len];
dis.read(tempData);
String str = new String(tempData);
Message msg = new Message(cmdType, playerId, str);
if (msg != null) {
inDataList.push(msg);
}
} catch (Exception e) {
// TODO: 读取数据流错误处理
}
}
/**
* 读取消息队列的内容,根据cmdType,进行逻辑处理
*/
private void handleLogic() {
// TODO 判断消息队列是否为空,得到最新的消息,解析后处理
if (inDataList.isEmpty()) {
return;
}
Message msg = (Message) inDataList.pop();
if (msg == null) {
return;
}
int cmdType = msg.getCmdType();
switch (cmdType) {
// 桌子反馈信息,玩家第一次注册成功后返回信息
case Message.DESKS_RESP:
handleDesksInfo(msg);
break;
// 坐下之后的逻辑处理
case Message.UPDATEDESK_RESP:
handleUpdateDesk(msg);
break;
case Message.GAME_RESP:
handleGameResp(msg);
break;
case Message.EXIT_REQ:
break;
default:
break;
}
}
/**
* 处理桌子的信息
*
* @param msg
*/
private void handleDesksInfo(Message msg) {
// TODO 处理服务器端返回的桌子信息
String data = msg.getMessage();
System.out.println("client recieved desks: " + data);
game.setDesks(data);
}
/**
*
* @param msg
*/
private void handleUpdateDesk(Message msg) {
// TODO 读取玩家id
int playerId = msg.getPlayerId();
System.out.println("client playerId: " + playerId);
game.takeSeat();
}
/**
* 处理游戏过程中的命令交互
* move等
* @param msg
*/
private void handleGameResp(Message msg) {
// TODO 得到具体的消息,
String str = msg.getMessage();
System.out.println("client recieve game message " + str
+ System.currentTimeMillis());
if (game.getCanvas() != null) {
game.getCanvas().receiveMessage(str);
}
}
}