本系列,是记录自己入门嵌入式领域的学习笔记。
看看能坚持多久。
今天是2023年5月4日
源代码的来源:https://github.com/taichi-maker/ESP8266_Multiplayer_Pong
项目需求:
ESP8266_OLED屏幕实现局域网复古乒乓球对战
硬件连接:
D1(8266)<------------>SCL(oled)
D2(8266)<------------>SDA(oled)
D5(8266)<------------>按键UP引脚
D6(8266)<------------>按键DOWN引脚
3V3(8266)<----------->VCC(oled)
GND(8266)<----------->GND(oled)
备注:使用的两个按键另一端均为接地(GND)
程序源码:
引入的库文件的头文件
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Ticker.h>
//
作为STA_slave需要的参数
#define ssid "XXXXXXX" //这里改成你的设备当前环境下WIFI名字
#define password "XXXXXXX" //这里改成你的设备当前环境下WIFI密码
IPAddress master_IP(192, 168, 1, 14); //master机子接入点的ip地址
//
///UDP传输相关参数
WiFiUDP Udp;//实例化WiFiUDP对象
unsigned int localUdpPort = 4321; // 自定义本地监听端口
unsigned int remoteUdpPort = 1234; // 自定义远程监听端口
int slavepad = 16; //slave机的球拍位置
int masterpad = 16; //master机的球拍位置
Ticker changedata;//实例化一个定时器对象
//
//游戏运行的各项参数///
uint8_t ball_x = 64, ball_y = 32;
uint8_t ball_x0 = 64, ball_y0 = 32;
uint8_t ball_dir_x = 1, ball_dir_y = 1;
unsigned long ball_update;
unsigned long paddle_update;
const uint8_t CPU_X = 12;
uint8_t cpu_y = 16;
const uint8_t PLAYER_X = 115;
uint8_t player_y = 16;
const unsigned long PADDLE_RATE = 33;
const unsigned long BALL_RATE = 16;
const uint8_t PADDLE_HEIGHT = 24;
int scoreCPU = 0;
int scoreUSER = 0;
int startflag = 0;
int keyflag = 0;
//int end_x = 0;
uint8_t new_x = 1;
uint8_t new_y = 1;
//
/按键引脚定义/
#define UP_BUTTON 14//GOIO14=D5
#define DOWN_BUTTON 12//GOIO12=D6
//
/oled显示定义/
#define SCREEN_WIDTH 128 // OLED宽度像素
#define SCREEN_HEIGHT 64 // OLED高度像素
// 0.96寸SSD1306,I2C协议 (SDA, SCL 标号)
#define OLED_RESET 3 // Reset pin ,虽然用不上但是还是要设置
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//
///初始化使用的函数
void drawCourt();;//画出球场
void splash();//初始界面
void printScreen();//打印双方分数
void Multiplayer();//游戏主函数。多人联机是由单人游戏扩展而来。单人游戏文件可在github测试用文件中找到
void UDPsetup();//初始化UDP链接
void UDPgetstart();//初始化UDP链接
void UDPgetdata();//接受和发送游戏进行时传输的数据
void UDPsend();//UDP发送信息函数
void gamestart();//确定游戏开始的函数
void tochar();//进行数值和字符串转换并发送的函数
void change();//交换数据的函数。此函数包含tochar()和UDPgetdata()
void wifiSTAconnect();//作为slave机的AP热点开启初始化
//void gamerestart();
//
void setup() {
串口初始化
Serial.begin(115200);//打开串口
Serial.println();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);//使用I2C地址0x3C初始化(对于128x64)
display.clearDisplay();
unsigned long start = millis();
pinMode(UP_BUTTON, INPUT_PULLUP);//按键初始化为上拉输入
pinMode(DOWN_BUTTON, INPUT_PULLUP);
digitalWrite(UP_BUTTON, 1);
digitalWrite(DOWN_BUTTON, 1);
UDPsetup();//UDP链接初始化
changedata.attach(0.02, change);//开启定时器,每0.02秒就同步一次数据
splash();//开机初始化界面
wifiSTAconnect();//作为slave的无线终端初始化
gamestart();//确认开始游戏界面
drawCourt();//画球场的框线
printScores();//屏幕显示分数
while (millis() - start < 2000);
ball_update = millis();
paddle_update = ball_update;
}
void loop() {
Multiplayer();
}
//
void drawCourt() {
display.drawRect(0, 0, 128, 64, WHITE);
for (int i = 0; i < SCREEN_HEIGHT; i += 4) {
display.drawFastVLine(SCREEN_WIDTH / 2, i, 2, WHITE);
}
}
void splash()
{
display.clearDisplay();
display.setTextColor(WHITE);
centerPrint("PONG", 0, 3);
centerPrint("By BlackBox114", 24, 1);
centerPrint("Code by", 33, 1);
centerPrint("TaichiMacker", 42, 1);
display.fillRect(0, SCREEN_HEIGHT - 10, SCREEN_WIDTH, 10, WHITE);
display.setTextColor(BLACK);
centerPrint("Press key to start!", SCREEN_HEIGHT - 9, 1);
display.display();
while (true) {
ESP.wdtFeed();//长时间循环会触发看门狗复位,因此需要喂狗
if (digitalRead(DOWN_BUTTON) + digitalRead(UP_BUTTON) < 2) {
break;
}
display.clearDisplay();
}
// soundStart();
}
void centerPrint(char *text, int y, int size)
{
display.setTextSize(size);
display.setCursor(SCREEN_WIDTH / 2 - ((strlen(text)) * 6 * size) / 2, y);
display.print(text);
}
void printScores() {
//print scores
int SIZE = 2;
int SCORE_PADDING = 10;
//以分数位置为基准,修改整体宽度
int scoreCP