diff --git a/levels/albert_parklands/junctions.json b/levels/albert_parklands/junctions.json index 55b3b08..8a608e1 100644 --- a/levels/albert_parklands/junctions.json +++ b/levels/albert_parklands/junctions.json @@ -2,445 +2,535 @@ { "name": "Alice x George", "spawn": { - "dx": 0.766833198312044, - "dz": -0.641846434878719, - "x": -163.586282448655, - "z": 162.065991994404 + "x": -163.58628244865508, + "z": 162.06599199440433, + "y": 14.0, + "dx": 0.7668331983120437, + "dz": -0.6418464348787193 }, "streams": [ { - "interval": 1.5, "pts": [ [ - -71.6230075670676, - 85.0918821008208 + -71.62300756706763, + 85.0918821008208, + 15.68 ], [ - -72.1027981957511, - 85.4906175386659 + -72.10279819575109, + 85.49061753866586, + 15.69 ], [ - -82.5534519291224, - 94.8058802983977 + -82.55345192912239, + 94.80588029839768, + 16.5 ], [ - -104.449283255202, - 113.364728030556 + -104.44928325520195, + 113.36472803055571, + 16.93 ], [ - -114.552953384248, - 122.938157884478 + -114.55295338424757, + 122.93815788447793, + 16.38 ], [ - -118.635517096346, - 126.332146888185 + -118.63551709634598, + 126.33214688818488, + 16.11 ], [ - -124.179725942706, - 130.600603993254 + -124.17972594270637, + 130.60060399325408, + 15.66 ], [ - -132.412657846607, - 136.841371982625 + -132.4126578466066, + 136.84137198262476, + 15.15 ], [ - -135.426194974764, - 139.131158627196 + -135.42619497476394, + 139.13115862719584, + 15.05 ], [ - -137.017391502614, - 140.329922425279 + -137.0173915026139, + 140.32992242527928, + 15.02 ], [ - -142.2269104628, - 144.181294358731 + -142.22691046279974, + 144.18129435873087, + 14.99 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ -75.361941989609, - 84.8229236525054 + 84.82292365250544, + 16.0 ], [ - -80.9395388682742, - 78.6116377012041 + -80.93953886827424, + 78.61163770120406, + 16.61 ], [ - -82.5659998940916, - 76.7348960854059 + -82.56599989409156, + 76.7348960854059, + 16.75 ], [ - -115.405581435619, - 38.7415552213739 + -115.40558143561937, + 38.74155522137386, + 23.41 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - -145.437080580831, - 139.83908204088 + -145.4370805808313, + 139.83908204087984, + 15.0 ], [ - -140.236730470549, - 135.994503574748 + -140.2367304705485, + 135.99450357474848, + 15.01 ], [ - -138.687188507682, - 134.826983772678 + -138.6871885076824, + 134.82698377267795, + 15.02 ], [ - -135.676038606364, - 132.539006817179 + -135.67603860636424, + 132.53900681717874, + 15.1 ], [ - -127.454661333638, - 126.307027606927 + -127.45466133363814, + 126.30702760692736, + 15.64 ], [ - -121.996408938187, - 122.105516312011 + -121.99640893818653, + 122.1055163120108, + 15.97 ], [ - -118.197496828121, - 118.953524515431 + -118.19749682812089, + 118.9535245154313, + 16.16 ], [ - -108.01476176314, - 109.309193169476 + -108.01476176313997, + 109.30919316947609, + 16.87 ], [ - -86.0785257896557, - 90.7151769019407 + -86.07852578965569, + 90.71517690194068, + 16.9 ], [ - -75.6896883110217, - 81.454007661433 + -75.68968831102165, + 81.45400766143295, + 16.16 ], [ - -75.0830599635874, - 80.9460362988959 + -75.08305996358739, + 80.94603629889595, + 16.14 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - -111.320181741659, - 35.2103359785921 + -111.32018174165945, + 35.21033597859207, + 22.71 ], [ - -78.4807980853871, - 73.2034479147318 + -78.48079808538708, + 73.20344791473178, + 16.61 ], [ -76.9072614072839, - 75.0198778988802 + 75.01987789888024, + 16.48 ], [ - -71.344125541046, - 81.2149947472113 + -71.34412554104603, + 81.2149947472113, + 15.86 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - -72.1166888351082, - 80.6186568827489 + -72.11668883510822, + 80.61865688274891, + 15.94 ], [ - -63.3155168708224, - 85.2319664647318 + -63.31551687082244, + 85.23196646473183, + 15.12 ], [ - -54.5517817587045, - 95.5382290534301 + -54.55178175870453, + 95.53822905343011, + 14.31 ], [ - -39.7832019492811, - 112.967845683357 + -39.78320194928109, + 112.96784568335697, + 16.67 ], [ - -38.2495347293041, - 114.641424782394 + -38.24953472930413, + 114.64142478239386, + 16.96 ], [ - -37.46679081946, - 115.770892092411 + -37.466790819459995, + 115.77089209241056, + 17.13 ], [ - -36.907545471025, - 116.868308404357 + -36.90754547102499, + 116.86830840435711, + 17.26 ], [ - -36.6415428486163, - 117.9601284403 + -36.64154284861633, + 117.96012844030032, + 17.36 ], [ - -36.5496258677079, - 118.928290187952 + -36.54962586770791, + 118.92829018795193, + 17.43 ], [ - -36.5838040309518, - 120.631630966954 + -36.58380403095183, + 120.63163096695364, + 17.52 ], [ - -36.7335166728013, - 121.773248002537 + -36.733516672801336, + 121.77324800253669, + 17.57 ], [ - -36.9496009730767, - 122.555067847412 + -36.949600973076684, + 122.55506784741175, + 17.58 ], [ - -37.3111869258717, - 123.404225782126 + -37.31118692587169, + 123.40422578212599, + 17.59 ], [ - -38.0206496416879, - 124.385542652475 + -38.02064964168787, + 124.38554265247478, + 17.56 ], [ - -39.4579334455589, - 125.801006946898 + -39.45793344555888, + 125.80100694689808, + 17.47 ], [ - -41.9601597793989, - 127.878176766196 + -41.96015977939887, + 127.8781767661959, + 17.33 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - -45.4076787424784, - 123.721902834029 + -45.40767874247836, + 123.72190283402932, + 16.65 ], [ - -43.0308962305509, - 121.752064253174 + -43.03089623055088, + 121.75206425317394, + 16.81 ], [ -41.9792929338678, - 120.712785747195 + 120.7127857471952, + 16.87 ], [ - -41.9973981173857, - 120.721051417958 + -41.99739811738572, + 120.72105141795794, + 16.87 ], [ - -42.0626879873161, - 120.818306152528 + -42.06268798731611, + 120.81830615252781, + 16.87 ], [ - -42.0417354235454, - 120.781878397269 + -42.041735423545425, + 120.78187839726885, + 16.87 ], [ - -41.9741642668029, - 120.309115032842 + -41.974164266802894, + 120.30911503284231, + 16.85 ], [ - -41.9490832168424, - 119.004843012052 + -41.94908321684239, + 119.00484301205215, + 16.78 ], [ - -41.975684667957, - 118.800920359363 + -41.975684667956976, + 118.80092035936316, + 16.76 ], [ - -41.9467189152085, - 118.809115195214 + -41.94671891520851, + 118.80911519521383, + 16.77 ], [ -42.0788310934576, - 118.579643507368 + 118.57964350736775, + 16.74 ], [ - -42.3825061541171, - 118.116845217633 + -42.38250615411705, + 118.1168452176333, + 16.67 ], [ - -43.8908120639013, - 116.473204316403 + -43.89081206390128, + 116.47320431640294, + 16.4 ], [ - -58.6728283240367, - 99.0277813465423 + -58.67282832403665, + 99.02778134654227, + 14.55 ], [ - -66.8177230511832, - 89.3422647349603 + -66.81772305118318, + 89.3422647349603, + 15.08 ], [ -74.5893786955468, - 85.4192615169678 + 85.41926151696784, + 15.91 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 } ], "targets": [ - 26500, - 29000, - 46500 + 15000, + 35000, + 60000 ] }, { "name": "Margaret x Edward", "spawn": { - "dx": -0.742705793125526, - "dz": 0.669617879732749, - "x": 274.907915771107, - "z": -373.121177827394 + "x": 274.9079157711072, + "z": -373.12117782739404, + "y": 13.91, + "dx": -0.7427057931255263, + "dz": 0.6696178797327494 }, "streams": [ { - "interval": 1.5, "pts": [ [ - 185.833815296718, - -292.812645167915 + 185.8338152967176, + -292.8126451679154, + 14.05 ], [ - 193.655933950983, - -299.882511644341 + 193.65593395098287, + -299.88251164434115, + 14.74 ], [ - 211.377868675405, - -315.230725704805 + 211.37786867540518, + -315.2307257048046, + 15.6 ], [ - 216.02310568687, - -319.254598202675 + 216.02310568686988, + -319.25459820267537, + 16.29 ], [ - 237.642996194709, - -338.582293338578 + 237.6429961947087, + -338.58229333857753, + 18.91 ], [ - 239.660997181915, - -341.288346333546 + 239.66099718191472, + -341.2883463335457, + 19.31 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - 179.818121576327, - -304.166235842252 + 179.81812157632743, + -304.16623584225226, + 14.19 ], [ - 181.359839275663, - -302.406992562087 + 181.35983927566346, + -302.4069925620872, + 14.27 ], [ - 184.213303452985, - -299.144813785439 + 184.2133034529848, + -299.1448137854387, + 14.28 ], [ - 189.715557971244, - -292.541650836584 + 189.71555797124375, + -292.5416508365839, + 14.26 ], [ - 194.923453137675, - -286.336679339567 + 194.9234531376747, + -286.3366793395667, + 14.2 ], [ - 234.056756167219, - -241.131525360219 + 234.05675616721896, + -241.1315253602194, + 16.15 ], [ - 244.509931259631, - -229.329340361402 + 244.50993125963066, + -229.32934036140196, + 14.64 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - 243.953470490227, - -338.011965266358 + 243.95347049022743, + -338.01196526635846, + 16.8 ], [ - 241.329499501326, - -334.636448261753 + 241.32949950132615, + -334.63644826175323, + 16.37 ], [ - 219.611149514375, - -315.219013797425 + 219.61114951437548, + -315.21901379742513, + 15.39 ], [ - 214.913183354807, - -311.14886949499 + 214.91318335480702, + -311.1488694949895, + 15.27 ], [ - 197.217859554354, - -295.823855956056 + 197.21785955435436, + -295.8238559560563, + 14.84 ], [ - 189.454804209519, - -288.806594832065 + 189.45480420951895, + -288.8065948320647, + 14.03 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - 240.467498400426, - -225.74901403845 + 240.4674984004257, + -225.74901403845038, + 13.81 ], [ 229.982416914263, - -237.587550240129 + -237.5875502401286, + 14.69 ], [ - 190.834294657849, - -282.809813460791 + 190.83429465784906, + -282.80981346079136, + 13.75 ], [ - 185.573061534993, - -289.077589163396 + 185.5730615349928, + -289.07758916339617, + 13.81 ], [ - 180.092607888122, - -295.654847014577 + 180.09260788812207, + -295.6548470145767, + 13.73 ], [ - 177.296693403105, - -298.850189837967 + 177.29669340310514, + -298.8501898379666, + 13.58 ], [ - 175.756931830544, - -300.607199758038 + 175.7569318305437, + -300.6071997580377, + 13.51 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 } ], "targets": [ - 22500, - 25000, - 30000 + 15000, + 35000, + 60000 ] } -] +] \ No newline at end of file diff --git a/levels/albert_parklands/level.glb b/levels/albert_parklands/level.glb index 305a5ab..e4a323c 100644 Binary files a/levels/albert_parklands/level.glb and b/levels/albert_parklands/level.glb differ diff --git a/levels/albert_parklands/level.glb.import b/levels/albert_parklands/level.glb.import index cc34824..26a05c8 100644 --- a/levels/albert_parklands/level.glb.import +++ b/levels/albert_parklands/level.glb.import @@ -3,7 +3,7 @@ importer="scene" importer_version=1 type="PackedScene" -uid="uid://dm4gmb5igf0n5" +uid="uid://b3e8mqi8lqhx7" path="res://.godot/imported/level.glb-4aa597fe23a02438c7c91aac8329adb8.scn" [deps] diff --git a/levels/kangaroo_point/junctions.json b/levels/kangaroo_point/junctions.json index cdc4dd2..e684823 100644 --- a/levels/kangaroo_point/junctions.json +++ b/levels/kangaroo_point/junctions.json @@ -2,149 +2,174 @@ { "name": "Cliffs Corner", "spawn": { - "dx": 0.711628947630267, - "dz": -0.702555507340622, - "x": 21.7260085314512, - "z": -89.9672382353956 + "x": 21.72600853145121, + "z": -89.96723823539561, + "y": 6.96, + "dx": 0.7116289476302671, + "dz": -0.7025555073406219 }, "streams": [ { - "interval": 1.5, "pts": [ [ - 63.9261938834286, - -109.989375180132 + 63.92619388342862, + -109.98937518013152, + 17.17 ], [ 78.3750416498091, - -148.834021380346 + -148.8340213803462, + 25.6 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - 106.136602457004, - -179.682190508149 + 106.13660245700423, + -179.68219050814878, + 30.64 ], [ - 105.148984701035, - -213.871671308174 + 105.14898470103478, + -213.87167130817437, + 28.03 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - 83.4362514359038, - -146.951428620045 + 83.43625143590378, + -146.95142862004474, + 26.11 ], [ - 68.9874036695233, - -108.10678241983 + 68.98740366952329, + -108.10678241983003, + 17.79 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - 110.546733134203, - -214.027593892259 + 110.54673313420321, + -214.02759389225906, + 27.69 ], [ - 111.534350890173, - -179.838113092233 + 111.53435089017266, + -179.83811309223347, + 30.29 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - 110.037936896846, - -168.495835638497 + 110.03793689684629, + -168.49583563849748, + 31.15 ], [ - 105.077018158356, - -166.641057207958 + 105.07701815835642, + -166.64105720795808, + 31.55 ], [ - 102.766219089942, - -165.688685229298 + 102.76621908994164, + -165.6886852292976, + 31.69 ], [ - 100.056232383348, - -163.762330372999 + 100.0562323833477, + -163.76233037299872, + 31.53 ], [ 96.9873892973125, - -160.786566032783 + -160.78656603278262, + 31.04 ], [ - 94.5049985015079, - -158.034131644146 + 94.50499850150788, + -158.03413164414619, + 30.28 ], [ 91.4342291831665, - -153.718055174129 + -153.71805517412884, + 29.08 ], [ - 82.7084835068341, - -145.882804882052 + 82.70848350683406, + -145.88280488205245, + 25.76 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - 79.1028095788788, - -149.902645118338 + 79.10280957887883, + -149.90264511833848, + 25.94 ], [ - 87.5616128524851, - -157.481410426472 + 87.56161285248508, + -157.4814104264721, + 28.74 ], [ - 90.2585312272088, - -161.369924756482 + 90.25853122720883, + -161.369924756482, + 29.84 ], [ - 93.1092763097095, - -164.544256767181 + 93.10927630970947, + -164.5442567671812, + 30.49 ], [ - 96.5784627653289, - -167.893325227024 + 96.57846276532892, + -167.89332522702423, + 31.01 ], [ - 100.07071556656, - -170.367815571085 + 100.07071556655998, + -170.36781557108517, + 31.29 ], [ - 103.112804730391, - -171.671153192072 + 103.11280473039093, + -171.67115319207213, + 31.36 ], [ - 108.146577680852, - -173.553775961996 + 108.14657768085227, + -173.5537759619962, + 30.96 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 } ], "targets": [ - 4000, - 6500, - 10500 + 15000, + 35000, + 60000 ] } -] +] \ No newline at end of file diff --git a/levels/kangaroo_point/level.glb b/levels/kangaroo_point/level.glb index 0637267..5320b1b 100644 Binary files a/levels/kangaroo_point/level.glb and b/levels/kangaroo_point/level.glb differ diff --git a/levels/kangaroo_point/level.glb.import b/levels/kangaroo_point/level.glb.import index 5647f63..cf14dd4 100644 --- a/levels/kangaroo_point/level.glb.import +++ b/levels/kangaroo_point/level.glb.import @@ -3,7 +3,7 @@ importer="scene" importer_version=1 type="PackedScene" -uid="uid://dik381ld32een" +uid="uid://cr8nyyans2y6h" path="res://.godot/imported/level.glb-30461b4810ef38297351fb89cbe9aa18.scn" [deps] diff --git a/levels/queen_st_mall/junctions.json b/levels/queen_st_mall/junctions.json index f88b412..98fb92a 100644 --- a/levels/queen_st_mall/junctions.json +++ b/levels/queen_st_mall/junctions.json @@ -2,397 +2,432 @@ { "name": "Albert x Adelaide", "spawn": { - "dx": -0.663386853147646, - "dz": -0.748276608662107, - "x": 20.6920527258856, - "z": -24.7106522816088 + "x": 20.69205272588558, + "z": -24.71065228160878, + "y": 29.84, + "dx": -0.6633868531476461, + "dz": -0.7482766086621067 }, "streams": [ { - "interval": 1.5, "pts": [ [ - -58.8461484663001, - -114.424174209248 + -58.84614846630014, + -114.42417420924829, + 11.97 ], [ -53.880474905008, - -108.391854739427 + -108.39185473942744, + 12.77 ], [ - -51.2405150349884, - -105.525786544745 + -51.24051503498836, + -105.52578654474546, + 14.25 ], [ - -20.3529842406907, - -70.7696216351455 + -20.352984240690695, + -70.76962163514554, + 23.48 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - -86.703252503893, - -94.0877138699484 + -86.70325250389301, + -94.08771386994844, + 22.9 ], [ - -77.607019688744, - -101.920941690901 + -77.60701968874399, + -101.92094169090129, + 18.15 ], [ - -72.0652250322851, - -106.9478629653 + -72.06522503228508, + -106.94786296530025, + 14.98 ], [ - -68.7920906183039, - -109.508381296246 + -68.79209061830386, + -109.50838129624599, + 13.7 ], [ - -62.6926613135619, - -114.753855415977 + -62.692661313561906, + -114.75385541597699, + 12.25 ], [ - -56.4508191491618, - -120.138498306347 + -56.45081914916183, + -120.13849830634709, + 11.56 ], [ - -53.1441813532654, - -122.980904904961 + -53.14418135326541, + -122.9809049049611, + 11.66 ], [ - -38.7548693234, - -135.567757774861 + -38.75486932340002, + -135.5677577748611, + 14.48 ], [ - -8.13888016446398, - -163.054303917178 + -8.138880164463979, + -163.05430391717795, + 16.8 ], [ - 7.53742621322278, - -176.886292547868 + 7.537426213222782, + -176.88629254786764, + 19.45 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - -24.3893890595013, - -67.1825007647702 + -24.38938905950134, + -67.18250076477023, + 24.51 ], [ - -55.2720133743741, - -101.933152255045 + -55.272013374374126, + -101.93315225504524, + 15.33 ], [ - -57.9853352512913, - -104.883276460764 + -57.98533525129133, + -104.88327646076375, + 14.17 ], [ - -63.0150881333189, - -110.991982190617 + -63.01508813331892, + -110.99198219061685, + 12.81 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - 11.1101677795621, - -172.837154651951 + 11.110167779562063, + -172.83715465195058, + 20.06 ], [ - -4.54306405533622, - -159.025643282508 + -4.543064055336218, + -159.02564328250827, + 17.14 ], [ - -35.1638772092336, - -131.534796625037 + -35.16387720923361, + -131.5347966250365, + 14.59 ], [ - -49.5953698809185, - -118.910777494948 + -49.59536988091847, + -118.91077749494814, + 12.53 ], [ - -52.9260113021268, - -116.047565693668 + -52.92601130212681, + -116.04756569366813, + 12.11 ], [ - -59.1685752860572, - -110.662300983888 + -59.168575286057155, + -110.66230098388816, + 12.46 ], [ - -65.3362602521517, - -105.359015503696 + -65.33626025215173, + -105.35901550369637, + 14.71 ], [ -68.5423745958537, - -102.855244634386 + -102.85524463438601, + 15.97 ], [ -74.0429581637501, - -97.8641615087792 + -97.86416150877923, + 18.58 ], [ - -83.1794893924223, - -89.9958813300908 + -83.17948939242227, + -89.9958813300908, + 23.25 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - -63.049013950748, - -111.034041203303 + -63.049013950748005, + -111.03404120330288, + 12.8 ], [ - -67.6731119774683, - -116.885568358634 + -67.67311197746825, + -116.88556835863362, + 12.36 ], [ - -69.3364043278144, - -119.016515361795 + -69.33640432781439, + -119.01651536179543, + 12.14 ], [ - -72.7496535402502, - -122.556584617365 + -72.74965354025018, + -122.55658461736515, + 11.98 ], [ - -98.2440886423925, - -142.519976823492 + -98.24408864239251, + -142.51997682349207, + 18.09 ], [ - -106.032628822328, - -149.462816226915 + -106.03262882232805, + -149.46281622691504, + 21.13 ], [ - -127.254841098403, - -167.50831278782 + -127.2548410984026, + -167.5083127878196, + 27.66 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - -123.756786956036, - -171.622145212345 + -123.7567869560363, + -171.62214521234466, + 28.43 ], [ - -102.508313753821, - -153.554173373131 + -102.50831375382124, + -153.55417337313145, + 20.4 ], [ - -94.8493767077653, - -146.719492376612 + -94.84937670776534, + -146.71949237661244, + 17.28 ], [ -69.3394816295263, - -126.743555782696 + -126.74355578269574, + 11.23 ], [ - -65.3252993333639, - -122.631904237628 + -65.32529933336386, + -122.63190423762802, + 11.48 ], [ - -63.4329063916396, - -120.229317241236 + -63.432906391639634, + -120.22931724123647, + 11.7 ], [ - -58.8122226488711, - -114.382115196562 + -58.81222264887106, + -114.38211519656227, + 11.97 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 } ], "targets": [ - 23000, - 25500, - 29500 + 15000, + 35000, + 60000 ] }, { - "name": "Edward x Elizabeth", + "name": "Elizabeth x George", "spawn": { - "dx": 0.688388502507091, - "dz": 0.725342174160613, - "x": 171.921077302301, - "z": -175.651225571771 + "x": -167.94554211176842, + "z": 282.4630938016437, + "y": 13.4, + "dx": 0.7551073297079488, + "dz": -0.6556011902226315 }, "streams": [ { - "interval": 1.5, "pts": [ [ - 228.742601685131, - -123.809388411418 + -151.6480512074991, + 261.15863374688365, + 20.11 ], [ - 250.487851794393, - -101.124186911579 + -144.0595617023658, + 254.3334990786212, + 21.13 ], [ - 253.191844757795, - -98.1321613960494 + -143.3213169995492, + 253.69278253341383, + 21.21 ], [ - 258.485283289911, - -92.2834398309675 + -91.08224191170491, + 208.5453042937327, + 26.1 + ], + [ + -88.11035783744204, + 205.98090738044175, + 25.99 + ], + [ + -80.87164084704513, + 199.7122732897846, + 25.71 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - 184.819681990446, - -31.5997398360326 + -118.25454597584726, + 162.31711832498388, + 27.58 ], [ - 200.990172438104, - -45.5669611828909 - ], - [ - 206.298224766768, - -50.115127103271 - ], - [ - 208.012771617165, - -51.5958506176373 - ], - [ - 243.567491578602, - -82.5547120764429 - ], - [ - 246.131368490435, - -84.8446372752634 - ], - [ - 254.684705396329, - -92.485245640523 + -141.88997628727992, + 134.01017432495556, + 28.01 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - 254.481581996358, - -88.659853768515 + -77.33660099284295, + 203.79436751079447, + 25.77 ], [ - 249.186979870745, - -94.509861403438 + -84.57742467711269, + 210.06482501974904, + 26.02 ], [ - 246.577198699258, - -97.4003726882982 + -87.55143656981038, + 212.6310617067039, + 26.03 ], [ - 224.844319166858, - -120.07262598818 + -139.79024774732977, + 257.7783118670535, + 21.09 + ], + [ + -140.45452335644003, + 258.3539093219179, + 21.03 + ], + [ + -148.03695777611765, + 265.1736062536181, + 19.8 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - 258.282159889941, - -88.4580479589594 + -137.74491839162505, + 130.5491780750776, + 27.82 ], [ - 249.72869976276, - -80.817329524774 - ], - [ - 247.117079187487, - -78.4852615230074 - ], - [ - 211.558093240145, - -47.5226829818001 - ], - [ - 209.815723834205, - -46.017908496633 - ], - [ - 204.515981699117, - -41.4768916168623 - ], - [ - 188.349489765203, - -27.5131205641572 + -114.10948808019242, + 158.85612207510593, + 26.89 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - 258.480541378725, - -92.2886654287672 + -80.89109247754493, + 199.7292817019625, + 25.71 ], [ - 262.27371225915, - -88.1195420122156 + -74.7953733286614, + 194.34772839631796, + 25.24 ], [ - 266.827379303769, - -83.1100839184909 - ], - [ - 270.873333747605, - -78.6578477713867 - ], - [ - 298.089289341555, - -47.3042762934113 + -35.46218143888725, + 160.46495405823146, + 21.98 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - 254.709252094248, - -92.5069068273425 + -81.10769187758535, + 203.56321084385132, + 25.83 ], [ - 259.703037116882, - -96.8600914480509 + -86.41612277054091, + 197.68669995304248, + 25.87 ], [ - 263.665450959975, - -100.3447248693 + -97.11136428582687, + 185.75737187487675, + 26.43 ], [ - 288.615579063857, - -122.117679372756 + -118.18679983484368, + 162.3951682081065, + 27.58 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 } ], "targets": [ - 22000, - 24500, - 28500 + 15000, + 35000, + 60000 ] } -] +] \ No newline at end of file diff --git a/levels/queen_st_mall/level.glb b/levels/queen_st_mall/level.glb index 07c7e83..6f0e0b8 100644 Binary files a/levels/queen_st_mall/level.glb and b/levels/queen_st_mall/level.glb differ diff --git a/levels/queen_st_mall/level.glb.import b/levels/queen_st_mall/level.glb.import index ee4dd34..72d5d9c 100644 --- a/levels/queen_st_mall/level.glb.import +++ b/levels/queen_st_mall/level.glb.import @@ -3,7 +3,7 @@ importer="scene" importer_version=1 type="PackedScene" -uid="uid://djsujf76tbo3k" +uid="uid://do65sk46ogjid" path="res://.godot/imported/level.glb-f093d0a503a60c4e982eefdc88ad879e.scn" [deps] diff --git a/levels/southbank/junctions.json b/levels/southbank/junctions.json index 70e45a7..90ff585 100644 --- a/levels/southbank/junctions.json +++ b/levels/southbank/junctions.json @@ -2,345 +2,407 @@ { "name": "Melbourne x Merivale", "spawn": { - "dx": 0.852877329272599, - "dz": -0.522111349438832, "x": -596.868944790812, - "z": -210.352681833747 + "z": -210.35268183374677, + "y": 8.98, + "dx": 0.8528773292725991, + "dz": -0.5221113494388324 }, "streams": [ { - "interval": 1.5, "pts": [ [ - -522.243146999435, - -263.291609906853 + -522.2431469994345, + -263.2916099068527, + 7.69 ], [ - -513.298474365917, - -268.564620105823 + -513.2984743659174, + -268.5646201058227, + 7.44 ], [ - -505.766456184546, - -272.847714331466 + -505.76645618454586, + -272.8477143314658, + 6.89 ], [ - -497.908990415611, - -277.262924417905 + -497.90899041561073, + -277.2629244179048, + 6.23 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - -518.331960424561, - -316.208166257863 + -518.3319604245614, + -316.20816625786284, + 9.74 ], [ - -502.539989208635, - -289.117722143497 + -502.53998920863535, + -289.11772214349674, + 7.36 ], [ - -501.031072012682, - -286.533998911906 + -501.0310720126822, + -286.5339989119062, + 7.03 ], [ - -499.307492099731, - -283.769724904009 + -499.3074920997309, + -283.76972490400925, + 6.7 ], [ - -498.930545303579, - -283.241377841783 + -498.93054530357944, + -283.2413778417831, + 6.63 ], [ - -494.345014474119, - -276.414559193545 + -494.34501447411924, + -276.414559193545, + 6.05 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - -495.263684530077, - -272.555233182069 + -495.26368453007734, + -272.55523318206934, + 6.0 ], [ - -503.109412344477, - -268.146638068316 + -503.1094123444767, + -268.14663806831595, + 6.51 ], [ - -510.589252181608, - -263.893419493984 + -510.58925218160783, + -263.8934194939837, + 6.98 ], [ - -519.500789611495, - -258.639784893289 + -519.5007896114952, + -258.6397848932893, + 7.39 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - -498.827660471569, - -273.403598406429 + -498.82766047156883, + -273.4035984064291, + 6.2 ], [ - -503.407264010886, - -280.221611358154 + -503.4072640108861, + -280.2216113581537, + 6.94 ], [ - -503.859919895901, - -280.865348695483 + -503.85991989590116, + -280.8653486954825, + 7.03 ], [ - -505.652275149097, - -283.740348688276 + -505.6522751490968, + -283.7403486882755, + 7.41 ], [ - -507.204986888727, - -286.397833056652 + -507.20498688872703, + -286.3978330566516, + 7.75 ], [ -522.997174842978, - -313.488648942198 + -313.4886489421985, + 10.11 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - -497.709720982148, - -277.364279299137 + -497.7097209821479, + -277.3642792991366, + 6.22 ], [ - -489.265341389724, - -281.217004706688 + -489.2653413897242, + -281.21700470668776, + 6.15 ], [ - -470.163954224667, - -292.974174195101 + -470.16395422466655, + -292.9741741951012, + 5.43 ], [ - -453.397320014964, - -303.36964984342 + -453.3973200149641, + -303.3696498434199, + 6.15 ], [ - -438.717138348101, - -313.023771847006 + -438.7171383481014, + -313.0237718470059, + 8.99 ], [ - -428.175689682796, - -319.695221818248 + -428.17568968279613, + -319.6952218182481, + 11.09 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - -490.912703075514, - -271.24169070377 + -490.9127030755138, + -271.2416907037699, + 6.0 ], [ - -487.079481353019, - -265.232181447622 + -487.07948135301893, + -265.2321814476218, + 6.0 ], [ - -460.796114039586, - -221.705738945924 + -460.79611403958603, + -221.7057389459239, + 6.26 ], [ - -449.787661487498, - -203.621656847663 + -449.78766148749827, + -203.62165684766288, + 6.74 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 } ], "targets": [ - 35500, - 38000, - 73000 + 15000, + 35000, + 60000 ] }, { "name": "Grey x Glenelg", "spawn": { - "dx": 0.5279471843098, - "dz": 0.849277204792024, - "x": -137.35790798426, - "z": -96.075818860076 + "x": -137.3579079842604, + "z": -96.07581886007603, + "y": 13.36, + "dx": 0.5279471843098005, + "dz": 0.8492772047920241 }, "streams": [ { - "interval": 1.5, "pts": [ [ -66.8941396578206, - 18.0214549249385 + 18.021454924938546, + 8.55 ], [ - -68.9372122719242, - 14.7292502722074 + -68.93721227192415, + 14.729250272207434, + 8.67 ], [ - -74.0341764510855, - 5.78813512164328 + -74.03417645108553, + 5.788135121643277, + 9.23 ], [ - -78.6658442785157, - -1.69267819146961 + -78.66584427851572, + -1.692678191469608, + 9.75 ], [ - -82.8206925318667, - -8.34435236597675 + -82.82069253186671, + -8.344352365976752, + 10.15 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - -33.0502081552841, - -14.7586201862311 + -33.05020815528413, + -14.758620186231095, + 8.09 ], [ - -35.0675152831888, - -14.5994094114893 + -35.06751528318885, + -14.599409411489315, + 8.2 ], [ - -37.270016261863, - -13.9961460505448 + -37.27001626186296, + -13.996146050544787, + 8.29 ], [ - -43.3585248193085, - -10.7606682738875 + -43.35852481930847, + -10.760668273887504, + 8.5 ], [ - -53.6949181138706, - -4.20452046261836 + -53.694918113870564, + -4.204520462618362, + 8.68 ], [ - -56.3314625884028, - -2.47024586902805 + -56.331462588402815, + -2.4702458690280507, + 8.73 ], [ - -63.0911519484621, - 2.2185465904455 + -63.091151948462084, + 2.2185465904455017, + 8.85 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - -78.2407420345622, - -11.2051308338488 + -78.24074203456223, + -11.205130833848836, + 10.32 ], [ - -74.079811043889, - -4.54369540834144 + -74.07981104388904, + -4.543695408341438, + 9.85 ], [ - -69.3883249482344, - 3.03567007854908 + -69.38832494823436, + 3.0356700785490762, + 9.17 ], [ - -64.2732751867703, - 12.0075429283282 + -64.27327518677029, + 12.007542928328153, + 8.41 ], [ - -62.3066015113759, - 15.1728598756354 + -62.30660151137585, + 15.172859875635417, + 8.28 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ -66.1688465571084, - -2.2185465904455 + -2.2185465904455017, + 9.29 ], [ - -59.3783588139033, - -6.92854413081255 + -59.37835881390333, + -6.9285441308125515, + 9.26 ], [ - -56.6027334256873, - -8.75475233718959 + -56.602733425687326, + -8.754752337189586, + 9.26 ], [ - -46.1200499391949, - -15.4011401262142 + -46.12004993919494, + -15.401140126214159, + 9.08 ], [ - -39.5077365181293, - -18.9106763490265 + -39.50773651812935, + -18.910676349026538, + 8.74 ], [ -36.1005431869604, - -19.8996785886188 + -19.899678588618844, + 8.57 ], [ - -33.5155306840827, - -20.1385342138149 + -33.51553068408273, + -20.138534213814854, + 8.43 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - -62.4286691941866, - -1.5633764655738 + -62.42866919418658, + -1.5633764655737972, + 9.03 ], [ - -56.2253414936718, - 7.17631569340894 + -56.22534149367183, + 7.176315693408943, + 8.15 ], [ - -31.6082945749603, - 46.3990126063831 + -31.608294574960304, + 46.399012606383145, + 8.71 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - -105.444153258371, - 17.2933813892185 + -105.44415325837058, + 17.29338138921854, + 9.0 ], [ - -124.855497585617, - 29.0280377160981 + -124.85549758561747, + 29.02803771609806, + 10.01 ], [ - -145.965198973204, - 41.6802343084808 + -145.9651989732041, + 41.680234308480806, + 12.4 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 } ], "targets": [ - 22500, - 25000, - 29000 + 15000, + 35000, + 60000 ] } -] +] \ No newline at end of file diff --git a/levels/southbank/level.glb b/levels/southbank/level.glb index c838ef8..0e9eec5 100644 Binary files a/levels/southbank/level.glb and b/levels/southbank/level.glb differ diff --git a/levels/southbank/level.glb.import b/levels/southbank/level.glb.import index 75a1581..fbf89fe 100644 --- a/levels/southbank/level.glb.import +++ b/levels/southbank/level.glb.import @@ -3,7 +3,7 @@ importer="scene" importer_version=1 type="PackedScene" -uid="uid://dw52qeb8csi30" +uid="uid://dxm6gf8nrgrl1" path="res://.godot/imported/level.glb-17af9cdeb05fd15a816097b7ae0fb96c.scn" [deps] diff --git a/levels/story_bridge/junctions.json b/levels/story_bridge/junctions.json index f5a8f98..5f60cd3 100644 --- a/levels/story_bridge/junctions.json +++ b/levels/story_bridge/junctions.json @@ -2,185 +2,219 @@ { "name": "Bridge Approach", "spawn": { - "dx": -0.114095858645717, - "dz": -0.993469745407426, - "x": 35.5160890575852, - "z": -118.596483088614 + "x": 35.51608905758518, + "z": -118.5964830886139, + "y": 6.7, + "dx": -0.11409585864571734, + "dz": -0.9934697454074263 }, "streams": [ { - "interval": 1.5, "pts": [ [ - 21.8244656781075, - -237.813875098783 + 21.82446567810751, + -237.81387509878263, + 37.66 ], [ - 23.1457200273832, - -226.455207706528 + 23.145720027383163, + -226.45520770652828, + 37.76 ], [ - 24.7882096121438, - -213.848153713549 + 24.788209612143817, + -213.84815371354867, + 35.66 ], [ - 26.1455691749522, - -200.297419769933 + 26.145569174952232, + -200.29741976993301, + 31.44 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - 2.19994158852704, - -240.327171190027 + 2.199941588527042, + -240.32717119002737, + 36.31 ], [ - -2.52481722237557, - -243.919505367749 + -2.5248172223755736, + -243.91950536774928, + 35.81 ], [ - -6.32534953080772, - -247.60965512377 + -6.325349530807717, + -247.60965512377, + 35.17 ], [ - -15.1839832375373, - -255.261358332787 + -15.183983237537262, + -255.2613583327868, + 33.26 ], [ - -19.8227220865701, - -258.67299529667 + -19.822722086570074, + -258.6729952966697, + 32.36 ], [ - -24.2795153329838, - -261.703355786389 + -24.279515332983824, + -261.70335578638884, + 31.56 ], [ - -29.0114379744006, - -263.890761064968 + -29.011437974400625, + -263.89076106496833, + 30.9 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.8, "pts": [ [ - 20.7724471517801, - -199.7593122304 + 20.772447151780117, + -199.75931223039953, + 31.4 ], [ - 19.4233779811381, - -213.232863886751 + 19.423377981138138, + -213.23286388675078, + 35.3 ], [ - 17.786545159723, - -225.792452293243 + 17.78654515972297, + -225.7924522932427, + 37.39 ], [ - 16.4606356403737, - -237.18991410136 + 16.46063564037367, + -237.18991410136036, + 37.31 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.8, "pts": [ [ - -26.7370429025148, - -268.788426535065 + -26.737042902514784, + -268.7884265350654, + 30.16 ], [ - -21.6112433779486, - -266.398068213575 + -21.61124337794858, + -266.3980682135746, + 30.89 ], [ - -16.704188313209, - -263.081481102976 + -16.704188313209045, + -263.0814811029762, + 31.77 ], [ - -11.7617743504717, - -259.438496866914 + -11.761774350471743, + -259.43849686691397, + 32.83 ], [ - -2.72241951437748, - -251.63195487599 + -2.7224195143774796, + -251.63195487598963, + 34.86 ], [ - 0.983930787446262, - -248.024220632365 + 0.9839307874462617, + -248.02422063236523, + 35.6 ], [ - 5.46498065752023, - -244.628278010132 + 5.4649806575202335, + -244.6282780101317, + 36.2 ] ], - "speed": 11.0 + "speed": 11.0, + "interval": 1.8 }, { - "interval": 1.5, "pts": [ [ - 11.2707008429023, - -197.847843241665 + 11.27070084290225, + -197.84784324166512, + 31.27 ], [ - 10.8961758047183, - -204.766417702285 + 10.896175804718348, + -204.76641770228525, + 33.12 ], [ - 10.4764778796752, - -211.209757888086 + 10.476477879675205, + -211.20975788808624, + 34.75 ], [ 9.92304078347784, - -216.207006965937 + -216.20700696593718, + 35.63 ], [ - 8.93295830185362, - -221.625317668162 + 8.932958301853615, + -221.62531766816238, + 36.37 ], [ - 7.50873869919987, - -226.865371707994 + 7.508738699199866, + -226.8653717079938, + 36.97 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 }, { - "interval": 1.5, "pts": [ [ - 28.875188928697, - -229.492425462448 + 28.875188928696993, + -229.49242546244793, + 38.44 ], [ - 28.7254802520939, - -214.053661592775 + 28.72548025209394, + -214.05366159277472, + 35.92 ], [ - 28.1508746327618, - -209.459560296273 + 28.150874632761848, + -209.45956029627345, + 34.63 ], [ - 27.2791473530598, - -204.781298995536 + 27.279147353059784, + -204.7812989955361, + 32.98 ], [ - 26.0948795290309, - -199.443402630656 + 26.094879529030933, + -199.44340263065618, + 31.15 ] ], - "speed": 12.0 + "speed": 12.0, + "interval": 1.5 } ], "targets": [ - 5000, - 7500, - 11500 + 15000, + 35000, + 60000 ] } -] +] \ No newline at end of file diff --git a/levels/story_bridge/level.glb b/levels/story_bridge/level.glb index 4fb3a09..0037fdd 100644 Binary files a/levels/story_bridge/level.glb and b/levels/story_bridge/level.glb differ diff --git a/levels/story_bridge/level.glb.import b/levels/story_bridge/level.glb.import index 4ec43b3..aa848b3 100644 --- a/levels/story_bridge/level.glb.import +++ b/levels/story_bridge/level.glb.import @@ -3,7 +3,7 @@ importer="scene" importer_version=1 type="PackedScene" -uid="uid://bjd3utm2spgs0" +uid="uid://dduudwpqocdxu" path="res://.godot/imported/level.glb-045fc5cf8c0e529ecdc2678ee7acde2a.scn" [deps] diff --git a/shot_bridge_dem.png.import b/shot_bridge_dem.png.import new file mode 100644 index 0000000..2f85ce7 --- /dev/null +++ b/shot_bridge_dem.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cfq88o84umvip" +path="res://.godot/imported/shot_bridge_dem.png-75be2353aa1d96cb1fa690daade691e3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://shot_bridge_dem.png" +dest_files=["res://.godot/imported/shot_bridge_dem.png-75be2353aa1d96cb1fa690daade691e3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/shot_kp_dem.png.import b/shot_kp_dem.png.import new file mode 100644 index 0000000..12f6245 --- /dev/null +++ b/shot_kp_dem.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://boesb5lcxhlfv" +path="res://.godot/imported/shot_kp_dem.png-c9ce5dfc952a5ba8544840830a36b4c0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://shot_kp_dem.png" +dest_files=["res://.godot/imported/shot_kp_dem.png-c9ce5dfc952a5ba8544840830a36b4c0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/shot_kp_top.png.import b/shot_kp_top.png.import new file mode 100644 index 0000000..5a798b2 --- /dev/null +++ b/shot_kp_top.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dv0r0ctfsvyse" +path="res://.godot/imported/shot_kp_top.png-9b910b7280f9d3c8de3410ea2430621a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://shot_kp_top.png" +dest_files=["res://.godot/imported/shot_kp_top.png-9b910b7280f9d3c8de3410ea2430621a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/shot_trolleys.png.import b/shot_trolleys.png.import new file mode 100644 index 0000000..d2738b9 --- /dev/null +++ b/shot_trolleys.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://w384sbljyqjk" +path="res://.godot/imported/shot_trolleys.png-4bc10206031793a54eda76f31a101806.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://shot_trolleys.png" +dest_files=["res://.godot/imported/shot_trolleys.png-4bc10206031793a54eda76f31a101806.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/src/game.gd b/src/game.gd index 744523b..7e0f0ec 100644 --- a/src/game.gd +++ b/src/game.gd @@ -81,6 +81,7 @@ var busts := 0 var escapes := 0 var drag_end: Vector3 +var drag_end_y := 0.0 var drag_len := 0.0 var gear := 1 var revs := 0.0 @@ -165,7 +166,7 @@ func _ready() -> void: var sp: Dictionary = junction["spawn"] var jf := Vector3(sp["dx"], 0, sp["dz"]).normalized() car.transform = Transform3D(Basis.looking_at(jf, Vector3.UP), - _clear_spawn(Vector3(sp["x"], 0.7, sp["z"]), jf)) + _clear_spawn(Vector3(sp["x"], float(sp.get("y", 0.0)) + 0.7, sp["z"]), jf)) car.hold_wreck = true # The marker test lives in the branch condition, not inside it: as an `elif` # with the test inside, a level without a drag strip (the code-built carpark) @@ -174,7 +175,8 @@ func _ready() -> void: elif mode == "drag" and _drag_markers(level).size() == 2: var mk := _drag_markers(level) drag_end = Vector3(mk[1].global_position.x, 0.0, mk[1].global_position.z) - var from := Vector3(mk[0].global_position.x, 0.7, mk[0].global_position.z) + drag_end_y = mk[1].global_position.y + var from := Vector3(mk[0].global_position.x, mk[0].global_position.y + 0.7, mk[0].global_position.z) var dir := (drag_end - Vector3(from.x, 0, from.z)).normalized() drag_len = Vector3(from.x, 0, from.z).distance_to(drag_end) car.transform = Transform3D(Basis.looking_at(dir, Vector3.UP), @@ -189,7 +191,8 @@ func _ready() -> void: var f := -t.basis.z f.y = 0.0 f = f.normalized() if f.length_squared() > 0.001 else Vector3.FORWARD - car.transform = Transform3D(Basis.looking_at(f, Vector3.UP), Vector3(t.origin.x, 0.7, t.origin.z)) + car.transform = Transform3D(Basis.looking_at(f, Vector3.UP), + Vector3(t.origin.x, t.origin.y + 0.7, t.origin.z)) else: car.position = Vector3.UP * 0.6 add_child(car) @@ -244,10 +247,10 @@ func _ready() -> void: var strip := Path3D.new() var sc := Curve3D.new() sc.add_point(car.global_position + lane) - sc.add_point(drag_end + Vector3.UP * 0.7 + lane) + sc.add_point(drag_end + Vector3.UP * (drag_end_y + 0.7) + lane) # a 2-point curve makes rival.gd's fmod() lookahead wrap to the start once # it nears the end, spinning the car around -- extend past the line instead - sc.add_point(drag_end + Vector3.UP * 0.7 + lane + fwd * 120.0) + sc.add_point(drag_end + Vector3.UP * (drag_end_y + 0.7) + lane + fwd * 120.0) strip.curve = sc add_child(strip) var pool := Registry.cars().values() @@ -296,7 +299,8 @@ func _ready() -> void: var path := Path3D.new() var curve := Curve3D.new() for p in stream["pts"]: - curve.add_point(Vector3(p[0], 0, p[1])) + # third component (when baked) is terrain height + curve.add_point(Vector3(p[0], float(p[2]) if p.size() > 2 else 0.0, p[1])) path.curve = curve add_child(path) var L := curve.get_baked_length() @@ -447,7 +451,8 @@ func _spawn_smashables(level: Node) -> void: add_child(b) var t: Transform3D = (m as Node3D).global_transform b.global_transform = Transform3D( - Basis(Vector3.UP, t.basis.get_euler().y), Vector3(t.origin.x, 0.75, t.origin.z)) + Basis(Vector3.UP, t.basis.get_euler().y), + Vector3(t.origin.x, t.origin.y + 0.72, t.origin.z)) b.sleeping = true n += 1 for prefix in SMASHABLE: @@ -514,7 +519,7 @@ func _spawn_smashables(level: Node) -> void: var t: Transform3D = (m as Node3D).global_transform b.global_transform = Transform3D( Basis(Vector3.UP, t.basis.get_euler().y), - Vector3(t.origin.x, size.y * 0.5 + 0.02, t.origin.z)) + Vector3(t.origin.x, t.origin.y + size.y * 0.5 + 0.02, t.origin.z)) b.sleeping = true n += 1 diff --git a/tools/build_all_junctions.sh b/tools/build_all_junctions.sh index d08707e..4a1ac2b 100755 --- a/tools/build_all_junctions.sh +++ b/tools/build_all_junctions.sh @@ -14,7 +14,7 @@ while IFS='|' read -r id json lat lon specs; do IFS=';' read -ra SPEC <<< "$specs" python3 tools/osm_junction.py "$C/$json" "levels/$id/junctions.json" "$lat" "$lon" "${SPEC[@]}" done <<'EOF' -queen_st_mall|brisbane_cbd.json|-27.4699|153.0251|Albert x Adelaide|Albert Street|Adelaide Street;Edward x Elizabeth|Edward Street|Elizabeth Street +queen_st_mall|brisbane_cbd.json|-27.4699|153.0251|Albert x Adelaide|Albert Street|Adelaide Street;Elizabeth x George|Elizabeth Street|George Street southbank|southbank.json|-27.4775|153.0215|Melbourne x Merivale|Melbourne Street|Merivale Street;Grey x Glenelg|Grey Street|Glenelg Street albert_parklands|albert_parklands.json|-27.4740|153.0280|Alice x George|Alice Street|George Street;Margaret x Edward|Margaret Street|Edward Street story_bridge|story_bridge.json|-27.4635|153.0355|Bridge Approach|Bradfield Highway|Kemp Place diff --git a/tools/build_level_osm.py b/tools/build_level_osm.py index 2554abf..420d3cc 100644 --- a/tools/build_level_osm.py +++ b/tools/build_level_osm.py @@ -41,6 +41,50 @@ TEX = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "assets", " M_LAT = 110574.0 M_LON = 111320.0 * math.cos(math.radians(LAT0)) +# ---- real terrain (tools/fetch_dem.py output next to the area json) -------- +import numpy as _np +DEM = None +DEM_META = None +_dem_base = src[:-5] if src.endswith(".json") else src +if os.path.exists(_dem_base + "_dem.f32"): + DEM_META = json.load(open(_dem_base + "_dem.json")) + DEM = _np.fromfile(_dem_base + "_dem.f32", dtype=" 0 else list(reversed(r)) -def poly_bm(pts, z, h=0.0): - """Filled (optionally extruded) polygon bmesh from closed pt list.""" +def poly_bm(pts, z, h=0.0, drape=False): + """Filled (optionally extruded) polygon bmesh from closed pt list. + drape=True adds terrain height per vertex (parks); flat otherwise (water).""" bm = bmesh.new() - verts = [bm.verts.new((x, y, z)) for x, y in pts[:-1]] + verts = [bm.verts.new((x, y, z + (H(x, y) if drape else 0.0))) for x, y in pts[:-1]] face = bm.faces.new(verts) if h > 0.0: res = bmesh.ops.extrude_face_region(bm, geom=[face]) @@ -241,9 +286,27 @@ def poly_bm(pts, z, h=0.0): bmesh.ops.triangulate(bm, faces=bm.faces) return bm -def ribbon(bm, pts, half, z, mat=0, drop=None, offset=0.0): +def _subdivide(pts, step=8.0): + """Split long segments so draped ribbons follow the terrain instead of + chording across it -- an OSM segment can run 100+ m, and a straight strip + over curved ground diverges from the collision mesh by metres. That read + in-game as the car sinking to its windows mid-block.""" + out = [pts[0]] + for i in range(1, len(pts)): + (x1, y1), (x2, y2) = out[-1], pts[i] + L = math.hypot(x2 - x1, y2 - y1) + n = max(int(L / step), 1) + for k in range(1, n + 1): + out.append((x1 + (x2 - x1) * k / n, y1 + (y2 - y1) * k / n)) + return out + +def ribbon(bm, pts, half, z, mat=0, drop=None, offset=0.0, zs=None): """Strip of width 2*half along a polyline, shifted sideways by `offset`. - `drop` chamfers the edges down to z-PATH_H.""" + `drop` chamfers the edges down to z-PATH_H. Heights come from the terrain + (per segment END, not per corner, so roads don't twist across their width); + `zs` overrides with explicit per-point heights (bridge decks).""" + if zs is None and DEM is not None: + pts = _subdivide(pts) for i in range(len(pts) - 1): (x1, y1), (x2, y2) = pts[i], pts[i + 1] dx, dy = x2 - x1, y2 - y1 @@ -251,79 +314,88 @@ def ribbon(bm, pts, half, z, mat=0, drop=None, offset=0.0): if L < 0.1: continue nx, ny = -dy / L, dx / L + h1 = zs[i] if zs else H(x1, y1) + h2 = zs[i + 1] if zs else H(x2, y2) + if zs is None: + CARVE.append((x1, y1, h1)) + CARVE.append((x2, y2, h2)) if offset: x1, y1 = x1 + nx * offset, y1 + ny * offset x2, y2 = x2 + nx * offset, y2 + ny * offset if drop is None: - quad(bm, [(x1 + nx * half, y1 + ny * half, z), (x1 - nx * half, y1 - ny * half, z), - (x2 - nx * half, y2 - ny * half, z), (x2 + nx * half, y2 + ny * half, z)], mat) + quad(bm, [(x1 + nx * half, y1 + ny * half, z + h1), (x1 - nx * half, y1 - ny * half, z + h1), + (x2 - nx * half, y2 - ny * half, z + h2), (x2 + nx * half, y2 + ny * half, z + h2)], mat) else: inner = max(half - PATH_CHAMFER, half * 0.35) - for s0, s1, z0, z1 in ((half, inner, z - drop, z), (inner, -inner, z, z), - (-inner, -half, z, z - drop)): - quad(bm, [(x1 + nx * s0, y1 + ny * s0, z0), (x1 + nx * s1, y1 + ny * s1, z1), - (x2 + nx * s1, y2 + ny * s1, z1), (x2 + nx * s0, y2 + ny * s0, z0)], mat) + for s0, s1, d0, d1 in ((half, inner, drop, 0.0), (inner, -inner, 0.0, 0.0), + (-inner, -half, 0.0, drop)): + quad(bm, [(x1 + nx * s0, y1 + ny * s0, z - d0 + h1), (x1 + nx * s1, y1 + ny * s1, z - d1 + h1), + (x2 + nx * s1, y2 + ny * s1, z - d1 + h2), (x2 + nx * s0, y2 + ny * s0, z - d0 + h2)], mat) # ------------------------------------------------------------------- props def add_tree(fol, jac, frond, trunk, x, y, rng): """Fig (broad layered canopy), jacaranda (same shape, purple), or palm.""" + z0 = H(x, y) if rng.random() < 0.18: h = rng.uniform(6.5, 9.5) - cone(trunk, (x, y, h / 2), 0.22, 0.14, h, 7) + cone(trunk, (x, y, z0 + h / 2), 0.22, 0.14, h, 7) for i in range(7): a = i * math.tau / 7 + rng.uniform(-0.25, 0.25) reach = rng.uniform(1.8, 2.5) - tip = Vector((x + math.cos(a) * reach, y + math.sin(a) * reach, h - rng.uniform(0.8, 1.6))) - beam(frond, Vector((x, y, h)), tip, 0.7, 0.12) + tip = Vector((x + math.cos(a) * reach, y + math.sin(a) * reach, z0 + h - rng.uniform(0.8, 1.6))) + beam(frond, Vector((x, y, z0 + h)), tip, 0.7, 0.12) else: # canopy well clear of the roof line of a car, and built from three # offset spheres so the silhouette breaks up instead of reading as a ball clear = rng.uniform(3.6, 4.8) r = rng.uniform(1.7, 2.5) - cone(trunk, (x, y, (clear + 1.0) / 2), 0.20, 0.13, clear + 1.0, 7) + cone(trunk, (x, y, z0 + (clear + 1.0) / 2), 0.20, 0.13, clear + 1.0, 7) target = jac if rng.random() < 0.22 else fol # jacaranda season is eternal here for i in range(3): off = Vector((rng.uniform(-1, 1), rng.uniform(-1, 1), 0)) * r * 0.42 - blob(target, (x + off.x, y + off.y, clear + r * (0.45 + 0.34 * i)), + blob(target, (x + off.x, y + off.y, z0 + clear + r * (0.45 + 0.34 * i)), (r * rng.uniform(0.75, 1.05), r * rng.uniform(0.75, 1.05), r * rng.uniform(0.55, 0.75)), subdiv=2) def add_bench(bm, x, y, rng): + z0 = H(x, y) a = rng.random() * math.tau d = Vector((math.cos(a), math.sin(a), 0)) p = Vector((-d.y, d.x, 0)) for s in (-0.75, 0.75): - c = Vector((x, y, 0)) + d * s + c = Vector((x, y, z0)) + d * s beam(bm, c + Vector((0, 0, 0.02)), c + Vector((0, 0, 0.45)), 0.36, 0.07) - a0 = Vector((x, y, 0.47)) - d * 0.95 + a0 = Vector((x, y, z0 + 0.47)) - d * 0.95 slab(bm, [(a0 + p * 0.28).to_tuple(), (a0 - p * 0.28).to_tuple(), (a0 - p * 0.28 + d * 1.9).to_tuple(), (a0 + p * 0.28 + d * 1.9).to_tuple()], 0.08) def add_signal(bm, lens, x, y, rng): """Aussie traffic signal: pole, lantern head, mast arm with a second head. Lenses go in their own bmesh so they can be emissive.""" + z0 = H(x, y) h = 3.9 - cone(bm, (x, y, h / 2), 0.10, 0.08, h, 6) + cone(bm, (x, y, z0 + h / 2), 0.10, 0.08, h, 6) a = rng.random() * math.tau d = Vector((math.cos(a), math.sin(a), 0)) p = Vector((-d.y, d.x, 0)) - for at, top in ((Vector((x, y, 0)) + p * 0.22, h - 0.15), - (Vector((x, y, 0)) + d * 3.6, h + 0.55)): + for at, top in ((Vector((x, y, z0)) + p * 0.22, z0 + h - 0.15), + (Vector((x, y, z0)) + d * 3.6, z0 + h + 0.55)): # lantern housing + three stacked lenses beam(bm, at + Vector((0, 0, top - 1.0)), at + Vector((0, 0, top)), 0.34, 0.34) for i, m in enumerate((0, 1, 2)): c = at + Vector((0, 0, top - 0.22 - i * 0.32)) # must clear beam()'s 0.05 m minimum length or the lens silently vanishes beam(lens, c + d * 0.15, c + d * 0.28, 0.20, 0.20, m) - beam(bm, Vector((x, y, h + 0.4)), Vector((x, y, h + 0.4)) + d * 3.6, 0.13, 0.13) # mast arm + beam(bm, Vector((x, y, z0 + h + 0.4)), Vector((x, y, z0 + h + 0.4)) + d * 3.6, 0.13, 0.13) # mast arm def add_power_pole(bm, wire_bm, x, y, prev, rng): """Timber power pole with a crossarm; wires sag to the previous pole.""" + z0 = H(x, y) h = 8.6 - cone(bm, (x, y, h / 2), 0.19, 0.13, h, 6) - beam(bm, (x - 0.95, y, h - 0.5), (x + 0.95, y, h - 0.5), 0.11, 0.11) - tops = [Vector((x - 0.8, y, h - 0.38)), Vector((x, y, h - 0.05)), Vector((x + 0.8, y, h - 0.38))] + cone(bm, (x, y, z0 + h / 2), 0.19, 0.13, h, 6) + beam(bm, (x - 0.95, y, z0 + h - 0.5), (x + 0.95, y, z0 + h - 0.5), 0.11, 0.11) + tops = [Vector((x - 0.8, y, z0 + h - 0.38)), Vector((x, y, z0 + h - 0.05)), Vector((x + 0.8, y, z0 + h - 0.38))] if prev is not None: for a, b in zip(prev, tops): mid = (a + b) / 2 - Vector((0, 0, (a - b).length * 0.045)) # catenary sag @@ -335,7 +407,7 @@ def add_shelter(bm, glassbm, x, y, rng): a = rng.random() * math.tau d = Vector((math.cos(a), math.sin(a), 0)) p = Vector((-d.y, d.x, 0)) - c = Vector((x, y, 0)) + c = Vector((x, y, H(x, y))) for sd in (-1.8, 1.8): for sp in (-1.1, 1.1): f = c + d * sd + p * sp @@ -460,23 +532,27 @@ for e in d["elements"]: bm = bmesh.new() gf = 0.0 if qld else min(GROUND_FLOOR, h * 0.45) + # rigid terrain lift: base at the LOWEST terrain under the footprint so + # the uphill side cuts into the slope; walls run 2 m below base so no + # daylight shows under the downhill edge + bz = min(H(x, y) for x, y in ring) for i in range(len(ring)): (x1, y1), (x2, y2) = ring[i], ring[(i + 1) % len(ring)] if gf > 0.0: - quad(bm, [(x1, y1, 0), (x2, y2, 0), (x2, y2, gf), (x1, y1, gf)], 2) - quad(bm, [(x1, y1, gf), (x2, y2, gf), (x2, y2, h), (x1, y1, h)], 0) + quad(bm, [(x1, y1, bz - 2.0), (x2, y2, bz - 2.0), (x2, y2, bz + gf), (x1, y1, bz + gf)], 2) + quad(bm, [(x1, y1, bz + gf), (x2, y2, bz + gf), (x2, y2, bz + h), (x1, y1, bz + h)], 0) try: - bm.faces.new([bm.verts.new((x, y, h)) for x, y in ring]).material_index = 1 + bm.faces.new([bm.verts.new((x, y, bz + h)) for x, y in ring]).material_index = 1 except ValueError: pass if not qld: for i in range(len(ring)): # parapet caps the roof edge (x1, y1), (x2, y2) = ring[i], ring[(i + 1) % len(ring)] - beam(bm, (x1, y1, h + 0.45), (x2, y2, h + 0.45), 0.35, 0.9, 0) + beam(bm, (x1, y1, bz + h + 0.45), (x2, y2, bz + h + 0.45), 0.35, 0.9, 0) if h > 26: # rooftop plant room cx = sum(p[0] for p in ring) / len(ring) cy = sum(p[1] for p in ring) / len(ring) - beam(bm, (cx - 2.5, cy, h + 1.4), (cx + 2.5, cy, h + 1.4), 4.0, 2.8, 1) + beam(bm, (cx - 2.5, cy, bz + h + 1.4), (cx + 2.5, cy, bz + h + 1.4), 4.0, 2.8, 1) bmesh.ops.triangulate(bm, faces=bm.faces) add_obj("bld_%d-col" % e["id"], bm, [fac, M_CORRO if qld else M_ROOF, M_SHOP], {0: 13.0 if not qld else 6.5, 1: 9.0 if not qld else 3.0, 2: 4.6}) @@ -492,16 +568,16 @@ for e in d["elements"]: mx, my = (ex1 + ex2) / 2, (ey1 + ey2) / 2 ux, uy = (ex2 - ex1) / eL, (ey2 - ey1) / eL half = min(4.0, eL * 0.35) - a = Vector((mx - ux * half, my - uy * half, h + 2.6)) - b = Vector((mx + ux * half, my + uy * half, h + 2.6)) + a = Vector((mx - ux * half, my - uy * half, bz + h + 2.6)) + b = Vector((mx + ux * half, my + uy * half, bz + h + 2.6)) bb = bill_bm[e["id"] % 3] beam(bb, a, b, 0.25, 3.0) - beam(bb, Vector((mx, my, h)), Vector((mx, my, h + 1.4)), 0.3, 0.3) + beam(bb, Vector((mx, my, bz + h)), Vector((mx, my, bz + h + 1.4)), 0.3, 0.3) # street awning over the footpath -- not every shop has one, and a whole # street at one height in one colour reads as a painted stripe if not qld and 6.0 < h < 45.0 and rng.random() < 0.7: - az = AWNING_Z + rng.uniform(-0.35, 0.5) + az = bz + AWNING_Z + rng.uniform(-0.35, 0.5) amat = e["id"] % 3 out = AWNING_OUT * rng.uniform(0.85, 1.1) for i in range(len(ring)): @@ -522,7 +598,7 @@ for e in d["elements"]: if not closed: continue try: - bm = poly_bm(pts, -0.35) + bm = poly_bm(pts, WATER_Z) except Exception: continue # ponytail: water is solid (-col) so cars skim it instead of falling forever @@ -534,11 +610,12 @@ for e in d["elements"]: continue ring = ring_ccw(pts) bm = bmesh.new() + pz = min(H(x, y) for x, y in ring) for i in range(len(ring)): # raised corten planter box (x1, y1), (x2, y2) = ring[i], ring[(i + 1) % len(ring)] - quad(bm, [(x1, y1, 0), (x2, y2, 0), (x2, y2, 0.5), (x1, y1, 0.5)], 0) + quad(bm, [(x1, y1, pz), (x2, y2, pz), (x2, y2, pz + 0.5), (x1, y1, pz + 0.5)], 0) try: - bm.faces.new([bm.verts.new((x, y, 0.5)) for x, y in ring]).material_index = 1 + bm.faces.new([bm.verts.new((x, y, pz + 0.5)) for x, y in ring]).material_index = 1 except ValueError: bm.free() continue @@ -551,7 +628,7 @@ for e in d["elements"]: if not closed: continue try: - bm = poly_bm(pts, 0.02) + bm = poly_bm(pts, 0.02, drape=True) except Exception: continue add_obj("park_%d" % e["id"], bm, [M_GRASS], 14.0) @@ -579,8 +656,8 @@ for e in d["elements"]: elif tags.get("natural") == "cliff": bm = bmesh.new() for i in range(len(pts) - 1): - beam(bm, Vector((pts[i][0], pts[i][1], 7.0)), - Vector((pts[i + 1][0], pts[i + 1][1], 7.0)), 2.0, 14.0) + beam(bm, Vector((pts[i][0], pts[i][1], H(*pts[i]) + 1.0)), + Vector((pts[i + 1][0], pts[i + 1][1], H(*pts[i + 1]) + 1.0)), 2.0, 14.0) add_obj("cliff_%d-col" % e["id"], bm, [M_ROCK], 12.0) counts["cliff"] += 1 @@ -608,7 +685,10 @@ for e in d["elements"]: wide = ROAD_W.get(hw, 6.0) rkey = "mall" if hw == "pedestrian" else ("bus" if hw == "busway" else "road") - ribbon(road_bm[rkey], pts, wide / 2, 0.03) + deck = None + if tags.get("bridge") in ("yes", "viaduct") or (bridge_name and tags.get("name") == bridge_name): + deck = bridge_profile(pts, named=(tags.get("name") == bridge_name)) + ribbon(road_bm[rkey], pts, wide / 2, 0.03, zs=deck) counts["road"] += 1 if hw in ("residential", "unclassified"): # timber power poles down one side with sagging wires -- the single @@ -661,8 +741,12 @@ for e in d["elements"]: L = math.hypot(x2 - x1, y2 - y1) for k in range(int(L / 9.0)): t0, t1 = (k * 9.0 + 1.5) / L, (k * 9.0 + 5.0) / L + dz = None + if deck is not None: + dz = [deck[i] + (deck[i + 1] - deck[i]) * t0, + deck[i] + (deck[i + 1] - deck[i]) * t1] ribbon(line_bm, [(x1 + (x2 - x1) * t0, y1 + (y2 - y1) * t0), - (x1 + (x2 - x1) * t1, y1 + (y2 - y1) * t1)], 0.09, 0.045) + (x1 + (x2 - x1) * t1, y1 + (y2 - y1) * t1)], 0.09, 0.045, zs=dz) # street trees: OSM maps a fraction of what Brisbane actually has, so line the # kerbs of named streets and the mall edges with our own, deterministically @@ -696,9 +780,9 @@ for tx, ty, seed in tree_sites: add_tree(fol_bm, jac_bm, frond_bm, trunk_bm, tx, ty, random.Random(seed)) counts["tree"] += 1 -add_obj("roads", road_bm["road"], [M_ROAD], 8.0) -add_obj("mall_paving", road_bm["mall"], [M_MALL], 4.0) -add_obj("busway", road_bm["bus"], [M_BUSRED], 8.0) +add_obj("roads-col", road_bm["road"], [M_ROAD], 8.0) +add_obj("mall_paving-col", road_bm["mall"], [M_MALL], 4.0) +add_obj("busway-col", road_bm["bus"], [M_BUSRED], 8.0) add_obj("trees_foliage", fol_bm, [M_FOLIAGE], 0.9, smooth=True) add_obj("trees_jacaranda", jac_bm, [M_JAC], 0.9, smooth=True) add_obj("trees_fronds", frond_bm, [M_FOLIAGE], 0.9) @@ -736,13 +820,22 @@ if bridge_name: s0, s1 = 0.175 * T, 0.825 * T N = 26 bm = bmesh.new() + deck_zs = bridge_profile([(pp.x, pp.y) for pp in pts], named=True) + def deck_at(sd): + for i2 in range(1, len(dists)): + if dists[i2] >= sd: + f2 = (sd - dists[i2 - 1]) / max(dists[i2] - dists[i2 - 1], 0.001) + return deck_zs[i2 - 1] + (deck_zs[i2] - deck_zs[i2 - 1]) * f2 + return deck_zs[-1] samples = [] for i in range(N + 1): t = i / N - p = at(s0 + (s1 - s0) * t) + sd = s0 + (s1 - s0) * t + p = at(sd) + p = Vector((p.x, p.y, deck_at(sd))) # truss base rides the deck h = 4.0 + 16.0 * (math.exp(-((t - 0.32) / 0.10) ** 2) + math.exp(-((t - 0.68) / 0.10) ** 2)) \ + 6.0 * math.sin(math.pi * t) - fwd = (at(min(s0 + (s1 - s0) * t + 4, T)) - p) + fwd = (at(min(sd + 4, T)) - p) fwd.z = 0 fwd.normalize() samples.append((p, Vector((-fwd.y, fwd.x, 0)), h)) @@ -859,15 +952,54 @@ if level_id == "southbank": bpy.context.collection.objects.link(obj_a) print("grand arbour tendrils: %d" % n_t) -# ground slab sized to content (convex collider: huge trimesh tris break raycasts) +# ground: a terrain grid sampled from the DEM (or a flat slab when there is +# none). Small triangles are deliberate -- one huge trimesh tri breaks raycasts. xs = [v.co.x for o in bpy.data.objects if o.type == "MESH" for v in o.data.vertices] ys = [v.co.y for o in bpy.data.objects if o.type == "MESH" for v in o.data.vertices] -gx, gy = (min(xs) + max(xs)) / 2, (min(ys) + max(ys)) / 2 -bm = bmesh.new() -res = bmesh.ops.create_cube(bm, size=1.0) -bmesh.ops.scale(bm, vec=(max(xs) - min(xs) + 100, max(ys) - min(ys) + 100, 1.0), verts=res["verts"]) -bmesh.ops.translate(bm, vec=(gx, gy, -0.5), verts=res["verts"]) -add_obj("ground-convcol", bm, [M_GROUND], 18.0) +x0g, x1g = min(xs) - 50, max(xs) + 50 +y0g, y1g = min(ys) - 50, max(ys) + 50 +if DEM is not None: + STEP = 9.0 + nx = max(int((x1g - x0g) / STEP), 2) + ny = max(int((y1g - y0g) / STEP), 2) + sx = (x1g - x0g) / nx + sy = (y1g - y0g) / ny + carve = _np.full((ny + 1, nx + 1), _np.inf, dtype=_np.float64) + for cx, cy, ch in CARVE: + gi = int(round((cx - x0g) / sx)) + gj = int(round((cy - y0g) / sy)) + if 0 <= gi <= nx and 0 <= gj <= ny: + carve[gj, gi] = min(carve[gj, gi], ch) + # dilate one cell so the clamp covers the whole face a road crosses + dil = carve.copy() + for dj in (-1, 0, 1): + for di in (-1, 0, 1): + dil = _np.minimum(dil, _np.roll(_np.roll(carve, dj, axis=0), di, axis=1)) + bm = bmesh.new() + grid = [] + for j in range(ny + 1): + row = [] + for i in range(nx + 1): + gx2 = x0g + i * sx + gy2 = y0g + j * sy + gz = H(gx2, gy2) - 0.04 + if dil[j, i] != _np.inf: + gz = min(gz, dil[j, i] - 0.22) + row.append(bm.verts.new((gx2, gy2, gz))) + grid.append(row) + for j in range(ny): + for i in range(nx): + bm.faces.new((grid[j][i], grid[j][i + 1], grid[j + 1][i + 1], grid[j + 1][i])) + bmesh.ops.triangulate(bm, faces=bm.faces) + add_obj("terrain-col", bm, [M_GROUND], 18.0) + print("terrain grid %dx%d (%d carve samples)" % (nx, ny, len(CARVE))) +else: + gx, gy = (x0g + x1g) / 2, (y0g + y1g) / 2 + bm = bmesh.new() + res = bmesh.ops.create_cube(bm, size=1.0) + bmesh.ops.scale(bm, vec=(x1g - x0g, y1g - y0g, 1.0), verts=res["verts"]) + bmesh.ops.translate(bm, vec=(gx, gy, -0.5), verts=res["verts"]) + add_obj("ground-convcol", bm, [M_GROUND], 18.0) # parked-car / wheelie-bin markers -> empties; game.gd fills them with # shuntable RigidBodies at load (a static GLB can't carry physics bodies) @@ -877,7 +1009,7 @@ batches = [("PP", pp_spots, PP_CAP)] + [(k, v, SMASH_CAP[k]) for k, v in smash_s for prefix, spots, cap in batches: for i, (mx, my, yaw) in enumerate(spots[:cap]): emp = bpy.data.objects.new("%s_%03d" % (prefix, i), None) - emp.location = (mx, my, 0.05) + emp.location = (mx, my, H(mx, my) + 0.05) emp.rotation_euler = (0, 0, yaw) bpy.context.collection.objects.link(emp) counts[prefix.lower()] = min(len(spots), cap) @@ -911,7 +1043,7 @@ if best_run and best_run[0] >= 150.0: yaw = math.atan2(p1[1] - p0[1], p1[0] - p0[0]) for nm, p in (("DragStart", p0), ("DragEnd", p1)): emp = bpy.data.objects.new(nm, None) - emp.location = (p[0], p[1], 0.1) + emp.location = (p[0], p[1], H(p[0], p[1]) + 0.1) emp.rotation_euler = (0, 0, yaw) bpy.context.collection.objects.link(emp) counts["drag_m"] = int(run) @@ -920,7 +1052,7 @@ if spawn_arg: slat, slon, sbear = [float(v) for v in spawn_arg.split(",")] sx, sy = xy(slat, slon) sp = bpy.data.objects.new("Spawn", None) - sp.location = (sx, sy, 0.1) + sp.location = (sx, sy, H(sx, sy) + 0.1) sp.rotation_euler = (0, 0, math.radians(-sbear)) bpy.context.collection.objects.link(sp) @@ -931,7 +1063,7 @@ if rp_arg: plat, plon = [float(v) for v in pair.split(",")] px, py = xy(plat, plon) emp = bpy.data.objects.new("RP_%02d" % i, None) - emp.location = (px, py, 0.1) + emp.location = (px, py, H(px, py) + 0.1) bpy.context.collection.objects.link(emp) emp.parent = rp diff --git a/tools/fetch_dem.py b/tools/fetch_dem.py new file mode 100644 index 0000000..096e2b7 --- /dev/null +++ b/tools/fetch_dem.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +"""Fetch real elevation for a level's OSM area from the AWS terrain tiles. + +Usage: fetch_dem.py + +Reads the area's bounding box straight from its OSM geometry (the original +fetch bboxes were never recorded -- same trap as the junction specs), grabs +the covering terrarium tiles at z15 (~4.2 m/px at Brisbane's latitude), and +writes: + _dem.f32 row-major float32 heights in metres (little-endian) + _dem.json {"w", "h", "min_lat", "min_lon", "max_lat", "max_lon"} + +Terrarium encoding: height = R*256 + G + B/256 - 32768. +Tiles: https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png +(open data, no key). Data (c) Mapzen/AWS Terrain Tiles contributors. +""" +import io +import json +import math +import struct +import sys +import urllib.request + +from PIL import Image + +Z = 15 +URL = "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/%d/%d/%d.png" + + +def tile_of(lat, lon, z): + n = 2 ** z + xt = (lon + 180.0) / 360.0 * n + lat_r = math.radians(lat) + yt = (1.0 - math.asinh(math.tan(lat_r)) / math.pi) / 2.0 * n + return xt, yt + + +def tile_bounds(xt, yt, z): + n = 2 ** z + lon0 = xt / n * 360.0 - 180.0 + lat0 = math.degrees(math.atan(math.sinh(math.pi * (1 - 2 * yt / n)))) + return lat0, lon0 + + +def main(): + src, prefix = sys.argv[1], sys.argv[2] + d = json.load(open(src)) + lats, lons = [], [] + for e in d["elements"]: + for g in e.get("geometry") or []: + lats.append(g["lat"]) + lons.append(g["lon"]) + if e.get("type") == "node" and "lat" in e: + lats.append(e["lat"]) + lons.append(e["lon"]) + lo_lat, hi_lat = min(lats), max(lats) + lo_lon, hi_lon = min(lons), max(lons) + + x0, y1 = tile_of(lo_lat, lo_lon, Z) # south-west -> larger y tile index + x1, y0 = tile_of(hi_lat, hi_lon, Z) + tx0, tx1 = int(x0), int(x1) + ty0, ty1 = int(y0), int(y1) + cols = tx1 - tx0 + 1 + rows = ty1 - ty0 + 1 + print("bbox lat %.4f..%.4f lon %.4f..%.4f -> %dx%d tiles @z%d" + % (lo_lat, hi_lat, lo_lon, hi_lon, cols, rows, Z)) + + mosaic = Image.new("RGB", (cols * 256, rows * 256)) + for ty in range(ty0, ty1 + 1): + for tx in range(tx0, tx1 + 1): + req = urllib.request.Request(URL % (Z, tx, ty), + headers={"User-Agent": "BurnoutShitbox/1.0"}) + png = urllib.request.urlopen(req, timeout=60).read() + mosaic.paste(Image.open(io.BytesIO(png)), ((tx - tx0) * 256, (ty - ty0) * 256)) + + # mosaic geographic bounds (tile edges, not the request bbox) + m_hi_lat, m_lo_lon = tile_bounds(tx0, ty0, Z) + m_lo_lat, m_hi_lon = tile_bounds(tx1 + 1, ty1 + 1, Z) + + w, h = mosaic.size + px = mosaic.load() + out = open(prefix + "_dem.f32", "wb") + lo, hi = 1e9, -1e9 + for yy in range(h): + row = bytearray() + for xx in range(w): + r, g, b = px[xx, yy] + hm = r * 256 + g + b / 256.0 - 32768.0 + hm = max(hm, 0.0) # clamp bathymetry: the river reads as 0, not -8 + lo, hi = min(lo, hm), max(hi, hm) + row += struct.pack("