/*
* Copyright (C) 2012 JPII and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpii.navalbattle.pavo;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import maximusvladimir.dagen.Rand;
import com.jpii.navalbattle.io.Interactable;
import com.jpii.navalbattle.pavo.grid.EntityManager;
import com.jpii.navalbattle.pavo.grid.Location;
import com.jpii.navalbattle.pavo.io.PavoImage;
public class World extends Renderable implements Interactable {
private static final long serialVersionUID = 1L;
Chunk[] chunks;
PavoImage buffer;
boolean needsNewRender = false;
boolean[] generated;
boolean bufferLock = false;
WorldSize ws;
int width = 16;
int height = 8;
int lww = 800;
int lwh = 600;
EntityManager em;
TimeManager time = new TimeManager();
int sx = 0, anisx = 0, anisy = 0,sy = 0;
int anix, aniy;
PavoImage noise;
int zlevel;
Game game;
WorldStatus worldStatus;
public World(Game gameThing,WorldSize w) {
game = gameThing;
ws = w;
width = PavoHelper.getGameWidth(getWorldSize());
height = PavoHelper.getGameHeight(getWorldSize());
chunks = new Chunk[(width)*(height)];
for (int x = 0;x < width; x++) {
for (int z = 0; z < height; z++) {
int i = z*width+x;
chunks[i] = new Chunk(this);
chunks[i].setX(x);
chunks[i].setZ(z);
}
}
em = new EntityManager(this);
generated = new boolean[chunks.length];
buffer = new PavoImage(Game.Settings.currentWidth,Game.Settings.currentHeight,BufferedImage.TYPE_3BYTE_BGR);
makeNoise();
worldStatus = new WorldStatus(ws,time);
System.gc();
}
public boolean isReadyForGen() {
if (em == null)
return false;
if (em.isReadyForGen())
return true;
else
return false;
}
public WorldStatus getWorldStatus() {
return worldStatus;
}
public int getTotalChunks() {
return chunks.length;
}
public Game getGame() {
return game;
}
public void setEntityManager(EntityManager em) {
this.em = em;
}
public Chunk getChunk(int index) {
return chunks[index];
}
public Chunk getChunk(int x, int z) {
return getChunk(z*PavoHelper.getGameWidth(getWorldSize())+x);
}
public void setZoomLevel(int level) {
zlevel = level;
}
public int getZoomLevel() {
return zlevel;
}
public void makeNoise(){
noise = new PavoImage(Game.Settings.currentWidth,Game.Settings.currentHeight,BufferedImage.TYPE_3BYTE_BGR);
Rand ras = new Rand(Game.Settings.seed+22);
Graphics gs2 = noise.getGraphics();
for (int x = 0; x < Game.Settings.currentWidth; x+= 2) {
for (int y = 0; y < Game.Settings.currentHeight; y+=2) {
int rgb = ras.nextInt(127);
gs2.setColor(new Color(rgb,rgb,rgb));
gs2.fillRect(x,y,2,2);
}
}
gs2.dispose();
}
private void runLocLock(int x, int y) {
//motionEntity = null;
anix = x;
aniy = y;
stopani = true;
game.onWorldChange();
}
float _internalspeedconstant = 1.0f;
public void animatedSetLoc(Location l, float speed) {
_internalspeedconstant = 1.0f/speed;
int sc = l.getCol() * 50;
int sr = l.getRow() * 50;
//System.out.println("Headn towardz: "+ l);
animatedSetLoc(sc,sr);
}
public void animatedSetLoc(int x, int y) {
int ssx = Game.Settings.currentWidth/2;
int ssy = Game.Settings.currentHeight/2;
anix = x - ssx;
aniy = y - ssy;
stopani = false;
}
public void setLoc(int x, int y) {
if (sx != x || sy != y)
chunkrender = true;
runLocLock(x,y);
//System.out.println("x"+x+",y"+y);
sx = x;
sy = y;
}
public void setLocX(int x) {
if (sx != x)
chunkrender = true;
runLocLock(x,0);
sx = x;
}
public void setLocY(int y) {
if (sy != y)
chunkrender = true;
runLocLock(0,y);
sy = y;
}
long smallTicks = 0;
long localTicks = 0;
long startFPS = 0;
public void update() {
smallTicks += 100;
localTicks++;
time.update();
em.update(localTicks);
}
public boolean hasMoreChunks() {
for (int c = 0; c < chunks.length; c++) {
if (!generated[c])
return true;
}
Game.Settings.isFinishedGenerating = true;
return false;
}
public void genNextChunk() {
for (int c = 0; c < chunks.length; c++) {
Chunk chunk = chunks[c];
Game.getStats().SmKdn02nOaP(c*2);
while (chunk.isLocked()) {
}
chunk.lock();
if (!generated[c]){
chunk.render();
generated[c] = true;
needsNewRender = true;
}
chunkrender = true;
chunk.unlock();
chunks[c] = chunk;
}
}
// public Entity getMotionEntity() {
// return motionEntity;
// }
// Entity motionEntity;
// public void setMotionEntity(Entity e) {
// motionEntity = e;
// }
boolean chunkrender = false;
boolean stopani = true;
public boolean needsReChunkRender() {
return chunkrender;
}
/**
* This method should be called sparingly (which means DO NOT OVER USE). This method is multithreaded, so it puts no stress on the calling thread.
* This method is not actually deprecated, but it is called so to ensure that the above message is read.
*/
public void forceRender() {
chunkrender = true;
}
public boolean isBeingAnimated() {
return !stopani;
}
public synchronized void render() {
if (!stopani) {
int destx = anix;
int desty = aniy;
//int dx = Math.abs(destx) - Math.abs(sx);
//int dy = Math.abs(desty) - Math.abs(sy);
//int dx = -Math.abs(Math.abs(sx)+destx);
//int dy = -Math.abs(Math.abs(sy)+desty);
//int dx = Math.abs(destx) + sx;
//int dy = Math.abs(desty) + sy;
/*int
int ds = 90;
int ddx = (dx/ds);
int ddy = (dy/ds);
if (ddx > 1 && ddx < 6)
sx = destx;
if (ddy > 1 && ddy < 6)
sy = desty;
if (dx > 0)
sx += ddx;
else
sx -= ddx;
if (dy > 0)
sy += ddy;
else
sy -= ddy;*/
//float theta = (float)Math.atan2((-desty)-sy,(-destx)-sx);
//sx =
float dx = destx + (sx);
float dy = desty + (sy);
//System.out.println("d("+(-destx)+","+(-desty)+") s("+(sx+101)+","+(sy+100)+")");
int ccx = (int)(dx/_internalspeedconstant);
int ccy = (int)(dy/_internalspeedconstant);
if (ccx == 0 && ccy == 0)
stopani = true;
sx -= ccx;
sy -= ccy;
}
else if (!needsReChunkRender())
return;
long waitStart = System.currentTimeMillis();
while (bufferLock) {
}
long endWait = System.currentTimeMillis() - waitStart;
bufferLock = true;
long startDraw = System.currentTimeMillis();
if (lww != Game.Settings.currentWidth || lwh != Game.Settings.currentHeight) {
buffer = null;
buffer = new PavoImage(Game.Settings.currentWidth,Game.Settings.currentHeight,BufferedImage.TYPE_3BYTE_BGR);
lww = Game.Settings.currentWidth;
lwh = Game.Settings.currentHeight;
makeNoise();
}
int liveChunks = 0;
Graphics2D g = PavoHelper.createGraphics(buffer);
g.drawImage(noise, 0, 0, null);
//System.out.println("s("+sx+","+sy+")");
int startsyncx = (-sx) / 100;
int startsyncz = (-sy) / 100;
if (startsyncx < 0)
startsyncx = 0;
if (startsyncz < 0)
startsyncz = 0;
int syncwidth = (Game.Settings.currentWidth/100)+2;
int syncheight = (Game.Settings.currentHeight/100)+2;
for (int x = startsyncx; x < syncwidth+startsyncx; x++) {
for (int z = startsyncz; z < syncheight+startsyncz; z++) {
int index = z*width+x;
if (index >= 0 && index < chunks.length) {
Chunk chunk = chunks[index];
if (PavoHelper.isChunkVisibleOnScreen(this, chunk)) {
if (!chunk.isGenerated()) {
int rgb = Game.Settings.rand.nextInt(255);
if (Game.Settings.rand.nextBoolean())
g.setColor(new Color(6,rgb,13));
else
g.setColor(new Color(6,13,rgb));
g.fillRect(x*100,z*100,100,100);
}
else if (x-2 == width || z-2 == height) {
g.fillRect(sx+(x*100),sy+(z*100), 303, 303);
}
else {
if (chunk.needsBufferWrite())
chunk.writeBuffer();
if (chunk.getBuffer() != null) {
g.drawImage(chunk.getBuffer(), sx+(x*100),sy+(z*100),null);
}
}
liveChunks++;
}
}
}
}
g.dispose();
chunkrender = false;
long endDraw = System.currentTimeMillis() - startDraw;
Game.getStats().SmKAk10(endDraw);
Game.getStats().SmoOa01kwL(liveChunks);
Game.getStats().Smw2e33AK(endWait);
bufferLock = false;
}
public PavoImage getBuffer() {
return buffer;
}
public int getScreenX() {
return sx;
}
public int getScreenY() {
return sy;
}
// public void moveScreenTo(int x, int y) {
// anisx = x;
// anisy = y;
// }
public WorldSize getWorldSize() {
return ws;
}
public EntityManager getEntityManager() {
return em;
}
public TimeManager getTimeManager() {
return time;
}
public void save(String path) {
File file = new File(path);
boolean throwError = false;
try {
if (!file.exists()) {
if (!file.createNewFile()) {
throwError = true;
}
}
}
catch (Error err) {
}
catch (Exception ex) {
}
if (throwError)
throw new java.lang.IllegalArgumentException("Unable to save file. See store for details");
}
public void load(String path) {
}
public void peekElements() {
}
}