24h購物| | PChome| 登入
2013-05-17 23:06:36| 人氣5,025| 回應0 | 上一篇 | 下一篇

[JAVA][期末專題] 聊天室製作

推薦 0 收藏 0 轉貼0 訂閱站台





本次專題問題重點:

  • socket server 處理流程
  • 美工
  • JApplet 加載圖片不完整

1. socket server 處理流程
在 ServerThread.class 中,會等待新的顧客(Client) 開啟網路連線,
當沒有新的使用者時,則會停留在 Socket socket = serverSocket.accept();,
並且持續等待,等到接受到一個新的網路連線時,判斷後決定是否保留,
若要保留則會丟進 ClientThread.class 去負責個別的顧客傳送過來的值,
而這個顧客就不會再次在 ServerThread.class 中被處理到。

2. 美工

後來除了上圖的範例圖,又再次進行了修改(但並不在下方的程式碼中),
增加了一些小道具,由於為了使圖片重疊時不要太突兀,因此採用有透明效果的 .png 檔,在 drawImage() method 中不用擔心是支援這個功能的。

3. JApplet 加載圖片不完整

一般在 Eclipse 中進行 debug 動作時,並不會發生這種加載不完全的情況,而當檔案壓縮成 .jar 時,就很容易發生這種問題。因此,用的方法是
    public void loadImages() {
        tracker = new MediaTracker(this);
        try {
            for (int i = 0; i < imgNames.length; i++) {
                img[i] = getImage(getDocumentBase(), imgNames[i]);
                tracker.addImage(img[i], i);
            }
        } catch (Exception e) {
            System.err.println("Error loading image");
        }

        try {
            tracker.waitForAll();
        } catch (Exception e) {
            System.err.println("Unknown error while loading images");
        }
    }

當圖片檔案大一點時,由於其他讀圖的方法可能是額外的線程,因此可能會被突如其來的指令中斷,進而發生了加載不完整的情況。使用 getImage() 去做,而
getDocumentBase() 則是 JApplet 裡頭的 method,得到當前的路徑,並且在路徑中去找圖片的檔名。則用 tracker 監聽有沒有發生圖片讀入錯誤。

而在 MServer.class 的地方也是會在壓成 .jar 發生這個問題,這裡(JFrame)由於沒有

getDocumentBase() method, 因此我們用                
img[i] = java.awt.Toolkit.getDefaultToolkit().getImage(               imgNames[i]);

代替之。所以基本上圖片都要放在 .class 同一個資料夾下,但在 Eclipse 中 debug,默認路徑則是在 Project 的資料夾(也就是與 bin, src, .settings 同一個資料夾)中。壓成 .jar 時,記得要將圖片一起壓入(這一點我還不確定。),壓縮有封包的類似語法如下:

jar cvfm MServer.jar manifest.mf Server\*.class Server\*.png Server\*.jpg


4. 圖檔製作

網路上抓取的圖片不一定都是 .png 檔,更別說是透明處理,因此我這裡使用 PhotoImpact 12,很陽春簡單的初階使用者可以學的,開啟新檔案-選擇透明背景-將要的圖片複製貼上-點選右鍵-內容-透明度、透明色彩、RGB 容許誤差,這樣調一調就可以上場了。
最好把檔案用小的一點,畢竟真正看得到的部分還只有一小塊,用小一點跑得就比較快。

5. 遊戲構思


"火"轟炸當前方向前十個消失
"水"加速其自身速度
"冰"放慢其自身速度,
"陽光"轟炸當前為中心的 5*5 正方形。



package Server;

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import java.io.BufferedInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;

import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;

import java.lang.Thread;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentListener;
import java.awt.event.AdjustmentEvent;

public class MServer {
    // <UI>
    private JFrame frame; // main windows
    private JTextArea contentArea; // chat message post
    private JTextField txtMsg; // user post message
    private JTextField txtPort; // server open [port number]
    private JTextField txtMax; // max login users limited
    private JButton btnStart; // open server
    private JButton btnStop; // close server
    private JButton btnSend; // send [txtMsg]
    private JPanel northPanel;
    private JPanel southPanel;
    private JPanel chatPanel;
    private GPanel gamePanel;
    private JScrollPane leftPane;
    private JScrollPane rightPane;
    private JSplitPane centerSplit; // page windows
    private JList userList;
    private DefaultListModel listModel;
    // </UI>
    // <Socket&Server>
    boolean serverRunning = false;
    private ServerSocket serverSocket;
    private ServerThread serverThread;
    ArrayList<ClientThread> clientList;
    // </Socket&Server>
    // <Game>
    Timer timer;
    private boolean gameRunning = false;
    private int RTeamX, RTeamY, RTeamD, RTeamDinv;// U, D, L, R
    private int GTeamX, GTeamY, GTeamD, GTeamDinv;

    // </Game>

