将游戏部署到服务器会导致奇怪的行为

时间:2017-12-10 15:11:17

标签: java java-ee websocket glassfish java-websocket

我和朋友一起使用HTML5 WebSockets和java作为后端开发了类似于游戏的游戏,并且最近将我的游戏部署在Glassfish服务器上,该服务器运行在20 $ Digitalocean Droplet上(3GB ram,2cpu' s)

在开发游戏时,我使用IntelliJ和Netbeans的同事,在我们的PC上运行的Glassfish服务器上部署WAR文件时,一切都按预期工作。但是当在液滴上部署完全相同的WAR文件时,球的移动速度似乎快了3倍。

我尝试通过在虚拟机上安装与Droplet相同的Ubuntu服务器并执行我用于安装OpenJDK,Glassfish的相同步骤来重现该问题,但是在VM上它也运行良好。< / p>

其他带有1个CPU的液滴(尝试过ubuntu和centos)会产生同样的问题。我想知道这个问题的原因可能是我错过了什么?

以下是我用于连接/游戏的代码:

的WebSocket:

@ServerEndpoint("/singleplayer")
public class SingleplayerSocket {

    private static final Set<Session> PLAYERS = Collections.synchronizedSet(new HashSet<Session>());

    private Session session;
    private Gson gson;
    private Game game;

    private void sendMessage(String message) {
        try {
            for (Session player: PLAYERS) {
                if (player == session) {
                    player.getBasicRemote().sendText(message);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void gameStart() {
        game.start();
        sendMessage("Game started");
    }

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        gson = new Gson();
        PLAYERS.add(session);

        sendMessage("Connection established");
    }

    @OnMessage
    public void onMessage(String message) {
        if (session != null && session.isOpen()) {
            String messageType = gson.fromJson(message, MessageType.class).getMessage();

            switch (messageType) {

                case "gameSetup":
                    gameSetup(message);
                    break;

                case "gameStart":
                    gameStart();
                    break;
            }
        }
    }

    @OnClose
    public void onClose(Session session) {
        PLAYERS.remove(session);
        this.session = null;
    }
}

下面用球移动方法的游戏类:

        public class Game implements Runnable {

        private final int TARGET_FPS = 60;
        private final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;

        private volatile boolean gameRunning;
        private volatile boolean gamePaused;

        private Session session;
        private Thread thread;
        private Gson gson;

        public Game(Session session, int width, int height, String difficulty) {
            this.session = session;
            this.WIDTH = width;
            this.HEIGHT = height;
            gson = new Gson();
            timer = new Timer();

            setup(difficulty);
        }

        private void setGameRunning(boolean gameRunning) {
            this.gameRunning = gameRunning;
        }

        private void update(double delta) {
            ball.move(delta);
            collisionDetectionWalls();
            collisionDetectionPaddle();
            collisionDetectionBricks();
        }

        public void start() {
            thread = new Thread(this);
            thread.start();
            setGameRunning(true);
        }

        public void stop() {
            setGameRunning(false);
        }

        private void end(boolean won) {
            updateScore();
            sendGameEnd(won);
            stop();
        }

        private void sendMessage(String message) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void sendGameUpdate() {
            GameUpdateData data = new GameUpdateData(paddle, ball, bricks);
            GameUpdateResponse response = new GameUpdateResponse("gameUpdate", data);
            sendMessage(gson.toJson(response));
        }

        @Override
        public void run() {
            long lastLoopTime = System.nanoTime();
            long lastFpsTime = 0;

            while (gameRunning) {
                long currentTime = System.nanoTime();
                long updateLength = currentTime - lastLoopTime;
                lastLoopTime = currentTime;
                double delta = updateLength / ((double) OPTIMAL_TIME);

                lastFpsTime += updateLength;
                if (lastFpsTime >= 1000000000) {
                    lastFpsTime = 0;
                }

                if (!gamePaused) {
                    update(delta);
                    sendGameUpdate();
                }

                try {
                    long sleepTime = (System.nanoTime() - lastLoopTime + OPTIMAL_TIME) / 1000000;
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                }
            }
        }
    }

public class Ball {
    public void move(double delta) {
        if (isLaunched()){
            double trigoX = Math.cos(angle);
            double trigoY = Math.sin(angle);

            x += trigoX * velocity * delta;
            y += trigoY * velocity * delta;
        }
    }
}

2 个答案:

答案 0 :(得分:2)

在处理多人游戏时,我偶然发现了几个问题,并决定使用Javascript中的console.log()检查几个变量。我注意到点击按钮时游戏开始了两次并通过添加服务器端检查解决了问题,以防止在点击“播放”时多次启动游戏。按钮。

private void gameStart() {
    if (!game.isGameRunning()) {
        game.start();
        sendMessage("Game started");
    }
}

现在球的速度正常。

答案 1 :(得分:1)

也许你可以尝试System.currentTimeMillis(),因为System.nanoTime()不是threadsave。

参考: Is System.nanoTime() consistent across threads?