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.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.border.*;
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
public class BlobWars extends JFrame
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
BlobWars jt = new BlobWars();
|
||||
}
|
||||
private BlobWarsWorld m_world;
|
||||
private BlobWarsPanel m_panel;
|
||||
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()
|
||||
{
|
||||
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);
|
||||
// setResizable(false);
|
||||
setResizable(false);
|
||||
getContentPane().add(new JPanel() {{
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
add(new JPanel() {{
|
||||
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);
|
||||
}
|
||||
|
||||
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 javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import java.util.*;
|
||||
|
||||
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);
|
||||
setPreferredSize(sz);
|
||||
setMaximumSize(sz);
|
||||
m_world = world;
|
||||
m_gui = gui;
|
||||
}
|
||||
|
||||
public void paint(Graphics g)
|
||||
{
|
||||
// System.out.println("Width: " + getWidth() + " Height: " + getHeight());
|
||||
g.setColor(Color.RED);
|
||||
g.fillRect(0, 0, 40, 20);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
|
||||
/* 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.*;
|
||||
|
||||
public class BlobWarsServer extends Thread
|
||||
public class BlobWarsServer
|
||||
{
|
||||
public static final int PORT = 38491;
|
||||
|
||||
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 {
|
||||
m_socket = new ServerSocket(PORT);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
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 (;;)
|
||||
{
|
||||
Socket client;
|
||||
@ -22,6 +54,7 @@ public class BlobWarsServer extends Thread
|
||||
client = m_socket.accept();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Socket error!");
|
||||
e.printStackTrace();
|
||||
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 Socket m_socket;
|
||||
@ -38,11 +192,54 @@ public class BlobWarsServer extends Thread
|
||||
public ClientHandler(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()
|
||||
{
|
||||
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