imported from remote update
git-svn-id: svn://anubis/gvsu@97 45c1a28c-8058-47b2-ae61-ca45b979098e
This commit is contained in:
parent
a4356f557a
commit
7795f9bc1c
@ -1,29 +1,174 @@
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
import javax.swing.border.*;
|
import javax.swing.border.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
public class BlobWars extends JFrame
|
public class BlobWars extends JFrame
|
||||||
{
|
{
|
||||||
public static void main(String[] args)
|
private BlobWarsWorld m_world;
|
||||||
{
|
private BlobWarsPanel m_panel;
|
||||||
BlobWars jt = new BlobWars();
|
private JTextField m_nameField;
|
||||||
}
|
private JTextField m_serverField;
|
||||||
|
private JButton m_connectButton;
|
||||||
|
private EventHandler m_handler;
|
||||||
|
private javax.swing.Timer m_timer;
|
||||||
|
private Socket m_socket;
|
||||||
|
private BufferedWriter m_writer;
|
||||||
|
|
||||||
public BlobWars()
|
public BlobWars()
|
||||||
{
|
{
|
||||||
super("Josh's Blob Wars Game for CS654");
|
super("Josh's Blob Wars Game for CS654");
|
||||||
setSize(400, 500);
|
m_world = new BlobWarsWorld();
|
||||||
|
/* TODO: REMOVE */
|
||||||
|
m_world.addPlayer("Alice");
|
||||||
|
m_world.getPlayer("Alice").health = 0.8;
|
||||||
|
m_world.addPlayer("Bob the Bad");
|
||||||
|
m_world.getPlayer("Bob the Bad").health = 0.6;
|
||||||
|
m_world.addPlayer("Jo");
|
||||||
|
m_world.getPlayer("Jo").health = 0.4;
|
||||||
|
m_world.addPlayer("Triskaidekaphobia");
|
||||||
|
m_world.getPlayer("Triskaidekaphobia").health = 0.2;
|
||||||
|
/* END TODO */
|
||||||
|
|
||||||
|
m_handler = new EventHandler();
|
||||||
|
m_panel = new BlobWarsPanel(this, m_world);
|
||||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||||
// setResizable(false);
|
setResizable(false);
|
||||||
getContentPane().add(new JPanel() {{
|
getContentPane().add(new JPanel() {{
|
||||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
add(new JPanel() {{
|
add(new JPanel() {{
|
||||||
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||||
add(new JLabel("hi!"));
|
add(new JLabel("Player name: "));
|
||||||
|
add(m_nameField = new JTextField());
|
||||||
}});
|
}});
|
||||||
add(new BlobWarsPanel());
|
add(new JPanel() {{
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||||
|
add(new JLabel("Server: "));
|
||||||
|
add(m_serverField = new JTextField());
|
||||||
|
m_serverField.addKeyListener(m_handler);
|
||||||
|
add(m_connectButton = new JButton("Connect"));
|
||||||
|
m_connectButton.addActionListener(m_handler);
|
||||||
}});
|
}});
|
||||||
|
// add(new Box.Filler(new Dimension(0, 0),
|
||||||
|
// new Dimension(0, 10000),
|
||||||
|
// new Dimension(10000, 10000)));
|
||||||
|
// add(new JPanel() {{
|
||||||
|
// setLayout(new BorderLayout());
|
||||||
|
add(m_panel);
|
||||||
|
m_panel.addKeyListener(m_handler);
|
||||||
|
// }});
|
||||||
|
}});
|
||||||
|
setSize(getPreferredSize());
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPlayerName()
|
||||||
|
{
|
||||||
|
return m_nameField.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doConnect()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
m_socket = new Socket(m_serverField.getText(), BlobWarsServer.PORT);
|
||||||
|
m_writer = new BufferedWriter(
|
||||||
|
new OutputStreamWriter(m_socket.getOutputStream()));
|
||||||
|
m_writer.write("NAME:" + m_nameField.getText() + "\n");
|
||||||
|
} catch (Exception e) {
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
"Error connecting: " + e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(new Thread(new ClientHandler())).start();
|
||||||
|
m_connectButton.setEnabled(false);
|
||||||
|
m_nameField.setEnabled(false);
|
||||||
|
m_serverField.setEnabled(false);
|
||||||
|
m_panel.requestFocusInWindow();
|
||||||
|
m_timer = new javax.swing.Timer(50, m_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClientHandler implements Runnable
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
BufferedReader br;
|
||||||
|
try {
|
||||||
|
br = new BufferedReader(
|
||||||
|
new InputStreamReader(m_socket.getInputStream()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main client loop */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
String line = "";
|
||||||
|
try {
|
||||||
|
line = br.readLine();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
System.out.println("GOT LINE: " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EventHandler implements ActionListener, KeyListener
|
||||||
|
{
|
||||||
|
public void actionPerformed(ActionEvent e)
|
||||||
|
{
|
||||||
|
if (e.getSource() == m_connectButton)
|
||||||
|
{
|
||||||
|
doConnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyPressed(KeyEvent e)
|
||||||
|
{
|
||||||
|
if (e.getSource() == m_panel)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
switch (e.getKeyCode())
|
||||||
|
{
|
||||||
|
case KeyEvent.VK_UP:
|
||||||
|
m_writer.write("UP\n");
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_DOWN:
|
||||||
|
m_writer.write("DOWN\n");
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_LEFT:
|
||||||
|
m_writer.write("LEFT\n");
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_RIGHT:
|
||||||
|
m_writer.write("RIGHT\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {}
|
||||||
|
}
|
||||||
|
else if (e.getSource() == m_serverField)
|
||||||
|
{
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER)
|
||||||
|
{
|
||||||
|
doConnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyReleased(KeyEvent e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyTyped(KeyEvent e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
new BlobWars();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,107 @@
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.*;
|
import javax.swing.border.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public class BlobWarsPanel extends JPanel
|
public class BlobWarsPanel extends JPanel
|
||||||
{
|
{
|
||||||
public BlobWarsPanel()
|
private BlobWarsWorld m_world;
|
||||||
|
private BlobWars m_gui;
|
||||||
|
|
||||||
|
public BlobWarsPanel(BlobWars gui, BlobWarsWorld world)
|
||||||
{
|
{
|
||||||
Dimension sz = new Dimension(400, 400);
|
Dimension sz = new Dimension(500, 500);
|
||||||
setMinimumSize(sz);
|
setMinimumSize(sz);
|
||||||
setPreferredSize(sz);
|
setPreferredSize(sz);
|
||||||
setMaximumSize(sz);
|
setMaximumSize(sz);
|
||||||
|
m_world = world;
|
||||||
|
m_gui = gui;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void paint(Graphics g)
|
public void paint(Graphics g)
|
||||||
{
|
{
|
||||||
// System.out.println("Width: " + getWidth() + " Height: " + getHeight());
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
g.setColor(Color.RED);
|
|
||||||
g.fillRect(0, 0, 40, 20);
|
/* draw background */
|
||||||
|
g2d.setColor(Color.BLACK);
|
||||||
|
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
|
||||||
|
/* draw players */
|
||||||
|
for (Player p : m_world.getPlayers().values())
|
||||||
|
{
|
||||||
|
drawPlayer(p, g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawPlayer(Player p, Graphics g)
|
||||||
|
{
|
||||||
|
double xscl = p.x * getWidth();
|
||||||
|
double yscl = p.y * getHeight();
|
||||||
|
double rxscl = p.radius * getWidth();
|
||||||
|
double ryscl = p.radius * getHeight();
|
||||||
|
|
||||||
|
/* draw the blob circle */
|
||||||
|
g.setColor(p.name.equals(m_gui.getPlayerName())
|
||||||
|
? new Color(0.7f, 1.0f, 1.0f)
|
||||||
|
: Color.CYAN);
|
||||||
|
g.fillOval((int) (xscl - rxscl),
|
||||||
|
(int) (getHeight() - (yscl + ryscl)),
|
||||||
|
(int) (2 * rxscl),
|
||||||
|
(int) (2 * ryscl));
|
||||||
|
g.setColor(Color.BLUE);
|
||||||
|
g.drawOval((int) (xscl - rxscl),
|
||||||
|
(int) (getHeight() - (yscl + ryscl)),
|
||||||
|
(int) (2 * rxscl),
|
||||||
|
(int) (2 * ryscl));
|
||||||
|
|
||||||
|
/* draw the health bar */
|
||||||
|
Color hcol;
|
||||||
|
if (p.health >= 0.9)
|
||||||
|
hcol = Color.GREEN;
|
||||||
|
else if (p.health >= 0.5)
|
||||||
|
hcol = new Color((float) ((0.9 - p.health) / 0.4), 1.0f, 0.0f);
|
||||||
|
else if (p.health >= 0.1)
|
||||||
|
hcol = new Color(1.0f, (float) ((p.health - 0.1) / 0.4), 0.0f);
|
||||||
|
else
|
||||||
|
hcol = Color.RED;
|
||||||
|
int hbarwidth = (int) (rxscl * 1.4);
|
||||||
|
int hbarheight = (int) (ryscl * 0.2);
|
||||||
|
int hbarx = (int) (xscl - hbarwidth/2);
|
||||||
|
int hbary = (int) (getHeight() - (p.r < Math.PI
|
||||||
|
? (yscl - 3*hbarheight/2)
|
||||||
|
: (yscl + 5*hbarheight/2)));
|
||||||
|
g.setColor(hcol);
|
||||||
|
g.fillRect(hbarx, hbary, (int) (hbarwidth * p.health), hbarheight);
|
||||||
|
g.setColor(Color.BLUE);
|
||||||
|
g.drawRect(hbarx, hbary, hbarwidth, hbarheight);
|
||||||
|
|
||||||
|
/* draw the shooter triangle */
|
||||||
|
int[] s_pointsx = new int[3];
|
||||||
|
int[] s_pointsy = new int[3];
|
||||||
|
s_pointsx[0] = (int) (xscl + rxscl * Math.cos(p.r));
|
||||||
|
s_pointsy[0] = getHeight() -
|
||||||
|
(int) (yscl + ryscl * Math.sin(p.r));
|
||||||
|
s_pointsx[1] = (int) (xscl + rxscl * 0.3 * Math.cos(p.r + Math.PI / 2));
|
||||||
|
s_pointsy[1] = getHeight() -
|
||||||
|
(int) (yscl + ryscl * 0.3 * Math.sin(p.r + Math.PI / 2));
|
||||||
|
s_pointsx[2] = (int) (xscl + rxscl * 0.3 * Math.cos(p.r - Math.PI / 2));
|
||||||
|
s_pointsy[2] = getHeight() -
|
||||||
|
(int) (yscl + ryscl * 0.3 * Math.sin(p.r - Math.PI / 2));
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
g.fillPolygon(s_pointsx, s_pointsy, 3);
|
||||||
|
g.setColor(Color.BLACK);
|
||||||
|
g.drawPolygon(s_pointsx, s_pointsy, 3);
|
||||||
|
|
||||||
|
/* draw the player's name */
|
||||||
|
char[] chars = new char[p.name.length()];
|
||||||
|
p.name.getChars(0, p.name.length(), chars, 0);
|
||||||
|
int width = g.getFontMetrics().charsWidth(chars, 0, p.name.length());
|
||||||
|
int height = g.getFontMetrics().getHeight();
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
g.drawString(p.name,
|
||||||
|
(int) (xscl - width/2),
|
||||||
|
getHeight() - 4 - (p.y >= 0.5
|
||||||
|
? ((int) (yscl - ryscl - height))
|
||||||
|
: ((int) (yscl + ryscl)) ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,52 @@
|
|||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
|
||||||
public class BlobWarsServer extends Thread
|
public class BlobWarsServer
|
||||||
{
|
{
|
||||||
public static final int PORT = 38491;
|
public static final int PORT = 38491;
|
||||||
|
|
||||||
private ServerSocket m_socket;
|
private ServerSocket m_socket;
|
||||||
|
private BlobWarsWorld m_world;
|
||||||
|
private Vector<ClientUpdate> m_clientUpdates;
|
||||||
|
private HashMap<Socket, String> m_socketToPlayerName;
|
||||||
|
private HashMap<String, Player> m_lastPlayers;
|
||||||
|
private HashMap<Integer, Shot> m_lastShots;
|
||||||
|
|
||||||
public void run()
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
BlobWarsServer bws = new BlobWarsServer();
|
||||||
|
bws.mainloop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlobWarsServer()
|
||||||
|
{
|
||||||
|
m_world = new BlobWarsWorld();
|
||||||
|
m_clientUpdates = new Vector<ClientUpdate>();
|
||||||
|
m_socketToPlayerName = new HashMap<Socket, String>();
|
||||||
try {
|
try {
|
||||||
m_socket = new ServerSocket(PORT);
|
m_socket = new ServerSocket(PORT);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClientUpdate
|
||||||
|
{
|
||||||
|
public Socket socket;
|
||||||
|
public String message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mainloop()
|
||||||
|
{
|
||||||
|
if (m_socket == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new Thread(new ServerGameLoop()).start();
|
||||||
|
|
||||||
|
/* listen loop to accept new connections */
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Socket client;
|
Socket client;
|
||||||
@ -22,6 +54,7 @@ public class BlobWarsServer extends Thread
|
|||||||
client = m_socket.accept();
|
client = m_socket.accept();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("Socket error!");
|
System.out.println("Socket error!");
|
||||||
|
e.printStackTrace();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +64,127 @@ public class BlobWarsServer extends Thread
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processClientUpdate(ClientUpdate cu)
|
||||||
|
{
|
||||||
|
StringTokenizer st = new StringTokenizer(cu.message, ":");
|
||||||
|
Vector<String> tokens = new Vector<String>();
|
||||||
|
while (st.hasMoreTokens())
|
||||||
|
{
|
||||||
|
tokens.add(st.nextToken());
|
||||||
|
}
|
||||||
|
String[] arr = tokens.toArray(new String[1]);
|
||||||
|
if (arr.length < 2)
|
||||||
|
return;
|
||||||
|
if (arr[0].equals("NAME"))
|
||||||
|
{
|
||||||
|
m_world.addPlayer(arr[1]);
|
||||||
|
m_socketToPlayerName.put(cu.socket, arr[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* the rest of the commands all require a player to be registered */
|
||||||
|
if (!m_socketToPlayerName.containsKey(cu.socket))
|
||||||
|
return;
|
||||||
|
String playerName = m_socketToPlayerName.get(cu.socket);
|
||||||
|
if (arr[0].equals("SHOOT")) {
|
||||||
|
m_world.shoot(playerName);
|
||||||
|
} else if (arr[0].equals("UP")) {
|
||||||
|
m_world.moveUp(playerName);
|
||||||
|
} else if (arr[0].equals("DOWN")) {
|
||||||
|
m_world.moveDown(playerName);
|
||||||
|
} else if (arr[0].equals("LEFT")) {
|
||||||
|
m_world.moveLeft(playerName);
|
||||||
|
} else if (arr[0].equals("RIGHT")) {
|
||||||
|
m_world.moveRight(playerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ServerGameLoop implements Runnable
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Thread.sleep(45);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
System.out.println("ServerGameLoop: interrupted!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply changes from clients */
|
||||||
|
synchronized (m_clientUpdates)
|
||||||
|
{
|
||||||
|
for (ClientUpdate cu : m_clientUpdates)
|
||||||
|
{
|
||||||
|
processClientUpdate(cu);
|
||||||
|
}
|
||||||
|
m_clientUpdates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_world.step();
|
||||||
|
|
||||||
|
/* push updates to clients */
|
||||||
|
HashMap<String, Player> pushPlayers =
|
||||||
|
new HashMap<String, Player>();
|
||||||
|
HashMap<Integer, Shot> pushShots =
|
||||||
|
new HashMap<Integer, Shot>();
|
||||||
|
if (m_lastPlayers == null)
|
||||||
|
pushPlayers.putAll(m_world.getPlayers());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HashMap<String, Player> players = m_world.getPlayers();
|
||||||
|
for (String name : players.keySet())
|
||||||
|
{
|
||||||
|
if (!m_lastPlayers.containsKey(name))
|
||||||
|
pushPlayers.put(name, players.get(name));
|
||||||
|
else if (!players.get(name).equals(
|
||||||
|
m_lastPlayers.get(name)))
|
||||||
|
pushPlayers.put(name, players.get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_lastShots == null)
|
||||||
|
pushShots.putAll(m_world.getShots());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HashMap<Integer, Shot> shots = m_world.getShots();
|
||||||
|
for (Integer shotid : shots.keySet())
|
||||||
|
{
|
||||||
|
if (!m_lastShots.containsKey(shotid))
|
||||||
|
pushShots.put(shotid, shots.get(shotid));
|
||||||
|
else if (!shots.get(shotid).equals(
|
||||||
|
m_lastShots.get(shotid)))
|
||||||
|
pushShots.put(shotid, shots.get(shotid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write updated info to each client */
|
||||||
|
String sendLine = "";
|
||||||
|
for (Player p : pushPlayers.values())
|
||||||
|
{
|
||||||
|
sendLine += "PLAYER:" + p + "\n";
|
||||||
|
}
|
||||||
|
for (Shot s : pushShots.values())
|
||||||
|
{
|
||||||
|
sendLine += "SHOT:" + s + "\n";
|
||||||
|
}
|
||||||
|
synchronized (m_socketToPlayerName)
|
||||||
|
{
|
||||||
|
for (Socket client : m_socketToPlayerName.keySet())
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
BufferedWriter br = new BufferedWriter(
|
||||||
|
new OutputStreamWriter(
|
||||||
|
client.getOutputStream()));
|
||||||
|
br.write(sendLine, 0, sendLine.length());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ClientHandler implements Runnable
|
private class ClientHandler implements Runnable
|
||||||
{
|
{
|
||||||
private Socket m_socket;
|
private Socket m_socket;
|
||||||
@ -38,11 +192,54 @@ public class BlobWarsServer extends Thread
|
|||||||
public ClientHandler(Socket socket)
|
public ClientHandler(Socket socket)
|
||||||
{
|
{
|
||||||
m_socket = socket;
|
m_socket = socket;
|
||||||
System.out.println("Incoming connection from " + m_socket.getInetAddress().getAddress());
|
System.out.println("Incoming connection from " +
|
||||||
|
m_socket.getInetAddress().getHostAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
|
BufferedReader br;
|
||||||
|
try {
|
||||||
|
br = new BufferedReader(
|
||||||
|
new InputStreamReader(m_socket.getInputStream()));
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
ioe.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
String line;
|
||||||
|
try {
|
||||||
|
line = br.readLine();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
// TODO: remove this line to not print stack trace for
|
||||||
|
// a client that disconnects, and remove socket from
|
||||||
|
// HashMap after for() loop
|
||||||
|
ioe.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
System.out.println("SERVER GOT LINE: " + line);
|
||||||
|
if (line.equals("QUIT"))
|
||||||
|
{
|
||||||
|
synchronized (m_socketToPlayerName)
|
||||||
|
{
|
||||||
|
if (m_socketToPlayerName.containsKey(m_socket))
|
||||||
|
m_socketToPlayerName.remove(m_socket);
|
||||||
|
try {
|
||||||
|
m_socket.close();
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ClientUpdate cu = new ClientUpdate();
|
||||||
|
cu.socket = m_socket;
|
||||||
|
cu.message = line;
|
||||||
|
synchronized (m_clientUpdates)
|
||||||
|
{
|
||||||
|
m_clientUpdates.add(cu);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
206
cs654/final-proj/BlobWarsWorld.java
Normal file
206
cs654/final-proj/BlobWarsWorld.java
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class BlobWarsWorld
|
||||||
|
{
|
||||||
|
public static final double SHOT_SPEED = 0.3;
|
||||||
|
public static final double PLAYER_SPEED = 0.2;
|
||||||
|
public static final double PLAYER_SPIN_SPEED = Math.PI / 2;
|
||||||
|
|
||||||
|
private HashMap<String, Player> m_players;
|
||||||
|
private HashMap<Integer, Shot> m_shots;
|
||||||
|
private long m_lastStepTime;
|
||||||
|
private Integer m_shotID;
|
||||||
|
|
||||||
|
public BlobWarsWorld()
|
||||||
|
{
|
||||||
|
m_players = new HashMap<String, Player>();
|
||||||
|
m_shots = new HashMap<Integer, Shot>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean playerExists(String name)
|
||||||
|
{
|
||||||
|
return m_players.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer(String name)
|
||||||
|
{
|
||||||
|
return m_players.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addPlayer(String name)
|
||||||
|
{
|
||||||
|
if (playerExists(name))
|
||||||
|
return false;
|
||||||
|
Player p = new Player(name);
|
||||||
|
m_players.put(name, p);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p.x = (1.0 - 2 * Player.DEFAULT_RADIUS) * Math.random()
|
||||||
|
+ Player.DEFAULT_RADIUS;
|
||||||
|
p.y = (1.0 - 2 * Player.DEFAULT_RADIUS) * Math.random()
|
||||||
|
+ Player.DEFAULT_RADIUS;
|
||||||
|
} while (collidesWith(p).size() != 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shoot(String playerName)
|
||||||
|
{
|
||||||
|
if (!m_players.containsKey(playerName))
|
||||||
|
return;
|
||||||
|
/* TODO: check validity of shot, create Shot object */
|
||||||
|
Player p = m_players.get(playerName);
|
||||||
|
long curtime = (new Date()).getTime();
|
||||||
|
if ( ((curtime - p.lastShotTime) / 1000.0)
|
||||||
|
< Player.SHOT_DELAY)
|
||||||
|
{
|
||||||
|
/* calculate X & Y coordinates of shot */
|
||||||
|
double x = p.x + Math.cos(p.r) * (p.radius + Shot.DEFAULT_RADIUS);
|
||||||
|
double y = p.y + Math.sin(p.r) * (p.radius + Shot.DEFAULT_RADIUS);
|
||||||
|
m_shotID++;
|
||||||
|
Shot s = new Shot(m_shotID, curtime, x, y);
|
||||||
|
s.dx = Math.cos(p.r) * SHOT_SPEED;
|
||||||
|
s.dy = Math.sin(p.r) * SHOT_SPEED;
|
||||||
|
m_shots.put(m_shotID, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveUp(String playerName)
|
||||||
|
{
|
||||||
|
if (!m_players.containsKey(playerName))
|
||||||
|
return;
|
||||||
|
Player p = m_players.get(playerName);
|
||||||
|
p.dx = Math.cos(p.r) * PLAYER_SPEED;
|
||||||
|
p.dy = Math.cos(p.r) * PLAYER_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveDown(String playerName)
|
||||||
|
{
|
||||||
|
if (!m_players.containsKey(playerName))
|
||||||
|
return;
|
||||||
|
Player p = m_players.get(playerName);
|
||||||
|
p.dx = 0;
|
||||||
|
p.dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveLeft(String playerName)
|
||||||
|
{
|
||||||
|
if (!m_players.containsKey(playerName))
|
||||||
|
return;
|
||||||
|
Player p = m_players.get(playerName);
|
||||||
|
p.dr = PLAYER_SPIN_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveRight(String playerName)
|
||||||
|
{
|
||||||
|
if (!m_players.containsKey(playerName))
|
||||||
|
return;
|
||||||
|
Player p = m_players.get(playerName);
|
||||||
|
p.dr = -PLAYER_SPIN_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector<GameItem> collidesWith(GameItem gi)
|
||||||
|
{
|
||||||
|
Vector<GameItem> collideList = new Vector<GameItem>();
|
||||||
|
for (Player p : m_players.values())
|
||||||
|
{
|
||||||
|
if (p != gi && p.health > 0.0 && collidesWith(gi, p))
|
||||||
|
collideList.add(p);
|
||||||
|
}
|
||||||
|
for (Shot s : m_shots.values())
|
||||||
|
{
|
||||||
|
if (s != gi && collidesWith(gi, s))
|
||||||
|
collideList.add(s);
|
||||||
|
}
|
||||||
|
return collideList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean collidesWith(GameItem i1, GameItem i2)
|
||||||
|
{
|
||||||
|
double dx = i2.x - i1.x;
|
||||||
|
double dy = i2.y - i1.y;
|
||||||
|
double d2 = dx*dx + dy*dy;
|
||||||
|
double r = i1.radius + i2.radius;
|
||||||
|
double r2 = r*r;
|
||||||
|
return (d2 < r2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, Player> getPlayers()
|
||||||
|
{
|
||||||
|
return m_players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<Integer, Shot> getShots()
|
||||||
|
{
|
||||||
|
return m_shots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void step()
|
||||||
|
{
|
||||||
|
long curtime = (new Date()).getTime();
|
||||||
|
double elapsed = (curtime - m_lastStepTime) / 1000.0;
|
||||||
|
if (m_lastStepTime == 0)
|
||||||
|
elapsed = 0.001;
|
||||||
|
for (Player p : m_players.values())
|
||||||
|
{
|
||||||
|
p.x += p.dx * elapsed;
|
||||||
|
p.y += p.dy * elapsed;
|
||||||
|
p.r += p.dr * elapsed;
|
||||||
|
if (p.x < 0.0) p.x += 1.0;
|
||||||
|
if (p.x > 1.0) p.x -= 1.0;
|
||||||
|
if (p.y < 0.0) p.y += 1.0;
|
||||||
|
if (p.y > 1.0) p.y -= 1.0;
|
||||||
|
if (p.r < 0.0) p.r += Math.PI*2;
|
||||||
|
if (p.r > Math.PI*2) p.r -= Math.PI*2;
|
||||||
|
}
|
||||||
|
Vector<Integer> shotIDs = new Vector<Integer>();
|
||||||
|
shotIDs.addAll(m_shots.keySet());
|
||||||
|
for (Integer i : shotIDs)
|
||||||
|
{
|
||||||
|
Shot s = m_shots.get(i);
|
||||||
|
if (((curtime - s.createTime) / 1000.0) >= Shot.SHOT_DURATION)
|
||||||
|
{
|
||||||
|
m_shots.remove(i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.x += s.dx * elapsed;
|
||||||
|
s.y += s.dy * elapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate damage against players */
|
||||||
|
for (Player p : m_players.values())
|
||||||
|
{
|
||||||
|
Vector<GameItem> objs = collidesWith(p);
|
||||||
|
for (GameItem gi : objs)
|
||||||
|
{
|
||||||
|
if (gi instanceof Player)
|
||||||
|
{
|
||||||
|
p.health -= Player.COLLIDE_DAMAGE;
|
||||||
|
}
|
||||||
|
if (gi instanceof Shot)
|
||||||
|
{
|
||||||
|
p.health -= Shot.SHOT_DAMAGE;
|
||||||
|
Integer ifound = null;
|
||||||
|
for (Integer i : m_shots.keySet())
|
||||||
|
{
|
||||||
|
if (m_shots.get(i) == gi)
|
||||||
|
{
|
||||||
|
ifound = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ifound != null)
|
||||||
|
m_shots.remove(ifound);
|
||||||
|
}
|
||||||
|
if (p.health < 0.0)
|
||||||
|
p.health = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_lastStepTime = curtime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
cs654/final-proj/GameItem.java
Normal file
9
cs654/final-proj/GameItem.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
public class GameItem
|
||||||
|
{
|
||||||
|
public double radius;
|
||||||
|
public double x;
|
||||||
|
public double y;
|
||||||
|
public double dx;
|
||||||
|
public double dy;
|
||||||
|
}
|
41
cs654/final-proj/Player.java
Normal file
41
cs654/final-proj/Player.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
public class Player extends GameItem
|
||||||
|
{
|
||||||
|
public static final double DEFAULT_RADIUS = 0.06;
|
||||||
|
public static final double COLLIDE_DAMAGE = 0.002;
|
||||||
|
public static final double SHOT_DELAY = 4.0;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
public double health;
|
||||||
|
public double r;
|
||||||
|
public double dr;
|
||||||
|
public long lastShotTime;
|
||||||
|
|
||||||
|
public Player(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.radius = DEFAULT_RADIUS;
|
||||||
|
this.health = 1.0;
|
||||||
|
this.r = Math.random() * Math.PI * 2;
|
||||||
|
this.dr = 0;
|
||||||
|
this.dx = 0;
|
||||||
|
this.dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Player other)
|
||||||
|
{
|
||||||
|
return this.name.equals(other.name) &&
|
||||||
|
this.radius == other.radius &&
|
||||||
|
this.health == other.health &&
|
||||||
|
this.r == other.r &&
|
||||||
|
this.dr == other.dr &&
|
||||||
|
this.dx == other.dx &&
|
||||||
|
this.dy == other.dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("%s:%.3f:%.3f:%.3f:%.3f:%.3f:%.3f:%.3f:%.3f",
|
||||||
|
name, radius, health, x, y, r, dr, dx, dy);
|
||||||
|
}
|
||||||
|
}
|
37
cs654/final-proj/Shot.java
Normal file
37
cs654/final-proj/Shot.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
public class Shot extends GameItem
|
||||||
|
{
|
||||||
|
public static final double DEFAULT_RADIUS = 0.03;
|
||||||
|
public static final double SHOT_DURATION = 3.0;
|
||||||
|
public static final double SHOT_DAMAGE = 0.27;
|
||||||
|
|
||||||
|
public long createTime;
|
||||||
|
public Integer id;
|
||||||
|
|
||||||
|
public Shot(Integer id, long createTime, double x, double y)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
this.createTime = createTime;
|
||||||
|
this.radius = DEFAULT_RADIUS;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.dx = 0;
|
||||||
|
this.dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Shot other)
|
||||||
|
{
|
||||||
|
return this.createTime == other.createTime &&
|
||||||
|
this.radius == other.radius &&
|
||||||
|
this.x == other.x &&
|
||||||
|
this.y == other.y &&
|
||||||
|
this.dx == other.dx &&
|
||||||
|
this.dy == other.dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("%d:%.3f:%.3f:%.3f:%.3f:%.3f",
|
||||||
|
id, radius, x, y, dx, dy);
|
||||||
|
}
|
||||||
|
}
|
1
cs654/final-proj/make.bat
Executable file
1
cs654/final-proj/make.bat
Executable file
@ -0,0 +1 @@
|
|||||||
|
javac *.java
|
1
cs654/final-proj/run.bat
Executable file
1
cs654/final-proj/run.bat
Executable file
@ -0,0 +1 @@
|
|||||||
|
java BlobWars
|
1
cs654/final-proj/runserver.bat
Executable file
1
cs654/final-proj/runserver.bat
Executable file
@ -0,0 +1 @@
|
|||||||
|
java BlobWarsServer
|
Loading…
x
Reference in New Issue
Block a user