<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[uflow作品：流体模拟]]></title><description><![CDATA[<pre><code></code></pre>
<p dir="auto">import M5<br />
import time<br />
import random<br />
import gc</p>
<h1>================= 硬件与内存锁定 =================</h1>
<p dir="auto">M5.begin()<br />
lcd = M5.Lcd<br />
imu = M5.Imu<br />
gc.collect()<br />
gc.threshold(1024)</p>
<p dir="auto">try:<br />
lcd.setBrightness(255)<br />
except: pass</p>
<p dir="auto">WIDTH = lcd.width()   # 240<br />
HEIGHT = lcd.height() # 135</p>
<p dir="auto">SCALE = 5<br />
W = WIDTH // SCALE    # 48<br />
H = HEIGHT // SCALE   # 27<br />
TOTAL = W * H         # 1296</p>
<p dir="auto">grid = bytearray(TOTAL)  # bit0=流体, bit7=本帧已移动锁</p>
<p dir="auto">OFFSETS = (-1, 1, -W, W, -W-1, -W+1, W-1, W+1)</p>
<p dir="auto">COLOR_BG = 0x0000<br />
COLOR_FLUID = 0xFFE0     # 💡 已修改为黄色 (RGB565)<br />
COLOR_PAUSE = 0xF800</p>
<p dir="auto">VISCOSITY_THRESHOLD = 3<br />
SIDE_SLIP_PROB = 70      # 侧滑概率 (0-100)，控制安息角<br />
GRAV_DX, GRAV_DY = 0, 1</p>
<p dir="auto">idle_frames = 0<br />
MAX_IDLE_FRAMES = 5<br />
is_paused = False<br />
last_space_state = False<br />
frame_counter = 0        # 用于每帧改变随机种子</p>
<p dir="auto">def draw_cell(x, y, color):<br />
lcd.fillRect(x * SCALE, y * SCALE, SCALE, SCALE, color)</p>
<p dir="auto">def update_gravity():<br />
global GRAV_DX, GRAV_DY<br />
try:<br />
acc = imu.getAccel()<br />
gyro = imu.getGyro()<br />
ax, ay = int(-acc[0] * 10), int(acc[1] * 10)<br />
gz = int(gyro[2])<br />
if abs(ax) &lt; 2: ax = 0<br />
if abs(ay) &lt; 2: ay = 0<br />
if abs(ay) &gt;= abs(ax):<br />
GRAV_DX, GRAV_DY = 0, (1 if ay &gt; 0 else -1)<br />
else:<br />
GRAV_DX, GRAV_DY = (1 if ax &gt; 0 else -1), 0<br />
if abs(gz) &gt; 15:<br />
if GRAV_DY != 0: GRAV_DX = 1 if gz &gt; 0 else -1<br />
else: GRAV_DY = 1 if gz &gt; 0 else -1<br />
except: pass</p>
<p dir="auto">def check_keyboard():<br />
global is_paused, last_space_state, idle_frames<br />
current_space = False<br />
try:<br />
keys = M5.Keyboard.getKeys()<br />
for k in keys:<br />
if k == 32 or (isinstance(k, dict) and k.get('key') == 32):<br />
current_space = True; break<br />
except:<br />
try: current_space = M5.BtnA.isPressed()<br />
except: pass<br />
if current_space and not last_space_state:<br />
is_paused = not is_paused<br />
idle_frames = 0<br />
last_space_state = current_space</p>
<h1>================= 自然堆积求解器 =================</h1>
<p dir="auto">def solve_fluid():<br />
global frame_counter<br />
has_movement = False<br />
frame_counter += 1</p>
<pre><code># 奇偶帧交替扫描方向，打破逐行刷新伪影
if frame_counter &amp; 1:
    y_range = range(H-1, -1, -1)
else:
    y_range = range(H-2, -1, -2)

if GRAV_DX &gt; 0: x_range = range(W-1, -1, -1)
elif GRAV_DX &lt; 0: x_range = range(0, W, 1)
else: x_range = range(0, W, 1)

for y in y_range:
    row_off = y * W
    for x in x_range:
        idx = row_off + x
        val = grid[idx]
        if (val &amp; 0x01) == 0 or (val &amp; 0x80) != 0:
            continue
        
        moved = False
        nx, ny = x + GRAV_DX, y + GRAV_DY
        
        # 重力方向移动
        if 0 &lt;= nx &lt; W and 0 &lt;= ny &lt; H:
            t_idx = ny * W + nx
            if (grid[t_idx] &amp; 0x01) == 0:
                grid[idx] = 0
                grid[t_idx] = 0x81
                draw_cell(nx, ny, COLOR_FLUID)
                draw_cell(x, y, COLOR_BG)
                moved = True
                has_movement = True
        
        # 概率性粘性侧滑 → 形成三角形安息角
        if not moved:
            neighbor_count = 0
            for off in OFFSETS:
                n_idx = idx + off
                if 0 &lt;= n_idx &lt; TOTAL and (grid[n_idx] &amp; 0x01) == 1:
                    neighbor_count += 1
            
            if neighbor_count &gt;= VISCOSITY_THRESHOLD:
                if random.randint(0, 99) &lt; SIDE_SLIP_PROB:
                    if GRAV_DY != 0:
                        left_ok = (x &gt; 0 and (grid[idx-1] &amp; 0x01) == 0)
                        right_ok = (x &lt; W-1 and (grid[idx+1] &amp; 0x01) == 0)
                    else:
                        left_ok = (y &gt; 0 and (grid[idx-W] &amp; 0x01) == 0)
                        right_ok = (y &lt; H-1 and (grid[idx+W] &amp; 0x01) == 0)
                    
                    # 伪随机偏好替代确定性(x^y)&amp;1
                    prefer_left = ((x * 7 + y * 13 + frame_counter) &amp; 3) &lt; 2
                    
                    target = -1
                    if prefer_left and left_ok:
                        target = idx-1 if GRAV_DY != 0 else idx-W
                    elif right_ok:
                        target = idx+1 if GRAV_DY != 0 else idx+W
                    elif left_ok:
                        target = idx-1 if GRAV_DY != 0 else idx-W
                    
                    if target &gt;= 0:
                        grid[idx] = 0
                        grid[target] = 0x81
                        tx, ty = target % W, target // W
                        draw_cell(tx, ty, COLOR_FLUID)
                        draw_cell(x, y, COLOR_BG)
                        moved = True
                        has_movement = True

# 清除移动锁
for i in range(TOTAL):
    if grid[i] &amp; 0x80:
        grid[i] &amp;= 0x01

return has_movement
</code></pre>
<h1>================= 初始化 =================</h1>
<p dir="auto">lcd.clear(COLOR_BG)<br />
water_count = 0<br />
attempts = 0<br />
INIT_WATER = TOTAL // 3</p>
<p dir="auto">while water_count &lt; INIT_WATER and attempts &lt; INIT_WATER * 8:<br />
idx = random.randint(0, TOTAL - 1)<br />
attempts += 1<br />
if grid[idx] == 0:<br />
grid[idx] = 1<br />
water_count += 1<br />
draw_cell(idx % W, idx // W, COLOR_FLUID)</p>
<p dir="auto">lcd.show()<br />
print(f"[OK] Yellow fluid: {W}x{H}, slip_prob={SIDE_SLIP_PROB}%")</p>
<h1>================= 主循环 =================</h1>
<p dir="auto">while True:<br />
check_keyboard()<br />
if is_paused:<br />
draw_cell(0, 0, COLOR_PAUSE)<br />
lcd.show()<br />
time.sleep(0.05)<br />
continue</p>
<pre><code>update_gravity()
has_movement = solve_fluid()

if has_movement:
    lcd.show()
    idle_frames = 0
else:
    idle_frames += 1
    if idle_frames &gt; MAX_IDLE_FRAMES:
        time.sleep(0.1)
time.sleep(0.016)
</code></pre>
<pre><code></code></pre>
]]></description><link>https://community.m5stack.com/topic/8269/uflow作品-流体模拟</link><generator>RSS for Node</generator><lastBuildDate>Tue, 23 Jun 2026 00:26:14 GMT</lastBuildDate><atom:link href="https://community.m5stack.com/topic/8269.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 16 Jun 2026 14:34:22 GMT</pubDate><ttl>60</ttl></channel></rss>