显示学习4(基于树莓派Pico) -- 游戏

news/2024/5/9 19:28:10/文章来源:https://blog.csdn.net/fanged/article/details/137465948

来自:https://github.com/zelacerda/micropython

代码改造了一下,让它可以跑起来。

简单分析一下代码。外层是一个死循环,有一个状态机来对应不同的场景。

def loop():while True:if   state == 0: splash_screen()elif state == 1: game_waiting()elif state == 2: game_running()elif state == 3: game_over()

0是最开始的场景,通过检查按键进行切换。

button = Pin(13, Pin.IN)

按键之后切换到running。

def game_running():global stateif clicked(): flappy_bird.flap()flappy_bird.move()if flappy_bird.crashed():flappy_bird.y = HEIGHT - flappy_bird.heightstate = 3obstacle_1.scroll()obstacle_2.scroll()if obstacle_1.collided(flappy_bird.y) or obstacle_2.collided(flappy_bird.y):state = 3draw()

看了running其实就明白,所有的操作,以帧为单位

进入这一帧时,首先调用move函数,根据按键来更新小鸟的位置,然后判断小鸟是否飞出去了。

然后更新障碍物的位置,是scroll接口,然后判断障碍物和小鸟是否碰撞。

更新位置之后,调用draw接口,在Framebuffer中进行更新后显示。

显示的部分,还有挺有趣。小鸟,障碍物是这样表示的,是三个字符串:

# Bitmap images
BIRD = '07e018f021f871ecf9ecfcfcbe7e4c81717e4082307c0f80'
COL1 = '201c'*26+'ffff'+'800f'*4+'ffff'
COL2 = 'ffff'+'800f'*4+'ffff'+'201c'*26

然后基于这三个字符串创建的三个Framebuffer对象。

显示的时候一次调用blit方法加进去,有点类似memcpy。Framebuffer 的 blit 方法是用于将一个区域的图像数据从一个帧缓冲区复制到另一个帧缓冲区的方法。在图形编程中,blit 是 "block transfer"(块传输)的简称,通常用于在内存中进行图像数据的复制或传输操作。

在上面一旦检测到飞出画面或者碰到障碍物,就进到最后一个场景,结束画面。如果没问题就调用show接口,让屏幕正常显示继续循环。这个倒是没啥好说的。

可以看出,常规游戏的实现思路,就是基于2D图形的,以帧为单位,所有的逻辑操作都是基于2D的坐标体系。显示方面封装后就直接看做一块内存,逻辑处理完之后控制内存中数据的变化,最后把改动刷新到显示器。

改造后完整代码如下:

game.py

