288 lines
7.9 KiB
Java
288 lines
7.9 KiB
Java
|
|
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<String, Player> m_players;
|
|
private HashMap<Integer, Shot> m_shots;
|
|
private long m_lastStepTime;
|
|
private int m_shotID;
|
|
|
|
public BlobWarsWorld()
|
|
{
|
|
m_players = new HashMap<String, Player>();
|
|
m_shots = new HashMap<Integer, Shot>();
|
|
}
|
|
|
|
public void clear()
|
|
{
|
|
m_players.clear();
|
|
m_shots.clear();
|
|
}
|
|
|
|
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<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;
|
|
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<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)
|
|
{
|
|
/* player is "dead" */
|
|
p.health = 0.0;
|
|
p.dx = p.dy = p.dr = 0;
|
|
}
|
|
}
|
|
}
|
|
m_lastStepTime = curtime;
|
|
}
|
|
}
|
|
|