# 导入必要的模块
# machine: 用于ESP32的硬件控制,如引脚和ADC
# time: 时间相关函数
# random: 随机数生成
# ssd1306: OLED显示屏驱动
from machine import Pin, ADC, SoftI2C
from time import sleep
from random import randint
from ssd1306 import SSD1306_I2C
# 定义引脚号
# SCL和SDA用于I2C通信
# joy_x_Pin和joy_y_Pin用于摇杆的X和Y轴ADC输入
scl_Pin = 22
sda_Pin = 21
joy_x_Pin = 32
joy_y_Pin = 33
sw_Pin = 25
res_sw = Pin(sw_Pin,Pin.IN)
# 初始化I2C总线
i2c = SoftI2C(scl=scl_Pin, sda=sda_Pin)
# 初始化OLED显示屏,128x64像素
oled = SSD1306_I2C(128, 64, i2c)
# 初始化摇杆的ADC输入
joy_x = ADC(Pin(joy_x_Pin))
joy_x.atten(ADC.ATTN_11DB) # 设置衰减以扩展输入范围
joy_y = ADC(Pin(joy_y_Pin))
joy_y.atten(ADC.ATTN_11DB)
def game_init():
global food_x, food_y, snake, dir_x, dir_y, step, game_over
# 随机生成食物的位置
food_x = randint(0, 120)
food_y = randint(0, 60)
# 蛇的身体列表,每个元素是[x, y]坐标
snake = [[60, 30], [55, 30], [50, 30]]
# 蛇的移动方向
dir_x = 6 # X方向速度
dir_y = 0 # Y方向速度
step = 6 # 每次移动的步长
game_over = False
game_init()
last_btn = 1
# 主游戏循环
while True:
# 清空OLED显示屏
oled.fill(0)
print("res_sw_val:",res_sw.value())
# —————— 稳定按键检测:按下只触发一次 ——————
btn_val = res_sw.value()
# 只有 上一次松开 + 这次按下 才重启
if btn_val == 0 and last_btn == 1:
game_init()
sleep(0.1)
last_btn = btn_val # 记录上一次状态
print("last_btn:",last_btn)
# —————— 如果游戏结束,显示提示 ——————
if game_over:
oled.text("GAME OVER", 25, 20)
oled.text("Press button", 10, 40)
oled.text("to restart", 20, 50)
oled.show()
continue # 跳过后面的游戏逻辑
# 读取摇杆的X和Y轴值
joy_x_value = joy_x.read()
joy_y_value = joy_y.read()
# 根据摇杆值改变蛇的移动方向
if joy_x_value > 3000: # 摇杆向左
dir_x = -step
dir_y = 0
if joy_x_value < 1000: # 摇杆向右
dir_x = step
dir_y = 0
if joy_y_value > 3000: # 摇杆向上
dir_y = -step
dir_x = 0
if joy_y_value < 1000: # 摇杆向下
dir_y = step
dir_x = 0
# 计算蛇头的新位置
heda_x = snake[0][0] + dir_x
heda_y = snake[0][1] + dir_y
new_head = [heda_x, heda_y]
# 将新头部添加到蛇的身体前面
snake.insert(0, new_head)
# —————— 【新增】撞墙检测 ——————
if heda_x < 0 or heda_x > 125 or heda_y < 0 or heda_y > 60:
game_over = True # 撞墙 → 游戏结束
# 在OLED上绘制食物(用*表示)
oled.text("*", food_x, food_y)
# 绘制蛇的身体(用o表示)
for snake_x, snake_y in snake:
oled.text("o", snake_x, snake_y)
# 更新显示
oled.show()
# 检查蛇头是否吃到食物
if abs(heda_x - food_x) < 3 and abs(heda_y - food_y) < 3:
# 吃到食物,生成新食物位置
food_x = randint(0, 120)
food_y = randint(0, 60)
else:
# 没有吃到食物,移除蛇尾
snake.pop()
sleep(0.3)