Initial commit

This commit is contained in:
jsrobson10 2020-09-22 14:19:27 +10:00
commit f49f7b61e8
41 changed files with 2227 additions and 0 deletions

46
.classpath Normal file
View File

@ -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>

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bin

17
.project Normal file
View File

@ -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>

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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"));
}

View File

@ -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("");
}
}

View File

@ -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();
}

160
src/antsim/model/Model.java Normal file
View File

@ -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;
}
}

View File

@ -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;
}
}

87
src/antsim/nest/Nest.java Normal file
View File

@ -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;
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

178
src/antsim/util/AStar.java Normal file
View File

@ -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;
}
}

View File

@ -0,0 +1,6 @@
package antsim.util;
public interface AStarSearch
{
public int getWeight(int x, int y);
}

View File

@ -0,0 +1,9 @@
package antsim.util;
import bdf.types.BdfObject;
public interface ClassBdf
{
public void loadBDF(BdfObject bdf);
public void saveBDF(BdfObject bdf);
}

View File

@ -0,0 +1,6 @@
package antsim.worker;
public class WorkerComType
{
public static final int UPDATE = 1;
}

View File

@ -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();
}
}
});
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,8 @@
package antsim.worker;
import bdf.types.BdfReader;
public interface WorkerSocketCallback
{
public void onRecieve(BdfReader reader);
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,8 @@
./food.png
./nest.png
./list.txt
./big.png
./ant_food.png
./ant.png
./grass.png
./ant_eat_ant.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB