@@ -12,6 +12,7 @@ import androidx.compose.ui.graphics.drawscope.rotate
1212import androidx.compose.ui.graphics.lerp
1313import androidx.compose.ui.text.TextLayoutResult
1414import androidx.compose.ui.text.drawText
15+ import nz.aryan.akllive.data.Weather
1516import kotlin.math.PI
1617import kotlin.math.cos
1718import kotlin.math.sin
@@ -28,6 +29,7 @@ class Scenery(val city: Boolean, seed: Int) {
2829 val trees = ArrayList <Tree >()
2930 val stars: List <Triple <Float , Float , Float >>
3031 val clouds: List <FloatArray > // offset, y, scale, speed
32+ val drops: List <FloatArray > // x, phase, speed
3133
3234 init {
3335 val r = Random (seed * 7919 + 17 )
@@ -63,6 +65,7 @@ class Scenery(val city: Boolean, seed: Int) {
6365 }
6466 }
6567 }
68+ drops = List (120 ) { floatArrayOf(r.nextFloat(), r.nextFloat(), r.nextFloat()) }
6669 }
6770}
6871
@@ -108,13 +111,21 @@ private val Lit = Color(0xFFFFD98A)
108111 */
109112fun DrawScope.drawBusScene (
110113 s : Scenery , hour : Float , t : Float , progress : Float? , moving : Boolean ,
111- cancelled : Boolean , dest : TextLayoutResult ? , dp : Float , look : BusLook = BusLook (),
114+ cancelled : Boolean , dest : TextLayoutResult ? , dp : Float , look : BusLook = BusLook (), wx : Weather ? = null,
112115) {
113116 val w = size.width
114117 val h = size.height
115118 val ground = h * 0.74f
116- val sky = skyAt(hour)
117119 val night = isNight(hour)
120+ // the real weather: cloud cover greys the sky, rain darkens it further
121+ val cover = (wx?.cloudCover ? : 30 ) / 100f
122+ val rain = wx?.rain ? : 0
123+ val gloom = (((cover - 0.5f ) / 0.5f ).coerceIn(0f , 1f ) * 0.5f + rain * 0.08f ).coerceAtMost(0.7f )
124+ val grey = if (night) Color (0xFF141922 ) else Color (0xFF8C95A5 )
125+ val clear = skyAt(hour)
126+ val sky = Sky (lerp(clear.top, grey, gloom), lerp(clear.bottom, lerp(grey, Color .White , 0.25f ), gloom),
127+ lerp(clear.hills, grey, gloom * 0.5f ), lerp(clear.near, grey, gloom * 0.4f ))
128+ val sunShow = (1f - gloom * 1.7f ).coerceIn(0f , 1f )
118129
119130 // sky
120131 drawRect(Brush .verticalGradient(listOf (sky.top, sky.bottom), 0f , ground), size = Size (w, ground))
@@ -126,31 +137,37 @@ fun DrawScope.drawBusScene(
126137 val sy = ground - sin(p * PI ).toFloat() * ground * 0.78f
127138 val low = 1f - sin(p * PI ).toFloat()
128139 val sun = lerp(Color (0xFFFFF4D6 ), Color (0xFFFFB066 ), low)
129- drawCircle(Brush .radialGradient(listOf (sun.copy(alpha = 0.55f ), Color .Transparent ),
140+ drawCircle(Brush .radialGradient(listOf (sun.copy(alpha = 0.55f * sunShow ), Color .Transparent ),
130141 Offset (sx, sy), 46 * dp), 46 * dp, Offset (sx, sy))
131- drawCircle(sun, 13 * dp, Offset (sx, sy))
142+ drawCircle(sun.copy(alpha = sunShow) , 13 * dp, Offset (sx, sy))
132143 }
133- if (night) {
144+ if (night && sunShow > 0f ) {
134145 s.stars.forEachIndexed { i, (x, y, ph) ->
135- val a = 0.45f + 0.45f * sin(t * (0.8f + (i % 5 ) * 0.3f ) + ph)
146+ val a = ( 0.45f + 0.45f * sin(t * (0.8f + (i % 5 ) * 0.3f ) + ph)) * ( 1f - cover).coerceIn( 0f , 1f )
136147 drawCircle(Color .White .copy(alpha = a), (if (i % 7 == 0 ) 1.4f else 0.9f ) * dp,
137148 Offset (x * w, y * ground))
138149 }
139150 val mc = Offset (w * 0.82f , h * 0.2f )
140- drawCircle(Brush .radialGradient(listOf (Color (0x55FFF3D0 ), Color .Transparent ), mc, 30 * dp), 30 * dp, mc)
141- drawCircle(Color (0xFFFBF3DA ), 10 * dp, mc)
151+ drawCircle(Brush .radialGradient(listOf (Color (0x55FFF3D0 ).copy(alpha = 0.33f * sunShow), Color .Transparent ),
152+ mc, 30 * dp), 30 * dp, mc)
153+ drawCircle(Color (0xFFFBF3DA ).copy(alpha = sunShow), 10 * dp, mc)
142154 drawCircle(sky.top, 9 * dp, mc + Offset (4.5f * dp, - 2.5f * dp)) // crescent
143155 }
144156
145- // clouds drift by (daytime and dusk)
146- if (! night) {
147- val alpha = if (hour < 7.5f || hour > 18f ) 0.7f else 0.92f
148- for (c in s.clouds) {
157+ // clouds drift by: as many as the real cover, grey when it's raining, dark at night
158+ val clouds = if (wx == null ) (if (night) 0 else 5 ) else Math .round(cover * 5.4f ).coerceIn(0 , 5 )
159+ val cloudCol = when {
160+ night -> Color (0xFF2A3246 ).copy(alpha = 0.85f )
161+ rain > 0 || gloom > 0.3f -> lerp(Color .White , Color (0xFF8E98A8 ), 0.35f + gloom * 0.5f ).copy(alpha = 0.95f )
162+ else -> Color .White .copy(alpha = if (hour < 7.5f || hour > 18f ) 0.7f else 0.92f )
163+ }
164+ run {
165+ for (c in s.clouds.take(clouds)) {
149166 val span = w + 160 * dp
150167 val cx = ((c[0 ] * span + t * c[3 ] * dp) % span) - 80 * dp
151168 val cy = c[1 ] * ground
152- val k = c[2 ] * dp
153- val col = Color . White .copy(alpha = alpha)
169+ val k = c[2 ] * dp * ( 1f + gloom * 0.6f )
170+ val col = cloudCol
154171 drawCircle(col, 11 * k, Offset (cx, cy + 3 * k))
155172 drawCircle(col, 15 * k, Offset (cx + 14 * k, cy - 2 * k))
156173 drawCircle(col, 11 * k, Offset (cx + 30 * k, cy + 3 * k))
@@ -176,6 +193,12 @@ fun DrawScope.drawBusScene(
176193
177194 if (s.city) drawCity(s, sky, night, t, w, h, ground, dp) else drawSuburb(s, sky, night, w, h, ground, dp)
178195
196+ if (wx?.foggy == true ) {
197+ drawRect(Brush .verticalGradient(listOf (Color .White .copy(alpha = if (night) 0.08f else 0.2f ),
198+ Color .White .copy(alpha = if (night) 0.22f else 0.5f )), 0f , ground),
199+ size = Size (w, ground))
200+ }
201+
179202 // road
180203 val road = if (night) Color (0xFF22262F ) else Color (0xFF3B414D )
181204 drawRect(Color (0xFF8A919C ).copy(alpha = if (night) 0.5f else 1f ), Offset (0f , ground), Size (w, 3 * dp))
@@ -202,6 +225,23 @@ fun DrawScope.drawBusScene(
202225 val bx = x0 + (x1 - x0) * progress.coerceIn(0f , 1f )
203226 drawBus(bx, ground + 2 * dp + (h - ground) * 0.12f , bl, bh, t, night, moving, cancelled, dest, dp, look)
204227 }
228+
229+ // rain, falling on a slant
230+ if (rain > 0 ) {
231+ val n = intArrayOf(0 , 40 , 80 , 120 )[rain]
232+ val len = (if (rain == 1 ) 6f else 11f ) * dp
233+ val col = Color (0xFFD6E6FF ).copy(alpha = if (rain == 1 ) 0.35f else 0.5f )
234+ for (i in 0 until n) {
235+ val d = s.drops[i]
236+ val y = ((d[1 ] + t * (1.1f + d[2 ] * 0.8f )) % 1f ) * (h + len) - len
237+ val x = d[0 ] * (w + 30 * dp) - y * 0.2f
238+ drawLine(col, Offset (x, y), Offset (x - len * 0.2f , y + len), strokeWidth = 1.1f * dp, cap = StrokeCap .Round )
239+ }
240+ }
241+ if (wx?.thunder == true ) {
242+ val ph = t % 9f
243+ if (ph < 0.1f || ph in 0.22f .. 0.3f ) drawRect(Color .White .copy(alpha = 0.35f ))
244+ }
205245}
206246
207247/* * Rangitoto's low, even shield, with its summit bump, as seen from the city. */
0 commit comments