ProjectZombie/src/shootergame/world/chunk/Chunk.java

262 lines
6.5 KiB
Java

package shootergame.world.chunk;
import java.util.ArrayList;
import java.util.Random;
import shootergame.display.Camera;
import shootergame.entity.Entity;
import shootergame.entity.EntityAlive;
import shootergame.entity.particle.ParticleBreak;
import shootergame.init.Tiles;
import shootergame.tiles.Tile;
import shootergame.util.math.MathHelpers;
import shootergame.util.math.TileState;
import shootergame.util.math.range.Range2i;
import shootergame.util.math.vec.Vec2d;
import shootergame.util.math.vec.Vec2i;
import shootergame.world.layer.Layer;
public class Chunk
{
public static final Range2i CHUNK_SIZE = new Range2i(16, 16);
public static final Chunk CHUNK_EMPTY = new ChunkEmpty();
public static final int CHUNK_INDEX = CHUNK_SIZE.mx * CHUNK_SIZE.my;
public static final int SIMULATION_DISTANCE = 5;
private Tile tiles_back[] = new Tile[CHUNK_INDEX];
private Tile tiles_front[] = new Tile[CHUNK_INDEX];
private byte tiles_front_meta[] = new byte[CHUNK_INDEX];
private byte tiles_back_meta[] = new byte[CHUNK_INDEX];
private byte tiles_lighting_r[] = new byte[CHUNK_INDEX];
private byte tiles_lighting_g[] = new byte[CHUNK_INDEX];
private byte tiles_lighting_b[] = new byte[CHUNK_INDEX];
public ArrayList<Entity> entities = new ArrayList<Entity>();
private Layer layer;
private Vec2i c_pos;
public Chunk(Layer layer, Vec2i c_pos, Random rand)
{
// Set some specified values
this.layer = layer;
this.c_pos = c_pos;
// Loop over all the tiles in the chunk
for(int i=0;i<CHUNK_INDEX;i++)
{
// Make all these tiles void
tiles_back[i] = Tiles.VOID;
tiles_front[i] = Tiles.VOID;
tiles_back_meta[i] = 0;
tiles_front_meta[i] = 0;
tiles_lighting_b[i] = 0;
tiles_lighting_g[i] = 0;
tiles_lighting_r[i] = 0;
}
}
public void render(Camera camera)
{
// Loop over all the tiles
for(int i=0;i<CHUNK_INDEX;i++)
{
// Get the tile pos
Vec2i t_pos = Vec2i.fromId(CHUNK_SIZE, i);
// Render the tiles
TileState tsb = getBackTile(i);
TileState tsf = getFrontTile(i);
tiles_back[i].doRender(new Vec2d(t_pos.x + c_pos.x * 16, t_pos.y + c_pos.y * 16), camera, tsb);
tiles_front[i].doRender(new Vec2d(t_pos.x + c_pos.x * 16, t_pos.y + c_pos.y * 16), camera, tsf);
}
// Render all the entities
for(int i=0;i<entities.size();i++) {
Entity e = entities.get(i);
e.doRender(e.pos, camera);
}
}
public void spawnEntity(Entity e) {
e.chunk = this;
entities.add(e);
}
public void tickEntities()
{
// Loop over every entitiy
for(int i=0;i<entities.size();i++)
{
// Get the entity and tick it
Entity e = entities.get(i);
e.tick(this, layer);
}
}
public void checkEntities()
{
// Loop over every entity
for(int i=0;i<entities.size();i++)
{
// Get the entitiy
Entity e = entities.get(i);
// is this entity alive
if(e instanceof EntityAlive)
{
// Get the alive entity
EntityAlive ea = (EntityAlive)e;
// Kill the entity if it should be dead and continue to the next loop iteration
if(ea.getHealth() < 0) {
entities.remove(i);
continue;
}
}
// Has the entity left the chunk
int cx = c_pos.x * CHUNK_SIZE.mx;
int cy = c_pos.y * CHUNK_SIZE.my;
double px = e.pos.x;
double py = e.pos.y;
if(px > cx + CHUNK_SIZE.mx || px < cx || py > cy + CHUNK_SIZE.my || py < cy)
{
// Process the entity by layer and remove the entity from the array
layer.spawnEntity(e);
entities.remove(i);
i -= 1;
}
}
}
public void setBackTile(TileState tile, Vec2i pos)
{
// Get the id
Vec2i cpos = new Vec2i(0, 0);
cpos.x = MathHelpers.mod(pos.x, CHUNK_SIZE.mx);
cpos.y = MathHelpers.mod(pos.y, CHUNK_SIZE.my);
int id = cpos.getId(CHUNK_SIZE);
setBackTile(tile, id);
}
public void setBackTile(TileState tile, int id)
{
// Set the back tile
this.tiles_back[id] = tile.tile;
this.tiles_back_meta[id] = tile.meta;
}
public void setFrontTile(TileState tile, Vec2i pos)
{
// Get the id
Vec2i cpos = new Vec2i(0, 0);
cpos.x = MathHelpers.mod(pos.x, CHUNK_SIZE.mx);
cpos.y = MathHelpers.mod(pos.y, CHUNK_SIZE.my);
int id = cpos.getId(CHUNK_SIZE);
setFrontTile(tile, id);
}
public void setFrontTile(TileState tile, int id)
{
// Set the front tile
this.tiles_front[id] = tile.tile;
this.tiles_front_meta[id] = tile.meta;
}
public TileState getBackTile(Vec2i pos)
{
// Get the id
Vec2i cpos = new Vec2i(0, 0);
cpos.x = MathHelpers.mod(pos.x, CHUNK_SIZE.mx);
cpos.y = MathHelpers.mod(pos.y, CHUNK_SIZE.my);
int id = cpos.getId(CHUNK_SIZE);
return getBackTile(id);
}
public TileState getBackTile(int id)
{
// Send back the back tile
TileState ts = new TileState(this.tiles_back[id], this.tiles_back_meta[id]);
ts.light.x = this.tiles_lighting_r[id];
ts.light.y = this.tiles_lighting_g[id];
ts.light.z = this.tiles_lighting_b[id];
return ts;
}
public TileState getFrontTile(Vec2i pos)
{
// Get the id
Vec2i cpos = new Vec2i(0, 0);
cpos.x = MathHelpers.mod(pos.x, CHUNK_SIZE.mx);
cpos.y = MathHelpers.mod(pos.y, CHUNK_SIZE.my);
int id = cpos.getId(CHUNK_SIZE);
return getFrontTile(id);
}
public TileState getFrontTile(int id)
{
// Send back the front tile
TileState ts = new TileState(this.tiles_front[id], this.tiles_front_meta[id]);
ts.light.x = this.tiles_lighting_r[id];
ts.light.y = this.tiles_lighting_g[id];
ts.light.z = this.tiles_lighting_b[id];
return ts;
}
public void breakBackTile(Vec2i pos)
{
TileState ts = getBackTile(pos);
if(!ts.tile.unbreakable) {
setBackTile(layer.layergen.getTileDestroyed(), pos);
for(int i=0;i<20;i++) {
spawnEntity(new ParticleBreak(new Vec2d(pos.x+0.5, pos.y+0.5), ts));
}
}
}
public void breakFrontTile(Vec2i pos)
{
TileState ts = getFrontTile(pos);
if(!ts.tile.unbreakable) {
setFrontTile(Tiles.VOID.getDefaultState(), pos);
for(int i=0;i<20;i++) {
spawnEntity(new ParticleBreak(new Vec2d(pos.x+0.5, pos.y+0.5), ts));
}
}
}
public void killEntity(Entity e) {
entities.remove(e);
}
public ArrayList<Entity> getNearbyEntities(Vec2d pos, double distance)
{
// Get the list of entities to send back
ArrayList<Entity> nearby_entities = new ArrayList<Entity>();
// Loop over the entities
for(Entity e : entities)
{
if(
e.pos.x + distance > pos.x &&
e.pos.x - distance < pos.x &&
e.pos.y + distance > pos.y &&
e.pos.y - distance < pos.y
) {
if(MathHelpers.distance2d(e.pos.x, e.pos.y, pos.x, pos.y) < distance) {
nearby_entities.add(e);
}
}
}
// Send back the entities
return nearby_entities;
}
}