diff --git a/CitizenClass.pde b/CitizenClass.pde index a6a281e..89206be 100644 --- a/CitizenClass.pde +++ b/CitizenClass.pde @@ -3,6 +3,22 @@ int i_citizenAmount = 10; int i_selectedCitizen; int i_femaleCount; + +//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, + Citizen[] citizen = new Citizen[i_citizenAmount]; void initCitizen() { @@ -25,13 +41,13 @@ void initCitizen() { 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); } - for (int i = 0; i < citizen.length; i++) { + 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); + else citizen[i].spawn(100, 100); - if (citizen[i].b_randomRun) citizen[i].goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height))); //bad + if (citizen[i].b_randomRun) citizen[i].goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)), 10); //bad } selectCitizen(0); } @@ -54,12 +70,14 @@ class Citizen extends Entity { int i_age; int i_home; float f_movementSpeed; + float f_FOV = PI / 4.0; + int i_visionDistance = 60; boolean b_randomRun; GraphNode startNode, endNode; int startNodeID, endNodeID; GraphNode[] rNodes; - // ArrayList rNodesList = new ArrayList(); + // ArrayList rNodesList = new ArrayList(); int nextNode; IGraphSearch pathFinder; @@ -81,28 +99,11 @@ class Citizen extends Entity { 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) { - } + //setFocus(entity) durch geräusche auch von objekten ausserhalb des sichtfeldes aufrufbar + //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 - //entitiy-subklassen: papier - - //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, int i_direction(float f, float v) { @@ -110,61 +111,34 @@ class Citizen extends Entity { else if (f >= 0+v) return 1; else return 0; } + void update() { + f_angle = v2_direction.heading(); + if (b_moving) { //if rNodes.length > 0 - if (rNodes.length > nextNode) { - float f_xPosNext = rNodes[nextNode].xf(); - float f_yPosNext = rNodes[nextNode].yf(); - float f_movementVelo = f_movementSpeed; - //slow down movement velocity if moving diagnoally - 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_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) { - f_yPos = f_yPosNext; - f_xPos = f_xPosNext; - nextNode++; - } - } else { - b_moving = false; - nextNode = 0; - if (!b_randomRun) { - //check if standing on an other citizens position - } else { - goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height))); - } - } + move(); } + + watch(); + //look collision detection } - void debug() { - //draw Route - if (rNodes.length >= 2 && (b_drawPathLine || b_drawPathDestination)) { - pg_map.pushStyle(); - if (b_drawPathLine) { - pg_map.stroke(color(100, 100, 100)); - pg_map.strokeWeight(1); - pg_map.noFill(); - 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()); - } //draw destination - if (b_drawPathDestination) { - pg_map.stroke(160, 0, 0); - if (b_selected) pg_map.fill(255, 0, 0); - else pg_map.fill(0); - pg_map.ellipse(rNodes[rNodes.length-1].xf(), rNodes[rNodes.length-1].yf(), nodeSize, nodeSize); - } - pg_map.popStyle(); + void lookAt (int x, int y, int prio) { + } + void watch() { + if (b_moving) { } } - - void goTo(int x, int y) { + void goTo(int x, int y, int prio) { //add: go to node? go to house? int i_goToX = x; int i_goToY = y; int spread = 0; boolean findingWay = false; - + + + + while (!findingWay) { float nodeDistance = 1.0f; findingWay = true; @@ -185,12 +159,8 @@ class Citizen extends Entity { i_goToY+= spread; } } - - pathFinder.search(startNodeID, endNodeID, true); //returns null if no route is found - rNodes = pathFinder.getRoute(); - if (rNodes.length > 0) { nextNode = 0; b_moving = true; @@ -198,13 +168,70 @@ class Citizen extends Entity { // 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 - //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))); + //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)), 10); } } + void move() { + if (rNodes.length > nextNode) { + float f_xPosNext = rNodes[nextNode].xf(); + float f_yPosNext = rNodes[nextNode].yf(); + float f_movementVelo = f_movementSpeed; + //slow down movement velocity if moving diagnoally + 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_yPos += i_direction(f_yPosNext-f_yPos, f_movementVelo) * f_movementVelo; + + v2_direction.x = f_xPos - f_xPosNext; + v2_direction.y = f_yPos - f_yPosNext; + + if (abs(f_yPos - f_yPosNext) < f_movementVelo && abs(f_xPos - f_xPosNext) < f_movementVelo) { + f_yPos = f_yPosNext; + f_xPos = f_xPosNext; + nextNode++; + } + } else { + b_moving = false; + //v2_direction = + nextNode = 0; + if (!b_randomRun) { + //check if standing on an other citizens position + } else { + goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)), 10); + } + } + } + + void debug() { + //draw Route + if (rNodes.length >= 2) { + pg_map.pushStyle(); + pg_map.stroke(color(100, 100, 200)); + pg_map.strokeWeight(1); + pg_map.noFill(); + 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()); + //draw destination + pg_map.stroke(160, 0, 0); + if (b_selected) pg_map.fill(255, 0, 0); + else pg_map.fill(0); + pg_map.ellipse(rNodes[rNodes.length-1].xf(), rNodes[rNodes.length-1].yf(), nodeSize, nodeSize); + pg_map.popStyle(); + } + + + pg_map.stroke(color(100, 50, 50)); + for (int i = -5; i < 6; i++) { //16 rays + float fRayAngle = (f_angle) + i/TWO_PI; + pg_map.line(f_xPos, f_yPos, f_xPos-cos(fRayAngle)*i_visionDistance, f_yPos-sin(fRayAngle)*i_visionDistance); + } + pg_map.stroke(color(255, 255, 255)); + pg_map.line(f_xPos, f_yPos, f_xPos-cos(f_angle)*i_visionDistance, f_yPos-sin(f_angle)*i_visionDistance); + } } + String[][] S_citizenNames = { { "Marie", "Mari", "Sophie", "Maria", "Sophia", "Sofia", "Emilia", "Emma", "Hannah", "Hanna", "Anna", "Luisa", "Louisa", "Mia", "Emma", "Sophia", "Sofia", "Hanna", "Hannah", "Emilia", "Mia", "Anna", "Lina", "Mila", "Klara", "Clara", "Marie", "Lea", "Leah", "Lena", "Henri", "Luisa", "Ella", "Leni", "Sophie", "Sofie", "Marie", "Maria", "Luise", "Louise", "Sophia", "Sofia", "Elisabeth", "Katharina", "Catharina", "Charlotte", "Johanna", "Emilia", "Anna", "Luisa", "Louisa", "Victoria", "Viktoria", "Josefine", "Josephine", "Mathilda", "Matilda", "Layla", "Leyla", "Elif", "Nur", "Amira", "Aliyah", "Amina" }, diff --git a/Entities.pde b/Entities.pde index 1fa1bf4..61939e6 100644 --- a/Entities.pde +++ b/Entities.pde @@ -1,5 +1,6 @@ int i_interactableAmount = 10; + //entitiy-subklassen: papier .. computer .. mobiles ... books ... lamps ... tables ... Interactable[] interactables = new Interactable[10]; @@ -16,28 +17,42 @@ void initInteractables() { class Entity { String S_name; boolean b_linked; + int i(int x) { + return (x); + }; boolean b_selected; boolean b_moving; float f_xPos, f_yPos, f_xSpawn, f_ySpawn; - int i_diameter = 10; //ellipse representation on map + float f_angle; + int i_diameter = 10; 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); + //PVector v2_direction(int x, int y){ + // PVector pv = new PVector(f_xPos+x,f_yPos+y); + // return (pv); + //}; + PVector v2_direction = new PVector(0,0); - void spawn(int house) { + void spawn(int house) { //generic spawn 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; + v2_direction.x = f_xPos; + v2_direction.y = f_yPos + 10; + f_angle = 0; b_linked = true; } - void spawn(int x, int y) { + void spawn(int x, int y) { //specific spawn f_xSpawn = x; f_ySpawn = y; f_xPos = f_xSpawn; f_yPos = f_ySpawn; + v2_direction.x = f_xPos; + v2_direction.y = f_yPos + 10; b_linked = true; } void despawn() { diff --git a/UI.pde b/UI.pde index 1d0af93..18f8b53 100644 --- a/UI.pde +++ b/UI.pde @@ -1,25 +1,23 @@ +Button buttons[] = new Button[3]; + + int i_uiTransparency = 200; void initUI() { i_uiX = 0; i_uiY = 518; i_uiW = width; i_uiH = height - i_uiY; + + buttons[0] = new Button(15, 50, 100, i_debugTextSize, 5, "Autoplay", 0); + buttons[1] = new Button(15, 70, 100, i_debugTextSize, 5, "Lock Camera", 1); + buttons[2] = new Button(15, 90, 100, i_debugTextSize, 5, "Debug", 2); } + int i_uiX, i_uiY, i_uiW, i_uiH; int i_uiOffsetX, i_uiOffsetY, i_uiOffsetStartX, i_uiOffsetStartY, i_initUiY; void drawUI() { - strokeWeight(1); - line(i_uiX, i_uiY, i_uiX+i_uiW, i_uiY); - strokeWeight(0); - fill(255, i_uiTransparency); - rect(i_uiX, i_uiY, i_uiW, i_uiH); - rect(6, 4, 140, 31, 6); - fill(0); - textSize(30); - textAlign(LEFT); - text(String.format("%02d", hour()) + ":" + String.format("%02d", minute()) + ":" + String.format("%02d", second()), 10, 30); //camera tracking if (b_cameraFollow) { @@ -32,78 +30,154 @@ void drawUI() { } } + //draw + //buttons + strokeWeight(0); + textSize(i_debugTextSize); + for (int i = 0; i < buttons.length; i++) { + buttons[i].display(); + } + //clock + fill(255, i_uiTransparency); + rect(6, 4, 140, 31, 6); + textSize(30); + textAlign(LEFT); + fill(0); + text(String.format("%02d", hour()) + ":" + String.format("%02d", minute()) + ":" + String.format("%02d", second()), 10, 30); + //debug - String[] debug = { - "FPS: " + int(frameRate), - "Amount citizen: " + i_citizenAmount, - "Females: " + i_femaleCount + " Males: " + str(i_citizenAmount-i_femaleCount), - " ", - "Selected Citizen ID: " + i_selectedCitizen, - "Name: " + citizen[i_selectedCitizen].S_name, - "Gender: " + citizen[i_selectedCitizen].S_gender, - "Age: " + citizen[i_selectedCitizen].i_age, - "x: " + int(citizen[i_selectedCitizen].f_xPos), - "y: " + int(citizen[i_selectedCitizen].f_yPos), - "Movement speed: " + round(citizen[i_selectedCitizen].f_movementSpeed*100), - "Random Run: " + citizen[i_selectedCitizen].b_randomRun, - " ", - "Sunrise: " + S_sunrise, - "Sunset: " + S_sunset, - "Autoplay: " + b_autoPlayAfterSelect, - "Locked Camera: " + b_cameraFollow, - //"Velocity: ", - //"Outside", - //"Mood: " - }; - int ts = i_debugTextSize; - textSize(ts); - int line = 0; - int maxLinesPerColumn = i_uiH/ts; - int columnWidth = 130; - if (maxLinesPerColumn > 0) { - int requiredColumns = (debug.length/maxLinesPerColumn)+1; - for (int i = 0; i < requiredColumns; i++) { - while (((line-(maxLinesPerColumn*i)) * ts + ts-1)+i_uiY 0) { + int requiredColumns = (debug.length/maxLinesPerColumn)+1; + for (int i = 0; i < requiredColumns; i++) { + while (((line-(maxLinesPerColumn*i)) * i_debugTextSize + i_debugTextSize -1)+i_uiY i_x - i_margin && mouseX < i_x+i_w + i_margin && mouseY > i_y - i_margin && mouseY < i_y+i_h + i_margin) return true; + else return false; + } + void click() { + buttonFunctions(i_f); + } + void display() { + fill(150, 170, 250, 150); + rect(i_x, i_y, i_w, i_h, i_c); + fill(0); + text(s_t, i_tx, i_y + i_debugTextSize); + } +} + + boolean b_mouseChangeMapOffset, b_mouseChangeUiHeight; boolean b_hoverUI; void mousePressed() { if (mouseButton == LEFT) { + boolean clickUI = false; + + if (mouseX >= i_uiX && mouseX <= i_uiX+i_uiW && mouseY >= i_uiY-10 && mouseY <= i_uiY+10) { //drag and drop debug window size b_mouseChangeUiHeight = true; i_uiOffsetStartY = mouseY; i_initUiY = i_uiY; - } else if (mouseX >= i_uiX+i_uiW-135 && mouseX <= i_uiX+i_uiW-135+120 //autoplay button - && mouseY >= i_uiY+i_debugTextSize/2-5 && mouseY <= i_uiY+i_debugTextSize/2+i_debugTextSize+5) { - //if (b_autoPlayAfterSelect) { - // citizen[i_selectedCitizen].b_moving = false; - // citizen[i_selectedCitizen].b_randomRun = false; - //} - citizen[i_selectedCitizen].b_moving = !citizen[i_selectedCitizen].b_moving; - citizen[i_selectedCitizen].b_randomRun = !citizen[i_selectedCitizen].b_randomRun; - b_autoPlayAfterSelect = !b_autoPlayAfterSelect; - } else if (mouseX >= i_uiX+i_uiW-135 && mouseX <= i_uiX+i_uiW-135+120 //autoplay button - && mouseY >= i_uiY+i_debugTextSize/2+1.41*i_debugTextSize+i_debugTextSize/2-5 && mouseY <= i_uiY+i_debugTextSize/2+1.41*i_debugTextSize+i_debugTextSize/2+i_debugTextSize+5) { - b_cameraFollow = !b_cameraFollow; - } else { + clickUI = true; + } + + for (int i = 0; i < buttons.length; i++) { + if (buttons[i].hover()) { + buttons[i].click(); + clickUI = true; + } + } + + + if (!clickUI) { int selectedCitizen = i_selectedCitizen; //leftclick select citizen for (int i = 0; i < citizen.length; i++) { if (selectedCitizen != i) { @@ -127,7 +201,7 @@ void mousePressed() { citizen[i_selectedCitizen].b_randomRun = false; citizen[i_selectedCitizen].b_moving = false; } - citizen[i_selectedCitizen].goTo(constrain(i_mapViewToMap(mouseX, i_mapOffsetX), 0, pg_map.width), constrain(i_mapViewToMap(mouseY, i_mapOffsetY), 0, pg_map.height)); + citizen[i_selectedCitizen].goTo(constrain(i_mapViewToMap(mouseX, i_mapOffsetX), 0, pg_map.width), constrain(i_mapViewToMap(mouseY, i_mapOffsetY), 0, pg_map.height), 10); } } int i_mapViewToMap(int mouse, int offset) { @@ -144,6 +218,9 @@ void mouseDragged() { i_uiY = mouseY - i_uiOffsetStartY + i_initUiY; if (i_uiY > height) i_uiY = height; i_uiH = height - i_uiY; + + + //hook buttons to ui panel } } void mouseReleased() { diff --git a/citizen.pde b/citizen.pde index 4916ed8..c6e07e0 100644 --- a/citizen.pde +++ b/citizen.pde @@ -1,11 +1,14 @@ //settings 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_drawNodes = false; -boolean b_drawPathLine = true; -boolean b_drawPathDestination = true; + + boolean b_cameraFollow = true; boolean b_autoPlayAfterSelect = false; + +boolean b_debug = true; +boolean b_drawNodes = false; + float f_nodeResolution = 0.2; //defines density of path-finding nodes, multiplied with resolution int i_pathAlgorithm = 3; int i_debugTextSize = 10; @@ -69,7 +72,8 @@ void draw() { pg_map.beginDraw(); pg_map.background(127); - pg_map.image(img_map, 0, 0, img_houses.width, img_houses.height); + if(b_debug) pg_map.image(img_houses, 0, 0, img_houses.width, img_houses.height); + else 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); //image(img_streets, 0, 0, img_houses.width, img_houses.height); @@ -92,9 +96,14 @@ void draw() { citizen[i].update(); if (i != i_selectedCitizen) citizen[i].display(); - //citizen[i].debug(); + if(b_debug) + citizen[i].debug(); } } + + citizen[i_selectedCitizen].v2_direction.x = citizen[i_selectedCitizen].f_xPos - (float)constrain(i_mapViewToMap(mouseX, i_mapOffsetX), 0, pg_map.width); + citizen[i_selectedCitizen].v2_direction.y = citizen[i_selectedCitizen].f_yPos - (float)constrain(i_mapViewToMap(mouseY, i_mapOffsetY), 0, pg_map.height); + citizen[i_selectedCitizen].display(); pg_map.endDraw();