Simulation von Bürgern
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CitizenClass.pde 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. import java.lang.Double;
  2. int i_selectedCitizen;
  3. int i_femaleCount;
  4. int i_visionTransparency;
  5. boolean b_makeThemGo;
  6. //je nachdem wie hoch der derzeitige fokus ist wird es schwerer, ihn abzulenken.
  7. //intrinsischer fokus korreliert mit joy/motivation/positive erinnerung an etwas
  8. //zur welt:
  9. //
  10. //0-100:
  11. //motivation (bei arbeiter montag ~40, freitag ~80 - 100)
  12. //7 emotionen?
  13. // berufsfeld: webdesigner, pädagoge, schmuckdesigner, schmied
  14. // berufsstatus: beamter, selbstständiger, unternehmer, angestellter, grundschüler, gymnasiast, hauptschüler, realschüler, azubi, student, rentner
  15. // identität: gelbhemd, lokal, regional, national, international, fremd,
  16. Citizen[] citizen = new Citizen[i_citizenAmount];
  17. void initCitizen() {
  18. //namen: ethuriel, nathaniel, loriel, samuel, aluriel, aleriel, thaliel, suriel, kaliel,
  19. //int[][] claireArray = { { 00, 2 }, { 1, 3} };
  20. citizen[0] = new Citizen(0, 0, "", 0, 0);
  21. citizen[1] = new Citizen(1, 121, "Matze", 1, 28);
  22. citizen[2] = new Citizen(2, 18, "Freddy", 1, 28);
  23. citizen[3] = new Citizen(3, 59, "Korbi", 1, 28);
  24. citizen[4] = new Citizen(4, 121, "Lotte", 1, 26);
  25. citizen[5] = new Citizen(5, 18, "Reifi", 1, 26);
  26. citizen[6] = new Citizen(6, 59, "Grasso", 1, 28);
  27. citizen[7] = new Citizen(7, 121, "Nico", 1, 29);
  28. citizen[8] = new Citizen(8, 18, "Victor", 1, 28);
  29. citizen[9] = new Citizen(9, 59, "Paul", 1, 28);
  30. for (int i = 10; i < i_citizenAmount; i++) {
  31. int gender = int(random(0, 2));
  32. if (gender == 0) i_femaleCount++;
  33. int age = int(random(0, 100));
  34. citizen[i] = new Citizen(i, int(random(0, houses.size())), S_citizenNames[gender][int(random(0, S_citizenNames[gender].length))], gender, age);
  35. }
  36. for (int i = 1; i < citizen.length; i++) {
  37. citizen[i].spawn(citizen[i].i_home);
  38. }
  39. citizen[0].spawn(-500, -500);
  40. //if (citizen[i].b_randomRun) citizen[i].goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)), 10); //bad
  41. citizen[0].despawn();
  42. selectCitizen(0);
  43. }
  44. void selectCitizen(int i) {
  45. //citizen[i_selectedCitizen].b_randomRun = true;
  46. //citizen[i_selectedCitizen].b_moving = true;
  47. citizen[i_selectedCitizen].b_selected = false;
  48. //if (!b_autoPlayAfterSelect) {
  49. // citizen[i].b_randomRun = false;
  50. // citizen[i].b_moving = false;
  51. //}
  52. citizen[i].b_selected = true;
  53. i_selectedCitizen = i;
  54. }
  55. class Citizen extends Entity {
  56. int i_gender;
  57. String s_gender;
  58. int i_age;
  59. int i_home;
  60. String s_currentAction;
  61. int i_maxNodeDistance = 100; //amount of steps to circle around x, y until it finds the nearest node, if none found, breaks path finding. what to do then is defined in rescuePath()
  62. int i_spreadSteps = 10;
  63. float f_movementSpeed;
  64. float f_FOV = PI / 4.0;
  65. int i_visionDistance = 80;
  66. int i_lookRaySteps = 10;
  67. int i_id;
  68. int i_perceivedCitizen = -1;
  69. boolean b_perceivesCitizen;
  70. boolean b_randomRun = b_autoPlay;
  71. int i_goHomeHour, i_goHomeMinute;
  72. int i_goOutHour, i_goOutMinute;
  73. PVector dot = new PVector(0, 0);
  74. GraphNode startNode, endNode;
  75. int startNodeID, endNodeID;
  76. GraphNode[] rNodes;
  77. // ArrayList<GraphNode> rNodesList = new ArrayList<GraphNode>();
  78. int nextNode;
  79. IGraphSearch pathFinder;
  80. int pathAlgorithm = i_pathAlgorithm;
  81. Citizen(int id, int home, String name, int gender, int age) {
  82. i_id = id;
  83. i_home = home;
  84. s_name = name;
  85. i_gender = gender;
  86. s_gender = i_gender == 0 ? "Weiblich" : "Männlich";
  87. i_age = age;
  88. i_diameter = 30;
  89. pathFinder = makePathFinder(gs, pathAlgorithm);
  90. f_movementSpeed = random(f_walkSpeedMin, f_walkSpeedMax);
  91. rNodes = pathFinder.getRoute();
  92. s_currentAction = "current action here";
  93. c_color = color((int)(random(0, 255)), (int)(random(0, 255)), (int)(random(0, 255)));
  94. c_initialColor = c_color;
  95. c_selected = color(128, 50, 50);
  96. c_stroke = color(255, 255, 255);
  97. i_goHomeHour = (int)random(18, 21);
  98. i_goHomeMinute = (int)random(0, 59);
  99. i_goOutHour = (int)random(6, 9);
  100. i_goOutMinute = (int)random(0, 59);
  101. }
  102. int i_direction(float f, float v) {
  103. if (f <= 0-v) return -1;
  104. else if (f >= 0+v) return 1;
  105. else return 0;
  106. }
  107. void update() {
  108. if (b_turning) {
  109. turn();
  110. }
  111. if (b_moving) {
  112. move();
  113. }
  114. perceive();
  115. if (b_talking) {
  116. talk();
  117. }
  118. if (i_hours == i_goHomeHour && i_minutes == i_goHomeMinute) {
  119. b_randomRun = false;
  120. goTo((int)houses.get(i_home).v2_center.x, (int)houses.get(i_home).v2_center.y);
  121. }
  122. if (i_hours == i_goOutHour && i_minutes == i_goOutMinute) { //wake
  123. b_randomRun = true;
  124. i_location = 1;
  125. //goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)));
  126. goToRandom();
  127. }
  128. if (i_location == 1 && b_moving == false) { //sleep
  129. float r = red(c_color);
  130. float g = green(c_color);
  131. float b = blue(c_color);
  132. float r_new = (99*r + red(c_initialColor)) / 99.6666;
  133. float g_new = (99*g + green(c_initialColor)) / 99.6666;
  134. float b_new = (99*b + blue(c_initialColor)) / 99.6666;
  135. c_color = color(r_new, g_new, b_new);
  136. }
  137. }
  138. void display() {
  139. //if (b_selected) {
  140. pg_map.stroke(150, 150, 150, i_visionTransparency);
  141. pg_map.noFill();
  142. //pg_map.fill(127, 127, 127, i_visionTransparency);
  143. if (i_location == 1)
  144. pg_map.arc(f_xPos, f_yPos, i_visionDistance*2, i_visionDistance*2, f_angle+HALF_PI*1.5, f_angle+PI/2*2.5, PIE);
  145. //}
  146. //pg_map.stroke(c_stroke);
  147. pg_map.stroke(c_initialColor);
  148. pg_map.strokeWeight(1);
  149. if (b_selected) {
  150. pg_map.stroke(c_selected);
  151. pg_map.strokeWeight(3);
  152. }
  153. pg_map.fill(c_color);
  154. pg_map.ellipse(f_xPos, f_yPos, i_diameter, i_diameter);
  155. pg_map.fill(c_stroke);
  156. //pg_map.fill(c_initialColor);
  157. pg_map.textAlign(CENTER);
  158. pg_map.textSize(i_nameSize);
  159. int namePos = -i_diameter/3*2;
  160. if (b_talking) {
  161. pg_map.text("\"Hallo " + citizen[i_lastCitizenTalked].s_name + "\"", f_xPos, f_yPos-i_diameter/3*2);
  162. namePos = -i_diameter/3*2*2;
  163. }
  164. pg_map.text(s_name, f_xPos, f_yPos + namePos);
  165. pg_map.stroke(c_stroke);
  166. pg_map.strokeWeight(1);
  167. if (b_talking) {
  168. pg_map.line(f_xPos, f_yPos, citizen[i_lastCitizenTalked].f_xPos, citizen[i_lastCitizenTalked].f_yPos);
  169. }
  170. }
  171. void perceive() {
  172. b_perceivesCitizen = false;
  173. i_perceivedCitizen = -1;
  174. // if (!b_talking) {
  175. for (int i = -5; i < 6; i++) { //10 rays
  176. float f_rayAngle = (f_angle) + i/TWO_PI;
  177. for (int j = 0; j < 10; j++) { //10 steps of collision detection per ray
  178. for (int k = 1; k < i_lookRaySteps; k ++) {
  179. dot.x = f_xPos-k*((cos(f_rayAngle)*i_visionDistance)/i_lookRaySteps);
  180. dot.y = f_yPos-k*((sin(f_rayAngle)*i_visionDistance)/i_lookRaySteps);
  181. //if (b_debug)pg_map.point(dot.x, dot.y);
  182. for (int l = 0; l < citizen.length; l++) {
  183. if (dot.x > citizen[l].i_collBoundX && dot.x < citizen[l].i_collBoundX + citizen[l].i_collBoundW
  184. && dot.y > citizen[l].i_collBoundY && dot.y < citizen[l].i_collBoundY + citizen[l].i_collBoundH) {
  185. if (l != i_id && !b_perceivesCitizen && citizen[l].i_location == 1 && i_location == 1) {
  186. b_perceivesCitizen = true;
  187. i_perceivedCitizen = l;
  188. if (i_lastCitizenTalked != l && citizen[l].i_lastCitizenTalked != i_id) {
  189. turnTo(f_xPos-citizen[l].f_xPos, f_yPos-citizen[l].f_yPos, 2);
  190. if (citizen[l].i_perceivedCitizen == i_id) { //if perceived citizen perceives me and din't talk to me last time
  191. talkTo(citizen[l]);
  192. citizen[l].talkTo(this);
  193. }
  194. }
  195. }
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. boolean b_talking;
  203. boolean b_movingBeforeTalk;
  204. int i_talkTimeStart;
  205. int i_talkTime = 5; //how long talk in seconds
  206. int i_lastCitizenTalked = -1;
  207. void talkTo(Citizen citizen) { //replace passing whole entity with passing id
  208. b_talking = true;
  209. //i_talkTimeStart = second();
  210. i_talkTimeStart = frameCount;
  211. b_movingBeforeTalk = b_moving;
  212. b_moving = false;
  213. i_lastCitizenTalked = citizen.i_id;
  214. }
  215. void talk() { //means: exchange colors
  216. float r = red(c_color);
  217. float g = green(c_color);
  218. float b = blue(c_color);
  219. float r_new = (19*r + red(citizen[i_lastCitizenTalked].c_color)) / 20;
  220. float g_new = (19*g + green(citizen[i_lastCitizenTalked].c_color)) / 20;
  221. float b_new = (19*b + blue(citizen[i_lastCitizenTalked].c_color)) / 20;
  222. c_color = color(r_new, g_new, b_new);
  223. //if (second() > (i_talkTimeStart + i_talkTime < 60 ? i_talkTimeStart + i_talkTime : i_talkTimeStart - 60 + i_talkTime)) {
  224. if (frameCount > i_talkTimeStart + i_talkTime * frameRate) {
  225. //c_color = (c_color + citizen[i_lastCitizenTalked].c_color) / 2;
  226. b_talking = false;
  227. //b_moving = b_movingBeforeTalk;
  228. b_moving = true;
  229. //prevent talking to the same person right after
  230. }
  231. }
  232. void goToRandom() {
  233. int randomNodeId = (int)random(0, gNodes.length);
  234. preparePath((int)gNodes[randomNodeId].x(), (int)gNodes[randomNodeId].y());
  235. getPath();
  236. }
  237. void goTo(int x, int y) {
  238. preparePath(x, y);
  239. getPath();
  240. }
  241. void goTo(House house) {
  242. preparePath((int)house.v2_center.x, (int)house.v2_center.y);
  243. getPath();
  244. }
  245. void move() {
  246. i_collBoundX = (int)f_xPos - (i_diameter/2);
  247. i_collBoundY = (int)f_yPos - (i_diameter/2);
  248. i_collBoundW = i_diameter;
  249. i_collBoundH = i_diameter;
  250. if (rNodes.length > nextNode) {
  251. float f_xPosNext = rNodes[nextNode].xf();
  252. float f_yPosNext = rNodes[nextNode].yf();
  253. float f_movementVelo = f_movementSpeed;
  254. if ((int)rNodes[nextNode].xf() != (int)f_xPos && int(rNodes[nextNode].yf()) != (int)f_yPos) f_movementVelo = f_movementVelo / 1.41; //slow down movement velocity if moving diagnoally
  255. f_xPos += i_direction(f_xPosNext-f_xPos, f_movementVelo) * f_movementVelo;
  256. f_yPos += i_direction(f_yPosNext-f_yPos, f_movementVelo) * f_movementVelo;
  257. turnTo(f_xPos-f_xPosNext, f_yPos-f_yPosNext, map(nextNode, 0, rNodes.length, 4, 1)); //lets them turn faster when they start their journey (looks like more motivation)
  258. if (abs(f_yPos - f_yPosNext) < f_movementVelo && abs(f_xPos - f_xPosNext) < f_movementVelo) {
  259. f_yPos = f_yPosNext;
  260. f_xPos = f_xPosNext;
  261. nextNode++;
  262. }
  263. } else {
  264. b_moving = false;
  265. nextNode = 0;
  266. if (!b_randomRun) {
  267. //check if standing on an other citizens position?
  268. } else {
  269. //goTo((int)random(0, pg_map.width), (int)random(0, pg_map.height));
  270. goToRandom();
  271. }
  272. }
  273. }
  274. void debug() {
  275. //draw Route
  276. if (rNodes.length >= 2) {
  277. pg_map.pushStyle();
  278. pg_map.stroke(color(100, 100, 200));
  279. pg_map.strokeWeight(1);
  280. pg_map.noFill();
  281. for (int i = 1; i < rNodes.length; i++)
  282. pg_map.line(rNodes[i-1].xf(), rNodes[i-1].yf(), rNodes[i].xf(), rNodes[i].yf());
  283. //draw destination
  284. pg_map.stroke(160, 0, 0);
  285. if (b_selected) pg_map.fill(255, 0, 0);
  286. else pg_map.fill(0);
  287. pg_map.ellipse(rNodes[rNodes.length-1].xf(), rNodes[rNodes.length-1].yf(), nodeSize, nodeSize);
  288. pg_map.popStyle();
  289. }
  290. }
  291. //moved this all the way down, extracted from old goTo(), hoping to never see again
  292. boolean b_pathFindKaputt;
  293. float nodeDistance;
  294. void getNodeDistance(float x, float y) { //circles around x, y until it finds the nearest node
  295. nodeDistance = 1.0f;
  296. while (gs.getNodeAt(x, y, 0, nodeDistance) == null && nodeDistance < i_maxNodeDistance) {
  297. nodeDistance++;
  298. }
  299. if (nodeDistance >= i_maxNodeDistance) {
  300. b_pathFindKaputt = true;
  301. }
  302. }
  303. void preparePath(int x, int y) { //tests if paths are available (to prevent failing on encapsuled areas)
  304. int spread = 0;
  305. boolean works = false;
  306. while (!works && !b_pathFindKaputt) {
  307. works = true;
  308. getNodeDistance(f_xPos, f_yPos);
  309. if (b_pathFindKaputt) break;
  310. startNodeID = gs.getNodeAt(f_xPos, f_yPos, 0, nodeDistance).id();
  311. getNodeDistance(x, y);
  312. if (b_pathFindKaputt) break;
  313. endNodeID = gs.getNodeAt(x, y, 0, nodeDistance).id();
  314. if (pathFinder.search(startNodeID, endNodeID, true) == null) {
  315. works = false;
  316. spread += i_spreadSteps;
  317. x+= spread;
  318. y+= spread;
  319. }
  320. if (spread >= i_spreadSteps * i_maxNodeDistance) b_pathFindKaputt = true;
  321. }
  322. }
  323. void getPath() {
  324. if (!b_pathFindKaputt) {
  325. pathFinder.search(startNodeID, endNodeID, true);
  326. rNodes = pathFinder.getRoute(); //this is the array i want here
  327. nextNode = 0; //necessary for move()
  328. b_moving = true;
  329. } else {
  330. rescuePath();
  331. }
  332. }
  333. void rescuePath() {
  334. b_pathFindKaputt = false;
  335. //teleport somewhere and go home - needs better solution!!! maybe give a little push?
  336. int randomNodeId = (int)random(0, gNodes.length);
  337. f_xPos = (int)gNodes[randomNodeId].x();
  338. f_yPos = (int)gNodes[randomNodeId].y();
  339. //goTo((int)houses.get(i_home).v2_center.x, (int)houses.get(i_home).v2_center.y);
  340. goToRandom();
  341. }
  342. }
  343. String[][] S_citizenNames = { { "Marie", "Mari", "Sophie", "Maria", "Sophia", "Sofia", "Emilia", "Emma", "Hannah", "Hanna", "Anna", "Luisa", "Louisa", "Mia", "Emma", "Sophia", "Sofia", "Hanna", "Hannah", "Emilia",
  344. "Mia", "Anna", "Lina", "Mila", "Klara", "Clara", "Marie", "Lea", "Leah", "Lena", "Henri", "Luisa", "Ella", "Leni", "Sophie", "Sofie", "Marie", "Maria", "Luise", "Louise", "Sophia", "Sofia",
  345. "Elisabeth", "Katharina", "Catharina", "Charlotte", "Johanna", "Emilia", "Anna", "Luisa", "Louisa", "Victoria", "Viktoria", "Josefine", "Josephine", "Mathilda", "Matilda", "Layla", "Leyla", "Elif", "Nur", "Amira", "Aliyah", "Amina" },
  346. { "Maximilian", "Alexander", "Paul", "Elias", "Ben", "Noah", "Noa", "Leon", "Léon", "Louis", "Luis", "Jonas", "Felix", "Ben", "Paul", "Noah", "Noa", "Leon", "Léon", "Jonas", "Felix",
  347. "Elias", "Louis", "Luis", "Lukas", "Lucas", "Maximilian", "Finn", "Henry", "Emil", "Luca", "Luka", "Jakob", "Jacob", "Alexander", "Maximilian", "Elias", "Paul", "Michael", "Karl", "Carl",
  348. "Johannes", "Nico", "Luka", "Johann", "Stefan", "Louis", "Luis", "Christian", "Kristian", "Anton", "Andreas", "David", "Mohammed", "Ali", "Malik", "Emir", "Yusuf", "Ilyas" } };