女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何構建Arduino供電的迷你復古游戲機

454398 ? 來源:網絡整理 ? 作者:網絡整理 ? 2019-11-29 09:01 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

曾經想知道編寫自己的復古游戲需要多少工作? Pong為Arduino編寫代碼有多容易?和我一起,向我展示如何構建Arduino供電的迷你復古游戲機,以及如何從頭開始編寫Pong。最終結果如下:

構建計劃

這是一個相當簡單的電路。 電位器(電位器)將控制游戲,而Arduino將會驅動OLED顯示屏。這將在面包板上生產,但是您可能希望將其制成永久性電路并將其安裝在箱子中。之前我們已經寫過有關重新創建Pong的文章,但是今天我將向您展示如何從頭開始編寫代碼,并分解每個部分。

您需要的內容

這是您需要的:

1 x Arduino(任何型號)

1 x 10k電位器

1 x 0.96英寸I2C OLED顯示屏

1 x面包板

各種公頭》公連接線

任何Arduino都應該工作,請查看我們的購買指南如果您不確定要購買哪種型號。

這些OLED顯示器非常酷。通常可以購買白色,藍色,黃色或這三種的混合物。它們確實是全彩色的,但是它們又增加了該項目的復雜性和成本。

電路

這是一個非常簡單的電路。如果您對Arduino沒有太多的經驗,請先查看這些初學者項目。

在這里是:

在鍋的前面,將左引腳連接到 + 5V ,將右引腳連接到接地。將中間引腳連接到模擬引腳0 (A0)。

使用I2C協議連接OLED顯示器。將 VCC 和 GND 連接到Arduino + 5V 和接地。將 SCL 連接到模擬五( A5 )。將 SDA 連接到模擬4 ( A4 )。它連接到模擬引腳的原因很簡單。這些引腳包含I2C協議所需的電路。確保它們正確連接,并且沒有交叉。確切的引腳會因型號而異,但是Nano和Uno會使用A4和A5。如果您未使用Arduino或Nano,請查看模型的Wire庫文檔。

電位器測試

上傳此測試代碼(請確保從中選擇正確的電路板和端口工具》 面板和工具》 端口菜單):

void setup() {

// put your setup code here, to run once:

Serial.begin(9600); // setup serial

}

void loop() {

// put your main code here, to run repeatedly:

Serial.println(analogRead(A0)); // print the value from the pot

delay(500);

}

現在打開串行監視器(右上》 串行監視器)并轉動鍋。您應該看到在串行監視器上顯示的值。完全逆時針應為零,完全逆時針應為 1023 :

您稍后會對此進行調整,但現在就可以了。如果什么也沒有發生,或者您不做任何事情就改變了值,請斷開并仔細檢查電路。

OLED測試

OLED顯示的配置稍微復雜一些。您需要安裝兩個庫才能首先驅動顯示。從Github下載Adafruit_SSD1306和Adafruit-GFX庫。將文件復制到您的庫文件夾中。這取決于您的操作系統

Mac OS:/用戶/用戶名/Documents/Arduino/libraries

Linux:/home/Username/Sketchbook

Windows:/Users/Arduino/libraries

現在上傳測試草圖。轉到文件》 示例》 Adafruit SSD1306 》 ssd1306_128x64_i2c 。這應該給您一個包含大量圖形的大草圖:

如果上傳后沒有任何反應,請斷開連接并再次檢查您的連接。如果示例不在菜單中,則可能需要重新啟動Arduino IDE。

代碼

現在是時候編寫代碼了。我將解釋每個步驟,所以如果您只想使其運行,請跳到最后。這是相當數量的代碼,因此,如果您不確定,請查看以下10個免費資源以學習編碼。

首先包括必要的庫:

#include

#include

#include

#include

SPI 和 WIRE 是用于處理I2C通信的兩個Arduino庫。 Adafruit_GFX 和 Adafruit_SSD1306 是您先前安裝的庫。

下一步,配置顯示:

Adafruit_SSD1306 display(4);

然后設置運行游戲所需的所有變量:

int resolution[2] = {128, 64}, ball[2] = {20, (resolution[1] / 2)};

const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, SPEED = 3;

int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0;

char ballDirectionHori = ‘R’, ballDirectionVerti = ‘S’;

boolean inProgress = true;

這些變量存儲運行游戲所需的所有數據。其中一些存儲球的位置,屏幕的大小,球員的位置等。請注意其中的一些是 const 的意思,它們是恒定的,并且永遠不會改變。