'''
Flappy Bird for ESP8266 modules
github.com/zelacerda/micropythonVersion 1.0
2017 - by zelacerda
'''import ssd1306
from framebuf import FrameBuffer as FB
from machine import I2C, Pin
from utime import sleep
import time
#from urequests import post# Screen dimensions
WIDTH   = 128
HEIGHT  = 64# Initialize pins
i2c = I2C(1, scl=Pin(7), sda=Pin(6))
oled = ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c)
button = Pin(13, Pin.IN)# Some helper functions
def random(a,b):seed = int(time.time() * 1000)  # 将当前时间转换为毫秒级别的整数# 利用种子生成伪随机数random_num = (seed * 1103515245 + 12345) % (2**31)# 将随机数映射到指定范围[a, b]return random_num % (b - a + 1) + adef to_bytearray(s):return bytearray([int('0x'+s[i:i+2]) for i in range(0,len(s),2)])def write_high_score(n):f = open('fb_high_score', 'w')f.write(str(n))f.close()def read_high_score():return 0def send_score(n):url = "http://things.ubidots.com/api/v1.6/devices/NodeMCU?token="token = "A1E-5ZY9vbCGtRiqVinrnhrQxgA4FDSBaA"url += tokenheaders = {"Content-Type": "application/json"}data = '{"flappy-bird-score": ' + str(n) + '}'#post(url, data=data, headers=headers)# Bitmap images
BIRD = '07e018f021f871ecf9ecfcfcbe7e4c81717e4082307c0f80'
COL1 = '201c'*26+'ffff'+'800f'*4+'ffff'
COL2 = 'ffff'+'800f'*4+'ffff'+'201c'*26
bird_size = (16,12)
colu_size  = (16,32)# Generate sprites
bird = FB(to_bytearray(BIRD),bird_size[0],bird_size[1],3)
col1 = FB(to_bytearray(COL1),colu_size[0],colu_size[1],3)
col2 = FB(to_bytearray(COL2),colu_size[0],colu_size[1],3)class FlappyBird:def __init__(self):self.height = bird_size[1]self.y = HEIGHT // 2 - self.height // 2self.vel = -wing_powerdef move(self):self.vel += gravityself.y = int(self.y + self.vel)def flap(self):self.vel = -wing_powerdef crashed(self):y_limit = HEIGHT - self.heightreturn self.y > y_limitclass Obstacle:def __init__(self, x):self.gap = random(6+gap_size, HEIGHT-6-gap_size)self.x = xself.score = 0def scroll(self):self.x -= velocityif self.x < -colu_size[0]:self.score += 1self.x = WIDTHself.gap = random(6+gap_size, HEIGHT-6-gap_size)def collided(self, y):if self.x < bird_size[0] and \self.x > -colu_size[0] and \(self.gap - y > gap_size or y + bird_size[1] - self.gap > gap_size):return Trueelse:return Falsedef clicked():global pressedif button.value() == 1 and not pressed:pressed = Truereturn Trueelif button.value() == 0 and pressed:pressed = Falsereturn Falsedef draw():oled.fill(0)oled.blit(bird, 0, flappy_bird.y)oled.blit(col1,obstacle_1.x,obstacle_1.gap-gap_size-colu_size[1])oled.blit(col2,obstacle_1.x,obstacle_1.gap+gap_size)oled.blit(col1,obstacle_2.x,obstacle_2.gap-gap_size-colu_size[1])oled.blit(col2,obstacle_2.x,obstacle_2.gap+gap_size)oled.fill_rect(WIDTH//2 - 13, 0, 26, 9, 0)oled.text('%03d' % (obstacle_1.score + obstacle_2.score), WIDTH//2 - 12, 0)oled.show()# Game parameters
high_score  = read_high_score()
gap_size    = 13
velocity    = 3
gravity     = .8
wing_power  = 4
state       = 0
pressed     = False# Game state functions
def splash_screen():global stateoled.fill(0)oled.blit(col2, (WIDTH-colu_size[0])//2, HEIGHT-12)oled.blit(bird, (WIDTH-bird_size[0])//2, HEIGHT-12-bird_size[1])oled.rect(0, 0, WIDTH, HEIGHT, 1)oled.text('F L A P P Y', WIDTH//2-44, 3)oled.text('B I R D', WIDTH//2-28, 13)oled.text('Record: ' + '%03d' % high_score, WIDTH//2-44, HEIGHT//2-6)oled.show()state = 1def game_waiting():global state,score,flappy_bird,obstacle_1,obstacle_2, pressedif clicked():flappy_bird = FlappyBird()obstacle_1 = Obstacle(WIDTH)obstacle_2 = Obstacle(WIDTH + (WIDTH + colu_size[0]) // 2)state = 2def game_running():global stateif clicked(): flappy_bird.flap()flappy_bird.move()if flappy_bird.crashed():flappy_bird.y = HEIGHT - flappy_bird.heightstate = 3obstacle_1.scroll()obstacle_2.scroll()if obstacle_1.collided(flappy_bird.y) or obstacle_2.collided(flappy_bird.y):state = 3draw()def game_over():global state, high_scoreoled.fill_rect(WIDTH//2-32, 10, 64, 23, 0)oled.rect(WIDTH//2-32, 10, 64, 23, 1)oled.text('G A M E', WIDTH//2-28, 13)oled.text('O V E R', WIDTH//2-28, 23)score = obstacle_1.score + obstacle_2.scoreif score > high_score:high_score = scoreoled.fill_rect(WIDTH//2-48, 37, 96, 14, 0)oled.rect(WIDTH//2-48, 37, 96, 14, 1)oled.text('New record!',WIDTH//2-44, 40)write_high_score(high_score)oled.show()try:send_score(score)except:passstate = 1def loop():while True:if   state == 0: splash_screen()elif state == 1: game_waiting()elif state == 2: game_running()elif state == 3: game_over()loop()

oled驱动,ssd1306.py

# MicroPython SSD1306 OLED driver, I2C and SPI interfacesfrom micropython import const
import framebuf# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class SSD1306(framebuf.FrameBuffer):def __init__(self, width, height, external_vcc):self.width = widthself.height = heightself.external_vcc = external_vccself.pages = self.height // 8self.buffer = bytearray(self.pages * self.width)super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)self.init_display()def init_display(self):for cmd in (SET_DISP | 0x00,  # off# address settingSET_MEM_ADDR,0x00,  # horizontal# resolution and layoutSET_DISP_START_LINE | 0x00,SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0SET_MUX_RATIO,self.height - 1,SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0SET_DISP_OFFSET,0x00,SET_COM_PIN_CFG,0x02 if self.width > 2 * self.height else 0x12,# timing and driving schemeSET_DISP_CLK_DIV,0x80,SET_PRECHARGE,0x22 if self.external_vcc else 0xF1,SET_VCOM_DESEL,0x30,  # 0.83*Vcc# displaySET_CONTRAST,0xFF,  # maximumSET_ENTIRE_ON,  # output follows RAM contentsSET_NORM_INV,  # not inverted# charge pumpSET_CHARGE_PUMP,0x10 if self.external_vcc else 0x14,SET_DISP | 0x01,):  # onself.write_cmd(cmd)self.fill(0)self.show()def poweroff(self):self.write_cmd(SET_DISP | 0x00)def poweron(self):self.write_cmd(SET_DISP | 0x01)def contrast(self, contrast):self.write_cmd(SET_CONTRAST)self.write_cmd(contrast)def invert(self, invert):self.write_cmd(SET_NORM_INV | (invert & 1))def show(self):x0 = 0x1 = self.width - 1if self.width == 64:# displays with width of 64 pixels are shifted by 32x0 += 32x1 += 32self.write_cmd(SET_COL_ADDR)self.write_cmd(x0)self.write_cmd(x1)self.write_cmd(SET_PAGE_ADDR)self.write_cmd(0)self.write_cmd(self.pages - 1)self.write_data(self.buffer)class SSD1306_I2C(SSD1306):def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):self.i2c = i2cself.addr = addrself.temp = bytearray(2)self.write_list = [b"\x40", None]  # Co=0, D/C#=1super().__init__(width, height, external_vcc)def write_cmd(self, cmd):self.temp[0] = 0x80  # Co=1, D/C#=0self.temp[1] = cmdself.i2c.writeto(self.addr, self.temp)def write_data(self, buf):self.write_list[1] = bufself.i2c.writevto(self.addr, self.write_list)class SSD1306_SPI(SSD1306):def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):self.rate = 10 * 1024 * 1024dc.init(dc.OUT, value=0)res.init(res.OUT, value=0)cs.init(cs.OUT, value=1)self.spi = spiself.dc = dcself.res = resself.cs = csimport timeself.res(1)time.sleep_ms(1)self.res(0)time.sleep_ms(10)self.res(1)super().__init__(width, height, external_vcc)def write_cmd(self, cmd):self.spi.init(baudrate=self.rate, polarity=0, phase=0)self.cs(1)self.dc(0)self.cs(0)self.spi.write(bytearray([cmd]))self.cs(1)def write_data(self, buf):self.spi.init(baudrate=self.rate, polarity=0, phase=0)self.cs(1)self.dc(1)self.cs(0)self.spi.write(buf)self.cs(1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1045371.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式——桥接模式07

桥接模式是将抽象部分与实现部分分离&#xff0c;可实现两部分的组合使用。 例如 遥控器 &#xff08;抽象部分&#xff09;与 设备&#xff08;实现部分 电视&#xff0c;空调等&#xff09;。遥控器调用的是 设备方实现的接口。 设计模式&#xff0c;一定要敲代码理解 抽象模…

【保姆级教程】如何在 Windows 上实现和 Linux 子系统的端口映射

写在前面 上次分享【保姆级教程】Windows上安装Linux子系统&#xff0c;搞台虚拟机玩玩&#xff0c;向大家介绍了什么是虚拟机以及如何在Windows上安装Linux虚拟机。对于开发同学而言&#xff0c;经常遇到的一个问题是&#xff1a;很多情况下代码开发需要依赖 Linux 系统&…

Chapter 1 - 8. Introduction to Congestion in Storage Networks

Storage Networks A storage network provides access to a remote storage device using any of the block, file, or object storage protocols explained in the previous section. 存储网络可使用上一节中介绍的任何一种块、文件或对象存储协议访问远程存储设备。 A stor…

微信小程序转盘抽奖

场景&#xff1a; 在微信小程序里面开展抽奖活动使用转盘抽奖&#xff1b;类似下图&#xff08;图片来自百度&#xff09; 方法&#xff1a; 使用lukcy-canvas组件 在 微信小程序 中使用 | 基于 Js / TS / Vue / React / 微信小程序 / uni-app / Taro 的【大转盘 & 九宫…

了解单链表

27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 思路一&#xff1a; 创建新的数组&#xff0c;遍历原数组&#xff0c;将不为val的值放到新数组当中。空间复杂度不为O(1) 思路二&#xff1a;双指针法 我们设置两个指针src&#xff08;源数据&#xff09;和dst&#xf…

深入浅出 -- 系统架构之单体架构

单体架构&#xff08;Monolithic Architecture&#xff09; 单体架构的定义 单体架构&#xff08;Monolithic Architecture&#xff09;是一种传统的软件架构模式&#xff0c;将整个应用程序作为一个单一的、统一的单元进行开发、部署和扩展。在单体架构中&#xff0c;所有的功…

《QT实用小工具·二十四》各种数学和数据的坐标演示图

1、概述 源码放在文章末尾 该项目实现了各种数学和数据的坐标演示图&#xff0c;下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #ifndef FRMMAIN_H #define FRMMAIN_H#include <QWidget> class QAbstractButton;namespace Ui { class frmMain; }class fr…

MySQL数据库(基础篇)

数据库相关概念 关系型数据库 概念: 建立在关系模型基础上&#xff0c;由多张相互连接的二维表组成的数据库。 特点&#xff1a; 1.使用表存储数据&#xff0c;格式统一&#xff0c;便于维护 2.使用SQL语言操作&#xff0c;标准统一&#xff0c;使用方便 SOL SQL通用语法 …

​网络socket编程(二)——面向流的TCP编程及测试(SocketTool)、Wireshark软件使用

目录 一、书接上回&#xff08;select()函数使用注意事项&#xff09; 二、面向流(TCP)的socket编程 2.1 TCP服务端编程和测试 2.1.1 TCP服务器原理流程图 2.1.2 TCP服务端编程实战 2.1.3 测试 2.2 TCP客户端编程和测试 三、Wireshark抓包软件的使用 3.1 Wireshark是什…

ABAP 前导0的处理

前导0这个东西真的很烦&#xff0c;经常因为前导0导致连接条件有问题&#xff0c;出不来数据&#xff0c;这里就总结一下前导0 在sql语句中的添加和去除 文章目录 ABAP 前导0的处理添加前导0-自适应运行结果 去除前导0方法一、使用SUBSTRING截取运行结果 方法二、去零法运行结…

Apache Echarts(智能生成图表)-数据可视化

Apache ECharts 是一款基于Javascript的数据可视化图表库&#xff0c;提供直观生动可交互&#xff0c;可个行化定制的数据可视化图表 Apache ECharts是一个基于JavaScript的开源可视化库&#xff0c;用于创建交互式的、可定制的图表和数据可视化。它是由百度前端开发团队开发和…

微信自动回复这样设置,让你的沟通更加高效便捷!

面对繁忙的生活和不断涌入的信息&#xff0c;我们往往无法及时回复微信好友的消息&#xff0c;这给沟通带来了一定的困扰。有没有一种方法能够让我们在忙碌的同时&#xff0c;依然能够及时回复好友并提高沟通效率呢&#xff1f; 答案是肯定的&#xff01;我们可以通过微信管理…

transformers in tabular tiny survey 2024.4.8

推荐阅读 NIPS‘22 Why do tree-based models still outperform deep learning on typical tabular data?nips’23 When Do Neural Nets Outperform Boosted Trees on Tabular Data? TabLLM pmlr2023, Few-shot Classification of Tabular Data with Large Language Model…

HDLbits 刷题 --7420

The 7400-series integrated circuits are a series of digital chips with a few gates each. The 7420 is a chip with two 4-input NAND gates. Create a module with the same functionality as the 7420 chip. It has 8 inputs and 2 outputs. 译&#xff1a; 7400系列集…

【刷题】备战蓝桥杯 — dfs 算法

送给大家一句话&#xff1a; 风度真美&#xff01; 即使流泪&#xff0c;也要鼓掌&#xff0c; 即使失望&#xff0c;也要满怀希望。 ——刘宝增 dfs 算法 1 前言2 洛谷 P1030 [NOIP2001 普及组] 求先序排列题目描述算法思路 3 洛谷 P1294 高手去散步题目描述算法思路 4 蓝桥…

Struts2的入门:新建项目——》导入jar包——》jsp,action,struts.xml,web.xml——》在项目运行

文章目录 配置环境tomcat 新建项目导入jar包新建jsp界面新建action类新建struts.xml,用来配置action文件配置Struts2的核心过滤器&#xff1a;web.xml 启动测试给一个返回界面在struts.xml中配置以实现页面的跳转&#xff1a;result再写个success.jsp最后在项目运行 配置环境 …

探索未来游戏:生成式人工智能AI如何重塑你的游戏世界?

生成式人工智能&#xff08;Generative AI&#xff09;正以前所未有的速度改变着各行各业的运作模式。其中&#xff0c;游戏产业作为科技应用的前沿阵地&#xff0c;正经历着前所未有的变革。本文将探讨生成式人工智能如何重塑游戏产业&#xff0c;以及这一变革背后的深远影响。…

哪些医疗器械申请FDA,需要准备网络安全文件?需要提交的文件都是什么样的?

一、什么类型的医疗器械需要递交网络安全文件&#xff1f; FD&C法案第524B条(c) 条将“网络设备”定义为&#xff1a; 1&#xff09;经申请人验证、安装或授权的软件或设备&#xff1b; 2&#xff09;具备连接互联网的能力&#xff1b; 3&#xff09;包含经申请人验证、…

linux------jekins构建cicd

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…

景区云旅游/视频慢直播方案设计与平台搭建

一、行业背景 经文化和旅游部数据中心测算&#xff0c;今年清明节假期3天全国国内旅游出游1.19亿人次&#xff0c;按可比口径较2019年同期增长11.5%&#xff1b;国内游客出游花费539.5亿元&#xff0c;较2019年同期增长12.7%。踏青赏花和户外徒步成为假期的热门出游主题。随着…