    public MServer() {
        frame = new JFrame("MServer - Phi");
        contentArea = new JTextArea("");
        txtMsg = new JTextField();
        txtMax = new JTextField("10"); // default users limited = 10
        txtPort = new JTextField("2047"); // default port number = 2047
        btnStart = new JButton("On"); // open server
        btnStop = new JButton("Off"); // close server
        btnSend = new JButton("↵ ");
        northPanel = new JPanel();
        southPanel = new JPanel(new BorderLayout());
        chatPanel = new JPanel();
        gamePanel = new GPanel();
        listModel = new DefaultListModel();
        userList = new JList(listModel);
        leftPane = new JScrollPane(userList);
        rightPane = new JScrollPane(contentArea);

        contentArea.setEditable(false);
        contentArea.setBackground(Color.BLACK);
        contentArea.setForeground(Color.GREEN);
        //contentArea.setFont(new Font("Calibri", Font.ITALIC, 20));
        contentArea.setFont(new Font("微軟正黑體", Font.ITALIC, 20));

        btnStop.setEnabled(false);

        userList.setBackground(Color.BLACK);
        userList.setForeground(Color.GREEN);
        //userList.setFont(new Font("Calibri", Font.ITALIC, 20));
        userList.setFont(new Font("微軟正黑體", Font.ITALIC, 20));

        northPanel.setLayout(new GridLayout(1, 6));
        northPanel.setBorder(new TitledBorder("Setting"));
        northPanel.add(new JLabel("User Limit"));
        northPanel.add(txtMax);
        northPanel.add(new JLabel("Port Number"));
        northPanel.add(txtPort);
        northPanel.add(btnStart);
        northPanel.add(btnStop);

        southPanel.setLayout(new BorderLayout());
        southPanel.setBorder(new TitledBorder("Input"));
        southPanel.add(txtMsg, BorderLayout.CENTER);
        southPanel.add(btnSend, BorderLayout.EAST);

        leftPane.setBorder(new TitledBorder("User List"));

        rightPane.setBorder(new TitledBorder("Room Message"));

        centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane,
                rightPane);
        centerSplit.setDividerLocation(100);

        chatPanel.setLayout(new BorderLayout());
        chatPanel.add(northPanel, BorderLayout.NORTH);
        chatPanel.add(centerSplit, BorderLayout.CENTER);
        chatPanel.add(southPanel, BorderLayout.SOUTH);

        frame.setLayout(new GridLayout(2, 1));
        frame.add(gamePanel);
        frame.add(chatPanel);
        frame.setSize(800, 650);
        frame.setResizable(false);

