entities, improved pathfinding errorhandling

This commit is contained in:
2019-01-20 19:26:15 +01:00
parent 17d68f52bf
commit b848b0534b
3 changed files with 177 additions and 94 deletions

View File

@@ -1,38 +1,41 @@
import java.lang.Double; import java.lang.Double;
int i_citizenAmount = 5; int i_citizenAmount = 10;
int i_selectedCitizen;
int i_femaleCount; int i_femaleCount;
Citizen[] citizen = new Citizen[i_citizenAmount]; Citizen[] citizen = new Citizen[i_citizenAmount];
void initCitizen() { void initCitizen() {
//namen: ethuriel, nathaniel, loriel, samuel, aluriel, aleriel, thaliel, suriel, kaliel, //namen: ethuriel, nathaniel, loriel, samuel, aluriel, aleriel, thaliel, suriel, kaliel,
//int[][] claireArray = { { 00, 2 }, { 1, 3} }; //int[][] claireArray = { { 00, 2 }, { 1, 3} };
citizen[0] = new Citizen(800, "Test", 0,27); citizen[0] = new Citizen(800, "Test", 0, 27);
citizen[1] = new Citizen(121, "Matze", 1, 28); citizen[1] = new Citizen(121, "Matze", 1, 28);
citizen[2] = new Citizen(18, "Freddy", 1, 28); citizen[2] = new Citizen(18, "Freddy", 1, 28);
citizen[3] = new Citizen(59, "Korbi", 1, 28); citizen[3] = new Citizen(59, "Korbi", 1, 28);
citizen[4] = new Citizen(121, "Lotte", 1, 26); citizen[4] = new Citizen(121, "Lotte", 1, 26);
//citizen[5] = new Citizen(18, "Reifi", 1, 26); citizen[5] = new Citizen(18, "Reifi", 1, 26);
//citizen[6] = new Citizen(59, "Grasso", 1, 28); citizen[6] = new Citizen(59, "Grasso", 1, 28);
//citizen[7] = new Citizen(121, "Nico", 1, 29); citizen[7] = new Citizen(121, "Nico", 1, 29);
//citizen[8] = new Citizen(18, "Victor", 1, 28); citizen[8] = new Citizen(18, "Victor", 1, 28);
//citizen[9] = new Citizen(59, "Paul", 1, 28); citizen[9] = new Citizen(59, "Paul", 1, 28);
for (int i = 10; i < i_citizenAmount; i++) { for (int i = 10; i < i_citizenAmount; i++) {
int gender = int(random(0, 2)); int gender = int(random(0, 2));
if (gender == 0) i_femaleCount++; if (gender == 0) i_femaleCount++;
int age = int(random(0, 100)); int age = int(random(0, 100));
citizen[i] = new Citizen(int(random(0, houses.size())), S_citizenNames[gender][int(random(0, S_citizenNames[gender].length))], gender, age); citizen[i] = new Citizen(int(random(0, houses.size())), S_citizenNames[gender][int(random(0, S_citizenNames[gender].length))], gender, age);
} }
for (int i = 0; i < citizen.length; i++) {
if (i != i_selectedCitizen)
citizen[i].spawn(citizen[i].i_home);
else citizen[i].spawn(100,100);
for (int i = 0; i < citizen.length; i++) { if (citizen[i].b_randomRun) citizen[i].goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height))); //bad
citizen[i].spawn(citizen[i].i_home);
} }
selectCitizen(0); selectCitizen(0);
} }
int i_selectedCitizen;
void selectCitizen(int i) { void selectCitizen(int i) {
citizen[i_selectedCitizen].b_randomRun = true; citizen[i_selectedCitizen].b_randomRun = true;
citizen[i_selectedCitizen].b_moving = true; citizen[i_selectedCitizen].b_moving = true;
@@ -45,27 +48,22 @@ void selectCitizen(int i) {
i_selectedCitizen = i; i_selectedCitizen = i;
} }
class Citizen { class Citizen extends Entity {
int i_xSpawn, i_ySpawn, i_diameter;
boolean b_linked;
boolean b_moving;
int i_home;
String S_name;
float f_xPos, f_yPos;
float f_movementSpeed;
boolean b_selected;
int i_gender; int i_gender;
String S_gender; String S_gender;
int i_age; int i_age;
boolean b_randomRun = true; int i_home;
//0-100: float f_movementSpeed;
//motivation (bei arbeiter montag ~40, freitag ~80 - 100) boolean b_randomRun;
//7 emotionen?
// berufsfeld: webdesigner, pädagoge, schmuckdesigner, schmied GraphNode startNode, endNode;
// berufsstatus: beamter, selbstständiger, unternehmer, angestellter, grundschüler, gymnasiast, hauptschüler, realschüler, azubi, student, rentner int startNodeID, endNodeID;
GraphNode[] rNodes;
// ArrayList<GraphNode> rNodesList = new ArrayList<GraphNode>();
int nextNode;
// identität: gelbhemd, lokal, regional, national, international, fremd, IGraphSearch pathFinder;
int pathAlgorithm = i_pathAlgorithm;
Citizen(int home, String name, int gender, int age) { Citizen(int home, String name, int gender, int age) {
i_home = home; i_home = home;
@@ -76,29 +74,37 @@ class Citizen {
i_diameter = 15; i_diameter = 15;
pathFinder = makePathFinder(gs, pathAlgorithm); pathFinder = makePathFinder(gs, pathAlgorithm);
f_movementSpeed = random(0.1, 2); f_movementSpeed = random(0.1, 2);
}
void spawn(int house) {
PVector v2_spawnPoint = houses.get(house).v2_randomSpawnPoint();
i_xSpawn = int(v2_spawnPoint.x);
i_ySpawn = int(v2_spawnPoint.y);
f_xPos = i_xSpawn;
f_yPos = i_ySpawn;
rNodes = pathFinder.getRoute(); rNodes = pathFinder.getRoute();
if (b_randomRun) goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height))); c_selected = color(128, 50, 50);
b_linked = true; c_color = color(0, 0, 0);
c_stroke = color(255, 255, 255);
} }
//citizen kann "lookat" mit 180° winkel mit bullseye förmigen gradient welches die chance etwas zu bemerken darstellt
void lookAt (Entity entity) {
}
//citizen kann "focus", guckt mit den augen in die richtung. 2. augen-vektor! kopf wird mitgedreht je nach "openness"
//citizen kann "take", nimmt gegenstand in die hand. arraylist "holds" - gegenstände in der hand
void despawn() { //entitiy-subklassen: papier
b_linked = false;
} //setFocus(entity) durch geräusche auch von objekten ausserhalb des sichtfeldes aufrufbar
//je nachdem wie hoch der derzeitige fokus ist wird es schwerer, ihn abzulenken.
//intrinsischer fokus korreliert mit joy/motivation/positive erinnerung an etwas
//zur welt:
//
//0-100:
//motivation (bei arbeiter montag ~40, freitag ~80 - 100)
//7 emotionen?
// berufsfeld: webdesigner, pädagoge, schmuckdesigner, schmied
// berufsstatus: beamter, selbstständiger, unternehmer, angestellter, grundschüler, gymnasiast, hauptschüler, realschüler, azubi, student, rentner
// identität: gelbhemd, lokal, regional, national, international, fremd,
boolean b_moveDiagonally() {
if (int(rNodes[nextNode].xf()) != int(f_xPos) && int(rNodes[nextNode].yf()) != int(f_yPos)) return true;
else return false;
}
int i_direction(float f, float v) { int i_direction(float f, float v) {
if (f <= 0-v) return -1; if (f <= 0-v) return -1;
else if (f >= 0+v) return 1; else if (f >= 0+v) return 1;
@@ -107,17 +113,13 @@ class Citizen {
void update() { void update() {
if (b_moving) { //if rNodes.length > 0 if (b_moving) { //if rNodes.length > 0
if (rNodes.length > nextNode) { if (rNodes.length > nextNode) {
float f_xPosNext = rNodes[nextNode].xf(); float f_xPosNext = rNodes[nextNode].xf();
float f_yPosNext = rNodes[nextNode].yf(); float f_yPosNext = rNodes[nextNode].yf();
float f_movementVelo = f_movementSpeed; float f_movementVelo = f_movementSpeed;
//slow down movement velocity if moving diagnoally
if (b_moveDiagonally()) f_movementVelo = f_movementVelo / 1.41; if (int(rNodes[nextNode].xf()) != int(f_xPos) && int(rNodes[nextNode].yf()) != int(f_yPos)) f_movementVelo = f_movementVelo / 1.41;
f_xPos += i_direction(f_xPosNext-f_xPos, f_movementVelo) * f_movementVelo; f_xPos += i_direction(f_xPosNext-f_xPos, f_movementVelo) * f_movementVelo;
f_yPos += i_direction(f_yPosNext-f_yPos, f_movementVelo) * f_movementVelo; f_yPos += i_direction(f_yPosNext-f_yPos, f_movementVelo) * f_movementVelo;
if (abs(f_yPos - f_yPosNext) < f_movementVelo && abs(f_xPos - f_xPosNext) < f_movementVelo) { if (abs(f_yPos - f_yPosNext) < f_movementVelo && abs(f_xPos - f_xPosNext) < f_movementVelo) {
f_yPos = f_yPosNext; f_yPos = f_yPosNext;
f_xPos = f_xPosNext; f_xPos = f_xPosNext;
@@ -135,7 +137,7 @@ class Citizen {
} }
} }
void display() { void debug() {
//draw Route //draw Route
if (rNodes.length >= 2 && (b_drawPathLine || b_drawPathDestination)) { if (rNodes.length >= 2 && (b_drawPathLine || b_drawPathDestination)) {
pg_map.pushStyle(); pg_map.pushStyle();
@@ -145,7 +147,7 @@ class Citizen {
pg_map.noFill(); pg_map.noFill();
for (int i = 1; i < rNodes.length; i++) for (int i = 1; i < rNodes.length; i++)
pg_map.line(rNodes[i-1].xf(), rNodes[i-1].yf(), rNodes[i].xf(), rNodes[i].yf()); pg_map.line(rNodes[i-1].xf(), rNodes[i-1].yf(), rNodes[i].xf(), rNodes[i].yf());
} } //draw destination
if (b_drawPathDestination) { if (b_drawPathDestination) {
pg_map.stroke(160, 0, 0); pg_map.stroke(160, 0, 0);
if (b_selected) pg_map.fill(255, 0, 0); if (b_selected) pg_map.fill(255, 0, 0);
@@ -154,37 +156,36 @@ class Citizen {
} }
pg_map.popStyle(); pg_map.popStyle();
} }
pg_map.stroke(255);
pg_map.fill(0);
if (b_selected) pg_map.fill(c_selectedCitizen);
pg_map.ellipse(f_xPos, f_yPos, i_diameter, i_diameter);
pg_map.fill(255);
pg_map.textAlign(CENTER);
pg_map.textSize(10);
pg_map.text(S_name, f_xPos, f_yPos-10);
} }
GraphNode startNode, endNode;
int startNodeID, endNodeID;
GraphNode[] rNodes;
ArrayList<GraphNode> rNodesList = new ArrayList<GraphNode>();
int nextNode;
IGraphSearch pathFinder;
int pathAlgorithm = i_pathAlgorithm;
void goTo(int x, int y) { void goTo(int x, int y) {
//add: go to node? go to house? //add: go to node? go to house?
float nodeDistance = 1.0f; int i_goToX = x;
while (gs.getNodeAt(f_xPos, f_yPos, 0, nodeDistance) == null) { int i_goToY = y;
nodeDistance++; int spread = 0;
boolean findingWay = false;
while (!findingWay) {
float nodeDistance = 1.0f;
findingWay = true;
while (gs.getNodeAt(f_xPos, f_yPos, 0, nodeDistance) == null) {
nodeDistance++;
}
startNodeID = gs.getNodeAt(f_xPos, f_yPos, 0, nodeDistance).id();
nodeDistance = 1.0f;
while (gs.getNodeAt(i_goToX, i_goToY, 0, nodeDistance) == null) {
nodeDistance++;
}
endNodeID = gs.getNodeAt(i_goToX, i_goToY, 0, nodeDistance).id();
if (pathFinder.search(startNodeID, endNodeID, true) == null) {
findingWay = false;
spread += 10;
i_goToX+= spread;
i_goToY+= spread;
}
} }
startNodeID = gs.getNodeAt(f_xPos, f_yPos, 0, nodeDistance).id();
nodeDistance = 1.0f;
while (gs.getNodeAt(x, y, 0, nodeDistance) == null) {
nodeDistance++;
}
endNodeID = gs.getNodeAt(x, y, 0, nodeDistance).id();
pathFinder.search(startNodeID, endNodeID, true); //returns null if no route is found pathFinder.search(startNodeID, endNodeID, true); //returns null if no route is found
@@ -193,11 +194,11 @@ class Citizen {
if (rNodes.length > 0) { if (rNodes.length > 0) {
nextNode = 0; nextNode = 0;
b_moving = true; b_moving = true;
//for (int i = 0; i < rNodes.length; i++) {
for (int i = 0; i < rNodes.length; i++) { // rNodesList.add(rNodes[i]);
rNodesList.add(rNodes[i]); //}
} } else { //implement more intelligent design which calls goTo not in this frame (this can cause infinite loops), but in the next 120 frames or so
} else { //also at this point i can move recalculating the nodes into the next frames if no route is found (not only random)..
if (b_randomRun) goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height))); if (b_randomRun) goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)));
} }
} }

68
Entities.pde Normal file
View File

@@ -0,0 +1,68 @@
int i_interactableAmount = 10;
Interactable[] interactables = new Interactable[10];
void initInteractables() {
for (int i = 0; i < interactables.length; i++) {
interactables[i] = new Interactable("Interactable", "Content");
}
for (int i = 0; i < interactables.length; i++) {
interactables[i].spawn(citizen[int(random(0, citizen.length))].i_home);
}
}
class Entity {
String S_name;
boolean b_linked;
boolean b_selected;
boolean b_moving;
float f_xPos, f_yPos, f_xSpawn, f_ySpawn;
int i_diameter = 10; //ellipse representation on map
int i_nameSize = 12;
color c_selected = color(128, 50, 50);
color c_color = color(50, 200, 80);
color c_stroke = color(255, 255, 255);
void spawn(int house) {
PVector v2_spawnPoint = houses.get(house).v2_randomSpawnPoint();
f_xSpawn = v2_spawnPoint.x;
f_ySpawn = v2_spawnPoint.y;
f_xPos = f_xSpawn;
f_yPos = f_ySpawn;
b_linked = true;
}
void spawn(int x, int y) {
f_xSpawn = x;
f_ySpawn = y;
f_xPos = f_xSpawn;
f_yPos = f_ySpawn;
b_linked = true;
}
void despawn() {
b_linked = false;
}
void display() {
pg_map.stroke(c_stroke);
pg_map.fill(c_color);
if (b_selected) pg_map.fill(c_selected);
pg_map.ellipse(f_xPos, f_yPos, i_diameter, i_diameter);
pg_map.fill(c_stroke);
pg_map.textAlign(CENTER);
pg_map.textSize(i_nameSize);
pg_map.text(S_name, f_xPos, f_yPos-10);
}
}
class Interactable extends Entity {
Interactable(String name, String description) {
S_name = name;
}
void update() {
}
}

View File

@@ -2,7 +2,7 @@
boolean b_smallerImage = false; //use a cropped, smaller version of the 1920x1080 image for faster development boolean b_smallerImage = false; //use a cropped, smaller version of the 1920x1080 image for faster development
boolean b_loadSun = false; //load sun from web-api instead of local json file (local file is adressed to january 4th 2019. might implement a check that downloads today's information only once... boolean b_loadSun = false; //load sun from web-api instead of local json file (local file is adressed to january 4th 2019. might implement a check that downloads today's information only once...
boolean b_drawNodes = false; boolean b_drawNodes = false;
boolean b_drawPathLine = false; boolean b_drawPathLine = true;
boolean b_drawPathDestination = true; boolean b_drawPathDestination = true;
boolean b_cameraFollow = true; boolean b_cameraFollow = true;
boolean b_autoPlayAfterSelect = false; boolean b_autoPlayAfterSelect = false;
@@ -12,11 +12,15 @@ int i_debugTextSize = 10;
int i_mapW, i_mapH; int i_mapW, i_mapH;
int i_windowW, i_windowH; int i_windowW, i_windowH;
int i_viewportW, i_viewportH; int i_viewportW, i_viewportH;
color c_selectedCitizen = color(128, 50, 50);
//void mousePressed() { //void mousePressed() {
// citizen[0].goTo(constrain(mouseX, 0, img_houses.width), constrain(mouseY, 0, img_houses.height)); // citizen[0].goTo(constrain(mouseX, 0, img_houses.width), constrain(mouseY, 0, img_houses.height));
//} //}
void spawnCitizen() { //happens after construction
}
void setup() { void setup() {
size(700, 600); size(700, 600);
@@ -29,6 +33,10 @@ void setup() {
img_streets = loadImage(dataPath("map/streets.png")); img_streets = loadImage(dataPath("map/streets.png"));
pg_map = createGraphics(img_houses.width, img_houses.height); pg_map = createGraphics(img_houses.width, img_houses.height);
pg_map.beginDraw();
//pg_map.blendMode(MULTIPLY);
pg_map.endDraw();
surface.setResizable(true); surface.setResizable(true);
registerMethod("pre", this); registerMethod("pre", this);
@@ -40,6 +48,7 @@ void setup() {
initPathFinding(); initPathFinding();
initWeather(); initWeather();
initCitizen(); initCitizen();
initInteractables();
initUI(); initUI();
} }
@@ -58,25 +67,32 @@ void draw() {
background(127); background(127);
pg_map.beginDraw(); pg_map.beginDraw();
pg_map.background(127);
pg_map.image(img_map, 0, 0, img_houses.width, img_houses.height); pg_map.image(img_houses, 0, 0, img_houses.width, img_houses.height);
//pg_map.image(img_houses, 0, 0, img_houses.width, img_houses.height); //pg_map.image(img_houses, 0, 0, img_houses.width, img_houses.height);
//image(img_streets, 0, 0, img_houses.width, img_houses.height); //image(img_streets, 0, 0, img_houses.width, img_houses.height);
pg_map.fill(0); pg_map.fill(0);
//pg_map.textSize(7); pg_map.textSize(7);
//pg_map.textAlign(CENTER); pg_map.textAlign(CENTER);
//for (House house : houses) { //for (House house : houses) {
// house.display(); // house.display();
//} //}
if (b_drawNodes) drawNodes(); if (b_drawNodes) drawNodes();
for (int i = 0; i < interactables.length; i++) {
interactables[i].update();
interactables[i].display();
}
for (int i = 0; i < citizen.length; i++) { for (int i = 0; i < citizen.length; i++) {
if (citizen[i].b_linked) { if (citizen[i].b_linked) {
citizen[i].update(); citizen[i].update();
if (i != i_selectedCitizen) if (i != i_selectedCitizen)
citizen[i].display(); //citizen[i].display();
citizen[i].debug();
} }
} }
citizen[i_selectedCitizen].display(); citizen[i_selectedCitizen].display();
@@ -84,6 +100,4 @@ void draw() {
pg_map.endDraw(); pg_map.endDraw();
image(pg_map, i_mapOffsetX, i_mapOffsetY, i_mapW, i_mapH); image(pg_map, i_mapOffsetX, i_mapOffsetY, i_mapW, i_mapH);
drawUI(); drawUI();
} }