package beaver.game;
import java.io.*;
import java.net.*;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.JOptionPane;
import org.newdawn.fizzy.Body;
import org.newdawn.fizzy.Circle;
import org.newdawn.fizzy.DynamicBody;
import org.newdawn.fizzy.Rectangle;
import org.newdawn.fizzy.StaticBody;
import org.newdawn.fizzy.World;
import org.newdawn.slick.Animation;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.ImageBuffer;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;
import beaver.game.GameplayState.Item;
//Need to disable holding of enter key in networked mode
//How to get init to be called before update?
//gotta add a bunch of shit that ant fixed in the real game
public class ClientState extends GameplayState{
private Socket serverConn;
private String serverIP;
private DataInputStream fromServer;
private DataOutputStream toServer;
private ObjectOutputStream objOut;
private ObjectInputStream objIn;
private boolean isHost;
private Queue<String> p1Moves = null;
private Queue<String> p2Moves = null;
int movesVersion = 0;
private boolean hasStarted = false;
private long gameStartTime;
public ClientState(int stateID, String ip) {
super(stateID);
serverIP = ip;
}
public void connect(){
try {
serverConn = new Socket(serverIP,Constants.SERVER_PORT);
fromServer = new DataInputStream(serverConn.getInputStream());
toServer = new DataOutputStream(serverConn.getOutputStream());
objIn = new ObjectInputStream(serverConn.getInputStream());
objOut = new ObjectOutputStream(serverConn.getOutputStream());
String message;
try {
message = fromServer.readUTF();
if(message.equalsIgnoreCase("error")){
handleError();
}
p1 = (Player) objIn.readObject();
p2 = (Player) objIn.readObject();
terrainBitmap = (float[][]) objIn.readObject();
isHost = fromServer.readBoolean();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
printState();
}
private void handleError() {
System.out.println("Unable to establish connection to host");
System.exit(1);
}
public void printState(){
System.out.println("Player ID: " + p1.getID());
System.out.println("Player name: " + p1.getName());
System.out.println("Host: " + isHost);
if(terrainBitmap==null){
System.out.println("Error retreiving bitmap");
return;
}
}
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
p1Moves = new LinkedList<String>();
p2Moves = new LinkedList<String>();
connect();
if(isHost){
currentPlayer = p1;
}else{
currentPlayer = p2;
}
///////////////////////////////////
try {
bg_sprite = new Image("data/8bitBGgood.gif");
} catch (SlickException e) {
e.printStackTrace();
}
gc.setTargetFrameRate(Constants.FRAME_RATE);
gc.setVSync(true);
worldCenterX = gc.getWidth() / 2;
worldCenterY = gc.getHeight() / 2;
world = new World();
world.setIterations(Constants.ITERATIONS);
world.setGravity(-10);
terrainy = new ImageBuffer(Constants.MAX_WIDTH, Constants.MAX_HEIGHT*2);
SlickDisplay();
terrainyImage = terrainy.getImage();
createTerrainBody2(-terrainyImage.getWidth()/2, -terrainyImage.getHeight()/2);
for (int i = 0; i < Constants.BEAVERS_PER_TEAM; i++) {
int[] coord = randomFreeCoordinate(20);
p1.getTeam()[i].setBody(new DynamicBody(new Circle(10.0f), -100*i, 1300));
p1.getTeam()[i].getBody().setDensity(1);
p1.getTeam()[i].getBody().setFriction(1000);
p1.getTeam()[i].getBody().setRestitution(0f);
p1.getTeam()[i].getBody().setAngularDamping(1f);
p1.getTeam()[i].getBody().setFixedRotation(true);
world.add(p1.getTeam()[i].getBody());
}
for (int i = 0; i < Constants.BEAVERS_PER_TEAM; i++) {
int[] coord = randomFreeCoordinate(20);
p2.getTeam()[i].setBody(new DynamicBody(new Circle(10.0f), -100*i, 1300));
p2.getTeam()[i].getBody().setDensity(1);
p2.getTeam()[i].getBody().setFriction(1000);
p2.getTeam()[i].getBody().setRestitution(0f);
p2.getTeam()[i].getBody().setAngularDamping(1f);
p2.getTeam()[i].getBody().setFixedRotation(true);
world.add(p2.getTeam()[i].getBody());
}
//Add the invisible boundary
boundary = addBoundary(Constants.MAX_WIDTH*2,Constants.MAX_HEIGHT*3);
boundary.setRestitution(0f);
world.add(boundary);
world.addBodyListener(boundary, this);
// load beaver images to use in our animation
Image beaver = new Image("data/bazooka4.png");
Image beaver2 = new Image("data/bazooka5.png");
Image[] frames = {beaver.getFlippedCopy(false, true).getScaledCopy(0.5f), beaver2.getFlippedCopy(false, true).getScaledCopy(0.5f)};
Image[] frames2 = {beaver.getFlippedCopy(true, true).getScaledCopy(0.5f), beaver2.getFlippedCopy(true, true).getScaledCopy(0.5f)};
team1Moving = new Animation(frames, 1000, false); // duration in ms
team1MovingR = new Animation(frames2, 1000, false); // duration in ms
Image beaver3 = new Image("data/darkBazooka4.png");
Image beaver4 = new Image("data/darkBazooka5.png");
Image[] frames3 = {beaver3.getFlippedCopy(false, true).getScaledCopy(0.5f), beaver4.getFlippedCopy(false, true).getScaledCopy(0.5f)};
Image[] frames4 = {beaver3.getFlippedCopy(true, true).getScaledCopy(0.5f), beaver4.getFlippedCopy(true, true).getScaledCopy(0.5f)};
team2Moving = new Animation(frames3, 1000, false); // duration in ms
team2MovingR = new Animation(frames4, 1000, false); // duration in ms
// add the mouse listener
gc.getInput().addMouseListener(this);
//add two items to the world
item = new Item[]{new Item(), new Item()};
item[0].setTypeAmmo();
item[1].setTypeHP();
item[0].getBody().setFriction(1000);
item[1].getBody().setFriction(1000);
item[0].getBody().setRestitution(0);
item[1].getBody().setRestitution(0);
item[0].getBody().setFixedRotation(true);
item[1].getBody().setFixedRotation(true);
world.add(item[0].getBody());
world.add(item[1].getBody());
world.addBodyListener(item[0].getBody(), this);
world.addBodyListener(item[1].getBody(), this);
Body currentBeaverBody = currentPlayer.getCurrentBeaver().getBody();
crosshairAngle = 45;
crosshair = new StaticBody(new Rectangle(50f,5f),currentBeaverBody.getX(),currentBeaverBody.getY());
world.add(crosshair);
crosshair.setRotation(crosshairAngle);
crosshairImage = new Image("data/crosshair.png").getScaledCopy(0.5f);
bulletImage = new Image("data/wood.png").getScaledCopy(0.5f);
healthImage = new Image("data/health.png").getScaledCopy(0.5f);
ammoImage = new Image("data/ammo.png").getFlippedCopy(false, true).getScaledCopy(0.5f);
timer(Constants.SECONDS_PER_TURN);
///////////////////////////////////////////////
if(currentPlayer==p2){
waitToStart();
}
}
private void waitToStart() {
try {
toServer.writeInt(Constants.GET_MOVES);
toServer.writeInt(movesVersion);
p2Moves = (Queue<String>) objIn.readObject();
while(p2Moves==null){
Thread.sleep(Constants.NETWORK_WAIT);
toServer.writeInt(Constants.GET_MOVES);
toServer.writeInt(movesVersion);
p2Moves = (Queue<String>) objIn.readObject();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("RECEIVED OPPONENTS MOVES, PLAYING THEM NOW");
}
private void endTurn(GameContainer gc) throws SlickException{
if(currentPlayer==p1){
try{
System.out.println("Writing " + p1Moves.size() + " moves to server");
toServer.writeInt(Constants.WRITE_MOVES);
objOut.writeUnshared(p1Moves);
p1Moves.clear();
toServer.writeInt(Constants.GET_MOVES);
toServer.writeInt(movesVersion);
p2Moves = (Queue<String>) objIn.readObject(); //causing problems
while(p2Moves==null){
Thread.sleep(Constants.NETWORK_WAIT);
toServer.writeInt(Constants.GET_MOVES);
toServer.writeInt(movesVersion);
p2Moves = (Queue<String>) objIn.readObject();
}
System.out.println("OTHER PLAYER SENT ME " + p2Moves.size() + " MOVES");
} catch(IOException e){
throw new SlickException(e.getMessage());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
try {
toServer.writeInt(Constants.OPPONENT_TURN_ENDED);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Body currentBeaverBody = currentPlayer.getCurrentBeaver().getBody();
if (currentBeaverBody.isAttached()) currentBeaverBody.setActive(true);
//Cycle Player
nextPlayer();
currentBeaverBody = currentPlayer.getCurrentBeaver().getBody();
worldCenterX = gc.getWidth()/2 - (currentBeaverBody.getX()*scale);
worldCenterY = gc.getHeight()/2 - (currentBeaverBody.getY()*-scale);
timer(Constants.SECONDS_PER_TURN);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
if(currentPlayer.hasLost()){
if(currentPlayer==p1){
JOptionPane.showMessageDialog(null,"Player 2 Wins!");
}
else{
JOptionPane.showMessageDialog(null,"Player 1 Wins!");
}
sbg.enterState(BeaversGame.MAINMENUSTATE);
}
//if necessary remove beaver bodies
Beaver[] p1Team = p1.getTeam();
Beaver[] p2Team = p2.getTeam();
for(int i=0;i<Constants.BEAVERS_PER_TEAM;i++){
if(!p1Team[i].isAlive() && p1Team[i].getBody().isAttached()){
p1Team[i].getBody().setActive(false);
world.remove(p1Team[i].getBody());
}
if(!p2Team[i].isAlive() && p2Team[i].getBody().isAttached()){
p2Team[i].getBody().setActive(false);
world.remove(p2Team[i].getBody());
}
}
//if necessary, kill the bullet
if (killBullet){
if (bullet.isAttached()) {
bullet.setActive(false);
world.remove(bullet);
}
killBullet = false;
}
//if necessary, remove an item
for (int i = 0; i < item.length; i++){
if (item[i].remove == true && item[i].getBody().isAttached()) {
item[i].getBody().setActive(false);
world.remove(item[i].getBody());
}
}
//Check win condition
Body currentBeaverBody = currentPlayer.getCurrentBeaver().getBody();
Beaver currentBeaver = currentPlayer.getCurrentBeaver();
this.radius = currentBeaver.getCurrentWeapon().getBlastRadius();
if (powerSeqEngaged) {
if (power >= 150) power = 0;
else power+=4;
}
// Keep the camera centered at all times *GIANNI*
if(!cameraOnBullet){
if (currentBeaverBody.isAttached())
if (!currentBeaverBody.isSleeping()){
worldCenterX = gc.getWidth()/2 - (currentBeaverBody.getX()*scale);
worldCenterY = gc.getHeight()/2 - (currentBeaverBody.getY()*-scale);
}
}
else{
if (bullet.isAttached()){
worldCenterX = gc.getWidth()/2 - (bullet.getX()*scale);
worldCenterY = gc.getHeight()/2 - (bullet.getY()*-scale);
}
}
for (int i = 0; i < Constants.UPDATES; i++) {
boolean keypress = false;
Input input = gc.getInput();
if(currentPlayer == p1){
if (input.isKeyPressed(Input.KEY_C)) {
worldCenterX = gc.getWidth()/2 - (currentBeaverBody.getX()*scale);
worldCenterY = gc.getHeight()/2 - (currentBeaverBody.getY()*-scale);
}
if (input.isKeyDown(Input.KEY_Z)) {
if (scale > 0.001f) scale = scale - 0.001f;// /updates;
}
if (input.isKeyDown(Input.KEY_X)) {
scale = scale + 0.001f;// /updates;
}
if (input.isKeyDown(Input.KEY_W)) {
worldCenterY -= 0.1f;// /updates;
}
if (input.isKeyDown(Input.KEY_S)) {
worldCenterY += 0.1f;// /updates;
}
if(input.isKeyPressed(Input.KEY_R)){
p1Moves.add("r");
System.out.println(crosshairAngle);
crosshairAngle = 45;
keypress = true;
}
if(input.isKeyPressed(Input.KEY_Q)){
p1Moves.add("q");
currentPlayer.getCurrentBeaver().cycleWeapon();
keypress = true;
}
if (input.isKeyDown(Input.KEY_A)) {
worldCenterX -= 0.1f;// /updates;
}
if (input.isKeyPressed(Input.KEY_O)) {
p1Moves.add("o");
keypress = true;
endTurn(gc);
}
if (input.isKeyDown(Input.KEY_D)) {
worldCenterX += 0.1f;// /updates;
}
if (input.isKeyDown(Input.KEY_RIGHT)) {
p1Moves.add("right");
if(endTurn>0){
continue;
}
if (crosshairAngle > 180) crosshairAngle = 180-(crosshairAngle-180);
team1MovingR.update(delta*100);
team2MovingR.update(delta*100);
currentPlayer.getCurrentBeaver().setFacingR(true);
if (currentBeaverBody.getAngularVelocity() > -1.5)
currentBeaverBody.setAngularVelocity(currentBeaverBody
.getAngularVelocity() - 0.05f);
currentBeaverBody.setAngularVelocity(-1.5f);
keypress=true;
}
if (input.isKeyDown(Input.KEY_LEFT)) {
p1Moves.add("left");
if(endTurn>0){
continue;
}
if (crosshairAngle < 180) crosshairAngle = 180+(180-crosshairAngle);
team1Moving.update(delta*100);
team2Moving.update(delta*100);
currentPlayer.getCurrentBeaver().setFacingR(false);
if (currentBeaverBody.getAngularVelocity() < 1.5)
currentBeaverBody.setAngularVelocity(currentBeaverBody.getAngularVelocity() + 0.05f);
currentBeaverBody.setAngularVelocity(1.5f);
keypress = true;
}
if (input.isKeyDown(Input.KEY_UP)){
p1Moves.add("up");
if(endTurn>0){
continue;
}
if (crosshairAngle < 180 && crosshairAngle > 0) crosshairAngle -= 0.1f;
else if (crosshairAngle > 180 && crosshairAngle < 360) crosshairAngle += 0.1f;
keypress = true;
}
if (input.isKeyDown(Input.KEY_DOWN)){
p1Moves.add("down");
if(endTurn>0){
continue;
}
if (crosshairAngle < 180 && crosshairAngle > 0) crosshairAngle += 0.1f;
else if (crosshairAngle > 180 && crosshairAngle < 360) crosshairAngle -= 0.1f;
keypress = true;
}
if (input.isKeyPressed(Input.KEY_ENTER)) {
p1Moves.add("enter");
if(endTurn>0){
continue;
}
if(currentPlayer.getCurrentBeaver().getCurrentWeapon().getAmmo()>0){
currentPlayer.getCurrentBeaver().useWeapon();
if (!powerSeqEngaged) {
power = 1;
powerSeqEngaged = true;
}
else {
powerSeqEngaged = false;
currentBeaverBody.setActive(false);
bullet = new DynamicBody(new Circle(5),currentBeaverBody.getX(),currentBeaverBody.getY());
bullet.setBullet(true);
bullet.setRestitution(0);
float x = (float) (Math.sin(Math.toRadians(crosshairAngle)));
float y = (float) (Math.cos(Math.toRadians(crosshairAngle)));
float xForce = (power/50)*(x)*10000000f;
float yForce = (power/50)*(y)*10000000f;
//System.out.println("x is "+x+", y is "+y+", angle at"+crosshairAngle);
world.add(bullet);
world.addBodyListener(bullet, this);
bullet.applyForce(xForce, yForce);
//Shot is fired, turn is over
cameraOnBullet = true;
}
}
keypress = true;
}
if (input.isKeyPressed(Input.KEY_SPACE)) {
p1Moves.add("space");
if (currentBeaverBody.getYVelocity() < 0.7 && currentBeaver.getFacingR()) {
currentBeaverBody.applyForce(0, 1500000f);// /updates);
}
if (currentBeaverBody.getYVelocity() > -0.7 && !currentBeaver.getFacingR()) {
currentBeaverBody.applyForce(0, 1500000f);// /updates);
}
keypress = true;
}
if (input.isKeyPressed(Input.KEY_ESCAPE)){
sbg.enterState(BeaversGame.MAINMENUSTATE);
}
if(!keypress){
p1Moves.add(" ");
}
}
else{
if(!p2Moves.isEmpty()){
handleMove(p2Moves.remove(),gc,sbg,delta);
}
}
if (drawCircle) {
addExplosionToTerrain((int) collisionX, (int) collisionY, this.radius);
drawCircle = false;
}
if (System.currentTimeMillis() >= endTime || endTurn == 0) {
endTurn = -1;
endTurn(gc);
cameraOnBullet = false;
}
if (endTurn > 0) endTurn--;
world.update(1f / Constants.UPDATES_PER_SECOND);
}
}
private void handleMove(String move, GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
Body currentBeaverBody = currentPlayer.getCurrentBeaver().getBody();
Beaver currentBeaver = currentPlayer.getCurrentBeaver();
this.radius = currentBeaver.getCurrentWeapon().getBlastRadius();
if(move.equalsIgnoreCase("r")){
System.out.println(crosshairAngle);
crosshairAngle = 45;
}
if(move.equalsIgnoreCase("q")){
currentPlayer.getCurrentBeaver().cycleWeapon();
}
if (move.equalsIgnoreCase("o")) {
endTurn = 5000;
}
if (move.equalsIgnoreCase("right")) {
if(endTurn>0){
return;
}
if (crosshairAngle > 180) crosshairAngle = 180-(crosshairAngle-180);
team1MovingR.update(delta*100);
team2MovingR.update(delta*100);
currentPlayer.getCurrentBeaver().setFacingR(true);
if (currentBeaverBody.getAngularVelocity() > -1.5)
currentBeaverBody.setAngularVelocity(currentBeaverBody
.getAngularVelocity() - 0.05f);
currentBeaverBody.setAngularVelocity(-1.5f);
}
if (move.equalsIgnoreCase("left")) {
if(endTurn>0){
return;
}
if (crosshairAngle < 180) crosshairAngle = 180+(180-crosshairAngle);
team1Moving.update(delta*100);
team2Moving.update(delta*100);
currentPlayer.getCurrentBeaver().setFacingR(false);
if (currentBeaverBody.getAngularVelocity() < 1.5)
currentBeaverBody.setAngularVelocity(currentBeaverBody.getAngularVelocity() + 0.05f);
currentBeaverBody.setAngularVelocity(1.5f);
}
if (move.equalsIgnoreCase("up")){
if(endTurn>0){
return;
}
if (crosshairAngle < 180 && crosshairAngle > 0) crosshairAngle -= 0.1f;
else if (crosshairAngle > 180 && crosshairAngle < 360) crosshairAngle += 0.1f;
}
if (move.equalsIgnoreCase("down")){
if(endTurn>0){
return;
}
if (crosshairAngle < 180 && crosshairAngle > 0) crosshairAngle += 0.1f;
else if (crosshairAngle > 180 && crosshairAngle < 360) crosshairAngle -= 0.1f;
}
if (move.equalsIgnoreCase("enter")) {
if(endTurn>0){
return;
}
if(currentPlayer.getCurrentBeaver().getCurrentWeapon().getAmmo()>0){
currentPlayer.getCurrentBeaver().useWeapon();
if (!powerSeqEngaged) {
power = 1;
powerSeqEngaged = true;
}
else {
powerSeqEngaged = false;
currentBeaverBody.setActive(false);
bullet = new DynamicBody(new Circle(5),currentBeaverBody.getX(),currentBeaverBody.getY());
bullet.setBullet(true);
bullet.setRestitution(0);
float x = (float) (Math.sin(Math.toRadians(crosshairAngle)));
float y = (float) (Math.cos(Math.toRadians(crosshairAngle)));
float xForce = (power/50)*(x)*10000000f;
float yForce = (power/50)*(y)*10000000f;
//System.out.println("x is "+x+", y is "+y+", angle at"+crosshairAngle);
world.add(bullet);
world.addBodyListener(bullet, this);
bullet.applyForce(xForce, yForce);
//Shot is fired, turn is over
cameraOnBullet = true;
}
}
}
if (move.equalsIgnoreCase("space")) {
if (currentBeaverBody.getYVelocity() < 0.7 && currentBeaver.getFacingR()) {
currentBeaverBody.applyForce(0, 1500000f);// /updates);
}
if (currentBeaverBody.getYVelocity() > -0.7 && !currentBeaver.getFacingR()) {
currentBeaverBody.applyForce(0, 1500000f);// /updates);
}
}
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
bg_sprite.draw();
//g.setBackground(new Color(0,61,245));
g.setAntiAlias(true);
g.setColor(Color.white);
g.pushTransform();
g.translate(worldCenterX, worldCenterY);
g.scale(scale, -scale);
g.drawImage(terrainyImage, -terrainyImage.getWidth()/2, -terrainyImage.getHeight()/2);
g.popTransform();
g.pushTransform();
g.translate(worldCenterX, worldCenterY);
g.scale(scale, -scale);
for (int i = 0; i < world.getBodyCount(); i++) {
Body body = world.getBody(i);
if (!body.equals(terrainBody) && !body.equals(boundary)) {
g.setColor(Color.black);
drawBody(g, body);
}
}
g.popTransform();
g.setColor(Color.white);
placeCrosshairs();
if(currentPlayer==p1){
g.drawString(
"Left/right to move, space to jump, up/down to aim, enter to shoot."
+ "\nZ and X to zoom in and out, and R to reset the crosshair."
+ "\nW,A,S,D to pan, and ESC to pause.",
10, 25);
}
else{
g.drawString("OPPONENT'S TURN", 10, 25);
}
g.drawString(
"\n Time Remaining: "
+ (int)((endTime - System.currentTimeMillis()) / 1000f), 30,
500);
drawStats(g);
}
}