屏幕分辨率和焊球位置存儲在數組中。數組是相似事物的集合,對于球,存儲坐標( X 和 Y )。訪問數組中的元素很容易(不要在文件中包含此代碼):

resolution[1];

由于數組從零開始,因此將返回分辨率數組中的第二個元素( 64 )。更新元素甚至更容易(同樣,不包含此代碼):

ball[1] = 15;

在 void setup()內,配置顯示:/p》 void setup() {

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

display.display();

}

第一行告訴Adafruit庫,您的顯示器正在使用什么尺寸和通訊協議(在這種情況下,為 128 x 64 和 I2C )。第二行( display.display())告訴屏幕顯示緩沖區中存儲的內容(無內容)。

創建兩個名為 drawBall 和 eraseBall :

void drawBall(int x, int y) {

display.drawCircle(x, y, BALL_SIZE, WHITE);

}

void eraseBall(int x, int y) {

display.drawCircle(x, y, BALL_SIZE, BLACK);

}

這些采用 x 和 y 坐標并使用顯示庫中的 drawCircle 方法將其繪制在屏幕上。這使用了前面定義的常量 BALL_SIZE 。嘗試更改此設置,看看會發生什么。此drawCircle方法接受像素顏色-黑色或白色。因為這是單色顯示(一種顏色),所以白色表示像素處于打開狀態,黑色表示像素處于關閉狀態。

現在創建一種稱為 moveAi 的方法:

void moveAi() {

eraseAiPaddle(aiPos);

if (ball[1] 》 aiPos) {

++aiPos;

}

else if (ball[1] 《 aiPos) {

--aiPos;

}

drawAiPaddle(aiPos);

}

此方法處理移動人工智能或 AI 播放器。這是一個非常簡單的計算機對手-如果球在槳上方,請向上移動。它在槳下面,向下移動。很簡單,但是效果很好。增量和減量符號( ++ aiPos 和 –aiPos )用于從aiPosition中添加或減去一個。您可以添加或減去更大的數字以使AI更快地移動,因此更難以克服。這樣做的方法如下:

aiPos += 2;

并且:

aiPos -= 2;

加號等于和負號符號是aiPos當前值加/減兩個的簡寫。這是另一種方法:

aiPos = aiPos + 2;

aiPos = aiPos - 1;

注意此方法如何首先擦除槳,并且然后再次繪制。必須這樣做。如果繪制了新的槳葉位置,則屏幕上將有兩個重疊的槳葉。

drawNet 方法使用兩個循環繪制球網:

void drawNet() {

for (int i = 0; i 《 (resolution[1] / WALL_WIDTH); ++i) {

drawPixel(((resolution[0] / 2) - 1), i * (WALL_WIDTH) + (WALL_WIDTH * i), WALL_WIDTH);

}

}

這將使用 WALL_WIDTH 變量來設置其大小。

創建名為 drawPixels 和的方法擦除像素。就像球形方法一樣,兩者之間的唯一區別是像素的顏色:

void drawPixel(int posX, int posY, int dimensions) {

for (int x = 0; x 《 dimensions; ++x) {

for (int y = 0; y 《 dimensions; ++y) {

display.drawPixel((posX + x), (posY + y), WHITE);

}

}

}

void erasePixel(int posX, int posY, int dimensions) {

for (int x = 0; x 《 dimensions; ++x) {

for (int y = 0; y 《 dimensions; ++y) {

display.drawPixel((posX + x), (posY + y), BLACK);

}

}

}

再次,這兩種方法都使用兩個 》循環繪制一組像素。循環不必使用庫 drawPixel 方法繪制每個像素,而是根據給定的尺寸繪制一組像素。

drawScore 方法使用庫的文本功能將播放器和AI得分寫入屏幕。這些存儲在 playerScore 和 aiScore 中:

void drawScore() {

display.setTextSize(2);

display.setTextColor(WHITE);

display.setCursor(45, 0);

display.println(playerScore);

display.setCursor(75, 0);

display.println(aiScore);

}

此方法還具有 eraseScore 對應,將像素設置為黑色或關閉。

最后四種方法非常相似。他們繪制并擦除了玩家和AI球拍:

void erasePlayerPaddle(int row) {

erasePixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH);

erasePixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH);

erasePixel(0, row, PADDLE_WIDTH);

erasePixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH);

erasePixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH);

}

注意他們如何調用之前創建的 erasePixel 方法。這些方法會繪制并擦除適當的槳。

主循環中還有更多邏輯。這是完整的代碼:

