Многопользовательская игра змея - PullRequest
0 голосов
/ 05 апреля 2020

Попытка написать многопользовательскую игру-змею с сервером и клиентами через сокеты

, поэтому, если один клиент подключается, все работает нормально, но как только второй подключается, первый перестает получать сервер данных.

Код сервера

private void serverGo() {

    try {
        ServerSocket serverSocket = new ServerSocket(6667);

        while (true) {
            Socket shakeSocket = serverSocket.accept();
            Socket receiverSocket = serverSocket.accept();
            System.out.println("receiver client connected!");
            Socket senderSocket = serverSocket.accept();
            System.out.println("sender client connected!");

            oos = new ObjectOutputStream(shakeSocket.getOutputStream());
            oos.writeObject(playerId);
            oos.flush();
            oos.reset();
            oos.close();
            clientNbr++;

            //System.out.println("player id " +playerId+ " connected");

            if(clientNbr==1){
                apple();
                Thread t1 = new Thread(new GameRun());
                t1.start();
                clientNbr=0;
            }

            Thread t = new Thread(new ClientHandler(senderSocket, receiverSocket));
            t.start();

        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private class ClientHandler implements Runnable {

    private Socket sender;
    private Socket receiver;

    public ClientHandler(Socket sender, Socket receiver) {

        this.sender=sender;
        this.receiver=receiver;

        playersMap.put("player" + playerId, new Player(playerId, snakeSetUp(), 5, 0));
        playerId++;
        System.out.println("players map size " +playersMap.size());
    }


    @Override
    public void run() {

        try {
            oos = new ObjectOutputStream(sender.getOutputStream());
            ois = new ObjectInputStream(receiver.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {       //receiving
            String playerId;
            while ((playerId = (String.valueOf(ois.readObject()))) != null) {
                int x = (int) ois.readObject();
                int y = (int) ois.readObject();
                Player p = playersMap.get("player" +playerId);
                p.setMoveX(x);
                p.setMoveY(y);
                playersMap.replace("player"+playerId,p);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class GameRun implements Runnable {

    @Override
    public void run() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {

                for (String player : playersMap.keySet()) {
                    Player p = playersMap.get(player);
                    //System.out.println(p.getPlayerId()+"  "+player);

                    int x = p.getSnake().get(0).getX() + p.getMoveX() * 2;
                    int y = p.getSnake().get(0).getY() + p.getMoveY() * 2;

                    if (x >= 500) {
                        x -= 500;
                    }
                    if (y < 0) {
                        y += 500;
                    }
                    if (x < 0) {
                        x += 500;
                    }
                    if (y >= 500) {
                        y -= 500;
                    }
                    p.snakeAdd(new Snake(x, y));
                    p.snakeRemove();

                    for (int i = 1; i < p.getSnake().size(); i++) {
                        if (p.getSnake().get(0).equals(p.getSnake().get(i))) {
                            timer.purge();
                            timer.cancel();
                        }
                    }

                    if (p.getSnake().get(0).equals(apple)) {
                        score += 3;
                        p.getSnake().add(new Snake(p.getSnake().get(0).getX() - p.getMoveX() * 2,
                                p.getSnake().get(0).getY() - p.getMoveY() * 2));
                        apple();
                    }
                }
                sendData();
            }
        }, 300, 75);
    }
}

private void sendData(){

    try {
        oos.writeObject(playersMap);
        oos.writeObject(apple);
        oos.flush();
        oos.reset();
        System.out.println("send");
    } catch (IOException e) {
        e.printStackTrace();
        //timer.cancel();
    }
}

код клиента

private void multiPlayerLobbyPlusGui(){

    try {

        Socket shake = new Socket("127.0.0.1", 6667);
        Socket sender = new Socket("127.0.0.1", 6667);
        receiver = new Socket("127.0.0.1", 6667);

        ois = new ObjectInputStream(shake.getInputStream());
        try {
            playerID= (int) ois.readObject();
            System.out.println("players ID "+playerID);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        ois = new ObjectInputStream(receiver.getInputStream());
        System.out.println("receiver connected!");
        oos = new ObjectOutputStream(sender.getOutputStream());
        System.out.println("sender connected!");


    }catch (IOException e) {
        e.printStackTrace();
    }


    JPanel multiPanel = new JPanel();
    multiPanel.setBackground(Color.black);
    multiPanel.setLayout(new BoxLayout(multiPanel, BoxLayout.Y_AXIS));
    multiPanel.setPreferredSize(new Dimension(mainPanelW, mainPanelH));

    String[] menuArray = new String[]{"Start", "Exit"};

    JList<String> multiJList = new JList<>(menuArray);
    multiJList.setFont(new Font(null, Font.BOLD, 25));
    DefaultListCellRenderer renderer = (DefaultListCellRenderer) multiJList.getCellRenderer();
    renderer.setHorizontalAlignment(SwingConstants.CENTER);
    multiJList.setBackground(Color.black);
    multiJList.setForeground(Color.white);
    multiJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    multiJList.setSelectionBackground(Color.black);
    multiJList.setSelectionForeground(Color.gray);
    UIManager.put("List.focusCellHighlightBorder", BorderFactory.createEmptyBorder());

    indexList=0;
    multiJList.addListSelectionListener(e -> {
        if (!e.getValueIsAdjusting()) {
            indexList = multiJList.getSelectedIndex();
        }
    });

    multiJList.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "multiAction");
    multiJList.getActionMap().put("multiAction", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (indexList == 0) {    //start
                frame.remove(multiPanel);
                //sendData(playerID, -pixMove, 0);
                multiPlayerGo();

            } else if (indexList == 1) {    //exit
                frame.remove(multiPanel);
                menuGui();
            }
        }
    });

    multiPanel.add(Box.createVerticalGlue());
    multiPanel.add(multiJList);
    multiPanel.add(Box.createVerticalGlue());
    frame.getContentPane().add(multiPanel);
    frame.pack();
    multiJList.requestFocusInWindow();
    multiJList.setSelectedIndex(indexList);
}

private void multiPlayerGo() {

    gameGui();

    Thread t = new Thread(new ReceivingData());
    t.start();

    mainPanel.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "left");

    mainPanel.getActionMap().put("left", new AbstractAction() {
         @Override
         public void actionPerformed(ActionEvent e) {
             if (moveX != pixMove) {
                 sendData(playerID, -pixMove, 0);
             }
         }
     });
     mainPanel.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "right");
     mainPanel.getActionMap().put("right", new AbstractAction() {
         @Override
         public void actionPerformed(ActionEvent e) {
             if (moveX != -pixMove) {
                 sendData(playerID, pixMove, 0);
             }
         }
     });
     mainPanel.getInputMap().put(KeyStroke.getKeyStroke("UP"), "up");
     mainPanel.getActionMap().put("up", new AbstractAction() {
         @Override
         public void actionPerformed(ActionEvent e) {
             if (moveY != pixMove) {
                 sendData(playerID, 0, -pixMove);
             }
         }
     });
     mainPanel.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "down");
     mainPanel.getActionMap().put("down", new AbstractAction() {
         @Override
         public void actionPerformed(ActionEvent e) {
             if (moveY != -pixMove) {
                 sendData(playerID, 0, pixMove);
             }
         }
     });
     mainPanel.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "esc");
     mainPanel.getActionMap().put("esc", new AbstractAction() {
         @Override
         public void actionPerformed(ActionEvent e) {
             try {
                 receiver.close();
             } catch (IOException ex) {
                 ex.printStackTrace();
             }
         }
     });
     mainPanel.requestFocusInWindow();
}

private class ReceivingData implements Runnable{


    @Override
    public void run() {

        try{
            while ((playersMap = (LinkedHashMap<String, Player>) ois.readObject())!=null){
                apple=(Snake) ois.readObject();
                System.out.println("receiving");

                for(String s: playersMap.keySet()){
                    if(playerID==playersMap.get(s).getPlayerId()){
                        snakePos=playersMap.get(s).getSnake();
                        //snake1.clear();
                    }else{
                        snake1=playersMap.get(s).getSnake();
                    }
                }
                mainPanel.updateUI();
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

private void sendData(int pId, int x, int y){
    try {
        oos.writeObject(pId);
        oos.writeObject(x);
        oos.writeObject(y);
        oos.flush();
        oos.reset();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

, поэтому я не получаю никаких ошибок во время выполнения или чего-либо еще, только первый клиент перестает получать, и если 3-й соединитель первый 2 прекращает получать данные, пробовал новый поток для отправки серверу форм, который иногда не помог просто получить ошибки одновременного выполнения. Ход идей, как это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...