I’ve downloaded slick and run the test. I’m not sure of the value of the visualisation though, since once I raise the number of entities to 10k it drops to under 1 fps (it’s rendering about once every 15 updates - each timed update and render takes less than 100ms).
With 1k or fewer entities any naive implementation will be fine (say, <1ms for updates and collision detection), so the visualisation doesn’t seem all that useful. Here’s a test class “CollisionTest2” that drops any graphical output - still using your existing interfaces apart from one extra method in ISpatialDataStructure:
public void clear();
I prints the mean and standard deviation of 50 update+collide calls. Your baseline implementations give:
Reference datastructure using sweep and prune strategy(quicksort) by Olli-Pekka Valtonen
1000 entities takes 192ms +/- 109.10838878372223
Reference datastructure using sweep and prune strategy(quicksort) by Olli-Pekka Valtonen
10000 entities takes 4909ms +/- 244.99901555071327
Reference datastructure using sweep and prune strategy(insertion sort) by Olli-Pekka Valtonen
1000 entities takes 152ms +/- 56.00231144306528
Regular Quadtree using sweep and prune strategy(quicksort) by Olli-Pekka Valtonen
1000 entities takes 28860ms +/- 677.3654851916602
package org.game;
import org.game.collision.Collision;
import org.game.collision.datastructures.*;
import org.game.collision.strategies.*;
import org.game.collision.strategies.SweepAndPruneStrategy.SortingAlgorithm;
import java.util.Random;
import java.util.ArrayList;
public class CollisionTest2{
public static void test(ISpatialDataStructure dataStructure, int entityCount){
Entity[] entities = new Entity[entityCount];
ArrayList<Collision> collisions = new ArrayList<Collision>();
Random random = new Random();
float maxWidth = dataStructure.getWidth();
float maxHeight = dataStructure.getHeight();
//run 20x50 test updates
int runs = 20;
int updatesPerRun = 50;
long[] times = new long[runs];
long mean = 0;
for(int i = 0; i < runs; i++){
dataStructure.clear();
//create the entities
for(int j = 0; j < entityCount; j++) {
float radius = 10 + random.nextFloat() * 90f;
float x = (-dataStructure.getWidth() + radius) / 2 + random.nextFloat() * (dataStructure.getWidth() - 2*radius);
float y = (-dataStructure.getHeight() + radius) / 2 + random.nextFloat() * (dataStructure.getHeight() - 2*radius);
x = Math.max(x,-maxWidth/2);
x = Math.min(x,maxWidth/2);
y = Math.max(x,-maxHeight/2);
y = Math.min(x,maxHeight/2);
float velX = random.nextFloat() * 10;
float velY = random.nextFloat() * 10;
Entity entity = new Entity(dataStructure, x, y, velX, velY, radius);
entities[j] = entity;
dataStructure.add(entity);
}
//do a run
long startTime = System.nanoTime();
for(int j = 0; j < updatesPerRun; j++){
dataStructure.update(10);
dataStructure.collide(collisions);
collisions.clear();
}
times[i] = System.nanoTime()-startTime;
mean += times[i];
if((i & 1) == 0){
System.out.print(".");
System.out.flush();
}
}
System.out.println("\n"+dataStructure.getInfo());
mean /= runs;
long variance = 0;
for(int i = 0; i < runs; i++)
variance += (mean-times[i])*(mean-times[i]);
variance /= runs;
double standardDeviation = Math.sqrt(variance);
System.out.println(entityCount+" entities takes "+(mean/1000000)+"ms +/- "+(standardDeviation/1000000));
}
public static void main(String[] args){
int width = 20000;
int height = 20000;
//ISpatialDataStructure dataStructure = new ReferenceDataStructure(width, height,new BruteforceStrategy());
ISpatialDataStructure dataStructure = new ReferenceDataStructure(width, height, new SweepAndPruneStrategy(SortingAlgorithm.InsertionSort));
//ISpatialDataStructure dataStructure = new RegularQuadtree(width, height, 7, new SweepAndPruneStrategy(SortingAlgorithm.Quicksort));
test(dataStructure,1000);
}
}