Micropython学习交流群 学习QQ群:786510434 提供多种固件下载和学习交流。

Micropython-扇贝物联 QQ群:31324057 扇贝物联是一个让你与智能设备沟通更方便的物联网云平台

Micropython学习交流群 学习QQ群:468985481 学习交流ESP8266、ESP32、ESP8285、wifi模块开发交流、物联网。

Micropython老哥俩的IT农场分享QQ群:929132891 为喜欢科创制作的小白们分享一些自制的计算机软硬件免费公益课程,由两位多年从事IT研发的中年大叔发起。

Micropython ESP频道

micropython esp32 st7735 4个按压式开关实现 贪吃蛇游戏


B站视频:https://www.bilibili.com/video/BV1dS4y1t7Lu?spm_id_from=333.337.search-card.all.click

电路连接

pin13 -- 开关负级 (用来控制角色的上移)

pin12 -- 开关负级 (用来控制角色的下移)

pin14 -- 开关负级 (用来控制角色的左移)

pin27 -- 开关负级 (用来控制角色的右移)

pin18 -- 开关正级

3.3v -- 屏幕VCC

GND -- 屏幕DNG

pin15 -- 屏幕SCL

pin0 -- 屏幕SDA

pin4 -- 屏幕RES

pin16 -- 屏幕DC

pin17 -- 屏幕CS

pin5 -- 屏幕BLK

Snipaste_2022-08-02_00-59-24.jpg


文件

st7735.py 大佬写的 st7735驱动

from time import sleep_ms    
from ustruct import pack    
from machine import SPI,Pin    
from micropython import const    
import framebuf    
#   ST7735V registers definitions    
NOP     = const(0x00) # No Operation    
SWRESET = const(0x01) # Software reset    
SLPIN   = const(0x10) # Sleep in & booster off    
SLPOUT  = const(0x11) # Sleep out & booster on    
PTLON   = const(0x12) # Partial mode on    
NORON   = const(0x13) # Partial off (Normal)    
INVOFF  = const(0x20) # Display inversion off    
INVON   = const(0x21) # Display inversion on    
DISPOFF = const(0x28) # Display off    
DISPON  = const(0x29) # Display on    
CASET   = const(0x2A) # Column address set    
RASET   = const(0x2B) # Row address set    
RAMWR   = const(0x2C) # Memory write    
RGBSET  = const(0x2D) # Display LUT set    
PTLAR   = const(0x30) # Partial start/end address set    
COLMOD  = const(0x3A) # Interface pixel format    
MADCTL  = const(0x36) # Memory data access control    
# panel function commands    
FRMCTR1 = const(0xB1) # In normal mode (Full colors)    
FRMCTR2 = const(0xB2) # In Idle mode (8-colors)    
FRMCTR3 = const(0xB3) # In partial mode + Full colors    
INVCTR  = const(0xB4) # Display inversion control    
PWCTR1  = const(0xC0) # Power control settings    
PWCTR2  = const(0xC1) # Power control settings    
PWCTR3  = const(0xC2) # In normal mode (Full colors)    
PWCTR4  = const(0xC3) # In Idle mode (8-colors)    
PWCTR5  = const(0xC4) # In partial mode + Full colors    
VMCTR1  = const(0xC5) # VCOM control    
GMCTRP1 = const(0xE0)    
GMCTRN1 = const(0xE1)    
class ST7735(framebuf.FrameBuffer):    
def __init__(self, width, height, spi, dc, rst, cs, rot=0, bgr=0):    
if dc is None:    
raise RuntimeError('TFT must be initialized with a dc pin number')    
dc.init(dc.OUT, value=0)    
if cs is None:    
raise RuntimeError('TFT must be initialized with a cs pin number')    
cs.init(cs.OUT, value=1)    
if rst is not None:    
rst.init(rst.OUT, value=1)    
else:    
self.rst =None    
self.spi = spi    
self.rot = rot    
self.dc = dc    
self.rst = rst    
self.cs = cs    
self.height = height    
self.width = width    
self.buffer = bytearray(self.height * self.width*2)    
super().__init__(self.buffer, self.width, self.height, framebuf.RGB565, self.width)    
if (self.rot ==0):    
madctl=0x00    
elif (self.rot ==1):    
madctl=0xa0    
elif (self.rot ==2):    
madctl=0xc0    
else :    
madctl=0x60    
if bgr==0:    
madctl|=0x08    
self.madctl = pack('>B', madctl)    
self.reset()    
self._write(SLPOUT)    
sleep_ms(120)    
for command, data in (    
(COLMOD,  b"\x05"),    
(MADCTL,  pack('>B', madctl)),    
):    
self._write(command, data)    
if self.width==80 or self.height==80:    
self._write(INVON, None)    
else:    
self._write(INVOFF, None)    
buf=bytearray(128)    
for i in range(32):    
buf[i]=i*2    
buf[i+96]=i*2    
for i in range(64):    
buf[i+32]=i    
self._write(RGBSET, buf)    
#self._write(NORON)    
#sleep_ms(10)    
self.show()    
self._write(DISPON)    
#sleep_ms(100)    
def reset(self):    
if self.rst is None:    
self._write(SWRESET)    
sleep_ms(50)    
return    
self.rst.off()    
sleep_ms(50)    
self.rst.on()    
sleep_ms(50)    
def _write(self, command, data = None):    
self.cs.off()    
self.dc.off()    
self.spi.write(bytearray([command]))    
self.cs.on()    
if data is not None:    
self.cs.off()    
self.dc.on()    
self.spi.write(data)    
self.cs.on()    
def show(self):    
if self.width==80 or self.height==80:    
if self.rot==0 or self.rot==2:    
self._write(CASET,pack(">HH", 26, self.width+26-1))    
self._write(RASET,pack(">HH", 1, self.height+1-1))    
else:    
self._write(CASET,pack(">HH", 1, self.width+1-1))    
self._write(RASET,pack(">HH", 26, self.height+26-1))    
else:    
if self.rot==0 or self.rot==2:    
self._write(CASET,pack(">HH", 0, self.width-1))    
self._write(RASET,pack(">HH", 0, self.height-1))    
else:    
self._write(CASET,pack(">HH", 0, self.width-1))    
self._write(RASET,pack(">HH", 0, self.height-1))    
self._write(RAMWR,self.buffer)    
def rgb(self,r,g,b):    
return ((r&0xf8)<<8)|((g&0xfc)<<3)|((b&0xf8)>>3)