#include

#include

#include

#include

Adafruit_SSD1306 display(4);

int resolution[2] = {128, 64}, ball[2] = {20, (resolution[1] / 2)};

const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, SPEED = 3;

int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0;

char ballDirectionHori = ‘R’, ballDirectionVerti = ‘S’;

boolean inProgress = true;

void setup() {

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

display.display();

}

void loop() {

if (aiScore 》 9 || playerScore 》 9) {

// check game state

inProgress = false;

}

if (inProgress) {

eraseScore();

eraseBall(ball[0], ball[1]);

if (ballDirectionVerti == ‘U’) {

// move ball up diagonally

ball[1] = ball[1] - SPEED;

}

if (ballDirectionVerti == ‘D’) {

// move ball down diagonally

ball[1] = ball[1] + SPEED;

}

if (ball[1] 《= 0) { // bounce the ball off the top ballDirectionVerti = ‘D’; } if (ball[1] 》= resolution[1]) {

// bounce the ball off the bottom

ballDirectionVerti = ‘U’;

}

if (ballDirectionHori == ‘R’) {

ball[0] = ball[0] + SPEED; // move ball

if (ball[0] 》= (resolution[0] - 6)) {

// ball is at the AI edge of the screen

if ((aiPos + 12) 》= ball[1] && (aiPos - 12) 《= ball[1]) { // ball hits AI paddle if (ball[1] 》 (aiPos + 4)) {

// deflect ball down

ballDirectionVerti = ‘D’;

}

else if (ball[1] 《 (aiPos - 4)) {

// deflect ball up

ballDirectionVerti = ‘U’;

}

else {

// deflect ball straight

ballDirectionVerti = ‘S’;

}

// change ball direction

ballDirectionHori = ‘L’;

}

else {

// GOAL!

ball[0] = 6; // move ball to other side of screen

ballDirectionVerti = ‘S’; // reset ball to straight travel

ball[1] = resolution[1] / 2; // move ball to middle of screen

++playerScore; // increase player score

}

}

}

if (ballDirectionHori == ‘L’) {

ball[0] = ball[0] - SPEED; // move ball

if (ball[0] 《= 6) { // ball is at the player edge of the screen if ((playerPos + 12) 》= ball[1] && (playerPos - 12) 《= ball[1]) { // ball hits player paddle if (ball[1] 》 (playerPos + 4)) {

// deflect ball down

ballDirectionVerti = ‘D’;

}

else if (ball[1] 《 (playerPos - 4)) { // deflect ball up ballDirectionVerti = ‘U’; } else { // deflect ball straight ballDirectionVerti = ‘S’; } // change ball direction ballDirectionHori = ‘R’; } else { ball[0] = resolution[0] - 6; // move ball to other side of screen ballDirectionVerti = ‘S’; // reset ball to straight travel ball[1] = resolution[1] / 2; // move ball to middle of screen ++aiScore; // increase AI score } } } drawBall(ball[0], ball[1]); erasePlayerPaddle(playerPos); playerPos = analogRead(A2); // read player potentiometer playerPos = map(playerPos, 0, 1023, 8, 54); // convert value from 0 - 1023 to 8 - 54 drawPlayerPaddle(playerPos); moveAi(); drawNet(); drawScore(); } else { // somebody has won display.clearDisplay(); display.setTextSize(4); display.setTextColor(WHITE); display.setCursor(0, 0); // figure out who if (aiScore 》 playerScore) {

display.println(“YOU LOSE!”);

}

else if (playerScore 》 aiScore) {

display.println(“YOU WIN!”);

}

}

display.display();

}

void moveAi() {

// move the AI paddle

eraseAiPaddle(aiPos);

if (ball[1] 》 aiPos) {

++aiPos;

}

else if (ball[1] 《 aiPos) {

--aiPos;

}

drawAiPaddle(aiPos);

}

void drawScore() {

// draw AI and player scores

display.setTextSize(2);

display.setTextColor(WHITE);

display.setCursor(45, 0);

display.println(playerScore);

display.setCursor(75, 0);

display.println(aiScore);

}

void eraseScore() {

// erase AI and player scores

display.setTextSize(2);

display.setTextColor(BLACK);

display.setCursor(45, 0);

display.println(playerScore);

display.setCursor(75, 0);

display.println(aiScore);

}

void drawNet() {

for (int i = 0; i 《 (resolution[1] / WALL_WIDTH); ++i) {

drawPixel(((resolution[0] / 2) - 1), i * (WALL_WIDTH) + (WALL_WIDTH * i), WALL_WIDTH);

}

}

