基本上,我正在开发一个使用TCP作为传输协议的Java多人赛车游戏。下面是我的代码,我能知道为什么在输入IP地址之后gameframe没有出现吗?相反,目前只有在服务器关闭后才会显示它。我使用多线程来支持发送和接收。
Main (Client):-
public static void main(String[] args) throws IOException
{
String ipAddress = JOptionPane.showInputDialog(null, "Enter the address: ");
if (!ipAddress.isEmpty())
{
// Main program to declare GameFrame object
Socket socket = new Socket(ipAddress, 8888);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
DataOutputStream writer = new DataOutputStream(socket.getOutputStream());
Thread thread = new Thread(new GameFrame(socket, reader, writer));
thread.start();
}
}
GameFrame:-
public class GameFrame extends JFrame implements Runnable
{
// Exit message
private final String message = "Are you sure you want to exit the game?";
// Exit message popup title
private final String title = "Exiting Game";
// Declare RacingTrack object
private RacingTrack racingTrack;
// Declare JFrame object
private JFrame mainGameFrame;
public GameFrame(Socket socket, BufferedReader reader, DataOutputStream writer)
{
racingTrack = new RacingTrack(socket, reader, writer);
mainGameFrame = new JFrame();
mainGameFrame.setBounds(0, 0, 900, 700);
mainGameFrame.setLocationRelativeTo(null);
mainGameFrame.setVisible(true);
mainGameFrame.add(racingTrack);
mainGameFrame.addKeyListener(racingTrack);
mainGameFrame.setResizable(false);
mainGameFrame.setTitle("Karts Racing Game");
mainGameFrame.setFocusable(true);
mainGameFrame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
mainGameFrame.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
int result = JOptionPane.showConfirmDialog(null, message, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION)
mainGameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
else if (result == JOptionPane.NO_OPTION)
mainGameFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
}
});
}
@Override
public void run()
{
System.out.println("Game Frame Thread running.");
mainGameFrame.setVisible(true);
}
Server:-
public class Server
{
public static void main( String args[] )
{
int connectedClient = 0;
ServerSocket service = null;
Socket server = null;
BufferedReader inputStream;
DataOutputStream outputStream;
try
{
service = new ServerSocket(8888);
System.out.println("Server has started.");
}
catch (IOException e)
{
System.out.println(e);
}
try
{
while (connectedClient < 2)
{
server = service.accept();
connectedClient++;
ClientThread clientThread = new ClientThread(server, connectedClient);
System.out.println("Player " + connectedClient + " connected. IP Address: " + server.getInetAddress());
Thread thread = new Thread(clientThread);
thread.start();
System.out.println("Player: " + connectedClient + " thread running.");
}
}
catch (IOException e)
{
System.out.println(e);
}
}
}
ClientThread:-
public class ClientThread implements Runnable
{
Socket socket;
int playerNum;
boolean keepRunning = true;
int kartNumIndex;
int x;
int y;
int speed;
BufferedReader reader;
DataOutputStream writer;
ArrayList<ClientThread> clients = new ArrayList<>();
public ClientThread(Socket socket, int player)
{
this.socket = socket;
this.playerNum = player;
}
@Override
public void run()
{
try
{
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new DataOutputStream(socket.getOutputStream());
writer.writeByte(playerNum);
writer.flush();
while (keepRunning == true)
{
playerNum = reader.read();
kartNumIndex = reader.read();
x = reader.read();
y = reader.read();
speed = reader.read();
broadcastToAllClients(playerNum, kartNumIndex, x, y, speed);
}
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
}
public void broadcastToAllClients(int playerNum, int kartNumIndex, int x, int y, int speed)
{
try
{
for (ClientThread client : clients)
{
client.writer.write(playerNum);
client.writer.write(kartNumIndex);
client.writer.write(x);
client.writer.write(y);
client.writer.write(speed);
client.writer.flush();
}
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
}
}
RacingTrack Constructor (partial):-
public class RacingTrack extends JPanel implements KeyListener
{
Socket clientSocket;
BufferedReader reader;
DataOutputStream writer;
int playerNum;
int kartNum;
int kartImageIndex;
int x;
int y;
int speed;
private Kart kart1;
private Kart kart2;
private SoundEffect soundEffect;
private Timer animationTimer;
private final int delay = 0;
private Set<Integer> pressedKeys;
boolean isKart1Lose;
boolean isKart2Lose;
private ElapseCounter kart1T;
private ElapseCounter kart2T;
/* Coordinates, Width, and Height of the value given and modified */
/* Racing Track 1 */
// Grass
private final int GRASS_X_COOR = 150;
private final int GRASS_Y_COOR = 200;
private final int GRASS_WIDTH = 550;
private final int GRASS_HEIGHT = 320;
// Outer Edge
private final int OUTER_EDGE_X_COOR = 50;
private final int OUTER_EDGE_Y_COOR = 100;
private final int OUTER_EDGE_WIDTH = 750;
private final int OUTER_EDGE_HEIGHT = 520;
// Inner Edge
private final int INNER_EDGE_X_COOR = 150;
private final int INNER_EDGE_Y_COOR = 200;
private final int INNER_EDGE_WIDTH = 550;
private final int INNER_EDGE_HEIGHT = 320;
// Mid Lane
private final int MID_LANE_X_COOR = 100;
private final int MID_LANE_Y_COOR = 150;
private final int MID_LANE_WIDTH = 650;
private final int MID_LANE_HEIGHT = 420;
// Start Line
private final int START_LINE_X1_COOR = 425;
private final int START_LINE_Y1_COOR = 520;
private final int START_LINE_X2_COOR = 425;
private final int START_LINE_Y2_COOR = 620;
/* Racing Track 2 */
// Grass
private final int GRASS_TOP_X_COOR = 450;
private final int GRASS_TOP_Y_COOR = 240;
private final int GRASS_LEFT_X_COOR = 260;
private final int GRASS_LEFT_Y_COOR = 520;
private final int GRASS_RIGHT_X_COOR = 640;
private final int GRASS_RIGHT_Y_COOR = 520;
// Outer Lane
private final int OUTER_LANE_TOP_X_COOR = 450;
private final int OUTER_LANE_TOP_Y_COOR = 110;
private final int OUTER_LANE_LEFT_X_COOR = 50;
private final int OUTER_LANE_LEFT_Y_COOR = 622;
private final int OUTER_LANE_RIGHT_X_COOR = 850;
private final int OUTER_LANE_RIGHT_Y_COOR = 622;
// Mid Lane
private final int MID_LANE_TOP_X_COOR = 450;
private final int MID_LANE_TOP_Y_COOR = 170;
private final int MID_LANE_LEFT_X_COOR = 140;
private final int MID_LANE_LEFT_Y_COOR = 570;
private final int MID_LANE_RIGHT_X_COOR = 760;
private final int MID_LANE_RIGHT_Y_COOR = 570;
// Obtain car shape bounds
private Rectangle kart1Shape;
private Rectangle kart2Shape;
// Obtain outer edges bound
private Rectangle outerEdgeLeft = new Rectangle(OUTER_EDGE_X_COOR, OUTER_EDGE_Y_COOR, 1, OUTER_EDGE_HEIGHT);
private Rectangle outerEdgeTop = new Rectangle(OUTER_EDGE_X_COOR, OUTER_EDGE_Y_COOR, OUTER_EDGE_WIDTH, 1);
private Rectangle outerEdgeRight = new Rectangle(OUTER_EDGE_X_COOR + OUTER_EDGE_WIDTH, OUTER_EDGE_Y_COOR, 1, OUTER_EDGE_HEIGHT);
private Rectangle outerEdgeBottom = new Rectangle(OUTER_EDGE_X_COOR, OUTER_EDGE_Y_COOR + OUTER_EDGE_HEIGHT, OUTER_EDGE_WIDTH, 1);
private Line2D outerEdgeTop2 = new Line2D.Double(OUTER_LANE_TOP_X_COOR, OUTER_LANE_TOP_Y_COOR, OUTER_LANE_LEFT_X_COOR, OUTER_LANE_LEFT_Y_COOR);
private Line2D outerEdgeLeft2 = new Line2D.Double(OUTER_LANE_LEFT_X_COOR, OUTER_LANE_LEFT_Y_COOR, OUTER_LANE_RIGHT_X_COOR, OUTER_LANE_RIGHT_Y_COOR);
private Line2D outerEdgeRight2 = new Line2D.Double(OUTER_LANE_RIGHT_X_COOR, OUTER_LANE_RIGHT_Y_COOR, OUTER_LANE_TOP_X_COOR, OUTER_LANE_TOP_Y_COOR);
private Rectangle innerEdgeLeft = new Rectangle(GRASS_X_COOR, GRASS_Y_COOR, 1, GRASS_HEIGHT);
private Rectangle innerEdgeTop = new Rectangle(GRASS_X_COOR, GRASS_Y_COOR, GRASS_WIDTH, 1);
private Rectangle innerEdgeRight = new Rectangle(GRASS_X_COOR + GRASS_WIDTH, GRASS_Y_COOR, 1, GRASS_HEIGHT);
private Rectangle innerEdgeBottom = new Rectangle(GRASS_X_COOR, GRASS_Y_COOR + GRASS_HEIGHT, GRASS_WIDTH, 1);
private Line2D innerEdgeTop2 = new Line2D.Double(GRASS_TOP_X_COOR, GRASS_TOP_Y_COOR, GRASS_LEFT_X_COOR, GRASS_LEFT_Y_COOR);
private Line2D innerEdgeLeft2 = new Line2D.Double(GRASS_LEFT_X_COOR, GRASS_LEFT_Y_COOR, GRASS_RIGHT_X_COOR, GRASS_RIGHT_Y_COOR);
private Line2D innerEdgeRight2 = new Line2D.Double(GRASS_RIGHT_X_COOR, GRASS_RIGHT_Y_COOR, GRASS_TOP_X_COOR, GRASS_TOP_Y_COOR);
// Obtain goal line bound
private Rectangle goalLineBound = new Rectangle(START_LINE_X1_COOR, START_LINE_Y1_COOR, 1, START_LINE_Y2_COOR - START_LINE_Y1_COOR);
// Constructor
public RacingTrack(Socket socket, BufferedReader reader, DataOutputStream writer)
{
this.reader = reader;
this.writer = writer;
try
{
playerNum = reader.read();
System.out.println("I am Player Number " + playerNum);
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
// Set this JPanel to allow overlay layout
// so that the kart icons can be printed above it
this.setLayout(new OverlayLayout(this));
// Create kart objects
// Specify the kart number, x-coordinates and y-coordinates
// kart1 = new Kart(1, 430, 521);
// kart2 = new Kart(2, 430, 570);
if (playerNum == 1)
{
kart1 = new Kart(1, 430, 521);
try
{
writer.write(kart1.getKartNum());
writer.write(kart1.getKartImageIndex());
writer.write(kart1.getXCoordinate());
writer.write(kart1.getYCoordinate());
writer.write(kart1.getSpeed());
writer.flush();
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
try
{
kartNum = reader.read();
kartImageIndex = reader.read();
x = reader.read();
y = reader.read();
speed = reader.read();
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
kart2 = new Kart(kartNum, x, y);
kart2.setKartImageIndex(kartImageIndex);
kart2.setSpeed(speed);
}
else if (playerNum == 2)
{
try
{
kartNum = reader.read();
kartImageIndex = reader.read();
x = reader.read();
y = reader.read();
speed = reader.read();
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
kart1 = new Kart(kartNum, x, y);
kart1.setKartImageIndex(kartImageIndex);
kart1.setSpeed(speed);
kart2 = new Kart(1, 430, 570);
try
{
writer.write(kart2.getKartNum());
writer.write(kart2.getKartImageIndex());
writer.write(kart2.getXCoordinate());
writer.write(kart2.getYCoordinate());
writer.write(kart2.getSpeed());
writer.flush();
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
}
if (playerNum == 1)
kart1.start();
else if (playerNum == 2)
kart2.start();
isKart1Lose = false;
isKart2Lose = false;
kart1T = new ElapseCounter();
kart2T = new ElapseCounter();
pressedKeys = new HashSet<>();
animationTimer = new Timer(delay, new TimeHandler());
animationTimer.start();
}
private class TimeHandler implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
speedLabel.setText("<html>Kart 1 Speed: " + kart1.getSpeed() + " <br> Kart 2 Speed: " + kart2.getSpeed() + "</html>");
kart1Shape = kart1.getKartShape();
kart2Shape = kart2.getKartShape();
if (playerNum == 1)
{
if (isKart1Lose == false)
{
if (kart1Shape.intersects(outerEdgeLeft))
setKart1Lose();
else if (kart1Shape.intersects(outerEdgeTop))
setKart1Lose();
else if (kart1Shape.intersects(outerEdgeRight))
setKart1Lose();
else if (kart1Shape.intersects(outerEdgeBottom))
setKart1Lose();
else if (kart1Shape.intersects(innerEdgeLeft))
setKart1Lose();
else if (kart1Shape.intersects(innerEdgeTop))
setKart1Lose();
else if (kart1Shape.intersects(innerEdgeRight))
setKart1Lose();
else if (kart1Shape.intersects(innerEdgeBottom))
setKart1Lose();
else if (kart1Shape.intersects(goalLineBound))
winnerFound(1);
}
}
else if (playerNum == 2)
{
if (isKart2Lose == false)
{
if (kart2Shape.intersects(outerEdgeLeft))
setKart2Lose();
else if (kart2Shape.intersects(outerEdgeTop))
setKart2Lose();
else if (kart2Shape.intersects(outerEdgeRight))
setKart2Lose();
else if (kart2Shape.intersects(outerEdgeBottom))
setKart2Lose();
else if (kart2Shape.intersects(innerEdgeLeft))
setKart2Lose();
else if (kart2Shape.intersects(innerEdgeTop))
setKart2Lose();
else if (kart2Shape.intersects(innerEdgeRight))
setKart2Lose();
else if (kart2Shape.intersects(innerEdgeBottom))
setKart2Lose();
else if (kart2Shape.intersects(goalLineBound))
winnerFound(2);
}
}
if (kart1Shape.intersects(kart2Shape))
{
if (playerNum == 1)
isKart1Lose = true;
else
isKart2Lose = true;
if (playerNum == 1)
kart1T.setStop();
else
kart2T.setStop();
animationTimer.stop();
if (playerNum == 1)
kart1.stop();
else
kart2.stop();
}
if (isKart1Lose == true && isKart2Lose == true)
bothKartsCrashed();
repaint();
}
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
super.setBackground(Color.gray);
Color c1 = Color.green;
Color c2 = Color.black;
Color c3 = Color.white;
g.setColor( c1 );
// x-coordinate, y-coordinate, width, height
g.fillRect( GRASS_X_COOR, GRASS_Y_COOR, GRASS_WIDTH, GRASS_HEIGHT ); // grass
g.setColor( c2 );
g.drawRect( OUTER_EDGE_X_COOR, OUTER_EDGE_Y_COOR, OUTER_EDGE_WIDTH, OUTER_EDGE_HEIGHT ); // outer edge
g.drawRect( INNER_EDGE_X_COOR, INNER_EDGE_Y_COOR, INNER_EDGE_WIDTH, INNER_EDGE_HEIGHT ); // inner edge
g.setColor( c3 );
Graphics2D g2d = (Graphics2D)g.create();
Stroke dashed = new BasicStroke(2, BasicStroke.JOIN_BEVEL, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0);
g2d.setStroke(dashed);
g2d.drawRect( MID_LANE_X_COOR, MID_LANE_Y_COOR, MID_LANE_WIDTH, MID_LANE_HEIGHT ); // mid-lane marker
g2d.dispose();
g.drawLine( START_LINE_X1_COOR, START_LINE_Y1_COOR, START_LINE_X2_COOR, START_LINE_Y2_COOR ); // start line
if (playerNum == 1)
{
try
{
writer.write(kart1.getKartNum());
writer.write(kart1.getKartImageIndex());
writer.write(kart1.getXCoordinate());
writer.write(kart1.getYCoordinate());
writer.write(kart1.getSpeed());
writer.flush();
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
kart1.draw(g, this);
try
{
kartNum = reader.read();
kartImageIndex = reader.read();
x = reader.read();
y = reader.read();
speed = reader.read();
kart2.draw(g, this, x, y);
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
}
else if (kartNum == 2)
{
try
{
writer.write(kart2.getKartNum());
writer.write(kart2.getKartImageIndex());
writer.write(kart2.getXCoordinate());
writer.write(kart2.getYCoordinate());
writer.write(kart2.getSpeed());
writer.flush();
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
kart2.draw(g, this);
try
{
kartNum = reader.read();
kartImageIndex = reader.read();
x = reader.read();
y = reader.read();
speed = reader.read();
kart1.draw(g, this, x, y);
}
catch (IOException iOe)
{
iOe.printStackTrace();
}
}
}
@Override
public void keyTyped(KeyEvent e) { }
@Override
public synchronized void keyPressed(KeyEvent e)
{
int speed;
int carImageIndex;
// Add keypresses
pressedKeys.add(e.getKeyCode());
for (Iterator<Integer> it = pressedKeys.iterator(); it.hasNext();)
{
switch (it.next())
{
/* kart blue */
// Increase speed
// Each key press increases speed by 10
case KeyEvent.VK_UP:
if (isKart1Lose == false)
{
// get kart's speed
speed = kart1.getSpeed();
// increase the initial speed by 10
kart1.setSpeed(speed + 10);
// check if speed is more than 100
// if yes, set to 100 (maximum)
if (kart1.getSpeed() > 100)
kart1.setSpeed(100);
// drive the kart forward with the speed
moveForwardKart1(kart1.getSpeed());
}
break;
// Decrease speed
// Each key press decreases speed by 10
case KeyEvent.VK_DOWN:
if (isKart1Lose == false)
{
// get kart's speed
speed = kart1.getSpeed();
// decrease the initial speed by 10
kart1.setSpeed(speed - 10);
// check if speed is less than 0
// if yes, set to -1, then kart will reverse
// minimum is -1
if (kart1.getSpeed() < 0)
{
kart1.setSpeed(-1);
moveBackwardKart1();
}
// check if speed is 0
// if no, then drive the kart forward with the set speed
if (kart1.getSpeed() > 0)
moveForwardKart1(kart1.getSpeed());
}
break;
// Turn the kart to the left
case KeyEvent.VK_LEFT:
if (isKart1Lose == false)
{
// get kart's image index
carImageIndex = kart1.getKartImageIndex();
// set the kart's new image index
kart1.setKartImageIndex(carImageIndex - 1);
// if kart's image index is less than 0
// set it to 15
if (carImageIndex - 1 < 0)
kart1.setKartImageIndex(15);
}
break;
// Turn the kart to the right
case KeyEvent.VK_RIGHT:
if (isKart1Lose == false)
{
// get kart's image index
carImageIndex = kart1.getKartImageIndex();
// set the kart's new image index
kart1.setKartImageIndex(carImageIndex + 1);
// if kart's image index is more than 15
// set it to 0
if (carImageIndex + 1 > 15)
kart1.setKartImageIndex(0);
}
break;
}
}
}
@Override
public void keyReleased(KeyEvent e)
{
pressedKeys.remove(e.getKeyCode());
}
// For KART1
// Method that drive the kart forward with appropriate speed
// speed will affect the pixel displacement
// (speed / 10) to get the first digit so that the kart can move accordingly
// if speed is 1, the kart moves by 1 pixel; ie: x + 1 or y + 1 depends on direction
// if speed is 5, the kart moves by 5 pixel; ie: x + 5 or y + 5 depends on direction
// this is done by increasing or decreasing the x and/or y coordinates
private void moveForwardKart1(int speed)
{
switch (kart1.getKartImageIndex())
{
case 0:
kart1.setYCoordinate(kart1.getYCoordinate() - (speed / 10));
break;
case 1:
case 2:
case 3:
kart1.setXCoordinate(kart1.getXCoordinate() + (speed / 10));
kart1.setYCoordinate(kart1.getYCoordinate() - (speed / 10));
break;
case 4:
kart1.setXCoordinate(kart1.getXCoordinate() + (speed / 10));
break;
case 5:
case 6:
case 7:
kart1.setXCoordinate(kart1.getXCoordinate() + (speed / 10));
kart1.setYCoordinate(kart1.getYCoordinate() + (speed / 10));
break;
case 8:
kart1.setYCoordinate(kart1.getYCoordinate() + (speed / 10));
break;
case 9:
case 10:
case 11:
kart1.setXCoordinate(kart1.getXCoordinate() - (speed / 10));
kart1.setYCoordinate(kart1.getYCoordinate() + (speed / 10));
break;
case 12:
kart1.setXCoordinate(kart1.getXCoordinate() - (speed / 10));
break;
case 13:
case 14:
case 15:
kart1.setXCoordinate(kart1.getXCoordinate() - (speed / 10));
kart1.setYCoordinate(kart1.getYCoordinate() - (speed / 10));
break;
}
}
// For KART1
// Method that drive the kart backward (reverse)
// the coordinate(s) will only be increased or decreased by 1 pixel
// this is done by increasing or decreasing the x and/or y coordinates
private void moveBackwardKart1()
{
switch (kart1.getKartImageIndex())
{
case 0:
kart1.setYCoordinate(kart1.getYCoordinate() + 1);
break;
case 1:
case 2:
case 3:
kart1.setXCoordinate(kart1.getXCoordinate() - 1);
kart1.setYCoordinate(kart1.getYCoordinate() + 1);
break;
case 4:
kart1.setXCoordinate(kart1.getXCoordinate() - 1);
break;
case 5:
case 6:
case 7:
kart1.setXCoordinate(kart1.getXCoordinate() - 1);
kart1.setYCoordinate(kart1.getYCoordinate() - 1);
break;
case 8:
kart1.setYCoordinate(kart1.getYCoordinate() - 1);
break;
case 9:
case 10:
case 11:
kart1.setXCoordinate(kart1.getXCoordinate() + 1);
kart1.setYCoordinate(kart1.getYCoordinate() - 1);
break;
case 12:
kart1.setXCoordinate(kart1.getXCoordinate() + 1);
break;
case 13:
case 14:
case 15:
kart1.setXCoordinate(kart1.getXCoordinate() + 1);
kart1.setYCoordinate(kart1.getYCoordinate() + 1);
break;
}
}
}发布于 2022-03-14 07:37:48
您的代码打开套接字,然后引发一个新线程来启动游戏。套接字、读取器和写入器被传递到线程中,直到到达RacingTrack为止。RacingTrack构造函数立即尝试发送/接收数据,并注意读取数据是一个阻塞调用。。它等待数据被读取。
因此,除非关闭服务器并因此切断TCP连接,否则客户机仍然希望接收一些数据,因此耐心等待。
https://stackoverflow.com/questions/71463901
复制相似问题