tools.py 工具库

class DoubleNode:    
def __init__(self, val=None, next=None, prev=None):    
self.val = val    
self.next = next    
self.prev = prev     
class DoubleLinkedList:    
'''双向链表'''    
def __init__(self, node=None):    
self.head = node    
self.tail = self.head    
self.length = 0    
if node:    
self.length+=1    
def append(self, node):    
'''尾插'''    
if self.length:    
self.tail.next = node    
node.prev = self.tail    
self.tail = node    
else:    
self.head = node    
self.tail = self.head    
self.length+=1    
def add(self, node):    
'''头插'''    
if self.length:    
self.head.prev = node    
node.next = self.head    
self.head = node    
else:    
self.head = node    
self.tail = self.head    
self.length+=1    
def pop(self):    
'''尾删除'''    
self.tail = self.tail.prev    
node = self.tail.next    
self.tail.next = None    
return node

game.py 简单的游戏框架

'''    
Auther: LUWic    
Date: 2022-7-17    
Introduce: 基于st7735的游戏库    
'''    
import st7735, _thread    
class Game:    
def __init__(self, size, bg_color):    
self.size = size    
self.screen_size = size    
self.bg_color = bg_color    
self.event_list = []    
self.keys = {}    
def set_screen(self, spi, size, dc, rst, cs, rot=0, bgr=0):    
self.screen_size = size    
self.st7735 = st7735.ST7735(size[0], size[1], spi, dc, rst, cs, rot=rot, bgr=bgr)    
self.st7735.fill(0xFFF)    
self.st7735.show()    
def set_key(self, keys):    
'''    
            keys: {"key_name", Pin(2, Pin.IN)}    
        '''    
self.keys = keys    
_thread.start_new_thread(self.add_event, ())    
def set_bar(self):    
self.st7735.line(0, self.screen_size[1]-self.size[1], self.screen_size[0], self.screen_size[1]-self.size[1], 0x000)    
self.st7735.show()    
def restart(self):    
self.st7735.fill(0xFFF)    
self.st7735.show()    
self.set_bar()    
def get_event(self):    
if len(self.event_list):    
return self.event_list.pop(0)    
return None    
def add_event(self):    
_keys = {}    
for k in self.keys.keys():    
_keys[k]=0    
while True:    
for k,v in self.keys.items():    
if not v.value() and _keys[k]:    
self.event_list.append(k)    
_keys[k] = 0    
elif v.value():    
_keys[k] = 1

main.py 主程序

