好吧,所以我正在开发一款游戏(比如甚至还没有阿尔法),它假设是一对一的格斗游戏,其中一个人托管服务器而另一个人连接。但是现在代码太迟了,无法做任何事情。有人可以看看它并告诉我如何加快它? PS:我也在使用Slick2D lib。
服务器:
import java.net.*;
import java.io.*;
public class SlickServer{
public static void main(String[] args) throws IOException {
int MAX_PLAYERS = 3;
int playerNum = 0;
Player[] players = new Player[MAX_PLAYERS];
players[0] = new Player(25,25);
players[1] = new Player(125,125);
players[2] = new Player(225,225);
ServerSocket serverSocket = new ServerSocket(4444);
boolean listening = true;
while(listening){
System.out.println("Waiting to connect with: " + playerNum);
new ClientThread(serverSocket.accept(), players, playerNum).start();
//stops here.
System.out.println("Connected with: " + playerNum + " Now incrementing");
playerNum++;
System.out.println("Incremented to: " + playerNum);
}
serverSocket.close();
System.exit(0);
}
}
服务器线程:
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.io.*;
public class ClientThread extends Thread implements Runnable{
Socket acceptedSocket;
Player[] players;
int playerNum;
public ClientThread(Socket acceptedSocket, Player[] players, int playerNum){
super("ClientThread");
this.acceptedSocket = acceptedSocket;
this.players = players;
this.playerNum = playerNum;
}
public void run(){
try{
Socket clientSocket = acceptedSocket;
System.out.println("Accepted. Now creating I/O.");
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
System.out.println("I/O with: " + playerNum + " working.");
out.writeInt(playerNum);
out.flush();
while(true){
if(playerNum == 0){
players[0].x = in.readInt();
players[0].y = in.readInt();
out.writeInt(players[1].x);
out.writeInt(players[1].y);
out.flush();
}
else if(playerNum == 1){
players[1].x = in.readInt();
players[1].y = in.readInt();
out.writeInt(players[0].x);
out.writeInt(players[0].y);
out.flush();
}
else if(playerNum == 2){
players[2].x = in.readInt();
players[2].y = in.readInt();
out.writeInt(players[0].x);
out.writeInt(players[0].y);
out.flush();
}
}
}
catch(Exception e){
e.printStackTrace();
System.exit(1);
}
}
}
客户端:
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import java.io.*;
import java.net.*;
public class SlickClient extends BasicGame{
int MAX_PLAYERS = 3;
int playerNum = 0;
Player[] players;
ClientThread ct;
int serverDelay = 15;
public SlickClient()
{
super("Client");
}
@Override
public void init(GameContainer gc)
throws SlickException {
try{
players = new Player[MAX_PLAYERS];
players[0] = new Player(25,25);
players[1] = new Player(125,125);
ct = new ClientThread(players);
ct.start();
ct.setPriority(Thread.MAX_PRIORITY);
playerNum = ct.playerNum;
}
catch(Exception e){
e.printStackTrace();
}
}
@Override
public void update(GameContainer gc, int delta)
throws SlickException
{
Input input = gc.getInput();
if(input.isKeyDown(Input.KEY_A))
{
players[playerNum].x-=5;
}
if(input.isKeyDown(Input.KEY_D))
{
players[playerNum].x+=5;
}
if(input.isKeyDown(Input.KEY_W))
{
players[playerNum].y-=5;
}
if(input.isKeyDown(Input.KEY_S))
{
players[playerNum].y+=5;
}
}
public void render(GameContainer gc, Graphics g)
throws SlickException
{
g.fillRect(players[0].x, players[0].y, 50, 50);
g.fillRect(players[1].x, players[1].y, 50, 50);
}
public static void main(String[] args)
throws SlickException
{
AppGameContainer app =
new AppGameContainer( new SlickClient() );
app.setAlwaysRender(true);
app.setTargetFrameRate(30);
app.setDisplayMode(800, 600, false);
app.start();
}
}
class ClientThread extends Thread implements Runnable{
Socket socket;
Player[] players;
int playerNum;
ObjectOutputStream out;
ObjectInputStream in;
public ClientThread(Player[] players){
super("ClientThread");
try{
socket = new Socket("98.203.176.196", 4444);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
this.players = players;
playerNum = in.readInt();
System.out.println(playerNum);
}
catch(Exception e){
e.printStackTrace();
}
}
public void run(){
try{
while(true){
if(playerNum == 0){
try{
out.writeInt(players[0].x);
out.writeInt(players[0].y);
out.flush();
players[1].x = in.readInt();
players[1].y = in.readInt();
}
catch(Exception e){
e.printStackTrace();
}
}
else if(playerNum == 1){
try{
out.writeInt(players[1].x);
out.writeInt(players[1].y);
out.flush();
players[0].x = in.readInt();
players[0].y = in.readInt();
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
答案 0 :(得分:2)
当客户端位于远离服务器的远程计算机上时,它是否只是滞后?如果是这样,并且你在盒子之间有一个很好的ping时间,那么我会猜测并说你可能在这里遇到Nagle的算法?你推的数据非常小(writeInt)。
您可以尝试使用BufferedOutputStream中介,但如果您想尝试快速修复,也可以尝试在套接字上禁用Nagle。
Socket.setTcpNoDelay(真);
答案 1 :(得分:1)
您是否尝试过使用ObjectOutputStream
和ObjectInputStream
以外的其他内容来发送和接收数据?使用这些涉及序列化和反序列化对象,但似乎(虽然只是一种预感)使用DataOutputStream
可能会更快。
答案 2 :(得分:1)
你提供的代码是不完整的...我打算这样做,然后引导你完成如何操作,这样我就可以确定你会看到什么......但是我们将使用我们拥有的东西。
1)在同一台机器上为客户端和服务器运行它 - 它仍然很慢吗? 2)在机器之间平衡并查看速度 3)描述应用程序。
#1有助于查看它是否是网络问题。同一台机器上的客户端和服务器都消除了网络。
#2有助于了解它是否是一个网络问题。如果ping不好那么游戏就会很慢。
#3更难做,但会告诉你代码中的位置结果很慢。
要分析一下Visual VM(或者如果你正在使用netbeans只是在那里对它进行分析... eclipse可能也有一些东西,可能是一个插件)。
对于分析,我将从服务器开始,看看那里的速度慢,然后移动到客户端。我建议只是因为服务器中的内容较少,所以应该更容易看到发生了什么。
答案 3 :(得分:1)
嗯,你可以马上尝试几件事,但是你需要做一些工作来做你想做的事。
首先,您的客户端和服务器都处于非常紧凑的循环中。通常情况下,你正在使用的循环应该在每次传递中睡眠最少的时间,以防止循环消耗太多CPU什么都不做。
其次,您应该使用非阻塞I / O(在尝试读取之前检查每个客户端的输入)。
最后,除非您想要开始有关Java网络的学习练习,或者除非您有特定的目标需要非标准的通信协议,否则您可能需要考虑使用您可以简单扩展的服务器框架。一个简单的方法是使用Jetty或Tomcat构建服务器端,并为客户端使用Apache HTTPClient。
如果您选择使用专用服务器,Core Java书籍或Java Networking(O'Reilly)手册中的简单服务器框架将为您提供更好的基础。
希望有所帮助。
答案 4 :(得分:1)
这取决于为什么它很慢。这是一些建议
另外,通过“变得迟钝”来定义你的意思。你的意思是代码给出了差的帧速率吗?移动注册需要很长时间?弄清楚这将是优化的第一步。
祝你好运。即使对于具有网络游戏编程经验的专业开发人员来说,让战斗游戏在网络上做出响应也是一项艰巨的任务。您可能需要修改您的游戏设计,以帮助隐藏滞后 - 某些事情在网络中是不可能的。
答案 5 :(得分:1)
如果您需要,可以尝试使用数据报套接字。如果底层数据包被丢弃,它就会消失,但由于你只是更新位置,它应该没问题。