本站改版新增arduino频道
pin13 -- 开关负级 (用来控制角色的上移)
pin12 -- 开关负级 (用来控制角色的下移)
pin14 -- 开关负级 (用来控制角色的左移)
pin27 -- 开关负级 (用来控制角色的右移)
pin18 -- 开关正级
3.3v -- 屏幕VCC
GND -- 屏幕DNG
pin15 -- 屏幕SCL
pin0 -- 屏幕SDA
pin4 -- 屏幕RES
pin16 -- 屏幕DC
pin17 -- 屏幕CS
pin5 -- 屏幕BLK

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] = 1main.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
晋ICP备14006235号-22 晋公网安备14108102001165号
执行时间: 0.0095319747924805 seconds