void drawPixel(int posX, int posY, int dimensions) {

// draw group of pixels

for (int x = 0; x 《 dimensions; ++x) {

for (int y = 0; y 《 dimensions; ++y) {

display.drawPixel((posX + x), (posY + y), WHITE);

}

}

}

void erasePixel(int posX, int posY, int dimensions) {

// erase group of pixels

for (int x = 0; x 《 dimensions; ++x) {

for (int y = 0; y 《 dimensions; ++y) {

display.drawPixel((posX + x), (posY + y), BLACK);

}

}

}

void erasePlayerPaddle(int row) {

erasePixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH);

erasePixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH);

erasePixel(0, row, PADDLE_WIDTH);

erasePixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH);

erasePixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH);

}

void drawPlayerPaddle(int row) {

drawPixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH);

drawPixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH);

drawPixel(0, row, PADDLE_WIDTH);

drawPixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH);

drawPixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH);

}

void drawAiPaddle(int row) {

int column = resolution[0] - PADDLE_WIDTH;

drawPixel(column, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH);

drawPixel(column, row - PADDLE_WIDTH, PADDLE_WIDTH);

drawPixel(column, row, PADDLE_WIDTH);

drawPixel(column, row + PADDLE_WIDTH, PADDLE_WIDTH);

drawPixel(column, row + (PADDLE_WIDTH * 2), PADDLE_WIDTH);

}

void eraseAiPaddle(int row) {

int column = resolution[0] - PADDLE_WIDTH;

erasePixel(column, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH);

erasePixel(column, row - PADDLE_WIDTH, PADDLE_WIDTH);

erasePixel(column, row, PADDLE_WIDTH);

erasePixel(column, row + PADDLE_WIDTH, PADDLE_WIDTH);

erasePixel(column, row + (PADDLE_WIDTH * 2), PADDLE_WIDTH);

}

void drawBall(int x, int y) {

display.drawCircle(x, y, BALL_SIZE, WHITE);

}

void eraseBall(int x, int y) {

display.drawCircle(x, y, BALL_SIZE, BLACK);

}

這是您最終得到的結果:

對代碼很有信心,您可以進行許多修改:

添加難度級別菜單(更改AI和球速)。

向其中添加一些隨機移動

為兩個玩家添加另一個底池。

添加一個暫停按鈕。

現在看看這些復古游戲Pi Zero項目。

