package state;
import java.awt.Point;
import org.lwjgl.input.Keyboard;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.elements.render.TextRenderer;
import de.lessvoid.nifty.screen.Screen;
import TrackRider.Coach;
import TrackRider.CoalCoach;
import engine.Map;
import static engine.Engine.appSpeed;
import static engine.Engine.elapsedAppTime;
import static engine.Engine.ShaderHandler;
import engine.State;
import TrackRider.Train;
import de.lessvoid.nifty.elements.render.ImageRenderer;
import de.lessvoid.nifty.render.NiftyImage;
import engine.Passenger;
import engine.StateManager;
import engine.Station;
import graphics.gui.ProgressbarControl;
import graphics.model.terrain.Terrain;
import static graphics.Graphics.setClearColor;
import static engine.Engine.pause;
import static engine.Engine.resume;
import java.util.Locale;
import java.util.Random;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
/**
*
* @author Kami Nasri
* @author Jari Saaranen <rasaari@gmail.com>
* @author simokr
*/
public class Game extends State {
private Map map;
private Train train;
private Terrain terrain;
private Vector2f gameCameraMultipliers;
private long passengerTimer;
private boolean KEY_POWER_UP;
private boolean KEY_POWER_DOWN;
private boolean KEY_BRAKES_ON;
private boolean KEY_BRAKES_OFF;
private boolean KEY_CURSOR_LEFT;
private boolean KEY_CURSOR_RIGHT;
private boolean KEY_CURSOR_UP;
private boolean KEY_CURSOR_DOWN;
private boolean KEY_TURN_LEFT;
private boolean KEY_TURN_RIGHT;
private boolean KEY_NO_TURN;
private boolean KEY_BUY_COAL;
private boolean KEY_REPAIR;
private final float POWER_CHANGE = 0.02f;
//GUI
private Screen screen;
private ProgressbarControl progressbarPower;
private ProgressbarControl progressbarHeat;
private ProgressbarControl progressbarDamage;
private Element niftyElement, tutorialElement, overheatElement, pausePopup;
private NiftyImage img;
private boolean popUpStuff;
String guiVelo;
@Override
public void init() {
setClearColor(new Vector3f(1.0f, 0.866f, 0.698f));
map = new Map();
terrain = new Terrain(Map.mapWidth*10, Map.mapHeight*10);
terrain.setPosition(0, -0.137f,0);
gameCameraMultipliers = new Vector2f((float) (-Math.PI/4.0), 3f);
passengerTimer = elapsedAppTime();
this.generateMap();
this.map.initializeStations();
this.map.updateRails();
train = new Train(map);
train.setLocation(map.findFreeSpace(9));
train.addCoach(Coach.COAL);
train.addCoach(Coach.PASSENGER);
//train.addCoach(Coach.PASSENGER);
//train.addCoach(Coach.PASSENGER);
//train.addCoach(Coach.PASSENGER);
//train.addCoach(Coach.PASSENGER);
//train.addCoach(Coach.PASSENGER);
this.KEY_POWER_UP = false;
this.KEY_POWER_DOWN = false;
this.KEY_TURN_LEFT = false;
this.KEY_TURN_RIGHT = false;
this.KEY_NO_TURN = false;
this.KEY_BRAKES_OFF = false;
this.KEY_BRAKES_ON = false;
this.KEY_CURSOR_LEFT = false;
this.KEY_CURSOR_RIGHT = false;
this.KEY_CURSOR_UP = false;
this.KEY_CURSOR_DOWN = false;
this.KEY_REPAIR = false;
popUpStuff = false;
}
@Override
public void initGui() {
gui.gotoScreen("gameScreen");
this.screen = gui.getScreen("gameScreen");
this.progressbarPower = screen.findControl("progressbar_power", ProgressbarControl.class);
this.progressbarHeat = screen.findControl("progressbar_heat", ProgressbarControl.class);
this.progressbarDamage = screen.findControl("progressbar_damage", ProgressbarControl.class);
if(tutorialElement == null){
tutorialElement = gui.createPopup("popupExit");
gui.showPopup(screen, tutorialElement.getId(), null);
}
}
@Override
public void render() {
this.terrain.render();
this.map.render();
this.train.render();
//Gui
this.niftyElement = gui.getCurrentScreen().findElementByName("velocity");
this.niftyElement.getRenderer(TextRenderer.class).getColor().setAlpha(1f);
String velocity = String.format(Locale.ENGLISH, "%.2f km/h - %.2f m/s", train.getBalancedVelocity()*3.6f, train.getBalancedVelocity());
this.niftyElement.getRenderer(TextRenderer.class).setText("Velocity: " +velocity); //Better way to trim float?
this.progressbarPower.setProgress(train.getPowerLevel());
this.progressbarHeat.setProgress(train.getHeat());
this.progressbarDamage.setProgress(train.getDamage());
if(train.getOverheat()){
this.img = gui.getRenderEngine().createImage(gui.getScreen("gameScreen"), "res/texture/overheat.png", false);
this.overheatElement = gui.getCurrentScreen().findElementByName("overheat");
this.overheatElement.getRenderer(ImageRenderer.class).setImage(img);
}else{
this.img = gui.getRenderEngine().createImage(gui.getScreen("gameScreen"), "res/texture/borderBox_1.png", false);
this.overheatElement = gui.getCurrentScreen().findElementByName("overheat");
this.overheatElement.getRenderer(ImageRenderer.class).setImage(img);
}
this.niftyElement = gui.getCurrentScreen().findElementByName("coals");
String coals = String.format(Locale.ENGLISH, "%d", train.getCoals());
this.niftyElement.getRenderer(TextRenderer.class).setText("coal: " + coals);
this.niftyElement = gui.getCurrentScreen().findElementByName("passengers");
String passengers = String.format(Locale.ENGLISH, "%d", train.getPassengerCount());
this.niftyElement.getRenderer(TextRenderer.class).setText("Passengers: " + passengers);
this.niftyElement = gui.getCurrentScreen().findElementByName("cash");
String cash = String.format(Locale.ENGLISH, "%.2f", train.getCash());
this.niftyElement.getRenderer(TextRenderer.class).setText("cash: " + cash + " $");
String stations = "Stations:\n";
for(Station station: map.getStations()) {
int onTime = 0;
for(Passenger p : train.getPassengerListToStation(station)) {
if(!p.isLate()) onTime++;
}
Station underTrain = map.getStationAtTile(train.getGridLocation());
if(underTrain != null && underTrain.equals(station)) {
stations += "\\#76e639#";
}
stations += station.getName() + " (" + onTime + " / " + train.getPassengersToStation(station)+") ";
if(underTrain != null && underTrain.equals(station)) {
stations += "<--";
}
stations += "\n";
}
niftyElement = gui.getCurrentScreen().findElementByName("stations");
niftyElement.getRenderer(TextRenderer.class).setText(stations);
}
@Override
public void update() {
// update keystates
while(Keyboard.next()) {
switch(Keyboard.getEventKey()) {
case Keyboard.KEY_A:
this.KEY_POWER_UP = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_Z:
this.KEY_POWER_DOWN = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_LEFT:
this.KEY_TURN_LEFT = Keyboard.getEventKeyState()? true: false;
this.KEY_CURSOR_LEFT = this.KEY_TURN_LEFT;
break;
case Keyboard.KEY_RIGHT:
this.KEY_TURN_RIGHT = Keyboard.getEventKeyState()? true: false;
this.KEY_CURSOR_RIGHT = this.KEY_TURN_RIGHT;
break;
case Keyboard.KEY_UP:
this.KEY_NO_TURN = Keyboard.getEventKeyState()? true: false;
this.KEY_CURSOR_UP = this.KEY_NO_TURN;
break;
case Keyboard.KEY_DOWN:
this.KEY_CURSOR_DOWN = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_C:
this.KEY_BRAKES_ON = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_V:
this.KEY_BRAKES_OFF = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_B:
this.KEY_BUY_COAL = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_R:
this.KEY_REPAIR = Keyboard.getEventKeyState()? true: false;
break;
case Keyboard.KEY_F5:
if(Keyboard.getEventKeyState() == false){
ShaderHandler.reloadAll();
}
break;
case Keyboard.KEY_PAUSE:
if(Keyboard.getEventKeyState() == false){
pause();
if(pausePopup == null){
pausePopup = gui.createPopup("popupPause");
gui.showPopup(screen, pausePopup.getId(), null);
}
}
break;
}
if(Keyboard.getEventKey() == Keyboard.KEY_F1 && Keyboard.getEventKeyState() == false){
if(tutorialElement == null){
tutorialElement = gui.createPopup("popupExit");
gui.showPopup(screen, tutorialElement.getId(), null);
}
else{
gui.closePopup(tutorialElement.getId());
this.popUpStuff = true;
tutorialElement = null;
}
}
}
if (this.KEY_POWER_UP) {
this.train.setPowerLevel(this.train.getPowerLevel() + POWER_CHANGE * appSpeed() * 0.5f);
}
else if (this.KEY_POWER_DOWN) {
this.train.setPowerLevel(this.train.getPowerLevel() - POWER_CHANGE * appSpeed() * 0.5f);
}
if (this.KEY_BRAKES_ON) {
this.train.setBrakes(true);
}
else if (this.KEY_BRAKES_OFF) {
this.train.setBrakes(false);
}
/* L-Alt or R-Alt is down */
if (Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU)) {
/* Camera keyboard controls */
if(this.KEY_CURSOR_LEFT)
this.gameCameraMultipliers.x -= 0.04f*appSpeed();
else if(this.KEY_CURSOR_RIGHT)
this.gameCameraMultipliers.x += 0.04f*appSpeed();
if(this.KEY_CURSOR_DOWN)
this.gameCameraMultipliers.y = Math.min(10f, this.gameCameraMultipliers.y + 0.06f * appSpeed());
else if(this.KEY_CURSOR_UP){
this.gameCameraMultipliers.y = Math.max(0f, this.gameCameraMultipliers.y - 0.06f * appSpeed());
}
}
else {
/* Train controls */
if (this.KEY_NO_TURN) {
this.train.requestTurn(0);
}
else {
if (this.KEY_TURN_LEFT) {
this.train.requestTurn(-1);
}
else if (this.KEY_TURN_RIGHT) {
this.train.requestTurn(1);
}
}
}
if(map.getStationAtTile(this.train.getGridLocation()) != null && this.KEY_BUY_COAL) {
CoalCoach coalCoach = this.train.findNotfullCoalCoach();
if(coalCoach != null){
/* Player has a non full coal coach */
float priceOfCoal = 2f;
int amountToBuy = 100;
/* Coal is 2 dollars / 100 units */
float cashToBuy = this.train.withdrawCash(priceOfCoal);
if(cashToBuy > 0.0f){
/* Player had enough cash */
coalCoach.addCoals((long) (amountToBuy));
}
}
}
if(this.KEY_REPAIR) {
if(this.train.getVelocity() > 0 && map.getStationAtTile(this.train.getGridLocation()) != null)
this.train.repair(30.0f);
else
this.train.repair(15.0f);
}
if(elapsedAppTime() - passengerTimer > 900) {
map.addRandomPassenger();
passengerTimer = elapsedAppTime();
}
this.train.update();
Vector3f camCenter = this.train.getModel().getPosition();
this.camera.setPosition(
camCenter.x+(float)Math.cos(this.gameCameraMultipliers.getX())*(2f + this.gameCameraMultipliers.getY()),
0.75f + this.gameCameraMultipliers.getY()*1.5f,
camCenter.z+(float)Math.sin(this.gameCameraMultipliers.getX())*(2f + this.gameCameraMultipliers.getY())
);
this.camera.lookAt(camCenter.x, 0.75f, camCenter.z);
// ending
if(
(train.getCoals() == 0 && map.getStationAtTile(train.getGridLocation()) == null && train.getVelocity() == 0f)
|| (train.getCoals() == 0 && train.getVelocity() == 0f && map.getStationAtTile(train.getGridLocation()) != null && train.getCash() < 2f)
|| (train.getDamage() == 1 && train.getVelocity() == 0f && map.getStationAtTile(train.getGridLocation()) == null && train.getCash() < 30.0f)
|| (train.getDamage() == 1 && train.getVelocity() == 0f && map.getStationAtTile(train.getGridLocation()) != null && train.getCash() < 15.0f)
) {
StateManager.pop();
StateManager.push(new End(train.getPassedDistance()));
}
}
/**
* Generates rectangular track
*/
private void generateMap() {
int rectPoints = 15;
Random rand = new Random();
Point nodes[] = new Point[rectPoints];
for (int i = 0; i < rectPoints; i++) {
nodes[i] = new Point();
do {
nodes[i].x = Math.abs(rand.nextInt() % Map.mapWidth);
nodes[i].y = Math.abs(rand.nextInt() % Map.mapHeight);
}
while (Math.sqrt(Math.pow(nodes[i].x, 2) + Math.pow(nodes[i].y, 2)) < 16);
/* Make sure no two straight rails are next to each other */
for (int x = 0; x < i; x++){
if(nodes[i].x == nodes[x].x-1 || nodes[i].x == nodes[x].x+1
|| nodes[i].y == nodes[x].y-1 || nodes[i].y == nodes[x].y+1){
i--;
break;
}
}
}
Point last = nodes[0];
for (int i = 1; i < rectPoints; i++) {
int dx = (last.x > nodes[i].x)?-1:1;
int dy = (last.y > nodes[i].y)?-1:1;
for (int y = last.y; y != nodes[i].y+dy; y += dy) {
map.set(Map.TRACK, last.x, y);
map.set(Map.TRACK, nodes[i].x, y);
}
for (int x = last.x; x != nodes[i].x+dx; x += dx) {
map.set(Map.TRACK, x, last.y);
map.set(Map.TRACK, x, nodes[i].y);
}
last = nodes[i];
}
//add 10 stations
for(int i = 0; i < 10; i++) {
// is free track piece found
boolean found = false;
// while not found look for one
while(!found) {
int x = rand.nextInt(Map.mapWidth);
int y = rand.nextInt(Map.mapHeight);
// if it is a track
if(map.get(x, y) == Map.TRACK) {
found = true;
// add 10 stationblocks
for(int j = 0; j < 10; j++) {
map.set(Map.STATION, x, y);
int[] dirs = map.scan(x, y);
for(int d = 0; d < 8; d+=2) {
if(dirs[d] == Map.TRACK) {
if(d == 0) {
x+=1;
break;
}
else if(d == 2) {
y+=1;
break;
}
else if(d == 4) {
x-=1;
break;
}
else if(d == 6) {
y-=1;
break;
}
}
}
}
}
}
}
for (int i = 0; i < (Map.mapHeight*Map.mapWidth)/300; i++) {
int x = rand.nextInt(Map.mapWidth);
int y = rand.nextInt(Map.mapHeight);
while(map.get(x, y) != Map.EMPTY){
x = rand.nextInt(Map.mapWidth);
y = rand.nextInt(Map.mapHeight);
}
map.set(Map.TREE, x, y);
}
}
@Override
public void end() {
this.map.free();
this.train.free();
this.terrain.free();
}
@Override
public void paused(){
while(Keyboard.next()) {
switch(Keyboard.getEventKey()) {
case Keyboard.KEY_PAUSE:
if(Keyboard.getEventKeyState() == false){
resume();
if(pausePopup != null){
gui.closePopup(pausePopup.getId());
pausePopup = null;
}
}
break;
}
}
this.gameCameraMultipliers.x += 0.005*appSpeed();
Vector3f camCenter = this.train.getModel().getPosition();
this.camera.setPosition(
camCenter.x+(float)Math.cos(this.gameCameraMultipliers.getX())*(2f + this.gameCameraMultipliers.getY()),
0.75f + this.gameCameraMultipliers.getY()*1.5f,
camCenter.z+(float)Math.sin(this.gameCameraMultipliers.getX())*(2f + this.gameCameraMultipliers.getY())
);
this.camera.lookAt(camCenter.x, 0.75f, camCenter.z);
}
@Override
public void event() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}