import java.util.*; public class BlobWarsWorld { public static final double SHOT_SPEED = 0.4; public static final double PLAYER_SPEED = 0.2; public static final double PLAYER_SPIN_SPEED = Math.PI / 2; private HashMap m_players; private HashMap m_shots; private long m_lastStepTime; private int m_shotID; public BlobWarsWorld() { m_players = new HashMap(); m_shots = new HashMap(); } public void clear() { m_players.clear(); m_shots.clear(); } public void resetPlayers() { for (Player p : m_players.values()) { p.health = 1.0; p.dx = 0; p.dy = 0; } } public boolean playerExists(String name) { return m_players.containsKey(name); } public boolean shotExists(Integer id) { return m_shots.containsKey(id); } public Player getPlayer(String name) { return m_players.get(name); } public Shot getShot(Integer id) { return m_shots.get(id); } public void updatePlayer(String playerInfo) { StringTokenizer st = new StringTokenizer(playerInfo, ":"); if (st.hasMoreTokens()) { String name = st.nextToken(); if (!playerExists(name)) addPlayer(name); getPlayer(name).fromString(playerInfo); } } public void updateShot(String shotInfo) { StringTokenizer st = new StringTokenizer(shotInfo, ":"); if (st.hasMoreTokens()) { String idstr = st.nextToken(); Integer id = Integer.parseInt(idstr); if (!shotExists(id)) addShot(id); getShot(id).fromString(shotInfo); } } public void addShot(Integer id) { Shot s = new Shot(id, 0, 0, 0); m_shots.put(id, s); } 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 removePlayer(String name) { m_players.remove(name); } public void removeShot(Integer id) { m_shots.remove(id); } public void shoot(String playerName) { if (!m_players.containsKey(playerName)) return; Player p = m_players.get(playerName); if (p.health <= 0.0) return; 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) * (0.01 + p.radius + Shot.DEFAULT_RADIUS); double y = p.y + Math.sin(p.r) * (0.01 + 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); p.lastShotTime = curtime; } } public void moveUp(String playerName) { if (!m_players.containsKey(playerName)) return; Player p = m_players.get(playerName); if (p.health <= 0.0) return; p.dx = Math.cos(p.r) * PLAYER_SPEED; p.dy = Math.sin(p.r) * PLAYER_SPEED; p.dr = 0; } public void moveDown(String playerName) { if (!m_players.containsKey(playerName)) return; Player p = m_players.get(playerName); p.dx = 0; p.dy = 0; p.dr = 0; } public void moveLeft(String playerName) { if (!m_players.containsKey(playerName)) return; Player p = m_players.get(playerName); if (p.health <= 0.0) return; p.dr += PLAYER_SPIN_SPEED; if (Math.abs(p.dr) < 0.001) p.dr = 0; } public void moveRight(String playerName) { if (!m_players.containsKey(playerName)) return; Player p = m_players.get(playerName); if (p.health <= 0.0) return; p.dr -= PLAYER_SPIN_SPEED; if (Math.abs(p.dr) < 0.001) p.dr = 0; } public Vector collidesWith(GameItem gi) { Vector collideList = new Vector(); 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 getPlayers() { return m_players; } public HashMap 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 shotIDs = new Vector(); 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; if (s.x < 0.0) s.x += 1.0; if (s.x > 1.0) s.x -= 1.0; if (s.y < 0.0) s.y += 1.0; if (s.y > 1.0) s.y -= 1.0; } } /* calculate damage against players */ for (Player p : m_players.values()) { Vector 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) { /* player is "dead" */ p.health = 0.0; p.dx = p.dy = p.dr = 0; } } } m_lastStepTime = curtime; } }