Commit 99af70ab authored by lordbenedikt's avatar lordbenedikt
Browse files

Initial Commit

parents
modes
\ No newline at end of file
ArrayList<Integer> keys = new ArrayList<Integer>();
ArrayList<Knoten> knoten = new ArrayList<Knoten>();
ArrayList<Kante> kanten = new ArrayList<Kante>();
ArrayList<Knoten> selection = new ArrayList<Knoten>();
ArrayList<Knoten> path = new ArrayList<Knoten>();
ArrayList<Ant> ants = new ArrayList<Ant>();
ArrayList<Ant> updateAnts = new ArrayList<Ant>();
int antSpeed = 100;
int antTimer = antSpeed;
Knoten start;
Knoten ziel;
boolean moving = false;
PImage antIMG;
void setup() {
size(600, 600);
imageMode(CENTER);
antIMG = loadImage("ant.png");
int cols = 11;
int rows = 8;
for(int j = 0; j<rows; j++) {
for(int i = 0; i<cols; i++) {
knoten.add(new Knoten(50+i*50 +random(-20,20), 180+j*50 +random(-20,20)));
if(i>0) {
kanten.add(new Kante(knoten.get(j*cols+i-1),knoten.get(j*cols+i)));
}
if(j>0) {
kanten.add(new Kante(knoten.get((j-1)*cols+i),knoten.get(j*cols+i)));
}
}
}
}
void draw() {
background(100);
fill(255);
// instructions
text("MOUSE_LEFT: Knoten auswählen", 10, 15);
text("SHIFT + MOUSE_LEFT: Knoten zur Auswahl hinzufügen", 10, 30);
text("CTRL + MOUSE_LEFT: Knoten erstellen(inkl. Kanten zu allen ausgewählten Knoten)", 10, 45);
text("G: Ausgewählte Knoten bewegen(absetzen mit MOUSE_LEFT)", 10, 60);
text("X: Ausgewählte Knoten löschen", 10, 75);
text("CTRL + S: Ausgewählten Knoten zum Startknoten machen", 10, 90);
text("CTRL + Z: Ausgewählten Knoten zum Zielknoten machen", 10, 105);
// path length
text("Pfadlänge: " + aStar(start, ziel, path), 10, 130);
//editor action
//move knoten
if (moving) {
for (Knoten k : selection) {
k.x += mouseX-mouseLastX;
k.y += mouseY-mouseLastY;
}
}
//spawn ants
antTimer--;
if (antTimer <= 0) {
antTimer = (int)(antSpeed * random(0.1f, 1f));
if (start != null && path.size()>=2) {
ants.add(new Ant(start, path.get(1)));
}
}
updateAnts.addAll(ants);
for (Ant a : updateAnts) {
a.update();
}
updateAnts.clear();
//draw selection
for (Knoten k : selection) {
noStroke();
fill(255, 230, 200, 100);
circle(k.x, k.y, 50);
}
for (Kante k : kanten) {
stroke(255);
k.draw();
}
for (Knoten k : knoten) {
stroke(255);
k.draw();
}
for (Ant a : ants) {
a.draw();
}
//draw path length
//for (int i = 0; i<path.size(); i++) {
// text(i, path.get(i).x, path.get(i).y);
//}
//draw path ids
//for(int i = 0; i<path.size(); i++) {
// text(""+path.get(i),20,100+i*20);
//}
mouseLastX = mouseX;
mouseLastY = mouseY;
}
float rest(Knoten a, Knoten b) {
return dist(a.x, a.y, b.x, b.y);
}
float aStar(Knoten s, Knoten z, ArrayList<Knoten> path) {
if (s==null || z==null) {
path.clear();
return -1f;
}
HashMap<Knoten, Float> distance = new HashMap<Knoten, Float>();
distance.put(s, 0f);
ArrayList<Knoten> order = new ArrayList<Knoten>();
ArrayList<Knoten> todo = new ArrayList<Knoten>();
todo.add(s);
order.add(s);
while (!todo.isEmpty()) {
Knoten v = todo.get(0);
float minScore = distance.get(v) + rest(v, z);
for (int i = 1; i<todo.size(); i++) {
Knoten current = todo.get(i);
float currentScore = distance.get(current) + rest(current, z);
if (currentScore < minScore) {
minScore = currentScore;
v = current;
}
}
if (v == z) {
path.clear();
Knoten current = z;
path.add(z);
while (current != s) {
for (Knoten n : current.neighbours()) {
if (distance.containsKey(n)) {
if (distance.get(n) < distance.get(current) &&
distance.get(n)+dist(n.x, n.y, current.x, current.y)==distance.get(current)) {
path.add(0, n);
current = n;
break;
}
}
}
}
return distance.get(z);
}
todo.remove(v);
for (Knoten u : v.neighbours()) {
if (!distance.containsKey(u) || distance.get(u) > distance.get(v) + dist(v.x, v.y, u.x, u.y)) {
distance.put(u, distance.get(v)+dist(v.x, v.y, u.x, u.y));
todo.add(u);
order.add(u);
}
}
}
path.clear();
return -1f;
}
class Ant {
float x;
float y;
float dir = 0;
float speed = 1;
float progress = 0;
int isAtNode = 0;
Knoten v;
Knoten u;
Ant(Knoten v, Knoten u) {
this.x = v.x;
this.y = v.y;
this.v = v;
this.u = u;
dir = PVector.angleBetween(new PVector(v.x,v.y),new PVector(u.x,u.y));
}
void update() {
if (!knoten.contains(v) || !knoten.contains(u)) {
ants.remove(this);
return;
}
float distance = dist(v.x,v.y,u.x,u.y);
progress += speed/distance;
if (progress > 1) {
progress = 0;
isAtNode++;
if (isAtNode >= path.size()-1) {
ants.remove(this);
return;
}
v = u;
u = path.get(isAtNode+1);
}
dir = angle(u.x-v.x,u.y-v.y);
x = v.x + (progress*(u.x-v.x));
y = v.y + (progress*(u.y-v.y));
}
void draw() {
pushMatrix();
translate(x,y);
rotate(dir);
image(antIMG, 0, 0);
popMatrix();
}
}
float angle(float x, float y) {
float res;
if (x>0) res = atan(y/x) + HALF_PI;
else res = atan(y/x) + 3*HALF_PI;
return res;
}
class Kante {
Knoten a;
Knoten b;
Kante(Knoten a, Knoten b) {
this.a = a;
this.b = b;
}
boolean equals(Kante k) {
if (a==k.a && b==k.b) return true;
if (b==k.a && a==k.b) return true;
return false;
}
void draw() {
strokeWeight(2);
if(path.contains(a) && path.contains(b)) {
strokeWeight(5);
stroke(255,255,0);
}
line(a.x, a.y, b.x, b.y);
}
}
Kante getKante(Knoten a, Knoten b) {
Kante wanted = new Kante(a,b);
for (Kante k : kanten) {
if (k.equals(wanted))
return k;
}
return null;
}
void removeKante(Knoten a, Knoten b) {
Kante k = getKante(a,b);
if (k!=null)
kanten.remove(k);
}
void keyPressed() {
//add key to list
if (!keys.contains(keyCode)) {
keys.add(keyCode);
}
//delete Knoten
if (keyCode==((int)'X')) {
for(Knoten k : selection) {
k.delete();
}
selection.clear();
}
//assign start/ziel Knoten
if (keys.contains(CONTROL)) {
if (keyCode==((int)'S')) {
if (!selection.isEmpty())
start = selection.get(selection.size()-1);
}
if (keyCode==((int)'Z')) {
if (!selection.isEmpty())
ziel = selection.get(selection.size()-1);
}
//link all selected Knoten
if (keyCode==((int)'L')) {
for (int i = 0; i<selection.size(); i++) {
for (int j = i+1; j<selection.size(); j++) {
selection.get(i).link(selection.get(j));
}
}
}
//unlink all selected Knoten
if (keyCode==((int)'K')) {
for (int i = 0; i<selection.size(); i++) {
for (int j = i+1; j<selection.size(); j++) {
removeKante(selection.get(i), selection.get(j));
}
}
}
}
//move selection
if (keyIsDown('g')) {
moving = true;
}
}
void keyReleased() {
if (keys.contains(keyCode))
keys.remove((Integer)keyCode);
}
boolean keyIsDown(char c) {
return keys.contains((int)Character.toUpperCase(c));
}
boolean keyIsDown(int x) {
return keys.contains(x);
}
class Knoten {
float x;
float y;
Knoten(float x, float y) {
this.x = x;
this.y = y;
}
void link(Knoten knoten) {
Kante newKante = new Kante(this, knoten);
for (Kante k : kanten) {
if (k.equals(newKante)) return;
}
kanten.add(newKante);
}
ArrayList<Kante> getKanten() {
ArrayList<Kante> attached = new ArrayList<Kante>();
for (Kante kante : kanten) {
if (kante.a == this || kante.b == this)
attached.add(kante);
}
return attached;
}
void delete() {
kanten.removeAll(getKanten());
knoten.remove(this);
}
ArrayList<Knoten> neighbours() {
ArrayList<Knoten> neighbours = new ArrayList<Knoten>();
for(Kante k : getKanten()) {
if (!neighbours.contains(k.a) && k.a != this) {
neighbours.add(k.a);
}
if (!neighbours.contains(k.b) && k.b != this) {
neighbours.add(k.b);
}
}
return neighbours;
}
void draw() {
noStroke();
fill(255);
if (path.contains(this)) fill(255,255,0);
if (this == start) fill(0, 255, 0);
if (this == ziel) fill(255, 0, 0);
circle(x, y, 10);
}
}
ArrayList<Kante> getKanten(ArrayList<Knoten> multipleKnoten) {
ArrayList<Kante> result = new ArrayList<Kante>();
for (Knoten k : multipleKnoten) {
for (Kante kk : k.getKanten()) {
if (!result.contains(kk))
result.add(kk);
}
}
return result;
}
float mouseLastX;
float mouseLastY;
void mousePressed() {
if (keyIsDown(CONTROL)) {
if (mouseButton==LEFT) {
Knoten newKnoten = new Knoten(mouseX, mouseY);
knoten.add(newKnoten);
for (Knoten k : selection) {
kanten.add(new Kante(k, newKnoten));
}
selection.clear();
selection.add(newKnoten);
}
} else if (keyIsDown(SHIFT)) {
if (mouseButton==LEFT) {
Knoten closest = getClosestToMouse();
if (closest != null) {
if (!selection.contains(closest)) {
selection.add(closest);
} else {
selection.remove(closest);
}
}
}
} else if (mouseButton==LEFT) {
if (!moving) {
//select
selection.clear();
float shortestDistance = 50;
for (Knoten k : knoten) {
float currentDistance = dist(k.x, k.y, mouseX, mouseY);
if (currentDistance < shortestDistance) {
shortestDistance = currentDistance;
selection.clear();
selection.add(k);
}
}
} else {
if (!moving) {
selection.clear();
} else {
moving = false;
}
}
} else if (mouseButton==RIGHT) {
if (!moving) {
selection.clear();
} else {
moving = false;
}
}
}
Knoten getClosestToMouse() {
float shortestDistance = 50;
Knoten closest = null;
for (Knoten k : knoten) {
float currentDistance = dist(k.x, k.y, mouseX, mouseY);
if (currentDistance < shortestDistance) {
shortestDistance = currentDistance;
closest = k;
}
}
return closest;
}
var keys = [];
var knoten = [];
var kanten = [];
var selection = [];
var path = [];
var ants = [];
var updateAnts = [];
var antSpeed = 100;
var antTimer = antSpeed;
var pathLength = -1;
var start;
var ziel;
var moving = false;
var antIMG;
class Dictionary {
constructor() {
this.keys = [];
this.values = [];
}
getValue(keyy) {
for (let i = 0; i<this.keys.length; i++) {
if (this.keys[i] === keyy) {
return this.values[i];
}
}
}
getKey(value) {
for (let i = 0; i<this.values.length; i++) {
if (this.values[i] === value) {
return this.keys[i];
}
}
}
containsKey(keyy) {
for (const k of this.keys) {
if (k === keyy) {
return true;
}
}
return false;
}
put(keyy, value) {
let index = this.keys.indexOf(keyy);
if (index >= 0) {
this.values[index] = value;
} else {
this.keys.push(keyy);
this.values.push(value);
}
}
remove(keyy) {
for (let i = 0; i<this.keys.length; i++) {
if (this.keys === keyy) {
this.keys.splice(i, 1);
this.values.splice(i, 1);
}
}
}
}
function setup() {
createCanvas(1200, 800);
imageMode(CENTER);
antIMG = loadImage('data/ant.png');
let cols = 11;
let rows = 8;
for (var j = 0; j<rows; j++) {
for (let i = 0; i<cols; i++) {
knoten.push(new Knoten(50+i*50 +random(-20, 20), 180+j*50 +random(-20, 20)));
if (i>0) {
kanten.push(new Kante(knoten[j*cols+i-1], knoten[j*cols+i]));
}
if (j>0) {
kanten.push(new Kante(knoten[(j-1)*cols+i], knoten[j*cols+i]));
}
}
}
}
function draw() {
background(100);
document.body.style.background = "#646464";
if (moving) {
pathLength = aStar(start, ziel, path);
}
fill(0);
// instructions
text("MOUSE_LEFT: Knoten auswählen", 10, 15);
text("SHIFT + MOUSE_LEFT: Knoten zur Auswahl hinzufügen", 10, 30);
text("CTRL + MOUSE_LEFT: Knoten erstellen(inkl. Kanten zu allen ausgewählten Knoten)", 10, 45);
text("G: Ausgewählte Knoten bewegen(absetzen mit MOUSE_LEFT)", 10, 60);
text("X: Ausgewählte Knoten löschen", 10, 75);
text("A: Ausgewählten Knoten zum Startknoten machen", 10, 90);
text("Z: Ausgewählten Knoten zum Zielknoten machen", 10, 105);
// path length
text("Pfadlänge: " + pathLength, 10, 130);
//editor action
//move knoten
if (moving) {
selection.forEach((k) => {
k.x += mouseX-mouseLastX;
k.y += mouseY-mouseLastY;
}
);
}
//spawn ants
antTimer--;
if (antTimer <= 0) {
antTimer = floor(antSpeed * random(0.1, 1));
if (start !== null && path.length>=2) {
console.log("Path: " + path[1]);
console.log("Length: " + path.length);
ants.push(new Ant(path[0], path[1]));
}
}
updateAnts = updateAnts.concat(ants);
for (const a of updateAnts) {
a.update();
}
arrayClear(updateAnts);
//draw selection
for (const k of selection) {
noStroke();
fill(255, 230, 200, 100);
circle(k.x, k.y, 50);
}
for (const k of kanten) {
stroke(255);
k.draw();
}
for (const k of knoten) {
stroke(255);
k.draw();
}
for (const a of ants) {
a.draw();