将游戏部署到服务器会导致奇怪的行为
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将游戏部署到服务器会导致奇怪的行为相关的知识,希望对你有一定的参考价值。
我和朋友一起使用html5 WebSockets和java作为后端开发了类似于游戏的游戏,并且最近将我的游戏部署在运行在20 $ Digitalocean Droplet(3GB ram,2cpu)上的Glassfish服务器上。
在开发游戏时,我使用IntelliJ和Netbeans的同事,在我们的PC上运行的Glassfish服务器上部署WAR文件时,一切都按预期工作。但是当在液滴上部署完全相同的WAR文件时,球的移动速度似乎快了3倍。
我尝试通过在虚拟机上安装与Droplet相同的Ubuntu服务器并执行我用于安装OpenJDK,Glassfish的相同步骤来重现该问题,但是在VM上它也运行良好。
其他具有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;
}
}
}
在处理多人游戏时,我偶然发现了几个问题,并决定用javascript中的console.log()检查几个变量。我注意到点击按钮时游戏开始了两次,并通过添加服务器端检查解决了问题,以防止在点击“播放”按钮时多次启动游戏。
private void gameStart() {
if (!game.isGameRunning()) {
game.start();
sendMessage("Game started");
}
}
现在球的速度很好。
也许您可以尝试System.currentTimeMillis(),因为System.nanoTime()不是线程安全的。
参考:Is System.nanoTime() consistent across threads?
以上是关于将游戏部署到服务器会导致奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章
角度 4 将包含其他对象的对象传递给 FormBuilder.group 函数会导致奇怪的表单行为