from machine import Pin, SPI    
from game import Game    
from tools import DoubleNode, DoubleLinkedList    
import random, time    
class Snake:    
UP = -1    
DOWN = 1    
LEFT = -2    
RIGHT = 2    
def __init__(self, head, length, width, h_color, b_color, g):    
self.g = g      # 游戏基础对象    
self.length = length        ## 设置蛇的身体长度    
self.width = width      ## 设置蛇的身体宽度    
self.h_color = h_color      ## 设置蛇的头部颜色    
self.b_color = b_color      ## 设置蛇的身体颜色    
self.direction = Snake.RIGHT    
self.snake = DoubleLinkedList()       ## 保存蛇的身体    
self.snake.add(DoubleNode(head))    
node = self.snake.head    
for n in range(length):       ## 生成蛇的身体 并 进行绘制    
node = DoubleNode((node.val[0]-self.width, node.val[1]), prev=node)    
self.snake.append(node)    
self.g.st7735.fill_rect(node.val[0], node.val[1], self.width, self.width, self.b_color)    
self.g.st7735.fill_rect(self.snake.head.val[0], self.snake.head.val[1], self.width, self.width, self.h_color)    
self.show()    
def change_direction(self, event):    
if event:    
if event == "UP":    
direction = Snake.UP    
elif event == "DOWN":    
direction = Snake.DOWN    
elif event == "LEFT":    
direction = Snake.LEFT    
elif event == "RIGHT":    
direction = Snake.RIGHT    
if direction+self.direction != 0:    
self.direction = direction    
def move(self):    
self.g.st7735.fill_rect(self.snake.head.val[0], self.snake.head.val[1], self.width, self.width, self.b_color)    
if self.direction == Snake.UP:    
node = DoubleNode((self.snake.head.val[0], self.snake.head.val[1]-self.width))    
elif self.direction == Snake.DOWN:    
node = DoubleNode((self.snake.head.val[0], self.snake.head.val[1]+self.width))    
elif self.direction == Snake.LEFT:    
node = DoubleNode((self.snake.head.val[0]-self.width, self.snake.head.val[1]))    
elif self.direction == Snake.RIGHT:    
node = DoubleNode((self.snake.head.val[0]+self.width, self.snake.head.val[1]))    
if node.val != self.snake.head.next.val:    
tail = self.snake.pop()    
self.g.st7735.fill_rect(tail.val[0], tail.val[1], self.width, self.width, self.g.bg_color)    
self.snake.add(node)    
self.g.st7735.fill_rect(self.snake.head.val[0], self.snake.head.val[1], self.width, self.width, self.h_color)    
self.show()    
return self.die(self.snake.head)    
def die(self, node):    
if self.snake.head.val[0]==0 or self.snake.head.val[1]==self.g.screen_size[1]-self.g.size[1] or self.snake.head.val[0]==self.g.size[0] or self.snake.head.val[1]==self.g.screen_size[1]:    
return True    
node = self.snake.tail    
for n in range(self.length-3):    
if self.snake.head.val == node.val:    
return True    
node = node.prev    
return False    
def eat(self, snack):    
if self.snake.head.val == snack.position:    
self.length+=1    
node = DoubleNode((self.snake.tail.val[0]-self.width, self.snake.tail.val[1]), prev=self.snake.tail)    
self.snake.append(node)    
self.g.st7735.fill_rect(node.val[0], node.val[1], self.width, self.width, self.b_color)    
self.show()    
return True    
return False    
def show(self):    
self.g.st7735.show()    
class Snack:    
is_exist = False    
def __init__(self, position, width, color, g):    
self.g = g    
self.position = position    
self.color = color    
self.width = width    
self.show()    
def show(self):    
self.g.st7735.fill_rect(self.position[0], self.position[1], self.width, self.width, self.color)    
self.g.st7735.show()    
def main():    
Pin(18, Pin.OUT).value(1)    
spi=SPI(2, baudrate=20000000, polarity=0, phase=0, sck=Pin(15), mosi=Pin(0))    
game=Game((128,112), 0xFFF)    
game.set_screen(spi,(128, 128),dc=Pin(16),cs=Pin(17),rst=Pin(4),rot=2,bgr=0)    
game.set_bar()    
keys = {    
"UP": Pin(13, Pin.IN, Pin.PULL_DOWN),    
"DOWN": Pin(12, Pin.IN, Pin.PULL_DOWN),    
"LEFT": Pin(14, Pin.IN, Pin.PULL_DOWN),    
"RIGHT": Pin(27, Pin.IN, Pin.PULL_DOWN)    
}    
game.set_key(keys)    
while True:    
game.restart()    
width = 4    
length = 4    
snake = Snake((40, 64), length, width, 0x0F0, 0x000, game)    
while True:    
game.st7735.text("score: {}".format(snake.length-length-1), (game.screen_size[1]-game.size[1]-8)//2, (game.screen_size[1]-game.size[1]-8)//2, game.bg_color)    
game.st7735.text("score: {}".format(snake.length-length), (game.screen_size[1]-game.size[1]-8)//2, (game.screen_size[1]-game.size[1]-8)//2, 0x000)    
if not Snack.is_exist:    
position = (    
random.randint(width, game.size[0]//width-width)*width,    
random.randint((game.screen_size[1]-game.size[1])//width+width, game.size[1]//width-width)*width    
)    
snack = Snack(position, width, 0xF00, game)    
Snack.is_exist = True    
time.sleep_ms(30)    
event = game.get_event()    
snake.change_direction(event)    
snack.show()    
if snake.eat(snack):    
Snack.is_exist = False    
if snake.move():    
Snack.is_exist = False    
break    
time.sleep_ms(30)    
if __name__ == "__main__":    
main()


开源地址:https://github.com/LUWic/ESP32-Gluttonous-Snake


推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 ESP56.com All Rights Reserved

执行时间: 0.0093400478363037 seconds