Initial commit
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-glfw.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-glfw-javadoc.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-glfw-natives-linux.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-glfw-natives-macos.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-glfw-natives-windows.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-glfw-sources.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-natives-linux.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-natives-macos.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-natives-windows.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-openal.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-openal-javadoc.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-openal-natives-linux.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-openal-natives-macos.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-openal-natives-windows.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-openal-sources.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opencl.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opencl-javadoc.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opencl-sources.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengl.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengles.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengles-javadoc.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengles-natives-linux.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengles-natives-macos.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengles-natives-windows.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengles-sources.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengl-javadoc.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengl-natives-linux.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengl-natives-macos.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengl-natives-windows.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-opengl-sources.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-stb.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-stb-javadoc.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-stb-natives-linux.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-stb-natives-macos.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-stb-natives-windows.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/lwjgl-3.2.2-lightweight/lwjgl-stb-sources.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/binary-data-format-v3.0.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/GlEngine.jar"/>
|
||||
<classpathentry kind="lib" path="/home/josua/code/Java Libraries/mainloop.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1 @@
|
|||
bin
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>AntSim</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,11 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,11 @@
|
|||
package antsim.display;
|
||||
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class DisplayCamera
|
||||
{
|
||||
public static DisplayCamera CAMERA = new DisplayCamera();
|
||||
|
||||
public double zoom = 0.05;
|
||||
public Vec2d pos = new Vec2d(0, 0);
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package antsim.display;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
|
||||
import antsim.entity.Entity;
|
||||
import antsim.init.Models;
|
||||
import antsim.model.Model;
|
||||
import antsim.start.Start;
|
||||
import antsim.world.World;
|
||||
import gl_engine.graphics.GraphicsHelpers;
|
||||
import gl_engine.graphics.GraphicsShader;
|
||||
import gl_engine.matrix.Matrix4;
|
||||
import gl_engine.texture.TextureRef3D;
|
||||
import gl_engine.vec.Vec2d;
|
||||
import gl_engine.vec.Vec3d;
|
||||
import mainloop.task.IMainloopTask;
|
||||
|
||||
public class DisplayWindow implements IMainloopTask
|
||||
{
|
||||
public static final DisplayWindow WINDOW = new DisplayWindow();
|
||||
|
||||
private long window;
|
||||
private long monitor;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
public int fps;
|
||||
public GraphicsShader renderer;
|
||||
public GraphicsShader background;
|
||||
|
||||
public int glsl_matrix;
|
||||
public int glsl_projection;
|
||||
|
||||
public int glsl_bg_scale;
|
||||
public int glsl_bg_translate;
|
||||
|
||||
private boolean hasDoneSetup = false;
|
||||
|
||||
public void init()
|
||||
{
|
||||
// Initialize GLFW
|
||||
if(!GLFW.glfwInit()) {
|
||||
throw new RuntimeException("Failed to initialize GLFW");
|
||||
}
|
||||
|
||||
// Get the monitor size
|
||||
IntBuffer w = BufferUtils.createIntBuffer(1);
|
||||
IntBuffer h = BufferUtils.createIntBuffer(1);
|
||||
monitor = GLFW.glfwGetPrimaryMonitor();
|
||||
GLFW.glfwGetMonitorPhysicalSize(monitor, w, h);
|
||||
width = w.get()*4;
|
||||
height = h.get()*4;
|
||||
|
||||
//GLFW.glfwWindowHint(GLFW.GLFW_DOUBLEBUFFER, GLFW.GLFW_FALSE);
|
||||
|
||||
// Create the window
|
||||
window = GraphicsHelpers.initWindow("Ant Sim", width, height, 0);
|
||||
|
||||
renderer = new GraphicsShader("/resources/shader/renderer");
|
||||
renderer.use();
|
||||
|
||||
glsl_matrix = GL33.glGetUniformLocation(renderer.program, "matrix");
|
||||
glsl_projection = GL33.glGetUniformLocation(renderer.program, "projection");
|
||||
|
||||
background = new GraphicsShader("/resources/shader/background");
|
||||
background.use();
|
||||
|
||||
glsl_bg_scale = GL33.glGetUniformLocation(background.program, "scale");
|
||||
glsl_bg_translate = GL33.glGetUniformLocation(background.program, "translate");
|
||||
|
||||
// Make the context current
|
||||
GLFW.glfwMakeContextCurrent(this.window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopDelay(long millis) {
|
||||
return millis > Start.mspf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopRepeat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MainLoopUpdate()
|
||||
{
|
||||
int w[] = {0};
|
||||
int h[] = {0};
|
||||
GLFW.glfwGetFramebufferSize(this.window, w, h);
|
||||
width = w[0];
|
||||
height = h[0];
|
||||
|
||||
GL33.glBindFramebuffer(GL33.GL_FRAMEBUFFER, 0);
|
||||
GL33.glClear(GL33.GL_DEPTH_BUFFER_BIT | GL33.GL_COLOR_BUFFER_BIT);
|
||||
GL33.glViewport(0, 0, width, height);
|
||||
|
||||
background.use();
|
||||
|
||||
if(!hasDoneSetup)
|
||||
{
|
||||
hasDoneSetup = true;
|
||||
|
||||
int glsl_grass_tex = GL33.glGetUniformLocation(background.program, "tex");
|
||||
TextureRef3D grass_tex = Models.GRASS.getTextures()[0];
|
||||
|
||||
GL33.glUniform4f(glsl_grass_tex, grass_tex.sx, grass_tex.sy, grass_tex.ex, grass_tex.ey);
|
||||
}
|
||||
|
||||
double camera_zoom = DisplayCamera.CAMERA.zoom;
|
||||
Vec2d camera_pos = DisplayCamera.CAMERA.pos;
|
||||
|
||||
GL33.glUniform2f(glsl_bg_scale, (float)camera_zoom * (float)height / (float)width, (float)camera_zoom);
|
||||
GL33.glUniform2f(glsl_bg_translate, (float)camera_pos.x, (float)camera_pos.y);
|
||||
|
||||
Models.GRASS.setModel(Matrix4.identity());
|
||||
Models.GRASS.render();
|
||||
|
||||
renderer.use();
|
||||
|
||||
|
||||
|
||||
GL33.glUniformMatrix4fv(glsl_projection, true, Matrix4.multiply(
|
||||
Matrix4.translate(camera_pos.x, camera_pos.y, 0),
|
||||
Matrix4.scale(new Vec3d(camera_zoom * (double)height / (double)width, camera_zoom, 1))).getArray());
|
||||
|
||||
for(Entity e : World.WORLD.entities)
|
||||
{
|
||||
Model model = e.getModel();
|
||||
model.setModel(Matrix4.multiply(e.getMatrix(), Matrix4.translate(e.pos.x, e.pos.y, 0)));
|
||||
model.render();
|
||||
}
|
||||
|
||||
GLFW.glfwSwapBuffers(window);
|
||||
|
||||
fps += 1;
|
||||
}
|
||||
|
||||
public void pollEvents() {
|
||||
GLFW.glfwPollEvents();
|
||||
}
|
||||
|
||||
public boolean shouldClose() {
|
||||
return GLFW.glfwWindowShouldClose(window);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package antsim.entity;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import antsim.init.Entities;
|
||||
import antsim.model.Model;
|
||||
import antsim.start.Start;
|
||||
import antsim.start.StartServer;
|
||||
import antsim.util.ClassBdf;
|
||||
import antsim.world.World;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import gl_engine.matrix.Matrix4;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public abstract class Entity implements ClassBdf
|
||||
{
|
||||
public Vec2d pos = new Vec2d(0, 0);
|
||||
public Vec2d velocity = new Vec2d(0, 0);
|
||||
private boolean isDead;
|
||||
private boolean dirty;
|
||||
|
||||
public int getID() {
|
||||
for(int i=0;i<Entities.ENTITIES.size();i++) {
|
||||
Class<? extends Entity> ec = Entities.ENTITIES.get(i);
|
||||
if(ec == this.getClass()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static Entity loadEntity(BdfObject bdf)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the entity id
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
int id = (int)nl.get("id").getAutoInt();
|
||||
|
||||
// Send back null if the id is out of range
|
||||
if(id < 0 || id >= Entities.ENTITIES.size()) {
|
||||
System.out.println("Warning: Invalid ID detected: " + id);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the class and the constructor
|
||||
Class<? extends Entity> ecl = Entities.ENTITIES.get(id);
|
||||
Constructor<? extends Entity> econ = ecl.getConstructor(BdfObject.class);
|
||||
|
||||
// Send back the new entity
|
||||
return econ.newInstance(bdf);
|
||||
}
|
||||
|
||||
catch(
|
||||
NoSuchMethodException |
|
||||
InstantiationException |
|
||||
IllegalAccessException |
|
||||
IllegalArgumentException |
|
||||
InvocationTargetException e)
|
||||
{
|
||||
// Send null if there was an issue
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Model getModel();
|
||||
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
protected void markDirty() {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public Matrix4 getMatrix() {
|
||||
return Matrix4.identity();
|
||||
}
|
||||
|
||||
public void push(Vec2d amount) {
|
||||
velocity = velocity.add(amount);
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
pos = pos.add(velocity);
|
||||
velocity = velocity.multiply(0.8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBDF(BdfObject bdf)
|
||||
{
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
pos = new Vec2d(nl.get("pos"));
|
||||
velocity = new Vec2d(nl.get("velocity"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveBDF(BdfObject bdf)
|
||||
{
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
pos.BdfClassSave(nl.get("pos"));
|
||||
velocity.BdfClassSave(nl.get("velocity"));
|
||||
nl.set("id", bdf.newObject().setAutoInt(getID()));
|
||||
}
|
||||
|
||||
public void kill()
|
||||
{
|
||||
isDead = true;
|
||||
|
||||
if(Start.isServer) {
|
||||
StartServer.markNeedToUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDead() {
|
||||
return isDead;
|
||||
}
|
||||
|
||||
public void notDead() {
|
||||
isDead = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
package antsim.entity;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import antsim.init.Entities;
|
||||
import antsim.init.Models;
|
||||
import antsim.model.Model;
|
||||
import antsim.nest.Nest;
|
||||
import antsim.start.Start;
|
||||
import antsim.start.StartServer;
|
||||
import antsim.world.World;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import gl_engine.matrix.Matrix4;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class EntityAnt extends Entity implements EntityEdible
|
||||
{
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
private Random random;
|
||||
private long seed;
|
||||
public Nest nest;
|
||||
private Vec2d target;
|
||||
private double angle;
|
||||
private EntityEdible food_target;
|
||||
private int hasFood = 0;
|
||||
private double speed;
|
||||
private double hunger = 1;
|
||||
private boolean antDead;
|
||||
private int pregnant = -2;
|
||||
private boolean fighting;
|
||||
|
||||
public EntityAnt(Nest nest, Vec2d pos)
|
||||
{
|
||||
this.nest = nest;
|
||||
this.pos = pos;
|
||||
this.target = pos;
|
||||
this.speed = Math.random() * 0.1 + 0.9;
|
||||
|
||||
seed = RANDOM.nextLong();
|
||||
random = new Random(seed);
|
||||
}
|
||||
|
||||
public EntityAnt(BdfObject bdf) {
|
||||
loadBDF(bdf, true);
|
||||
}
|
||||
|
||||
public EntityAnt(BdfObject bdf, boolean dontLoadNest) {
|
||||
loadBDF(bdf, dontLoadNest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveBDF(BdfObject bdf) {
|
||||
super.saveBDF(bdf);
|
||||
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
nl.set("seed", bdf.newObject().setLong(seed));
|
||||
nl.set("angle", bdf.newObject().setDouble(angle));
|
||||
nl.set("hasFood", bdf.newObject().setAutoInt(hasFood));
|
||||
nl.set("hunger", bdf.newObject().setDouble(hunger));
|
||||
nl.set("speed", bdf.newObject().setDouble(speed));
|
||||
nl.set("pregnant", bdf.newObject().setAutoInt(pregnant));
|
||||
nl.set("nest", bdf.newObject().setAutoInt(nest.id));
|
||||
nl.set("fighting", bdf.newObject().setBoolean(fighting));
|
||||
nl.set("antDead", bdf.newObject().setBoolean(antDead));
|
||||
|
||||
target.BdfClassSave(nl.get("target"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBDF(BdfObject bdf) {
|
||||
loadBDF(bdf, true);
|
||||
}
|
||||
|
||||
public void loadBDF(BdfObject bdf, boolean loadNest) {
|
||||
super.loadBDF(bdf);
|
||||
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
seed = nl.get("seed").getLong();
|
||||
angle = nl.get("angle").getDouble();
|
||||
hasFood = (int)nl.get("hasFood").getAutoInt();
|
||||
hunger = nl.get("hunger").getDouble();
|
||||
speed = nl.get("speed").getDouble();
|
||||
pregnant = (int)nl.get("pregnant").getAutoInt();
|
||||
fighting = nl.get("fighting").getBoolean();
|
||||
antDead = nl.get("antDead").getBoolean();
|
||||
random = new Random(seed);
|
||||
|
||||
target = new Vec2d(nl.get("target"));
|
||||
|
||||
if(loadNest) {
|
||||
nest = World.WORLD.nests.get((int)nl.get("nest").getAutoInt());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getModel()
|
||||
{
|
||||
switch(hasFood)
|
||||
{
|
||||
case 1: return Models.ANT_FOOD;
|
||||
case 2: return Models.ANT_EAT_ANT;
|
||||
}
|
||||
|
||||
return Models.ANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix4 getMatrix() {
|
||||
return Matrix4.rotate(angle, 0, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update()
|
||||
{
|
||||
super.update();
|
||||
|
||||
if(antDead) {
|
||||
return;
|
||||
}
|
||||
|
||||
hunger -= 0.0015;
|
||||
|
||||
if(hunger < 0.125)
|
||||
{
|
||||
if(hasFood > 0)
|
||||
{
|
||||
hasFood = 0;
|
||||
hunger += 0.25;
|
||||
target = pos;
|
||||
}
|
||||
}
|
||||
|
||||
if(hunger <= 0) {
|
||||
antDead = true;
|
||||
}
|
||||
|
||||
Vec2d toTarget = target.subtract(pos);
|
||||
double distanceToTarget = toTarget.length();
|
||||
|
||||
if(pregnant == -1)
|
||||
{
|
||||
for(Entity e : World.WORLD.entities)
|
||||
{
|
||||
if(
|
||||
e instanceof EntityAnt && ((EntityAnt) e).nest == nest &&
|
||||
e != this && e.pos.squareDistance(pos) < 0.05)
|
||||
{
|
||||
pregnant = 20;
|
||||
((EntityAnt)e).pregnant = -2;
|
||||
distanceToTarget = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if(pregnant > 0) {
|
||||
pregnant -= 1;
|
||||
}
|
||||
|
||||
else if(pregnant == 0)
|
||||
{
|
||||
if(Start.isServer) {
|
||||
World.WORLD.entities.add(new EntityAnt(nest, pos.copy()));
|
||||
StartServer.markNeedToUpdate();
|
||||
}
|
||||
|
||||
hunger -= 0.25;
|
||||
pregnant = -2;
|
||||
}
|
||||
|
||||
if(distanceToTarget < 0.5)
|
||||
{
|
||||
for(Entity e : World.WORLD.entities)
|
||||
{
|
||||
if(e instanceof EntityNestEntrance && ((EntityNestEntrance) e).nest == nest)
|
||||
{
|
||||
EntityNestEntrance entrance = (EntityNestEntrance)e;
|
||||
|
||||
if(entrance.nest == nest && entrance.pos.squareDistance(pos) < 1)
|
||||
{
|
||||
hasFood = 0;
|
||||
nest.addFood();
|
||||
nest.ants.add(this);
|
||||
kill();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(fighting && e instanceof EntityAnt)
|
||||
{
|
||||
EntityAnt ea = (EntityAnt)e;
|
||||
|
||||
if(ea.fighting && ea.nest != nest && !ea.antDead && ea.hunger < hunger)
|
||||
{
|
||||
ea.antDead = true;
|
||||
hunger -= 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pregnant == -1) {
|
||||
pregnant = -2;
|
||||
}
|
||||
|
||||
if(food_target != null && !food_target.isDead() && food_target.onEaten())
|
||||
{
|
||||
if(food_target instanceof EntityAnt) {
|
||||
hasFood = 2;
|
||||
}
|
||||
|
||||
else {
|
||||
hasFood = 1;
|
||||
}
|
||||
}
|
||||
|
||||
food_target = null;
|
||||
|
||||
double targetType = random.nextDouble();
|
||||
|
||||
if(targetType > 0.6 && hunger > 0.5 && pregnant == -2)
|
||||
{
|
||||
EntityAnt closest = null;
|
||||
double distance = 50;
|
||||
boolean fight = false;
|
||||
|
||||
for(Entity e : World.WORLD.entities)
|
||||
{
|
||||
if(e instanceof EntityAnt && e != this)
|
||||
{
|
||||
EntityAnt ea = (EntityAnt)e;
|
||||
double d = e.pos.squareDistance(pos) * (ea.nest != nest ? 0.25 : 1);
|
||||
|
||||
if(d < distance && !ea.antDead && ea.hunger > 0.25 && ea.pregnant == -2) {
|
||||
distance = d;
|
||||
closest = (EntityAnt)e;
|
||||
fight = ea.nest != nest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(closest == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(fight) {
|
||||
fighting = true;
|
||||
closest.fighting = true;
|
||||
}
|
||||
|
||||
else {
|
||||
pregnant = -1;
|
||||
closest.pregnant = -1;
|
||||
}
|
||||
|
||||
target = closest.pos.copy();
|
||||
closest.target = pos.copy();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(targetType > 0.6 && hasFood == 0)
|
||||
{
|
||||
// Get the closest food item
|
||||
|
||||
EntityEdible closest = null;
|
||||
double distance = 1000;
|
||||
|
||||
for(Entity e : World.WORLD.entities)
|
||||
{
|
||||
if(!(e instanceof EntityEdible)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityEdible ee = (EntityEdible)e;
|
||||
|
||||
if(!ee.isEdible(this)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double d = e.pos.squareDistance(pos) / ee.getWeight();
|
||||
|
||||
if(d < distance)
|
||||
{
|
||||
distance = d;
|
||||
closest = ee;
|
||||
}
|
||||
}
|
||||
|
||||
if(closest != null) {
|
||||
target = closest.getPos().copy();
|
||||
food_target = closest;
|
||||
}
|
||||
|
||||
else {
|
||||
target = pos;
|
||||
}
|
||||
}
|
||||
|
||||
else if((targetType > 0.6 && hasFood > 0) || (hasFood == 0 && targetType < 1 - hunger))
|
||||
{
|
||||
// Find the nearest nest
|
||||
|
||||
EntityNestEntrance entrance = null;
|
||||
double distance = 0;
|
||||
|
||||
for(Entity e : World.WORLD.entities)
|
||||
{
|
||||
if(e instanceof EntityNestEntrance && ((EntityNestEntrance) e).nest == nest)
|
||||
{
|
||||
double d = e.pos.squareDistance(pos);
|
||||
|
||||
if(d < distance || entrance == null)
|
||||
{
|
||||
entrance = (EntityNestEntrance)e;
|
||||
distance = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(entrance != null) {
|
||||
target = entrance.pos.copy();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
target = pos.add(new Vec2d(random.nextDouble() * 20 - 10, random.nextDouble() * 20 - 10));
|
||||
}
|
||||
|
||||
toTarget = target.subtract(pos);
|
||||
distanceToTarget = toTarget.length();
|
||||
|
||||
angle = Math.toDegrees(Math.atan2(toTarget.x, toTarget.y));
|
||||
|
||||
seed = random.nextLong();
|
||||
random = new Random(seed);
|
||||
}
|
||||
|
||||
push(toTarget.normalize().multiply(0.05 * speed));
|
||||
}
|
||||
|
||||
public void exitNest(Vec2d pos)
|
||||
{
|
||||
if(Start.isServer)
|
||||
{
|
||||
this.pos = pos;
|
||||
|
||||
notDead();
|
||||
|
||||
target = pos.add(new Vec2d(random.nextDouble() * 20 - 10, random.nextDouble() * 20 - 10));
|
||||
|
||||
Vec2d toTarget = target.subtract(pos);
|
||||
|
||||
angle = Math.toDegrees(Math.atan2(toTarget.x, toTarget.y));
|
||||
|
||||
while(hunger < 0.75 && nest.takeFood()) {
|
||||
hunger += 0.25;
|
||||
}
|
||||
|
||||
seed = random.nextLong();
|
||||
random = new Random(seed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEdible(Entity entity) {
|
||||
return antDead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec2d getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWeight() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEaten()
|
||||
{
|
||||
kill();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package antsim.entity;
|
||||
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public interface EntityEdible
|
||||
{
|
||||
public boolean isEdible(Entity entity);
|
||||
public boolean isDead();
|
||||
public Vec2d getPos();
|
||||
public double getWeight();
|
||||
public boolean onEaten();
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package antsim.entity;
|
||||
|
||||
import antsim.init.Models;
|
||||
import antsim.model.Model;
|
||||
import antsim.start.Start;
|
||||
import bdf.types.BdfObject;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class EntityFood extends Entity implements EntityEdible
|
||||
{
|
||||
private int age;
|
||||
|
||||
public EntityFood(Vec2d pos) {
|
||||
this.pos = pos;
|
||||
this.age = 6000; // Stay for a minute
|
||||
}
|
||||
|
||||
public EntityFood(BdfObject bdf) {
|
||||
loadBDF(bdf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getModel() {
|
||||
return Models.FOOD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEdible(Entity entity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec2d getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update()
|
||||
{
|
||||
super.update();
|
||||
|
||||
if(!Start.isServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
age -= 1;
|
||||
|
||||
if(age <= 0) {
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEaten()
|
||||
{
|
||||
kill();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package antsim.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import antsim.init.Models;
|
||||
import antsim.model.Model;
|
||||
import antsim.nest.Nest;
|
||||
import antsim.start.Start;
|
||||
import antsim.start.StartServer;
|
||||
import antsim.world.World;
|
||||
import bdf.types.BdfArray;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class EntityNestEntrance extends Entity implements EntityEdible
|
||||
{
|
||||
private int cooldown;
|
||||
public Nest nest;
|
||||
|
||||
public EntityNestEntrance(BdfObject bdf) {
|
||||
loadBDF(bdf);
|
||||
}
|
||||
|
||||
public EntityNestEntrance(Nest nest, Vec2d pos) {
|
||||
this.nest = nest;
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBDF(BdfObject bdf) {
|
||||
super.loadBDF(bdf);
|
||||
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
|
||||
nest = World.WORLD.nests.get(nl.get("nest").getInteger());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveBDF(BdfObject bdf) {
|
||||
super.saveBDF(bdf);
|
||||
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
|
||||
nl.set("nest", bdf.newObject().setInteger(nest.id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update()
|
||||
{
|
||||
super.update();
|
||||
|
||||
if(Start.isServer && nest.ants.size() > 0)
|
||||
{
|
||||
cooldown -= 1;
|
||||
|
||||
if(cooldown <= 0)
|
||||
{
|
||||
EntityAnt ant = nest.ants.remove(0);
|
||||
World.WORLD.entities.add(ant);
|
||||
ant.nest = nest;
|
||||
ant.exitNest(pos);
|
||||
|
||||
StartServer.markNeedToUpdate();
|
||||
|
||||
cooldown = 50;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getModel() {
|
||||
return Models.NEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec2d getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWeight() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEdible(Entity entity) {
|
||||
return entity instanceof EntityAnt && ((EntityAnt)entity).nest == nest && nest.getFood() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEaten() {
|
||||
return nest.takeFood();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package antsim.init;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import antsim.entity.Entity;
|
||||
import antsim.entity.EntityAnt;
|
||||
import antsim.entity.EntityFood;
|
||||
import antsim.entity.EntityNestEntrance;
|
||||
import bdf.types.BdfObject;
|
||||
|
||||
public class Entities
|
||||
{
|
||||
public static final ArrayList<Class<? extends Entity>> ENTITIES = new ArrayList<>();
|
||||
|
||||
private static void register(Class<? extends Entity> e)
|
||||
{
|
||||
try {
|
||||
e.getConstructor(BdfObject.class);
|
||||
} catch (NoSuchMethodException | SecurityException err) {
|
||||
err.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
ENTITIES.add(e);
|
||||
}
|
||||
|
||||
public static void init()
|
||||
{
|
||||
register(EntityAnt.class);
|
||||
register(EntityFood.class);
|
||||
register(EntityNestEntrance.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package antsim.init;
|
||||
|
||||
import antsim.model.Model;
|
||||
import antsim.model.ModelFlat;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class Models
|
||||
{
|
||||
public static final Model ANT = new ModelFlat(Resources.ATLAS.get("/ant.png"));
|
||||
public static final Model ANT_FOOD = new ModelFlat(Resources.ATLAS.get("/ant_food.png"));
|
||||
public static final Model ANT_EAT_ANT = new ModelFlat(Resources.ATLAS.get("/ant_eat_ant.png"));
|
||||
public static final Model GRASS = new ModelFlat(Resources.ATLAS.get("/grass.png"), new Vec2d(2, 2));
|
||||
public static final Model FOOD = new ModelFlat(Resources.ATLAS.get("/food.png"));
|
||||
public static final Model NEST = new ModelFlat(Resources.ATLAS.get("/nest.png"));
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package antsim.init;
|
||||
|
||||
import gl_engine.texture.TextureAtlas3D;
|
||||
import gl_engine.texture.TextureRef3D;
|
||||
|
||||
public class Resources
|
||||
{
|
||||
public static TextureAtlas3D ATLAS;
|
||||
public static TextureRef3D TEX_EMPTY;
|
||||
|
||||
public static void init()
|
||||
{
|
||||
ATLAS = TextureAtlas3D.loadAll("/resources/texture/list.txt");
|
||||
ATLAS.generate();
|
||||
|
||||
TEX_EMPTY = ATLAS.get("");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package antsim.model;
|
||||
|
||||
import gl_engine.matrix.Matrix4;
|
||||
import gl_engine.texture.TextureRef3D;
|
||||
|
||||
public interface IModel
|
||||
{
|
||||
public int[] getIndicies();
|
||||
public float[] getVerticies();
|
||||
public TextureRef3D[] getTextures();
|
||||
public TextureRef3D getRandomChunk(int[] tex_id);
|
||||
public double getWidth();
|
||||
public double getHeight();
|
||||
public int getIndexSize();
|
||||
public int getSize();
|
||||
|
||||
public void bind();
|
||||
public void render();
|
||||
public void free();
|
||||
public void setModel(Matrix4 model);
|
||||
public boolean isLoaded();
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
package antsim.model;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.lwjgl.opengl.GL33;
|
||||
|
||||
import antsim.display.DisplayWindow;
|
||||
import antsim.init.Resources;
|
||||
import gl_engine.MathHelpers;
|
||||
import gl_engine.matrix.Matrix4;
|
||||
import gl_engine.texture.TextureRef3D;
|
||||
|
||||
public abstract class Model implements IModel
|
||||
{
|
||||
private static final Random rand = new Random();
|
||||
|
||||
public static final float OFFSET = 0.00001f;
|
||||
public static final int SIZE = 14;
|
||||
public static IModel bound = null;
|
||||
|
||||
int vao, vbo, ibo;
|
||||
boolean loaded = false;
|
||||
|
||||
public static void setGLArrayAttributes()
|
||||
{
|
||||
// aPos
|
||||
GL33.glVertexAttribPointer(0, 2, GL33.GL_FLOAT, false, Float.BYTES * SIZE, 0);
|
||||
GL33.glEnableVertexAttribArray(0);
|
||||
|
||||
// aTex
|
||||
GL33.glVertexAttribPointer(1, 3, GL33.GL_FLOAT, false, Float.BYTES * SIZE, Float.BYTES * 2);
|
||||
GL33.glEnableVertexAttribArray(1);
|
||||
|
||||
// aTexY
|
||||
GL33.glVertexAttribPointer(2, 2, GL33.GL_FLOAT, false, Float.BYTES * SIZE, Float.BYTES * 5);
|
||||
GL33.glEnableVertexAttribArray(2);
|
||||
|
||||
// aOffset
|
||||
GL33.glVertexAttribPointer(3, 2, GL33.GL_FLOAT, false, Float.BYTES * SIZE, Float.BYTES * 7);
|
||||
GL33.glEnableVertexAttribArray(3);
|
||||
|
||||
// aAnimate
|
||||
GL33.glVertexAttribPointer(4, 2, GL33.GL_FLOAT, false, Float.BYTES * SIZE, Float.BYTES * 9);
|
||||
GL33.glEnableVertexAttribArray(4);
|
||||
|
||||
// aFlags
|
||||
GL33.glVertexAttribPointer(5, 3, GL33.GL_FLOAT, false, Float.BYTES * SIZE, Float.BYTES * 11);
|
||||
GL33.glEnableVertexAttribArray(5);
|
||||
}
|
||||
|
||||
protected void generate()
|
||||
{
|
||||
if(loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
int[] indicies = this.getIndicies();
|
||||
float[] verticies = this.getVerticies();
|
||||
TextureRef3D[] refs = this.getTextures();
|
||||
|
||||
if(verticies.length % SIZE != 0 || refs.length * SIZE != verticies.length) {
|
||||
System.err.println("Invalid model: " + verticies.length + ", " + refs.length + ", " + indicies.length);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
int size = verticies.length/SIZE;
|
||||
double k = OFFSET;
|
||||
|
||||
for(int i=0;i<size;i++) {
|
||||
TextureRef3D ref = refs[i];
|
||||
verticies[i*SIZE + 2] = (float)MathHelpers.map(verticies[i*SIZE + 2], 0-k, 1+k, ref.sx, ref.ex);
|
||||
verticies[i*SIZE + 3] = (float)MathHelpers.map(verticies[i*SIZE + 3], 0-k, 1+k, ref.sy, ref.ey);
|
||||
verticies[i*SIZE + 4] = ref.z;
|
||||
verticies[i*SIZE + 5] = (float)MathHelpers.map(verticies[i*SIZE + 5], 0, 1, ref.sy, ref.ey);
|
||||
verticies[i*SIZE + 6] = (float)MathHelpers.map(verticies[i*SIZE + 6], 0, 1, ref.sy, ref.ey);
|
||||
}
|
||||
|
||||
vao = GL33.glGenVertexArrays();
|
||||
vbo = GL33.glGenBuffers();
|
||||
ibo = GL33.glGenBuffers();
|
||||
|
||||
GL33.glBindVertexArray(vao);
|
||||
|
||||
GL33.glBindBuffer(GL33.GL_ELEMENT_ARRAY_BUFFER, ibo);
|
||||
GL33.glBufferData(GL33.GL_ELEMENT_ARRAY_BUFFER, indicies, GL33.GL_STATIC_DRAW);
|
||||
|
||||
GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, vbo);
|
||||
GL33.glBufferData(GL33.GL_ARRAY_BUFFER, verticies, GL33.GL_STATIC_DRAW);
|
||||
|
||||
setGLArrayAttributes();
|
||||
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
public void bind()
|
||||
{
|
||||
if(loaded) {
|
||||
GL33.glBindVertexArray(vao);
|
||||
}
|
||||
|
||||
else {
|
||||
generate();
|
||||
}
|
||||
|
||||
bound = this;
|
||||
}
|
||||
|
||||
public void render()
|
||||
{
|
||||
if(bound != this) {
|
||||
bind();
|
||||
}
|
||||
|
||||
GL33.glDrawElements(GL33.GL_TRIANGLES, getIndexSize(), GL33.GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
public void free() {
|
||||
GL33.glDeleteBuffers(ibo);
|
||||
GL33.glDeleteBuffers(vbo);
|
||||
GL33.glDeleteVertexArrays(vao);
|
||||
loaded = false;
|
||||
}
|
||||
|
||||
public void setModel(Matrix4 model) {
|
||||
GL33.glUniformMatrix4fv(DisplayWindow.WINDOW.glsl_matrix, true, model.getArray());
|
||||
}
|
||||
|
||||
public TextureRef3D getRandomChunk(int[] tex_id)
|
||||
{
|
||||
TextureRef3D[] textures = getTextures();
|
||||
|
||||
if(textures.length == 0) {
|
||||
return Resources.TEX_EMPTY;
|
||||
}
|
||||
|
||||
tex_id[0] = (int)(rand.nextDouble() * textures.length);
|
||||
TextureRef3D texture = textures[tex_id[0]];
|
||||
TextureRef3D ref = new TextureRef3D();
|
||||
|
||||
float dx = texture.ex - texture.sx;
|
||||
float dy = texture.ey - texture.sy;
|
||||
float w = (float)getWidth();
|
||||
float h = (float)getHeight();
|
||||
|
||||
ref.sx = (float)MathHelpers.map((int)(rand.nextDouble()*16*w), 0, 16*w, texture.sx, texture.ex - dx/(16*w));
|
||||
ref.sy = (float)MathHelpers.map((int)(rand.nextDouble()*16*h), 0, 16*h, texture.sy, texture.ey - dy/(16*h));
|
||||
ref.ex = ref.sx + dx/(16*w);
|
||||
ref.ey = ref.sy + dy/(16*h);
|
||||
|
||||
ref.texmap = texture.texmap;
|
||||
ref.z = texture.z;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return loaded;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package antsim.model;
|
||||
|
||||
import antsim.init.Resources;
|
||||
import gl_engine.texture.TextureRef3D;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class ModelFlat extends Model
|
||||
{
|
||||
private TextureRef3D tex;
|
||||
private Vec2d size;
|
||||
private int animationSize;
|
||||
private int animationSpeed;
|
||||
|
||||
public ModelFlat(TextureRef3D tex, Vec2d size, int animationSize, int animationSpeed) {
|
||||
this.tex = tex;
|
||||
this.size = size;
|
||||
this.animationSpeed = animationSpeed;
|
||||
this.animationSize = animationSize;
|
||||
}
|
||||
|
||||
public ModelFlat(TextureRef3D tex, Vec2d size) {
|
||||
this(tex, size, 1, 1);
|
||||
}
|
||||
|
||||
public ModelFlat(TextureRef3D tex, int animationSize, int animationSpeed) {
|
||||
this(tex, new Vec2d(1, 1), animationSize, animationSpeed);
|
||||
}
|
||||
|
||||
public ModelFlat(TextureRef3D tex) {
|
||||
this(tex, new Vec2d(1, 1), 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIndicies() {
|
||||
return new int[] {
|
||||
0, 1, 2,
|
||||
2, 3, 0,
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getVerticies()
|
||||
{
|
||||
float x = (float)(size.x / 2);
|
||||
float y = (float)(size.y / 2);
|
||||
float asi = animationSize;
|
||||
float asp = animationSpeed;
|
||||
|
||||
return new float[] {
|
||||
-x, -y, 0, 0, 0, 0, 1, 0, 0, asi, asp, 0, 0, 0,
|
||||
-x, y, 0, 1, 0, 0, 1, 0, 0, asi, asp, 0, 0, 0,
|
||||
x, y, 1, 1, 0, 0, 1, 0, 0, asi, asp, 0, 0, 0,
|
||||
x, -y, 1, 0, 0, 0, 1, 0, 0, asi, asp, 0, 0, 0,
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRef3D[] getTextures() {
|
||||
return new TextureRef3D[] {
|
||||
tex, tex, tex, tex,
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWidth() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexSize() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package antsim.nest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import antsim.entity.EntityAnt;
|
||||
import bdf.types.BdfArray;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import gl_engine.vec.Vec2d;
|
||||
|
||||
public class Nest
|
||||
{
|
||||
public int id;
|
||||
private int population;
|
||||
private int food;
|
||||
|
||||
public ArrayList<EntityAnt> ants;
|
||||
|
||||
public Nest(int id)
|
||||
{
|
||||
this.id = id;
|
||||
|
||||
population = 10;
|
||||
food = 0;
|
||||
|
||||
ants = new ArrayList<EntityAnt>(population);
|
||||
|
||||
for(int i=0;i<population;i++) {
|
||||
ants.add(new EntityAnt(this, new Vec2d(0, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
public Nest(BdfObject bdf) {
|
||||
loadBDF(bdf);
|
||||
}
|
||||
|
||||
public void loadBDF(BdfObject bdf)
|
||||
{
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
BdfArray ants_bdf = nl.get("ants").getArray();
|
||||
|
||||
ants = new ArrayList<EntityAnt>(ants_bdf.size());
|
||||
food = nl.get("food").getInteger();
|
||||
population = nl.get("population").getInteger();
|
||||
id = nl.get("id").getInteger();
|
||||
|
||||
for(BdfObject ant_bdf : ants_bdf) {
|
||||
ants.add(new EntityAnt(ant_bdf, false));
|
||||
}
|
||||
}
|
||||
|
||||
public void saveBDF(BdfObject bdf)
|
||||
{
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
BdfArray ants_bdf = bdf.newArray(ants.size());
|
||||
|
||||
nl.set("food", bdf.newObject().setInteger(food));
|
||||
nl.set("population", bdf.newObject().setInteger(population));
|
||||
nl.set("ants", bdf.newObject().setArray(ants_bdf));
|
||||
nl.set("id", bdf.newObject().setInteger(id));
|
||||
|
||||
for(int i=0;i<ants.size();i++) {
|
||||
ants.get(i).saveBDF(ants_bdf.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public int getFood() {
|
||||
return food;
|
||||
}
|
||||
|
||||
public void addFood() {
|
||||
food += 1;
|
||||
}
|
||||
|
||||
public boolean takeFood()
|
||||
{
|
||||
if(food > 0) {
|
||||
food -= 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package antsim.start;
|
||||
|
||||
import antsim.entity.Entity;
|
||||
import antsim.entity.EntityAnt;
|
||||
import antsim.entity.EntityFood;
|
||||
import antsim.world.World;
|
||||
import gl_engine.MathHelpers;
|
||||
import gl_engine.vec.Vec2d;
|
||||
import mainloop.event.IMainloopEvent;
|
||||
import mainloop.manager.MainloopManager;
|
||||
import mainloop.task.IMainloopTask;
|
||||
|
||||
public class Start implements IMainloopEvent, IMainloopTask
|
||||
{
|
||||
public static final Start START = new Start();
|
||||
public static final int DEFAULT_PORT = 14972;
|
||||
|
||||
public static boolean isServer;
|
||||
public static MainloopManager mainloop;
|
||||
public static int mspf = 1000 / 60;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
System.out.println("Mainloop closed cleanly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEarly()
|
||||
{
|
||||
mspf -= 1;
|
||||
|
||||
if(mspf < 1) {
|
||||
mspf = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLate()
|
||||
{
|
||||
mspf += 1;
|
||||
|
||||
if(mspf > 1000) {
|
||||
mspf = 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
System.out.println("Mainloop started");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopDelay(long millis) {
|
||||
return millis > 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopRepeat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MainLoopUpdate()
|
||||
{
|
||||
for(int i=0;i<World.WORLD.entities.size();i++) {
|
||||
World.WORLD.entities.get(i).update();
|
||||
}
|
||||
|
||||
for(int i=0;i<World.WORLD.entities.size();i++) {
|
||||
if(World.WORLD.entities.get(i).isDead()) {
|
||||
World.WORLD.entities.remove(i);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(isServer)
|
||||
{
|
||||
counter += 1;
|
||||
|
||||
if(counter > 25) {
|
||||
counter -= 25;
|
||||
|
||||
World.WORLD.entities.add(new EntityFood(MathHelpers.moveTowards2(
|
||||
Math.sqrt(Math.random()) * 40, Math.random() * MathHelpers.TWO_PI)));
|
||||
|
||||
StartServer.markNeedToUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package antsim.start;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import antsim.display.DisplayCamera;
|
||||
import antsim.display.DisplayWindow;
|
||||
import antsim.entity.Entity;
|
||||
import antsim.entity.EntityAnt;
|
||||
import antsim.init.Entities;
|
||||
import antsim.init.Resources;
|
||||
import antsim.worker.WorkerComType;
|
||||
import antsim.worker.WorkerSocket;
|
||||
import antsim.world.World;
|
||||
import bdf.types.BdfArray;
|
||||
import bdf.types.BdfIndent;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import bdf.types.BdfReader;
|
||||
import gl_engine.MathHelpers;
|
||||
import gl_engine.vec.Vec2d;
|
||||
import mainloop.manager.MainloopManager;
|
||||
import mainloop.task.IMainloopTask;
|
||||
|
||||
public class StartClient implements IMainloopTask
|
||||
{
|
||||
private static WorkerSocket socket;
|
||||
|
||||
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException
|
||||
{
|
||||
MathHelpers.init();
|
||||
DisplayWindow.WINDOW.init();
|
||||
Resources.init();
|
||||
Entities.init();
|
||||
|
||||
String ip = "localhost";
|
||||
int port = Start.DEFAULT_PORT;
|
||||
|
||||
if(args.length > 0) {
|
||||
ip = args[0];
|
||||
}
|
||||
|
||||
if(args.length > 1) {
|
||||
port = Integer.parseInt(args[1]);
|
||||
}
|
||||
|
||||
System.out.println("IP: " + ip + ", Port: " + port);
|
||||
|
||||
Start.isServer = false;
|
||||
|
||||
socket = new WorkerSocket(ip, port, reader -> {
|
||||
onRecieveData(reader);
|
||||
});
|
||||
|
||||
socket.start();
|
||||
|
||||
Start.mainloop = new MainloopManager(Start.START);
|
||||
Start.mainloop.register(new StartClient());
|
||||
Start.mainloop.register(DisplayWindow.WINDOW);
|
||||
Start.mainloop.register(Start.START);
|
||||
|
||||
Start.mainloop.start();
|
||||
|
||||
socket.close();
|
||||
}
|
||||
|
||||
private static void onRecieveData(BdfReader reader)
|
||||
{
|
||||
BdfObject bdf = reader.getObject();
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
|
||||
int type = (int)nl.get("type").getAutoInt();
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case WorkerComType.UPDATE:
|
||||
World.WORLD.loadBDF(bdf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopDelay(long millis) {
|
||||
return millis > 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopRepeat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MainLoopUpdate()
|
||||
{
|
||||
if(DisplayWindow.WINDOW.shouldClose()) {
|
||||
Start.mainloop.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayWindow.WINDOW.pollEvents();
|
||||
|
||||
socket.update();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package antsim.start;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import antsim.entity.EntityNestEntrance;
|
||||
import antsim.init.Entities;
|
||||
import antsim.nest.Nest;
|
||||
import antsim.worker.WorkerComType;
|
||||
import antsim.worker.WorkerServer;
|
||||
import antsim.worker.WorkerSocket;
|
||||
import antsim.world.World;
|
||||
import bdf.types.BdfArray;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import bdf.types.BdfReader;
|
||||
import gl_engine.MathHelpers;
|
||||
import gl_engine.vec.Vec2d;
|
||||
import mainloop.manager.MainloopManager;
|
||||
import mainloop.task.IMainloopTask;
|
||||
|
||||
public class StartServer implements IMainloopTask
|
||||
{
|
||||
private static WorkerServer server;
|
||||
private static AtomicBoolean needToUpdate = new AtomicBoolean();
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException
|
||||
{
|
||||
MathHelpers.init();
|
||||
Entities.init();
|
||||
|
||||
Start.isServer = true;
|
||||
|
||||
int port = Start.DEFAULT_PORT;
|
||||
|
||||
if(args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
}
|
||||
|
||||
server = new WorkerServer(port);
|
||||
server.start();
|
||||
|
||||
Start.mainloop = new MainloopManager(Start.START);
|
||||
Start.mainloop.register(new StartServer());
|
||||
Start.mainloop.register(Start.START);
|
||||
|
||||
for(int i=0;i<2;i++)
|
||||
{
|
||||
Nest nest = new Nest(i);
|
||||
Vec2d area_pos = new Vec2d(Math.random() * 50 - 25, Math.random() * 50 - 25);
|
||||
|
||||
for(int j=0;j<50;j++)
|
||||
{
|
||||
World.WORLD.nests.add(nest);
|
||||
World.WORLD.entities.add(new EntityNestEntrance(
|
||||
nest, area_pos.add(new Vec2d(Math.random() * 20 - 10, Math.random() * 20 - 10))));
|
||||
}
|
||||
}
|
||||
|
||||
Start.mainloop.start();
|
||||
|
||||
server.close();
|
||||
}
|
||||
|
||||
public static void markNeedToUpdate() {
|
||||
needToUpdate.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopDelay(long millis) {
|
||||
return millis > 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean MainLoopRepeat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MainLoopUpdate()
|
||||
{
|
||||
server.update();
|
||||
|
||||
if(needToUpdate.getAndSet(false))
|
||||
{
|
||||
BdfReader reader = new BdfReader();
|
||||
BdfObject bdf = reader.getObject();
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
|
||||
nl.set("type", bdf.newObject().setAutoInt(WorkerComType.UPDATE));
|
||||
|
||||
World.WORLD.saveBDF(bdf);
|
||||
|
||||
server.broadcast(reader);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package antsim.util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import gl_engine.vec.Vec2i;
|
||||
|
||||
class Node
|
||||
{
|
||||
int x, y;
|
||||
int g, h, s;
|
||||
Node parent;
|
||||
|
||||
public Node(Node parent, int x, int y, int g, int h, int s) {
|
||||
this.parent = parent;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.g = g;
|
||||
this.h = h;
|
||||
this.s = s;
|
||||
}
|
||||
}
|
||||
|
||||
public class AStar
|
||||
{
|
||||
AStarSearch search;
|
||||
|
||||
Vec2i start;
|
||||
Vec2i goal;
|
||||
int radius;
|
||||
|
||||
List<Node> open;
|
||||
List<Node> closed;
|
||||
|
||||
Node now;
|
||||
Node found;
|
||||
|
||||
public AStar(Vec2i start, int radius, AStarSearch search)
|
||||
{
|
||||
this.search = search;
|
||||
this.start = start;
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public Vec2i[] getPath(Vec2i goal)
|
||||
{
|
||||
// Goal out of range
|
||||
if(this.posOutOfRange(goal.x, goal.y)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Start is a wall
|
||||
if(search.getWeight(start.x, start.y) == 100) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.goal = goal;
|
||||
this.open = new ArrayList<Node>(radius*4);
|
||||
this.closed = new ArrayList<Node>(radius*4);
|
||||
|
||||
now = new Node(null, start.x, start.y, 0, 0, 1);
|
||||
closed.add(now);
|
||||
|
||||
addNeighboursToList();
|
||||
|
||||
while(open.size() > 0)
|
||||
{
|
||||
// Found the goal
|
||||
if(found != null)
|
||||
{
|
||||
Node n = found;
|
||||
Vec2i[] path = new Vec2i[n.s];
|
||||
|
||||
for(int i=0;n!=null;i++) {
|
||||
path[i] = new Vec2i(n.x, n.y);
|
||||
n = n.parent;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
int nid = getEasiestNode();
|
||||
Node n = open.get(nid);
|
||||
|
||||
open.remove(nid);
|
||||
closed.add(n);
|
||||
now = n;
|
||||
|
||||
addNeighboursToList();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean neighbourInList(List<Node> nodes, int x, int y) {
|
||||
for(Node n : nodes) {
|
||||
if(n.x == x && n.y == y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean posOutOfRange(int x, int y) {
|
||||
return (
|
||||
x > start.x + radius ||
|
||||
x < start.x - radius ||
|
||||
y > start.y + radius ||
|
||||
y < start.y - radius);
|
||||
}
|
||||
|
||||
private void addNeighboursToList()
|
||||
{
|
||||
int neighbours[] = {
|
||||
1, 0,
|
||||
-1, 0,
|
||||
0, 1,
|
||||
0, -1
|
||||
};
|
||||
|
||||
for(int i=0;i<neighbours.length;i+=2)
|
||||
{
|
||||
int x = now.x + neighbours[i + 0];
|
||||
int y = now.y + neighbours[i + 1];
|
||||
|
||||
// Ignore out of range coords
|
||||
if(posOutOfRange(x, y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int weight = search.getWeight(x, y);
|
||||
|
||||
// Ignore all solid walls
|
||||
if(weight == 100) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore already open/closed points
|
||||
if(neighbourInList(open, x, y) || neighbourInList(closed, x, y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a new node
|
||||
Node node = new Node(now, x, y, g(weight, x, y), h(x, y), now.s + 1);
|
||||
|
||||
if(x == goal.x && y == goal.y) {
|
||||
found = node;
|
||||
}
|
||||
|
||||
open.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private int g(int w, int x, int y) {
|
||||
return now.g + (100 / (100 - w));
|
||||
}
|
||||
|
||||
private int h(int x, int y) {
|
||||
return Math.abs(x - goal.x) + Math.abs(y - goal.y);
|
||||
}
|
||||
|
||||
private int getEasiestNode()
|
||||
{
|
||||
Node check = null;
|
||||
int id = -1;
|
||||
|
||||
for(int i=0;i<open.size();i++)
|
||||
{
|
||||
Node n = open.get(i);
|
||||
|
||||
if(check == null || n.g + n.h < check.g + check.h) {
|
||||
check = n;
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package antsim.util;
|
||||
|
||||
public interface AStarSearch
|
||||
{
|
||||
public int getWeight(int x, int y);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package antsim.util;
|
||||
|
||||
import bdf.types.BdfObject;
|
||||
|
||||
public interface ClassBdf
|
||||
{
|
||||
public void loadBDF(BdfObject bdf);
|
||||
public void saveBDF(BdfObject bdf);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package antsim.worker;
|
||||
|
||||
public class WorkerComType
|
||||
{
|
||||
public static final int UPDATE = 1;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package antsim.worker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import antsim.entity.Entity;
|
||||
import antsim.start.StartServer;
|
||||
import antsim.world.World;
|
||||
import bdf.data.BdfDatabase;
|
||||
import bdf.types.BdfArray;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
import bdf.types.BdfReader;
|
||||
import bdf.util.DataHelpers;
|
||||
|
||||
public class WorkerServer extends Thread implements WorkerSocketCallback
|
||||
{
|
||||
AtomicBoolean sockets_reading;
|
||||
Vector<WorkerSocket> sockets;
|
||||
ServerSocket ss;
|
||||
|
||||
public WorkerServer(int port) throws IOException
|
||||
{
|
||||
ss = new ServerSocket(port);
|
||||
sockets = new Vector<WorkerSocket>();
|
||||
sockets_reading = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
sockets_reading.set(true);
|
||||
|
||||
// Update the sockets
|
||||
for(int i=0;i<sockets.size();i++)
|
||||
{
|
||||
WorkerSocket socket = sockets.get(i);
|
||||
|
||||
if(!socket.isAlive())
|
||||
{
|
||||
System.out.println("Shut down socket");
|
||||
sockets.remove(i);
|
||||
i -= 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
socket.update();
|
||||
}
|
||||
|
||||
sockets_reading.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while(ss.isBound())
|
||||
{
|
||||
try
|
||||
{
|
||||
Socket socket = ss.accept();
|
||||
WorkerSocket worker = new WorkerSocket(socket, this);
|
||||
worker.start();
|
||||
|
||||
while(sockets_reading.get()) {}
|
||||
sockets.add(worker);
|
||||
|
||||
StartServer.markNeedToUpdate();
|
||||
}
|
||||
|
||||
catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecieve(BdfReader reader) {
|
||||
try {
|
||||
reader.serializeHumanReadable(System.out);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
ss.close();
|
||||
}
|
||||
|
||||
public void broadcast(BdfReader reader)
|
||||
{
|
||||
sockets.forEach(socket ->
|
||||
{
|
||||
if(socket.isAlive())
|
||||
{
|
||||
try {
|
||||
socket.send(reader);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package antsim.worker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import bdf.data.BdfDatabase;
|
||||
import bdf.types.BdfObject;
|
||||
import bdf.types.BdfReader;
|
||||
import bdf.types.BdfTypes;
|
||||
import bdf.util.DataHelpers;
|
||||
|
||||
public class WorkerSocket extends Thread
|
||||
{
|
||||
private Socket socket;
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
private ArrayList<BdfReader> queue;
|
||||
private AtomicBoolean queue_reading;
|
||||
private WorkerSocketCallback callback;
|
||||
|
||||
public WorkerSocket(String ip, int port, WorkerSocketCallback callback) throws UnknownHostException, IOException
|
||||
{
|
||||
this.socket = new Socket(ip, port);
|
||||
this.in = socket.getInputStream();
|
||||
this.out = socket.getOutputStream();
|
||||
this.queue = new ArrayList<BdfReader>();
|
||||
this.queue_reading = new AtomicBoolean(false);
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public WorkerSocket(Socket socket, WorkerSocketCallback callback) throws IOException
|
||||
{
|
||||
this.socket = socket;
|
||||
this.in = socket.getInputStream();
|
||||
this.out = socket.getOutputStream();
|
||||
this.queue = new ArrayList<BdfReader>();
|
||||
this.queue_reading = new AtomicBoolean(false);
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
BdfReader next = this.next();
|
||||
|
||||
if(next == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback.onRecieve(next);
|
||||
}
|
||||
|
||||
public void send(BdfReader reader) throws IOException
|
||||
{
|
||||
BdfDatabase db = reader.serialize();
|
||||
|
||||
out.write(ByteBuffer.allocate(4).putInt(db.size()).array());
|
||||
db.writeToStream(out);
|
||||
}
|
||||
|
||||
public BdfReader next()
|
||||
{
|
||||
queue_reading.set(true);
|
||||
|
||||
if(queue.size() == 0)
|
||||
{
|
||||
queue_reading.set(false);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
BdfReader reader = queue.get(0);
|
||||
|
||||
queue.remove(0);
|
||||
|
||||
queue_reading.set(false);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while(!socket.isClosed())
|
||||
{
|
||||
int size;
|
||||
int buffer_size = 0;
|
||||
byte[] buffer_size_bytes = new byte[4];
|
||||
|
||||
in.read(buffer_size_bytes);
|
||||
buffer_size = ByteBuffer.wrap(buffer_size_bytes).getInt(0);
|
||||
|
||||
BdfDatabase database = new BdfDatabase(buffer_size);
|
||||
|
||||
for(int i=0;i<database.size();)
|
||||
{
|
||||
byte[] buffer = new byte[Math.min(1024, database.size() - i)];
|
||||
size = in.read(buffer);
|
||||
|
||||
if(size == -1) {
|
||||
Thread.sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
database.setBytes(buffer, i, size);
|
||||
i += size;
|
||||
}
|
||||
|
||||
BdfReader reader = new BdfReader(database);
|
||||
BdfObject bdf = reader.getObject();
|
||||
|
||||
if(bdf.getType() == BdfTypes.UNDEFINED) {
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
|
||||
while(queue_reading.get()) {}
|
||||
queue.add(reader);
|
||||
}
|
||||
}
|
||||
|
||||
catch(IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package antsim.worker;
|
||||
|
||||
import bdf.types.BdfReader;
|
||||
|
||||
public interface WorkerSocketCallback
|
||||
{
|
||||
public void onRecieve(BdfReader reader);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package antsim.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import antsim.entity.Entity;
|
||||
import antsim.nest.Nest;
|
||||
import bdf.types.BdfArray;
|
||||
import bdf.types.BdfIndent;
|
||||
import bdf.types.BdfNamedList;
|
||||
import bdf.types.BdfObject;
|
||||
|
||||
public class World
|
||||
{
|
||||
public static World WORLD = new World();
|
||||
|
||||
public ArrayList<Entity> entities = new ArrayList<Entity>();
|
||||
public ArrayList<Nest> nests = new ArrayList<Nest>();
|
||||
|
||||
public void loadBDF(BdfObject bdf)
|
||||
{
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
|
||||
BdfArray nests_bdf = nl.get("nests").getArray();
|
||||
BdfArray entities_bdf = nl.get("entities").getArray();
|
||||
|
||||
entities = new ArrayList<Entity>(entities_bdf.size());
|
||||
nests = new ArrayList<Nest>(nests_bdf.size());
|
||||
|
||||
for(BdfObject nest_bdf : nests_bdf) {
|
||||
nests.add(new Nest(nest_bdf));
|
||||
}
|
||||
|
||||
for(BdfObject entity_bdf : entities_bdf) {
|
||||
entities.add(Entity.loadEntity(entity_bdf));
|
||||
}
|
||||
}
|
||||
|
||||
public void saveBDF(BdfObject bdf)
|
||||
{
|
||||
BdfNamedList nl = bdf.getNamedList();
|
||||
|
||||
BdfArray entities_bdf = bdf.newArray(entities.size());
|
||||
BdfArray nests_bdf = bdf.newArray(nests.size());
|
||||
|
||||
for(int i=0;i<entities.size();i++) {
|
||||
entities.get(i).saveBDF(entities_bdf.get(i));
|
||||
}
|
||||
|
||||
for(int i=0;i<nests.size();i++) {
|
||||
nests.get(i).saveBDF(nests_bdf.get(i));
|
||||
}
|
||||
|
||||
nl.set("nests", bdf.newObject().setArray(nests_bdf));
|
||||
nl.set("entities", bdf.newObject().setArray(entities_bdf));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#version 330
|
||||
|
||||
uniform vec4 tex;
|
||||
uniform vec2 scale;
|
||||
uniform vec2 translate;
|
||||
uniform sampler3D atlas;
|
||||
|
||||
in vec3 pTex;
|
||||
|
||||
out vec4 colour;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 tex_coords = vec3(((pTex.xy * 2 - 1) / scale - translate) * 0.5 + 0.5, pTex.z);
|
||||
vec3 t = vec3(
|
||||
mod(tex_coords.x - tex.x, tex.z - tex.x) + tex.x,
|
||||
mod(tex_coords.y - tex.y, tex.w - tex.y) + tex.y,
|
||||
tex_coords.z);
|
||||
|
||||
colour = texture(atlas, t);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#version 330
|
||||
|
||||
layout (location = 0) in vec2 aPos;
|
||||
layout (location = 1) in vec3 aTex;
|
||||
|
||||
out vec3 pTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPos, 0, 1);
|
||||
pTex = aTex;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#version 330
|
||||
|
||||
out vec4 pColor;
|
||||
|
||||
in vec3 pTex;
|
||||
|
||||
uniform sampler3D atlas;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture(atlas, pTex);
|
||||
pColor = color;
|
||||
|
||||
discard(color.a == 0);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#version 330
|
||||
|
||||
layout (location = 0) in vec2 aPos;
|
||||
layout (location = 1) in vec3 aTex;
|
||||
layout (location = 2) in vec2 aTexY;
|
||||
layout (location = 3) in vec2 aOffset;
|
||||
layout (location = 4) in vec2 aAnimate;
|
||||
layout (location = 5) in vec3 aFlags;
|
||||
|
||||
out vec3 pTex;
|
||||
|
||||
uniform mat4 matrix;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPos, 0, 1) * matrix * projection;
|
||||
pTex = aTex;
|
||||
}
|
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 612 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.6 KiB |
|
@ -0,0 +1,8 @@
|
|||
./food.png
|
||||
./nest.png
|
||||
./list.txt
|
||||
./big.png
|
||||
./ant_food.png
|
||||
./ant.png
|
||||
./grass.png
|
||||
./ant_eat_ant.png
|
After Width: | Height: | Size: 1.0 KiB |