/*
PlAr is Platform Arena: a 2D multiplayer shooting game
Copyright (c) 2010, Antonio Ragagnin <spocchio@gmail.com>
All rights reserved.
This file is licensed under the New BSD License.
*/
package plar.core;
import java.util.*;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jbox2d.dynamics.World;
import org.jbox2d.collision.*;
import java.util.Collections;
import org.jbox2d.common.Vec2;
import plar.ClientServer.ShownElement;
/**
* Game is a sort of interface of the Level (that contains all of the Element)
* end the user that sends keyboard Input and receive the getScreen()
*
* It is used by the Server layer
*
* @author Antonio Ragagnin
*
*/
public class Game extends Thread {
/**
* the state of the game, 1... ** t ocommment ** i have really no idea about the use of this variable.
*/
private int gamestate;
/**
* point to the level
*/
public Level level;
/**
* the scale factor from the reality and the world to send to the client.
*/
public Vec2 scale;
/**
* chat between users
*/
private List<String> chat;
/**
* resolution of the screen of the client, in pixel.
*/
public Point screenResolution;
/**
* resolution of the piece of world show in the client, in meters.
*/
public Vec2 gameResolution;
/**
* list of aviable guns
*/
public List<String> gunList;
/**
* list of aviable players
*/
public List<String> playerList;
/**
* remaining time from the end of the game
*/
public long remaning=0;
public Game() {
screenResolution = new Point(800, 600);
gameResolution = new Vec2(10f , 10f );
chat = new ArrayList<String>();
for (int i = 0; i < 10; i++)
chat.add("");
scale = new Vec2();
}
public synchronized void restart()
{
List<ElementPlayer> ap= level.getPlayers();
for(ElementPlayer p:ap)
{
p.kills=p.killed=0;
level.delElement(p);
level.reSpawn(p);
}
}
public synchronized void setResolution(float x,float y)
{
gameResolution = new Vec2(x,y);
}
public synchronized void addPlayer(ElementPlayer s) {
level.respawnQueue.add(s);
}
/**
* return the screen centered on currentPlayer
*/
public synchronized ArrayList<ShownElement> getScreen(ElementPlayer currentPlayer) {
if(currentPlayer==null) return new ArrayList<ShownElement>();
Vec2 curpos = currentPlayer.getPosition();
if(curpos==null) return new ArrayList<ShownElement>();
Vec2 gameScreen = new Vec2();
gameScreen.x = curpos.x - gameResolution.x / 2;
gameScreen.y = curpos.y - gameResolution.y / 2;
List insideL = level.getScreen(gameScreen, gameResolution);
ArrayList<ShownElement> se = new ArrayList<ShownElement>();
Collections.sort(insideL);
ArrayList <Element> inside = (ArrayList <Element> ) insideL;
for (Element e : inside) {
Point p = new Point(
(int) (scale.x * (e.getPosition().x - gameScreen.x)),
(int) (scale.y * (e.getPosition().y - gameScreen.y)));
SpriteSet ss = e.getCurrentSpriteSet();
if (ss != null) {
if (ss.autoSize)
ss.updateSpriteSize(e);
se.add(new ShownElement(p, ss, e.getAngle()));
}
}
return se;
}
public void spawn(ElementPlayer p) {
sendChat(p.username + " respawn!");
p.gl.clear();
if (p.gl.size() == 0)
for (String sgun : gunList) {
Common.info(2, sgun);
try {
@SuppressWarnings("unchecked")
Class c = Class.forName(Common.gunsPackage+sgun);
Gun ogun = (Gun) c.newInstance();
ogun.owner = p;
p.gl.add(ogun);
} catch (Exception e) {
e.printStackTrace();
} catch (java.lang.NoClassDefFoundError e) {
e.printStackTrace();
}
}
p.currentGunIndex = 0;
ArrayList<Element> al = (ArrayList<Element>) level
.getElementsByType(Common.ElementType.SPAWNPOINT);
int rand = (int) (Math.random() * al.size());
rand = rand % al.size();
Element spawn = al.get(rand);
p.setPosition(spawn.getPosition().x , spawn.getPosition().y);
Common.PlayerSpawnInfo psi = new Common.PlayerSpawnInfo();
psi.energy=new Integer(Common.getProperty("startingLife"));
int startAmmoID=new Integer(Common.getProperty("initialAmmoID"));
p.gl.get(startAmmoID).addAmmo(new Integer(Common.getProperty("startingAmmo")));
psi.guns=p.gl;
p.actions.forceAction("status", psi );
level.addElement(p);
}
public synchronized void run() {
if (gamestate != 1)
return;
// check who died and add it to the dead list
// Ok();
try {
float dt = level.Dt;// / level.fractionT;
//Common.info(7, "Game.run() simulating "+dt+" x "+level.fractionT+ " = "+level.Dt);
//for (int i = 0; i < level.fractionT; i++)
level.world.step(dt, 1 ,1);
} catch (Exception ex) {
Common.info(7, "---> Game.run() JBox2D FAILED - world locked.");
ex.printStackTrace();
}
for (Element e : level.destroyQueue) {
// Common.info(3, "Game.delElement(): deleting "
// + e.body.getUserData());
// e.body.setUserData(null);
level.world.destroyBody(e.body);
}
for (Element e : level.respawnQueue) {
ElementPlayer p = (ElementPlayer) e;
spawn(p);
}
level.respawnQueue.clear();
level.destroyQueue.clear();
level.run();
for (Element e : level.getRunnable()) {
// Ok();
e.run();
}
}
public synchronized void addElement(Element e) {
level.addElement(e);
}
/*
public synchronized boolean ok() {
return !level.world.isLocked();
}
public synchronized void Ok() {
while (!ok()) {
try {
delta();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
*/
public synchronized void delta() throws InterruptedException {
sleep(20);
}
public synchronized void sendInput(ElementPlayer p, KeyFlag premuti) {
// Common.info(7,p.toString()+" sent "+premuti);
//Ok();
p.actions.forceAction("input", premuti);
}
public synchronized boolean setLevel(Level l) {
l.world = new World(l.g, true);
Common.info(1, "Game.setLevel() Loading level... of dimension" + l.dim + " and force"
+ l.world.getGravity());
l.Initialize();
scale.x = ((float) (screenResolution.x)) / gameResolution.x;
scale.y = ((float) (screenResolution.y)) / gameResolution.y;
//level.world.setWarmStarting(true);
//level.world.setContinuousPhysics(true);
if (gamestate == 0)
level = l;
return true;
}
public synchronized void sendChat(ElementPlayer p, String s) {
String nick;
nick = p.username;
sendChat("<"+nick+"> "+s);
}
public synchronized void sendChat(String s) {
Calendar cal = new GregorianCalendar();
int ore = cal.get(+ Calendar.HOUR_OF_DAY);
int minuti = cal.get(Calendar.MINUTE);
int secondi = cal.get(Calendar.SECOND);
chat.add(chat.size() - 1, "[" + ore + ":" + minuti +"] " + s);
chat.remove(0);
}
public String getGuns(ElementPlayer p) {
String s="";
for(int i=0; i< gunList.size(); i++)
{
if(p.currentGunIndex==i) s+="["+gunList.get(i)+"]";
else s+=" "+gunList.get(i)+" ";
s+=" "+p.gl.get(i).ammo+"\r\n";
}
return s;
}
public synchronized int getScore(ElementPlayer p) {
return p.kills;
}
public synchronized int getSpawns(ElementPlayer p) {
return p.killed;
}
public synchronized String getChat() {
return Common.joinAL(chat);
}
public synchronized void startGame() {
if (gamestate != 0)
return;
gamestate++;
}
}