【Android】简单的“云游戏”——推箱子第一关

简单介绍

用“云”的理念实现了简单的推箱子游戏,使用Socket和服务器通信。每次客户端(即安卓端)将操作命令发送给服务端,服务端进行判断等处理,生成一张图片返回给客户端。也就是客户端只是发送命令后显示服务端传回来的图片,逻辑的判断等都交给了服务端。

界面展示

客户端进入后可以用上下左右来操作,胜利有胜利画面,做的非常简陋,按两下返回键退出。
【Android】简单的“云游戏”——推箱子第一关_第1张图片
【Android】简单的“云游戏”——推箱子第一关_第2张图片

服务端

服务端是java application实现的,使用ServerSocket类,在线程中等待客户端发来请求,进行处理并返回图片。这里使用了二维数组来存储,程序的修改性不太好,写死了,采用了8乘8的矩阵,注释中有不同的数字代表什么含义,每次操作进行判断,并移动小人和箱子的位置,主要代码如下:
class ServerThread extends Thread {
	private Socket socket;
	BufferedImage image;
	int imageWidth = 400;// 图片的宽度
	int imageHeight = 400;// 图片的高度
	private int x = imageWidth / 2;
	private int y = imageHeight / 2;
	BufferedImage man = null;
	BufferedImage road = null;
	BufferedImage box = null;
	BufferedImage block = null;
	BufferedImage aim = null;
	BufferedImage win = null;
	//小人起始位置
	int mani = 4;
	int manj = 4;
	//障碍为0,道路为1,小人为2,箱子为3,目标为4,空为-1
	private static int[][] matrix = {{-1, -1, 0, 0, 0, -1, -1, -1},
														{-1, -1, 0, 4, 0, -1, -1, -1},
														{-1, -1, 0, 1, 0, 0, 0, 0},
														{0, 0, 0, 3, 1, 3, 4, 0},
														{0, 4, 1, 3, 2, 0, 0, 0},
														{0, 0, 0, 0, 3, 0, -1, -1, -1},
														{-1, -1, -1, 0, 4, 0, -1, -1},
														{-1, -1, -1, 0, 0, 0, -1, -1}};
	public ServerThread(Socket s) {
		System.out.println("constructor ServerThread...");
		this.socket = s;
		try {
			man = ImageIO.read(new File("images/man.png"));
			road = ImageIO.read(new File("images/road.jpg"));
			box = ImageIO.read(new File("images/box.jpg"));
			block = ImageIO.read(new File("images/block.jpg"));
			aim = ImageIO.read(new File("images/aim.jpg"));
			win = ImageIO.read(new File("images/win.png"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static boolean judgeWin()
	{
		if(matrix[1][3]==3 && matrix[3][6]==3 && matrix[4][1]==3 && matrix[6][4]==3)
		{
			return true;
		}
		return false;
	}
	public static boolean canGo(int x, int y)
	{
		if(matrix[x][y]==1 || matrix[x][y]==4)
		{
			return true;
		}
		return false;
	}
	 public void run() {
		try {
			// 创建一个serversocket对象,并让他在Port端口监听
			InputStream in = socket.getInputStream();
			OutputStream out = 	socket.getOutputStream();
			while (true) {
				// 调用serversocket的accept()方法,接收客户端发送的请求
				String msg = readString(in);
				System.out.println("msg:" + msg);
				if(msg.equals("right")){
					if(manj<7)//防止越界
					{
						if(canGo(mani, manj+1))
						{
							matrix[mani][manj] = 1;
							matrix[mani][++manj] = 2;
						}
						else if(manj <6 && matrix[mani][manj+1]==3 && canGo(mani, manj+2))
						{
							//应该区分aim和road,如果在aim上离开应该还是aim不该是1,
							//但第一关不存在这种情况
							matrix[mani][manj++] = 1;
							matrix[mani][manj] = 2;
							matrix[mani][manj+1] = 3;
						}
					}
				}
				else if(msg.equals("left")){
					if(manj>0)//防止越界
					{
						if(canGo(mani, manj-1))
						{
							matrix[mani][manj] = 1;
							matrix[mani][--manj] = 2;
						}
						else if(manj > 1 && matrix[mani][manj-1]==3 && canGo(mani, manj-2))
						{
							//应该区分aim和road,如果在aim上离开应该还是aim不该是1,
							//但第一关不存在这种情况
							matrix[mani][manj--] = 1;
							matrix[mani][manj] = 2;
							matrix[mani][manj-1] = 3;
						}
					}
				}
				else if(msg.equals("up"))
				{
					if(mani>0)//防止越界
					{
						if(canGo(mani-1, manj))
						{
							matrix[mani][manj] = 1;
							matrix[--mani][manj] = 2;
						}
						else if(mani > 1 && matrix[mani-1][manj]==3 && canGo(mani-2, manj))
						{
							//应该区分aim和road,如果在aim上离开应该还是aim不该是1,
							//但第一关不存在这种情况
							matrix[mani--][manj] = 1;
							matrix[mani][manj] = 2;
							matrix[mani-1][manj] = 3;
						}
					}
				}
				else if(msg.equals("down"))
				{
					if(mani<7)//防止越界
					{
						if(canGo(mani+1, manj))
						{
							matrix[mani][manj] = 1;
							matrix[++mani][manj] = 2;
						}
						else if(mani <6 && matrix[mani+1][manj]==3 && canGo(mani+2, manj))
						{
							//应该区分aim和road,如果在aim上离开应该还是aim不该是1,
							//但第一关不存在这种情况
							matrix[mani++][manj] = 1;
							matrix[mani][manj] = 2;
							matrix[mani+1][manj] = 3;
						}
					}
				}
				drawImage();
				FileInputStream fin = new FileInputStream("test.jpg");
				int avl = fin.available();
				writeInt(out, avl);
//				System.out.println("new byte");
				byte[] data = new byte[1024];
//				System.out.println("new byte over");
				int readNum, writeNum = 0;
				while (writeNum < avl) {
					out.flush();
					readNum = fin.read(data);
					// 将图片数据写入到输出流中
					out.write(data,0,readNum);
					writeNum += readNum;
//					System.out.println("readnum = "+readNum);
				}
//				System.out.println("Write over");
				out.flush();
				fin.close();
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	void createImage(String fileLocation) {
		try {
			FileOutputStream fos = new FileOutputStream(fileLocation);
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
			encoder.encode(image);
			bos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void drawImage() {
		image = new BufferedImage(imageWidth, imageHeight,
				BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, imageWidth, imageHeight);
		for(int i=0; i<8; i++)
		{
			for(int j=0; j<8; j++)
			{
				switch(matrix[i][j])
				{
				case 0:
					if(block!=null)
					g.drawImage(block, j*50, i*50, 50, 50, null);
					break;
				case 1:
					if(road!=null)
					g.drawImage(road, j*50, i*50, 50, 50, null);
					break;
				case 2:
					if(man!=null)
					g.drawImage(road, j*50, i*50, 50, 50, null);
					g.drawImage(man, j*50, i*50, 50, 50, null);
					break;
				case 3:
					if(box!=null)
					g.drawImage(box, j*50, i*50, 50, 50, null);
					break;
				case 4:
					if(aim!=null)
					g.drawImage(aim, j*50, i*50, 50, 50, null);
					break;
				}
			}
		}
		if (win != null && judgeWin()) {
			System.out.println("win win win!!!");
			g.drawImage(win, 130, 130, 200, 200, null);
		}
		g.dispose();
		createImage("test.jpg");
	}
	public static int readInt(InputStream in)throws Exception{
		byte[] b = new byte[4];
		in.read(b);
		int i = 0;
		for(int j = 3 ;j >= 0 ; --j){
			i = i << 8;
			i += b[j] & 0xff;
		}
		return i;
	}
	public static String readString(InputStream in)throws Exception{
		int t = readInt(in);
		byte[] b = new byte[t];
//		System.out.println("t = "+t);
		in.read(b);
		return new String(b);
	}
	public static void writeString(OutputStream out, String msg)throws Exception{
		byte[] b = msg.getBytes();
		writeInt(out, b.length);
		out.write(b);
	}
	public static void writeInt(OutputStream out, int it)throws Exception{
		byte[] b = new byte[4];
		for(int i = 0 ; i < 4 ; ++i){
			b[i] = (byte)it;
			it >>= 8;
		}
		out.write(b);
	}
}

客户端

客户端刚开始有一张初始图片,上下左右方向键点击时发送命令给服务器端,并等待发回图片,并将imgeview设置为新的图片,采用post方法在线程中更改图片,主要代码如下:
public class ClientSocket implements Runnable {
	private String ip;
	private int port;
	private Socket socket = null;
	OutputStream out = null;
	InputStream in = null;
	ImageView image = null;

	public ClientSocket(String ip, int port, ImageView img) {
		this.ip = ip;
		this.port = port;
		this.image = img;
	}

	/**
	 * 创建socket连接
	 * 
	 * @throws Exception
	 *             exception
	 */
	public void CreateConnection() {
		try {
			Log.e("out", ip + " " + port);
			socket = new Socket(ip, port);
			Log.e("out", "连接服务器成功!");
			in = socket.getInputStream();
			out = socket.getOutputStream();
			new Thread(this).start();
		} catch (Exception e) {
			Log.e("out", "连接服务器失败!");
			e.printStackTrace();
		}
	}

	public void sendMessage(String msg) throws Exception {
		writeString(out, msg);
		Log.e("out", msg);
	}

	public static void writeString(OutputStream out, String msg)
			throws Exception {
		byte[] b = msg.getBytes();
		Log.e("abc", "len = " + b.length);
		writeInt(out, b.length);
		out.write(b);
	}

	public static void writeInt(OutputStream out, int it) throws Exception {
		byte[] b = new byte[4];
		for (int i = 0; i < 4; ++i) {
			b[i] = (byte) it;
			it >>= 8;
		}
		out.write(b);
	}

	public void shutDownConnection() {
		try {
			if (out != null)
				out.close();
			if (in != null)
				in.close();
			if (socket != null)
				socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static int readInt(InputStream in) throws Exception {
		byte[] b = new byte[4];
		int len = in.read(b);
		Log.e("abc", "read len = " + len);
		int i = 0;
		for (int j = 3; j >= 0; --j) {
			i = i << 8;
			i += b[j] & 0xff;
		}
		return i;
	}

	public static String readString(InputStream in) throws Exception {
		int t = readInt(in);
		byte[] b = new byte[t];
		in.read(b);
		return new String(b);
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			// 不断监听输入流的数据情况
			Log.e("abc", "came in run");
			while (true) {
				// 当流中有数据时,读取数据并进行处理

				Log.e("abc", "read");
				// 创建data数组并将流中数据读取到数组中
				// Log.e("abc","mes "+in.readUTF());
				int t = readInt(in);
				Log.e("abc", "datasize=" + t);
				byte[] data = new byte[t];// 注此处同样没有处理图片大小超过int的范围的情况
				Log.e("abc", "new over");
				int readNum = 0;
				while (readNum < t) {
					int size = in.read(data, readNum, t - readNum);
					readNum += size;
				}
				Log.e("abc", "size = " + readNum);
				// 根据读到的文件数据创建Bitmap对象bitmap,因为将要在后面的内部类中使用bitmap,所以定义为
				final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
						data.length);
				// 将图片显示到ImageView上
				// 此处由于view中的组件都是线程不安全的,使用android提供的这个办法处理(详见下文“附2”)
				image.post(new Runnable() {
					public void run() {
						// 将bitmap显示到界面上
						image.setImageBitmap(bitmap);
					}
				});
				// 线程休息1s
//				Thread.sleep(1000);
			}
		} catch (Exception e) {
			Log.e("abc", "exit");
			e.printStackTrace();
		}
	}
}

工程地址

http://download.csdn.net/detail/felicitia/5575559

你可能感兴趣的:(移动开发,java,网络)