Micropython学习交流群 学习QQ群:786510434 提供多种固件下载和学习交流。
Micropython-扇贝物联 QQ群:31324057 扇贝物联是一个让你与智能设备沟通更方便的物联网云平台
Micropython学习交流群 学习QQ群:468985481 学习交流ESP8266、ESP32、ESP8285、wifi模块开发交流、物联网。
Micropython老哥俩的IT农场分享QQ群:929132891 为喜欢科创制作的小白们分享一些自制的计算机软硬件免费公益课程,由两位多年从事IT研发的中年大叔发起。
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] = 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