責任編輯:wv

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 游戲機
    +關注

    關注

    9

    文章

    304

    瀏覽量

    34483
  • Arduino
    +關注

    關注

    190

    文章

    6498

    瀏覽量

    192037
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    【項目分享】Xii-Boy-Ultra 無線便攜式 Wii 游戲機

    Xii-Boy Ultra 是一款小型便攜式 Wii 游戲機,采用垂直布局設計。該系統允許用戶無需使用焊錫,僅用螺絲刀就能輕松組裝和拆卸。 Xii-Boy Ultra 是一款采用垂直布局、小巧
    發表于 07-14 17:27

    【VisionFive 2單板計算機試用體驗】VisionFive 2一個霸氣的游戲機

    這次的測試活動,每人人手送一個游戲機,非常的好啊!!! 很高興收到賽昉科技發放的VisionFive 2開發板,VisionFive 2是全球首款集成了3D GPU的高性能量產RISC-V
    發表于 07-13 20:41

    樹莓派復古游戲,你會選哪一個?

    復古游戲與樹莓派單板計算機的組合十分常見。在樹莓派項目列表中,幾乎都會包含至少一個復古游戲項目。復古游戲
    的頭像 發表于 06-16 16:56 ?190次閱讀
    樹莓派<b class='flag-5'>復古</b><b class='flag-5'>游戲</b>,你會選哪一個?

    無風扇迷你工控選購指南

    無風扇迷你工控是許多工業應用的重要工具,特別是隨著工業在自動化、人工智能和邊緣計算等領域朝著更集成、更堅固的計算解決方案發展。無論您是在尋找用于邊緣人工智能處理的無風扇迷你工控、工
    的頭像 發表于 06-04 14:28 ?207次閱讀
    無風扇<b class='flag-5'>迷你</b>工控<b class='flag-5'>機</b>選購指南

    用 Lakka 和 樹莓派 打造終客廳游戲機

    盡管現代樹莓派單板計算機(SBC)的規格有了大幅提升,但它們的性能仍不足以在4K分辨率下以60幀每秒(FPS)的速度運行3A級PC游戲。不過,那些老派游戲——尤其是為老式游戲機設計的游戲
    的頭像 發表于 05-27 15:35 ?217次閱讀
    用 Lakka 和 樹莓派 打造終客廳<b class='flag-5'>游戲機</b>!

    樹莓派復古游戲機:用科技重現經典,讓童年永不落幕!

    復古游戲機是一種能讓你玩經典游戲機上的視頻游戲的設備。有了復古游戲機,你可以玩來自Atari的《
    的頭像 發表于 03-25 09:28 ?493次閱讀
    樹莓派<b class='flag-5'>復古</b><b class='flag-5'>游戲機</b>:用科技重現經典,讓童年永不落幕!

    樹莓派復古游戲“雙雄會”,Batocera 和 RetroPie 誰更懂你?

    要點包括:1.歷史和主要特點:Batocera于2016年作為Recalbox分支推出,是開源復古游戲發行版,可將計算機變游戲機;RetroPie始于2012年,基
    的頭像 發表于 03-25 09:19 ?986次閱讀
    樹莓派<b class='flag-5'>復古</b><b class='flag-5'>游戲</b>“雙雄會”,Batocera 和 RetroPie 誰更懂你?

    N9300-S16 MP3解碼芯片IC在抓娃娃游戲機中的應用方案

    隨著科技發展,抓娃娃游戲機融入音樂芯片成為創新趨勢。音樂增強玩家代入感,音頻模塊N9300-S16提供高品質音效。該芯片功能豐富,支持多種控制模式,為抓娃娃游戲機帶來音頻體驗升級,推動行業創新發展。
    的頭像 發表于 03-24 13:37 ?405次閱讀
    N9300-S16 MP3解碼芯片IC在抓娃娃<b class='flag-5'>游戲機</b>中的應用方案

    游戲機與數碼相機的理想選擇:HT4088高性能充電芯片

    討論HT4088在高性能便攜式設備中的應用,如游戲機和數碼相機,提供快速充電解決方案。
    的頭像 發表于 03-13 17:24 ?488次閱讀
    <b class='flag-5'>游戲機</b>與數碼相機的理想選擇:HT4088高性能充電芯片

    樹莓派與Arduino的區別是什么

    Pi): 樹莓派最初是作為教育工具設計的,旨在幫助學生學習計算機編程和電子工程。隨著時間的推移,它已經發展成為一個多功能的微型計算機,可以用于各種項目,包括但不限于: 家庭媒體中心 游戲機 網絡服務器 IoT(物聯網)設備 教育和學習平臺 Arduino
    的頭像 發表于 11-11 11:14 ?2332次閱讀

    開源項目!基于Arduino做的“魷魚游戲”BOSS面具,支持動作檢測

    引腳分配: 舵機1:數字2 舵機2:數字3 舵機3:數字5 舵機4:數字6 舵機5:數字9 確保你的舵機有合適的外部電源供電,因為Arduino板載的5V供電不足以為多個舵機供電
    發表于 10-28 10:18

    索尼PS5 Pro游戲機震撼發布

    游戲界的萬眾矚目下,索尼于近日舉行的PS5技術展示會上,由首席架構師Mark Cerny親自揭曉了萬眾期待的PS5 Pro游戲機。這款全新力作以699美元的定價,定于11月7日盛大發售,無疑為游戲愛好者們帶來了前所未有的震撼與
    的頭像 發表于 09-11 16:59 ?1021次閱讀

    基于 FPGA 的飛機大戰游戲系統設計

    喜歡老式電子游戲的買家。一些愛好者一直在收集復古游戲產品,一些普通玩家也開始收集舊式磁帶和CD,還有小時候玩過的游戲機。 雖然復古
    發表于 07-24 20:03

    藍牙模塊在無線游戲設備中的應用

    了更多的樂趣和可能性。本文將探討藍牙模塊在無線游戲設備中的應用,并分析其對游戲產業的影響。 藍牙模塊在無線游戲設備中的基礎應用主要體現在設備間的無線連接和數據傳輸。通過藍牙模塊,游戲
    的頭像 發表于 07-19 14:00 ?572次閱讀

    使用ESP8266-01和Arduino SDK安裝AT固件失敗了怎么解決?

    ESP8266-01 運行不規則 LED 瘋狂閃爍,游戲機被垃圾淹沒。 有誰能這么好,引導我走上正確的道路?我對 ESP8266-01 很陌生。
    發表于 07-19 06:08