我是来自 Arduino中文社区的 Zoologist, 个人爱好 Arduino 制作各种有趣的东西。 这次带来的是ESP32(DFRobot 的 FireBeetle )制作的俄罗斯方块游戏机。
“1984年,在当时还叫做苏联的那个国家的首都莫斯科,俄罗斯科学院(当然那时它也还叫做苏联科学院)总部计算机中心的一位工程师阿列克谢·帕基特诺夫开始考虑在计算机上自行开发一些简单的游戏,经过一段时间的尝试后,他通过另一款拼图游戏得到灵感,考虑让不同形状的图形依次下落,在矩形底部堆叠起来使之排列成完整的一行后消除,在另外两位同伴的协助下,他最终完成了这款被他命名为“Tetris”(俄语:Тетрис)的游戏,而我们今天更习惯叫它为“俄罗斯方块”。 1984年6月6日,是公认的俄罗斯方块诞生纪念日,游戏最初由苏联科学院计算中心的工程师阿列克谢·帕基特诺夫开发,他当时从另一款拼图游戏得到灵感。 根据另一位当事人的回忆,“Tetris”这个单词是阿列克谢自己发明并坚持使用的,来自反映俄罗斯方块图案基本结构的“四”(希腊语:tetra)和阿列克谢自己最喜爱的运动“网球”(tennis)的组合。《俄罗斯方块》的原名“Tetris”(俄语:Тетрис)是发明者阿列克谢·帕基特诺夫自己生造出来的单词,来自反映俄罗斯方块图案基本结构的“四”(希腊语:tetra)和阿列克谢自己最喜爱的运动“网球”(tennis)的组合。 公认的第一款俄罗斯方块原始程序诞生于1984年6月6日,在当时苏联仿制的Elektronika 60计算机上运行,因为这款计算机不能显示色块图案,原始版本只能用字符串来表示图形,但即便这样它也体现出了游戏本身的魅力,阿列克谢和他身边的朋友们很快都开始为之沉迷。1985年,开发同伴之一的瓦丁·格拉西莫夫在MS-DOS下移植了俄罗斯方块,让更多的个人电脑可以运行,游戏得以迅速的普及。 阿列克谢起初希望能合法贩卖俄罗斯方块游戏,但在苏联当时的制度下这十分困难,几经尝试都失败后,阿列克谢表示可以考虑把游戏版权交给国家——当时的苏联科学院。而在诞生后的数年时间里,俄罗斯方块一直都以免费拷贝的形式传播,从苏联扩展到了整个欧洲,也引起了更多人的注意。 第一个俄罗斯方块的程序在苏联仿制的Elektronika 60计算机上运行,因为无法显示色块只能用字符来表示图形,之后一年游戏移植了MS-DOS版,而这一版首次呈现出的图案画面也成为之后三十年来的游戏基础,甚至没有太多变化。 1986年匈牙利的程序员在Apple II和Commodore 64上移植了游戏,英国游戏公司Andromeda的一位经理人罗伯特·斯坦恩注意到了这个商机,他开始联系阿列克谢以及匈牙利的程序员试图购买俄罗斯方块的版权,并在确定到手之前就把它分别卖给了英国的游戏公司Mirrorsoft和美国的游戏公司Spectrum Holobyte,从而导致了接下来整整十余年时间关于俄罗斯方块的版权之争,甚至可以说改变了游戏发展史的一连串事件。” 上述文字节选自《三十年成就经典传奇 发展史》【参考1】 这次使用 ESP32 搭配 ILI9341(240*320)来实现一个掌上俄罗斯方块游戏机。
* 2、描述项目所面临的挑战及所解决的问题 1. ILI9341 的显示控制,最终选择使用 Adafruit_GFX 的显示库;特别注意这个库对 ESP32 有兼容性问题,通过修改 Adafruit_BusIOAdafruit_SPIDevice.cpp 这个文件解决:
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @param buffer The buffer to send and receive at the same time
* @param len The number of bytes to transfer
*/
void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
if (_spi) {
// hardware SPI is easy
//LABZDebug _spi->transfer(buffer, len);
_spi->transferBytes(buffer,NULL,len); //LABZDebug
return;
}
2.修改IL9341 的库兼容代码,增加了一个填充图像的函数 void Adafruit_ILI9341::fillImage(void *image, int x, int y, int w, int h) {
//drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w,int16_t h),
Adafruit_SPITFT::drawRGBBitmap(x, y,(uint16_t *)image, w, h);
}
3.增加了一个计分功能,每次消除行的时候,进行分数计算,具体在DeleteLine()函数中的 if (DeleteCount!=0) {score+=DeleteCount*DeleteCount;}2
4.增加了根据分数控制速度的机制,下降速度控制在 GetNextPosRot() 函数中:if ((millis()-TimeElsp)>Score2Level()) {pnext_pos->Y += 1;TimeElsp=millis();}Score2Level() 函数返回当前分数对应的延时,分数越高下落速度会越快;
5.显示“下一个” 的功能。设计在了 Draw() 函数中,出于对效率的考虑只有在下一个有变化的时候才会进行显示更新。同时,这里面还有一个特别的地方,比如,我们定义了一个image[20][20]的图像,但是我们想将它里面10 x 20 的内容显示出来是不可以直接使用 tft.fillImage 的,因为这个函数会默认将显示Buffer 认为是 20x20 大小的,因此会出现混乱。
* 3、描述项目硬件、软件部分涉及到的关键点
硬件: DFRobot 的 TinkerNode ESP32开发板,选择原因是它自带电源管理芯片,可以方便的使用18650充电电池,同时 ESP32 提供了强大的接口(SPI轻松达到 40Mhz)和性能(核心可达240Mhz);中景园的 ILI9431 TFT显示屏;以及一个用于控制的 PS2 摇杆,模拟输出 XY 四个方向以及一个开关按钮;
软件:使用 Arduino IDE 进行编辑,项目参考了开源设计https://github.com/MhageGH/esp32_ILI9328_Tetris。 。删除了项目中的串口控制和网络部分,修改为通过 PS2摇杆控制,另外加入了分数显示和现实下一个的功能。 * 4、项目材料清单展示 电路板 PS2 方向键 ILI9341 TFT 屏幕 DFRobot TinkerNode 排母若干 螺丝若干 项目演示视频: https://www.bilibili.com/video/BV1jA411e7h4/
!注意:请使用浏览器自带下载,迅雷等下载软件可能无法下载到有效资源。
欢迎加入EEWorld参考设计群,也许能碰到搞同一个设计的小伙伴,群聊设计经验和难点。 入群方式:微信搜索“helloeeworld”或者扫描二维码,备注:参考设计,即可被拉入群。 另外,如您在下载此设计遇到问题,也可以微信添加“helloeeworld”及时沟通。
EEWorld Datasheet 技术支持