        // <setting listener>
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        rightPane.getVerticalScrollBar().addAdjustmentListener(
                new AdjustmentListener() {
                    JScrollBar sb = rightPane.getVerticalScrollBar();

                    public void adjustmentValueChanged(AdjustmentEvent e) {
                        sb.setValue(sb.getMaximum());
                    }
                });
        txtMsg.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                send();// when touch [Enter] key
            }
        });
        btnSend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                send();
            }
        });
        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (serverRunning) {
                    JOptionPane.showMessageDialog(frame, "Server opened.",
                            "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                try {
                    int maxUser, portNumber;
                    maxUser = Integer.parseInt(txtMax.getText());
                    portNumber = Integer.parseInt(txtPort.getText());
                    if (maxUser < 0)
                        throw new Exception("maxUser < 0");
                    if (portNumber < 0)
                        throw new Exception("portNumber < 0");
                    openServer(maxUser, portNumber);
                } catch (Exception err) {
                    JOptionPane.showMessageDialog(frame, "Setting error.",
                            "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        btnStop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                closeServer();
            }
        });
        // </setting listener>
        frame.setVisible(true);
    }

    public void openServer(int maxUser, int portNumber)
            throws java.net.BindException {
        try {
            serverSocket = new ServerSocket(portNumber);
            serverThread = new ServerThread(serverSocket, maxUser);
            serverThread.start();
            clientList = new ArrayList<ClientThread>();
            serverRunning = true;
            contentArea.append("System> Server open.\r\n");
            btnStart.setEnabled(false);
            btnStop.setEnabled(true);
            txtMax.setEditable(false);
            txtPort.setEditable(false);
            timer = new Timer();
            timer.schedule(new GameHeart(), 1000, 20000);
        } catch (java.net.BindException e) {
            throw new java.net.BindException("Change port number.");
        } catch (Exception ee) {
            throw new java.net.BindException(ee.getMessage());
        }
    }

    public void closeServer() {
        try {
            if (serverThread != null)
                serverThread.stop();
            sendServerMessage("CLOSE@");
            for (int i = 0; i < clientList.size(); i++) {
                ClientThread cl = clientList.get(i);
                cl.reader.close();
                cl.writer.close();
                cl.socket.close();
            }
            clientList.clear();
            listModel.removeAllElements();
            if (serverSocket != null)
                serverSocket.close();
            serverRunning = false;

            contentArea.append("System> Server close.\r\n");
            btnStart.setEnabled(true);
            btnStop.setEnabled(false);
            txtMax.setEditable(true);
            txtPort.setEditable(true);
            timer.cancel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void send() {// admin type message
        if (!serverRunning || clientList.size() == 0) {
            contentArea.append("Error> Send message missed." + txtMsg.getText() + "\r\n");
            txtMsg.setText(null);
            return;
        }
        String msg = txtMsg.getText();
        if (msg == null || msg.equals("")) {
            contentArea.append("Error> Empty message.\r\n");
            return;
        }
        msg = "System> " + msg + "\r\n";
        sendServerMessage("SYSTEM@" + msg); // tell all clients
        contentArea.append(msg);
        txtMsg.setText(null);
        if (contentArea.getText().length() > 262144)
            contentArea.setText(contentArea.getText().substring(131072));
    }

    public void sendServerMessage(String msg) { // tell all clients
        for (int i = clientList.size() - 1; i >= 0; i--) {
            clientList.get(i).getWriter().println(msg);
            clientList.get(i).getWriter().flush();
        }
    }

    class ServerThread extends Thread {// get clients
        private ServerSocket serverSocket;
        private int maxUser;

        public ServerThread(ServerSocket serverSocket, int maxUser) {
            this.serverSocket = serverSocket;
            this.maxUser = maxUser;
        }

        public void run() {
            while (true) {
                try {
                    System.out.println("X");
                    Socket socket = serverSocket.accept();
                    BufferedReader reader = new BufferedReader(
                            new InputStreamReader(socket.getInputStream()));
                    PrintWriter writer = new PrintWriter(
                            socket.getOutputStream());
                    String msg = reader.readLine();
                    if (msg == null || msg.equals(""))
                        continue;
                    System.out.println(msg);
                    StringTokenizer st = new StringTokenizer(msg, "@");
                    User user = new User(st.nextToken(), st.nextToken());
                    // <check server loading>
                    if (clientList.size() == maxUser) {
                        writer.println("E@Server too busy.\r\n");
                        writer.flush();
                        reader.close();
                        socket.close();
                        continue;
                    }
                    // </check server loading>
                    // <check same user>
                    boolean sameFlag = false;
                    for (int i = 0; i < clientList.size() && !sameFlag; i++) {
                        if (clientList.get(i).user.getName().equals(
                                user.getName()))
                            sameFlag = true;
                    }
                    if (sameFlag) {
                        writer.println("E@Change username.\r\n");
                        writer.flush();
                        reader.close();
                        socket.close();
                        continue;
                    }
                    // </check same user>
                    String teamID = st.nextToken();
                    msg = "System> " + user.getName()
                            + " has entered the room.";
                    if (teamID.equals("1"))
                        msg += "(R Team)\r\n";
                    else
                        msg += "(G Team)\r\n";
                    listModel.addElement(user.getName());
                    ClientThread client = new ClientThread(socket, user);
                    client.start();
                    clientList.add(client);
                    contentArea.append(msg);
                    sendServerMessage("ADD@" + user.getName());
                    sendServerMessage("SYSTEM@" + msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class ClientThread extends Thread {// send message to client
        private Socket socket;
        private User user;
        private BufferedReader reader;
        private PrintWriter writer;
        private boolean alive = true;
        private boolean closeFlag = false;
        private Timer timer;

        public ClientThread(Socket socket, User user) {
            try {
                this.socket = socket;
                this.user = user;
                this.reader = new BufferedReader(new InputStreamReader(
                        socket.getInputStream(), "UTF-8"));
                this.writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
                // <build user list>
                for (int i = clientList.size() - 1; i >= 0; i--)
                    writer.println("ADD@" + clientList.get(i).user.getName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            timer = new Timer();
            timer.schedule(new AliveHeart(), 1000, 10000);
        }

        class AliveHeart extends TimerTask {
            public void run() {
                System.out.println("check alive");
                if (alive == false) {// client disconnected
                    closeConnection();
                }
                alive = false;
            }
        }

        public void closeConnection() {
            try {
                String msg;
                msg = "System> " + user.getName() + " has left the room.\r\n";
                contentArea.append(msg);
                sendServerMessage("SYSTEM@" + msg);
                sendServerMessage("DELETE@" + user.getName());
                reader.close();
                writer.close();
                socket.close();
                // UI list remove
                listModel.removeElement(user.getName());
                for (int i = 0; i < clientList.size(); i++) {
                    if (clientList.get(i).user.getName().equals(user.getName())) {
                        clientList.remove(i);
                        break;
                    }
                }
                closeFlag = true;
                timer.cancel();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void run() {
            String msg;
            while (!closeFlag) {
                try {
                    msg = reader.readLine();
                    dispatcherMessage(msg);
                } catch (Exception e) {
                    //e.printStackTrace();
                }
            }
        }

        public void dispatcherMessage(String msg) {
            if (msg == null || msg.equals(""))
                return;
            StringTokenizer st = new StringTokenizer(msg, "@");// CMD@MSG....,
            String cmd = st.nextToken();
            System.out.println(msg);
            if (cmd.equals("CLOSE")) {
                closeConnection();
                return;
            }
            if (cmd.equals("A")) {
                alive = true;
                return;
            }
            // CMD@GAME@TEAM@DIR
            if (cmd.equals("T")) {
                msg = st.nextToken();
                while (st.hasMoreTokens())
                    msg += "@" + st.nextToken();
                msg = user.getName() + "> " + msg + "\r\n";
                contentArea.append(msg);
                sendServerMessage("MSG@" + msg);
                return;
            }
            if (cmd.equals("GAME")) {
                System.out.println(msg);
                cmd = st.nextToken();
                int DIR = Integer.parseInt(st.nextToken());               
                if (cmd.equals("1")) {
                    if (DIR != RTeamDinv)
                        RTeamD = DIR;
                } else {
                    if (DIR != GTeamDinv)
                        GTeamD = DIR;
                }
                System.out.println(GTeamD);
            }
        }

        public BufferedReader getReader() {
            return reader;
        }

        public PrintWriter getWriter() {
            return writer;
        }
    }

    class GameHeart extends TimerTask {
        public void run() {
            if (gameRunning == true)
                return;
            gameRunning = true;
            gamePanel.newGame();
            sendServerMessage("GAME@NEWGAME");
            RTeamX = 30;
            RTeamY = 7;
            RTeamD = 2;// U, D, L, R
            RTeamDinv = 3;
            sendServerMessage("GAME@MOVE@" + 1 + "@" + RTeamX + "@" + RTeamY);
            gamePanel.doing(RTeamX, RTeamY, 1);
            GTeamX = 7;
            GTeamY = 7;
            GTeamD = 3;
            GTeamDinv = 2;
            sendServerMessage("GAME@MOVE@" + 2 + "@" + GTeamX + "@" + GTeamY);
            gamePanel.doing(GTeamX, GTeamY, 2);
            Timer timer = new Timer();
            timer.schedule(new GameProcess(), 1000, 200);
        }
    }

    class GameProcess extends TimerTask {
        int dx[] = { 0, 0, -1, 1 };
        int dy[] = { -1, 1, 0, 0 };
        int Dinv[] = { 1, 0, 3, 2 };

        public void run() {
            if (RTeamX + dx[RTeamD] < 0
                    || RTeamX + dx[RTeamD] >= 40
                    || RTeamY + dy[RTeamD] < 0
                    || RTeamY + dy[RTeamD] >= 15
                    || gamePanel.board[RTeamX + dx[RTeamD]][RTeamY + dy[RTeamD]] != 0) {
                for (int i = 0; i < 4; i++) {
                    if (RTeamX + dx[i] < 0 || RTeamX + dx[i] >= 40)
                        continue;
                    if (RTeamY + dy[i] < 0 || RTeamY + dy[i] >= 15)
                        continue;
                    if (gamePanel.board[RTeamX + dx[i]][RTeamY + dy[i]] == 0) {
                        RTeamD = i;
                        if (Math.random() * 2 > 1)
                            break;
                    }
                }
            }
            RTeamX += dx[RTeamD];
            RTeamY += dy[RTeamD];
            RTeamDinv = Dinv[RTeamD];

            if (GTeamX + dx[GTeamD] < 0
                    || GTeamX + dx[GTeamD] >= 40
                    || GTeamY + dy[GTeamD] < 0
                    || GTeamY + dy[GTeamD] >= 15
                    || gamePanel.board[GTeamX + dx[GTeamD]][GTeamY + dy[GTeamD]] != 0) {
                for (int i = 0; i < 4; i++) {
                    if (GTeamX + dx[i] < 0 || GTeamX + dx[i] >= 40)
                        continue;
                    if (GTeamY + dy[i] < 0 || GTeamY + dy[i] >= 15)
                        continue;
                    if (gamePanel.board[GTeamX + dx[i]][GTeamY + dy[i]] == 0) {
                        GTeamD = i;
                        if (Math.random() * 2 > 1)
                            break;
                    }
                }
            }
            GTeamX += dx[GTeamD];
            GTeamY += dy[GTeamD];
            GTeamDinv = Dinv[GTeamD];
            int RFlag = gamePanel.doing(RTeamX, RTeamY, 1);
            sendServerMessage("GAME@MOVE@" + 1 + "@" + RTeamX + "@" + RTeamY);
            int GFlag = gamePanel.doing(GTeamX, GTeamY, 2);
            sendServerMessage("GAME@MOVE@" + 2 + "@" + GTeamX + "@" + GTeamY);
            if (Math.random() > 0.93) {
                for (int i = 0; i < 5; i++) {
                    String cmd = gamePanel.eraseRandom();
                    if (!cmd.equals("")) {
                        sendServerMessage("GAME@ERASE@" + cmd);
                    }
                }
            }
            if (RFlag == 0 || GFlag == 0) {
                if (RFlag == 0 && GFlag == 0) {
                    txtMsg.setText("Deuce");
                } else if (RFlag == 0) {
                    txtMsg.setText("Green Team Win.");
                } else {
                    txtMsg.setText("Red Team Win.");
                }
                System.out.println(txtMsg.getText());
                send();
                this.cancel();
                gameRunning = false;
            }
        }
    }

    public static void main(String[] args) {
        new MServer();
    }
}

package Server;

import javax.swing.JPanel;

import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.io.InputStream;

public class GPanel extends JPanel {
    byte[][] board = new byte[800 / 20][300 / 20];
    int GX, GY, RX, RY;
    boolean startFlag = false;
    boolean endFlag = true;
    int ptX, ptY, ptC;
    Image image, body, ghead, rhead;
    Image img[] = new Image[4];
    private String imgNames[] = { "background.jpg", "body.png", "ghead.png",
            "rhead.png" };
    private MediaTracker tracker = null;

    public void loadImages() {
        tracker = new MediaTracker(this);
        try {
            for (int i = 0; i < imgNames.length; i++) {
                img[i] = java.awt.Toolkit.getDefaultToolkit().getImage(imgNames[i]);
                tracker.addImage(img[i], i);
            }
        } catch (Exception e) {
            System.err.println("Error loading image");
        }

        try {
            tracker.waitForAll();
        } catch (Exception e) {
            System.err.println("Unknown error while loading images");
        }
    }

    public void newGame() {
        startFlag = true;
        endFlag = false;
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                board[i][j] = 0;
            }
        }
        /*image = readImg("background.jpg");
        body = readImg("body.png");
        ghead = readImg("ghead.png");
        rhead = readImg("rhead.png");*/
        loadImages();
        GX = -1;
        GY = -1;
        RX = -1;
        RY = -1;
        repaint();
    }

    public int doing(int x, int y, int c) {
        if (x < 0 || y < 0 || x >= 800 / 20 || y >= 300 / 20) {
            startFlag = false;
            endFlag = true;
            return 0; // color c lose.
        }
        if (board[x][y] != 0) {
            startFlag = false;
            endFlag = true;
            return 0; // color c lose.
        }
        ptX = x;
        ptY = y;
        ptC = c;
        board[x][y] = (byte) c;
        if (c == 1) {
            RX = x;
            RY = y;
        }
        if (c == 2) {
            GX = x;
            GY = y;
        }
        repaint();
        return 1;
    }

    public String eraseRandom() {
        int x = (int) (Math.random() * board.length);
        int y = (int) (Math.random() * board[0].length);
        int count = 0;
        while (board[x][y] == 0 && count++ < 50) {
            x = (int) (Math.random() * board.length);
            y = (int) (Math.random() * board[0].length);
        }
        if (board[x][y] == 0)
            return "";
        board[x][y] = 0;
        return x + "@" + y;
    }

    @Override
    public void paintComponent(Graphics g) {
        // super.paintComponent(g);
        g.setColor(Color.black);
        if (image == null) {
            for (int i = 0; i < this.getHeight(); i++)
                g.drawLine(0, i, 800, i);
            image = img[0];
        } else {
            g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
        }
        for (int i = 0; i < 800 / 20; i++) {
            for (int j = 0; j < 300 / 20; j++) {
                if (board[i][j] == 0)
                    continue;
                if (board[i][j] == 1)
                    g.setColor(Color.red);
                else
                    g.setColor(Color.green);
                if (body != null) {
                    g.drawImage(body, i * 20, j * 20, 20, 20, null);
                    continue;
                }
                body = img[1];
                int xpoints[] = { i * 10 + 7, i * 10 + 14, i * 10 + 7, i * 10 };
                int ypoints[] = { j * 10, j * 10 + 7, j * 10 + 14, j * 10 + 7 };
                int npoints = 4;
                g.fillPolygon(xpoints, ypoints, npoints);
                // g.fillOval(i * 10, j * 10, 11, 11);
                // g.fillRect(i * 10, j * 10, 8, 8);
            }
        }
        if (GX >= 0 && ghead != null) {
            g.drawImage(ghead, GX * 20 - 15, GY * 20 - 15, 50, 50, null);
        }
        if (RX >= 0 && rhead != null) {
            g.drawImage(rhead, RX * 20 - 15, RY * 20 - 15, 50, 50, null);
        }
        ghead = img[2];
        rhead = img[3];
    }
}

package Server;

public class User {
    private String name;
    private String ip;

    public User(String name, String ip) {
        this.name = name;
        this.ip = ip;
    }

    public String getName() {
        return name;
    }

    public String getIp() {
        return ip;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

}

package Client;

import java.net.Socket;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Map;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import java.lang.Thread;

public class NetClient extends JApplet {

    MClient p;

    private MediaTracker tracker = null;
    Image img[] = new Image[4];
    private String imgNames[] = { "background.jpg", "body.png", "ghead.png",
            "rhead.png" };

    public void init() {
        MClient p = new MClient(this);
        this.getContentPane().add(p.frame);
        loadImages();
    }

    public void loadImages() {
        tracker = new MediaTracker(this);
        try {
            for (int i = 0; i < imgNames.length; i++) {
                img[i] = getImage(getDocumentBase(), imgNames[i]);
                tracker.addImage(img[i], i);
            }
        } catch (Exception e) {
            System.err.println("Error loading image");
        }

        try {
            tracker.waitForAll();
        } catch (Exception e) {
            System.err.println("Unknown error while loading images");
        }
    }

}

class MClient {
    // <UI>
    public JPanel frame; // main windows
    JTextArea contentArea; // chat message post
    JTextField txtMsg; // user post message
    private JTextField txtPort; // server open [port number]
    private JTextField txtHost; // server open [host ip address]
    private JTextField txtName; // user name
    private JButton btnStart; // open server
    private JButton btnStop; // close server
    private JButton btnSend; // send [txtMsg]
    private JButton btnCH; // game choose item
    private JPanel northPanel;
    private JPanel southPanel;
    private JPanel chatPanel;
    private GPanel gamePanel;
    private JScrollPane leftPane;
    private JScrollPane rightPane;
    private JSplitPane centerSplit; // page windows
    private JList userList;
    private DefaultListModel listModel;
    // </UI>
    int teamID, teamDir;
    boolean clientRunning = false;
    // <Socket&Client>
    private Socket socket;
    private PrintWriter writer;
    private BufferedReader reader;
    private ClientThread clientThread;
    Timer timer;
    NetClient parent;

    public MClient(NetClient parent) {
        this.parent = parent;
        frame = new JPanel();
        contentArea = new JTextArea("");
        txtMsg = new JTextField();
        txtName = new JTextField("guest"); // default users limited = 10
        txtPort = new JTextField("2047"); // default port number = 2047
        txtHost = new JTextField("127.0.0.1"); // default ip address
        btnStart = new JButton("LogIn"); // log in server
        btnStop = new JButton("LogOut"); // log out server
        btnSend = new JButton("↵ ");
        btnCH = new JButton("Green");
        northPanel = new JPanel();
        southPanel = new JPanel(new BorderLayout());
        chatPanel = new JPanel();
        gamePanel = new GPanel(this, this.parent);
        listModel = new DefaultListModel();
        userList = new JList(listModel);
        leftPane = new JScrollPane(userList);
        rightPane = new JScrollPane(contentArea);

        contentArea.setEditable(false);
        contentArea.setBackground(Color.BLACK);
        contentArea.setForeground(Color.GREEN);
        //contentArea.setFont(new Font("Calibri", Font.ITALIC, 20));
        contentArea.setFont(new Font("微軟正黑體", Font.ITALIC, 20));

        btnStop.setEnabled(false);

        userList.setBackground(Color.BLACK);
        userList.setForeground(Color.GREEN);
        //userList.setFont(new Font("Calibri", Font.ITALIC, 20));
        userList.setFont(new Font("微軟正黑體", Font.ITALIC, 20));

        northPanel.setLayout(new GridLayout(1, 8));
        northPanel.setBorder(new TitledBorder("Setting"));
        northPanel.add(new JLabel("Port"));
        northPanel.add(txtPort);
        northPanel.add(new JLabel("Host"));
        northPanel.add(txtHost);
        northPanel.add(new JLabel("Username"));
        northPanel.add(txtName);
        northPanel.add(btnStart);
        northPanel.add(btnStop);
        northPanel.add(btnCH);

        southPanel.setLayout(new BorderLayout());
        southPanel.setBorder(new TitledBorder("Input"));
        southPanel.add(txtMsg, BorderLayout.CENTER);
        southPanel.add(btnSend, BorderLayout.EAST);

        leftPane.setBorder(new TitledBorder("User List"));

        rightPane.setBorder(new TitledBorder("Room Message"));

        centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane,
                rightPane);
        centerSplit.setDividerLocation(100);

        chatPanel.setLayout(new BorderLayout());
        chatPanel.add(northPanel, BorderLayout.NORTH);
        chatPanel.add(centerSplit, BorderLayout.CENTER);
        chatPanel.add(southPanel, BorderLayout.SOUTH);

        frame.setLayout(new GridLayout(2, 1));
        frame.add(gamePanel);
        frame.add(chatPanel);
        frame.setSize(800, 650);

        // <setting listener>
        rightPane.getVerticalScrollBar().addAdjustmentListener(
                new AdjustmentListener() {
                    JScrollBar sb = rightPane.getVerticalScrollBar();

                    public void adjustmentValueChanged(AdjustmentEvent e) {
                        sb.setValue(sb.getMaximum());
                    }
                });
        txtMsg.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                send();// when touch [Enter] key
            }
        });
        btnSend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                send();
            }
        });
        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    int portNumber;
                    portNumber = Integer.parseInt(txtPort.getText());
                    if (portNumber < 0)
                        throw new Exception("portNumber < 0");
                    if (txtName.getText().equals(""))
                        throw new Exception("Change username.");
                    openConnection(portNumber, txtHost.getText(),
                            txtName.getText());
                } catch (Exception err) {
                    JOptionPane.showMessageDialog(frame, "Setting error.",
                            "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        btnStop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                closeConnection();
            }
        });
        btnCH.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (btnCH.getText().equals("Green")) {
                    btnCH.setText("Red");
                    teamID = 1;
                    sendMessage("T@" + txtName.getText() + " become RED Team.");
                } else {
                    btnCH.setText("Green");
                    teamID = 2;
                    sendMessage("T@" + txtName.getText()
                            + " become GREEN Team.");
                }
            }
        });
        // </setting listener>
        timer = new Timer();
        timer.schedule(new AliveHeart(), 1000, 2000);
    }

    public void openConnection(int portNumber, String host, String name) {
        try {
            socket = new Socket(host, portNumber);
            writer = new PrintWriter(new OutputStreamWriter(
                    socket.getOutputStream(), "UTF-8"));
            reader = new BufferedReader(new InputStreamReader(
                    socket.getInputStream(), "UTF-8"));
            sendMessage(name + "@" + socket.getLocalAddress().toString() + "@"
                    + teamID);
            clientThread = new ClientThread();
            clientThread.start();
            clientRunning = true;
            txtPort.setEditable(false);
            txtName.setEditable(false);
            txtHost.setEditable(false);
            btnStart.setEnabled(false);
            btnStop.setEnabled(true);
        } catch (Exception err) {
            contentArea.append("Error> Connection fails.\r\n");
        }
    }

    public void closeConnection() {
        try {
            sendMessage("CLOSE@");
            clientRunning = false;
            listModel.clear();
            txtPort.setEditable(true);
            txtName.setEditable(true);
            txtHost.setEditable(true);
            btnStart.setEnabled(true);
            btnStop.setEnabled(false);
        } catch (Exception e) {
            clientRunning = false;
            e.printStackTrace();
        }
    }

    public void send() { // admin type message
        if (!clientRunning) {
            contentArea.append("Error> Send message missed.\r\n");
            txtMsg.setText(null);
            return;
        }
        String msg = txtMsg.getText();
        if (msg == null || msg.equals("")) {
            contentArea.append("Error> Empty message.\r\n");
            return;
        }
        msg = msg + "\r\n";
        sendMessage("T@" + msg); // tell all clients
        txtMsg.setText(null);
        if (contentArea.getText().length() > 262144)
            contentArea.setText(contentArea.getText().substring(131072));
    }

    public void sendMessage(String msg) {
        if (writer != null) {
            writer.println(msg);
            writer.flush();
        }
    }

    public void sendGame() {
        if (!clientRunning) {
            contentArea.append("Error> Disconnect\r\n");
            return;
        }
        sendMessage("GAME@" + teamID + "@" + teamDir);
    }

    class ClientThread extends Thread { // listen server command
        public ClientThread() {
        }

        public void run() {
            String msg;
            while (clientRunning) {
                try {
                    msg = reader.readLine();
                    if (msg == null || msg.equals(""))
                        continue;
                    StringTokenizer st = new StringTokenizer(msg, "@");
                    String cmd = st.nextToken();
                    if (cmd.equals("CLOSE")) {
                        contentArea.append("System> Server close!\r\n");
                        closeConnection();
                    } else if (cmd.equals("ADD")) { // ADD@username
                        String name = st.nextToken();
                        listModel.addElement(name);
                    } else if (cmd.equals("DELETE")) { // DELETE@username
                        String name = st.nextToken();
                        if (name.equals(txtName.getText()))
                            closeConnection();
                        listModel.removeElement(name);
                    } else if (cmd.equals("MSG")) { // from other people message
                        msg = st.nextToken();
                        while (st.hasMoreTokens())
                            msg += "@" + st.nextToken();
                        contentArea.append(msg + "\r\n");
                    } else if (cmd.equals("SYSTEM")) { // system
                        contentArea.append(st.nextToken() + "\r\n");
                    } else if (cmd.equals("E")) {
                        contentArea.append("Error> " + st.nextToken() + "\r\n");
                        closeConnection();
                    } else if (cmd.equals("GAME")) {
                        cmd = st.nextToken();
                        if (cmd.equals("NEWGAME")) {
                            gamePanel.newGame();
                        } else if (cmd.equals("MOVE")) {
                            int TEAM, X, Y;
                            TEAM = Integer.parseInt(st.nextToken());
                            X = Integer.parseInt(st.nextToken());
                            Y = Integer.parseInt(st.nextToken());
                            gamePanel.doing(X, Y, TEAM);
                        } else if (cmd.equals("ERASE")) {
                            int X, Y;
                            X = Integer.parseInt(st.nextToken());
                            Y = Integer.parseInt(st.nextToken());
                            gamePanel.erase(X, Y);
                            System.out.println("erase");
                        }
                    } else {
                        System.out.println(msg);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    class AliveHeart extends TimerTask {
        public void run() {
            sendMessage("A@");
        }
    }

}

package Client;

import java.io.InputStream;

import javax.swing.JPanel;
import javax.swing.JApplet;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.MediaTracker;
import java.awt.event.KeyEvent;

public class GPanel extends JPanel implements KeyEventDispatcher {
    byte[][] board = new byte[800 / 20][300 / 20];
    int GX, GY, RX, RY;
    boolean startFlag = false;
    boolean endFlag = true;
    int ptX, ptY, ptC;
    MClient parent;
    NetClient gparent;
    Image image = null, body = null, ghead = null, rhead = null;

    Image readImg(String fileName) {
        Image icon = null;
        try {
            InputStream in = this.getClass().getResourceAsStream(fileName);
            if (in == null) {
                System.err.println("Image not found");
            }
            byte[] buffer = new byte[in.available()];
            in.read(buffer);
            icon = java.awt.Toolkit.getDefaultToolkit().createImage(buffer);
        } catch (java.io.IOException e) {
            System.err.println("Unable to read image");
        }
        return icon;
    }

    public GPanel(MClient parent, NetClient gparent) {
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventDispatcher(this);
        this.parent = parent;
        this.gparent = gparent;
        /*image = readImg("background.jpg");
        body = readImg("body.png");
        ghead = readImg("ghead.png");
        rhead = readImg("rhead.png");*/
        image = gparent.img[0];
        body = gparent.img[1];
        ghead = gparent.img[2];
        rhead = gparent.img[3];
        System.out.println(image == null);
        GX = -1;
        GY = -1;
        RX = -1;
        RY = -1;
    }

    public void newGame() {
        startFlag = true;
        endFlag = false;
        for (int i = 0; i < board.length; i++)
            for (int j = 0; j < board[0].length; j++)
                board[i][j] = 0;
        GX = -1;
        GY = -1;
        RX = -1;
        RY = -1;
        repaint();
    }

    public void erase(int x, int y) {
        board[x][y] = 0;
    }

    public int doing(int x, int y, int c) {
        if (x < 0 || y < 0 || x >= 800 / 20 || y >= 300 / 20) {
            startFlag = false;
            endFlag = true;
            return 0; // color c lose.
        }
        if (board[x][y] != 0) {
            startFlag = false;
            endFlag = true;
            return 0; // color c lose.
        }
        ptX = x;
        ptY = y;
        ptC = c;
        board[x][y] = (byte) c;
        if (c == 1) {
            RX = x;
            RY = y;
        }
        if (c == 2) {
            GX = x;
            GY = y;
        }
        repaint();
        return 1;
    }

    @Override
    public void paintComponent(Graphics g) {
        // super.paintComponent(g);
        g.setColor(Color.black);
        if (image == null) {
            for (int i = 0; i < this.getHeight(); i++)
                g.drawLine(0, i, 800, i);
            image = gparent.img[0];
        } else {
            g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
        }
        for (int i = 0; i < 800 / 20; i++) {
            for (int j = 0; j < 300 / 20; j++) {
                if (board[i][j] == 0)
                    continue;
                if (board[i][j] == 1)
                    g.setColor(Color.red);
                else
                    g.setColor(Color.green);
                if (body != null) {
                    g.drawImage(body, i * 20, j * 20, 20, 20, null);
                    continue;
                }
                body = gparent.img[1];
                int xpoints[] = { i * 10 + 7, i * 10 + 14, i * 10 + 7, i * 10 };
                int ypoints[] = { j * 10, j * 10 + 7, j * 10 + 14, j * 10 + 7 };
                int npoints = 4;
                g.fillPolygon(xpoints, ypoints, npoints);
                // g.fillOval(i * 10, j * 10, 11, 11);
                // g.fillRect(i * 10, j * 10, 8, 8);
            }
        }
        if (GX >= 0 && ghead != null) {
            g.drawImage(ghead, GX * 20 - 15, GY * 20 - 15, 50, 50, null);
        }
        if (RX >= 0 && rhead != null) {
            g.drawImage(rhead, RX * 20 - 15, RY * 20 - 15, 50, 50, null);
        }
        ghead = gparent.img[2];
        rhead = gparent.img[3];
    }

    public boolean dispatchKeyEvent(KeyEvent e) {
        if (e.getID() == KeyEvent.KEY_RELEASED)
            return false;
        switch (e.getKeyCode()) {
        case KeyEvent.VK_DOWN:
            parent.teamDir = 1;
            break;
        case KeyEvent.VK_UP:
            parent.teamDir = 0;
            break;
        case KeyEvent.VK_RIGHT:
            parent.teamDir = 3;
            break;
        case KeyEvent.VK_LEFT:
            parent.teamDir = 2;
            break;
        default:
            return false;
        }
        if (parent.txtMsg.getText().equals(""))
            parent.sendGame();
        return false;
    }
}

台長: Morris
人氣(5,025) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 不分類 | 個人分類: [學習]Java |
此分類下一篇:[JAVA][作業] JList 清單使用
此分類上一篇:[JAVA][作業] 練習線程

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文