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

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

3天內(nèi)不再提示

如何使用Arduino和圖形LCD創(chuàng)建體面的游戲

科技觀察員 ? 來源:circuitdigest ? 作者:阿斯文斯·拉吉 ? 2022-11-15 17:29 ? 次閱讀

編程一直很有趣,使用Arduino等開發(fā)平臺變得更好。幾乎每個程序員都會嘗試使用他們學習/練習的語言開發(fā)某種游戲。這有助于他們以有趣而富有成效的方式調(diào)整他們的編程技能。自從我接觸到Arduino以來,我一直是它的忠實粉絲,并且一直想嘗試一些很酷的東西,當我發(fā)現(xiàn)像諾基亞5110這樣的圖形LCD和Arduino可以變得多么酷時,我開發(fā)游戲的想法開始了。這是一種有趣的方式,可以調(diào)整一些編程技能,同時又能獲得樂趣,所以盡管你們可能也對開發(fā)游戲感興趣。因此,在本教程中,我們將學習如何使用 Arduino 和圖形 LCD 創(chuàng)建體面的游戲。

游戲計劃:

在我們開始之前,計劃你的游戲的實際運作方式是非常重要的。我選擇了諾基亞5110圖形LCD和操縱桿作為我的硬件選擇。我假設(shè)在本教程中您也選擇了相同的內(nèi)容。由于諾基亞5110沒有太多空間,因此我們將整個游戲計劃在顯示器的84 * 48像素分辨率內(nèi)。

pYYBAGNzXAeAaWyjAACRpsduyjE213.jpg

在這個空間內(nèi),我們必須緊密地適應游戲區(qū)域和記分板區(qū)域,該區(qū)域?qū)@示分數(shù)等內(nèi)容。了解放置東西的像素位置非常重要,以跟蹤像素位置并在屏幕上更新它們。

一旦確定了游戲屏幕外觀,我們就必須決定游戲中的角色。對于我的游戲,我們只有兩個,玩家角色是一艘宇宙飛船,一個是敵人角色,它應該看起來像一艘外星飛船。諾基亞LCD可以顯示位圖圖像,所以我決定使用該選項來顯示我的宇宙飛船和敵人。

因此,我們將有一艘宇宙飛船正在穿越外星人的宇宙飛船,這艘宇宙飛船將有三條車道可以改變,以避免與外星人撞擊。在任何時候,外星人只能占據(jù)兩條軌道,玩家應該能夠開車穿過自由軌道。一旦這些想法結(jié)束,我們就可以繼續(xù)硬件,然后進行編程。

電路圖:

這款Arduino游戲的電路非常簡單;我們只需要將諾基亞5110 LCD模塊和操縱桿與Arduino連接即可。完整的電路圖如下所示

poYBAGNzXBCAWjw_AAFiPzpKMrg196.jpg

諾基亞 5110 LCD 與 3.3V 配合使用,操縱桿模塊使用 5V 工作,因此請確保僅使用 3.3V 連接 LCD,因為 5V 可能會永久損壞它。LCD通過SPI協(xié)議與Arduino通信,操縱桿僅讀取ADC以讀取電壓變化。連接設(shè)置如下所示

poYBAGNzXBKATHMkAADQf6qxo8c323.jpg

先決條件:

在我們深入研究編程部分之前,重要的是你們使用顯示模塊和操縱桿很方便,因此您可以使用以下教程來了解有關(guān)它們的更多信息,然后回到這里以確保事情按照我們需要的方式工作!

為太空競賽游戲編程Arduino:

游戲的完整程序可以在本頁末尾找到;您可以直接在Arduino IDE上使用它并將其上傳到Board。但是,如果您想知道代碼中實際發(fā)生了什么,請進一步閱讀。

與往常一樣,我們從添加庫頭文件開始程序,我們需要為這個項目提供三個庫,默認情況下,SPI 庫會添加到您的 IDE 中。另外兩個庫必須從Adafruit Github頁面下載。如果您不確定如何添加庫,請按照先決條件部分中提到的 LCD 接口教程進行操作。

#include //SPI librarey for Communication

#include //Graphics lib for LCD

#include //Nokia 5110 LCD library

如果您遵循了本教程,您應該知道可以在LCD中顯示位圖圖像。因此,我們必須使用教程中提到的軟件將所需的圖像轉(zhuǎn)換為位圖代碼,您可以從Internet中選擇任何圖像并通過將它們轉(zhuǎn)換為位圖代碼來使用它。確保圖像足夠簡單,可以顯示在我們的LCD屏幕上,在實際嘗試LCD屏幕之前檢查預覽。在我們的程序中,我們使用了兩個位圖字符,一個是宇宙飛船,另一個是敵方飛船,兩者的位圖代碼都添加到我們的代碼中,如下所示。

//Bitmap Data for SpaceShip

static const unsigned char PROGMEM ship[] =

{

B00000000,B00000000,

B00000001,B00000000,

B00000011,B10000000,

B00000010,B10000000,

B00000010,B11000000,

B00000111,B11000000,

B00001101,B11100000,

B00011111,B11110000,

B00111111,B11111000,

B01111111,B11111100,

B01111111,B11111100,

B01111111,B11111100,

B00011111,B11110000,

B00000111,B11100000,

B00000000,B00000000,

};

//Bitmap Data for enemyship

static const unsigned char PROGMEM enemy[] =

{

B00000101,B11000000,

B00001011,B11100000,

B00000011,B11100000,

B00110011,B11111000,

B01111111,B11111100,

B10111111,B11111010,

B01110111,B11011100,

B01111110,B11111100,

B00111111,B11111100,

B11101111,B11101110,

B11000001,B00000110,

B10000001,B00000010,

B10000000,B00000010,

B00000000,B00000000,

};

我們必須指定諾基亞LCD 5110顯示器連接到的引腳。顯示器使用SPI通信進行通信,如果您遵循了上面的電路圖,則初始化LCD的代碼將如下所示,您無需更改它。

Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); //Specifiy the pins to which the LCD is connected

在設(shè)置功能中,我們只需以9600波特率啟動串行監(jiān)視器,以便我們可以調(diào)試內(nèi)容,然后初始化LCD顯示。我們還必須設(shè)置LCD顯示器的對比度,每個顯示器在不同的對比度水平下效果最好,因此請使用該值來檢查哪個最適合您。最后,我們還清除顯示屏以重新開始。

void setup() {

Serial.begin(9600); //Serial Monitor for Debugging

display.begin(); //Begin the LCD communication

display.setContrast(30); //Set the contrast of the display

display.clearDisplay(); // clears the screen and start new

}

清除屏幕后,我們立即跳入循環(huán)功能,然后顯示游戲屏幕。游戲屏幕只不過是顯示游戲的基本骨架以及分數(shù)和速度級別。我們使用線條功能繪制三條線作為邊框,并在右側(cè)顯示文本分數(shù)和速度,就像舊的復古手持游戲設(shè)備一樣。

void gamescreen()

{

//Draw the Border for Screen

display.drawLine(0, 0, 0, 47, BLACK);

display.drawLine(50, 0, 50, 47, BLACK);

display.drawLine(0, 47, 50, 47, BLACK);

//Enter Default Texts

display.setTextSize(1);

display.setTextColor(BLACK);

display.setCursor(52,2);

display.println("Speed");

display.setCursor(54,12);

display.println(game_speed);

display.setCursor(52,25);

display.println("Score");

display.setCursor(54,35);

display.println(score);

}

接下來,我們必須從用戶那里獲得輸入,以允許他/她控制宇宙飛船。輸入將從連接到引腳 A1 的操縱桿模塊接收。如果不移動,傳感器模擬值將為 512,沿 X 軸移動時將增加和減少。我們使用這些值來確定用戶是要向左還是向右移動。如果您發(fā)現(xiàn)難以理解以下程序,您應該閱讀先決條件中提到的與 Arduino 接口的操縱桿接口教程。

//Get input from user

Joy_X = analogRead(A1); //Read the X vaue from Joystick

if (Joy_X < 312 && POS!=1 && control==true) //If joy stick moves right

{ POS--; control = false;} //Decrement position of spaceship

else if (Joy_X > 712 && POS!=3 && control==true) //If joy stick moves right

{ POS++; control = false;} //Increment position of spaceship

else if (Joy_X >502 && Joy_X<522) //If joystick back to initial position

control = true; //Preare it for next move

//Input from user received

從用戶那里獲得宇宙飛船的位置后,我們必須將宇宙飛船放置在該特定位置。我們使用以下函數(shù)并將位置值作為參數(shù)傳遞,然后根據(jù)位置將宇宙飛船放置在其各自的軌道上。

void player_car(char pos) //Place the spaceship based on the user selected position

{

if (pos==1)

display.drawBitmap(2, 32, ship, 15, 15, BLACK);

if (pos==2)

display.drawBitmap(18, 32, ship, 15, 15, BLACK);

if (pos==3)

display.drawBitmap(34, 32, ship, 15, 15, BLACK);

}

現(xiàn)在我們的飛船已經(jīng)放在屏幕上并準備好參加比賽,我們必須介紹將與玩家一起競爭的敵艦。每當一艘敵艦越過屏幕時,我們都會假設(shè)他已經(jīng)死了,當他死了時,我們必須制造一艘新的宇宙飛船。下面的函數(shù)也做同樣的事情。它為兩艘敵艦創(chuàng)建一個新位置,并將它們放置在屏幕頂部。

if (enemy_dead) //Check of enemy ships are dead

{ //If they are dead

enemy_0_pos = POS; //create first enemy above the space ship

enemy_1_pos = random(0,4); //create secound enemy at some other random place

enemy_phase = 0; //Bring the enemy form the top

enemy_dead = false; //Enemy is created so they are not dead anymore

}

將敵艦放在屏幕頂部后,我們必須將其放下,使其像我們的玩家正在向上奔跑一樣長矛,為此,我們只需要增加相位(顯示圖像的位置),以便它慢慢下降。對兩艘敵艦都做了同樣的事情,如下所示

enemy_ship (enemy_0_pos,enemy_phase); enemy_phase++; //Place the first enemy on screen and drive him down

enemy_ship (enemy_1_pos,enemy_phase); enemy_phase++; //Place the secound enemy on screen and drive him down

函數(shù)enemy_ship如下所示,它與播放器汽車函數(shù)非常相似,但這里我們有兩個參數(shù)。一種是將敵人放在軌道上,另一種是將敵人移動到底部。

void enemy_ship(int place, int phase) //Place the enemy_ship in the new place and phase

{

if (place==1)

display.drawBitmap(2, phase, enemy, 15, 15, BLACK);

if (place==2)

display.drawBitmap(18, phase, enemy, 15, 15, BLACK);

if (place==3)

display.drawBitmap(34, phase, enemy, 15, 15, BLACK);

}

下一段代碼應該檢查宇宙飛船是否避開了敵艦。要檢查這一點,我們需要知道敵艦和玩家的宇宙飛船的位置。既然我們知道了這一切,我們只需要檢查宇宙飛船的位置是否與敵艦相同。只有當敵艦到達宇宙飛船附近時,我們才會檢查這一點。如果玩家沒有避開敵人,則意味著游戲結(jié)束。

if (enemy_phase>22 && ((enemy_0_pos == POS) || (enemy_1_pos == POS)) ) //If the Spaceship touches any one of the enemy

game_over(); //Display game over

如果玩家成功避開了敵人,那么我們應該殺死敵人并給玩家一分。為此,我們只需檢查敵人是否已到達屏幕底部,如果是,我們將使用以下代碼將其殺死

if (enemy_phase>40) //If thespace ship escapes the enemies

{enemy_dead = true; score++;} //Increase the score and kill the enemies

如果我們在獲得高分時不增加游戲的難度,那將是多么有趣。因此,我們使用另一個功能來監(jiān)控玩家的分數(shù),并根據(jù)分數(shù)提高游戲速度。速度實際上是通過使用延遲功能來控制的,這將控制游戲的刷新間隔,從而使它變得快或慢。

void Level_Controller() //Increase the speed of game based on the score.

{

if (score>=0 && score<=10) //If score 0-10

{

game_speed = 0; delay(80); //slow the game by 80ms

}

if (score>10 && score<=20) //If score 10-40

{

game_speed = 1; delay(70); //slow the game by 70ms

}

if (score>20 && score<=30) //If score 20-40

{

game_speed = 2; delay(60); //slow the game by 60ms

}

if (score>30 && score<=40) //If score 30-40

{

game_speed = 3; delay(50); //slow the game by 50ms

}

}

Arduino太空賽車游戲工作:

在確保了解硬件和程序后,只需構(gòu)建電路并將代碼上傳到Arduino板即可。您應該注意到游戲開始,如下所示

pYYBAGNzXBWAVm8mAACzuuYSUsA314.jpg

使用操縱桿通過向左或向右移動來逃離敵艦。為了避開每個敵人,你的分數(shù)會增加一個。當分數(shù)變高時,游戲的速度也會增加,也就是說,每獲得 10 分,速度就會增加 10 毫秒。您可以繼續(xù)在此游戲的基礎(chǔ)上引入新的關(guān)卡,或者每個人都使用加速度計進行一些硬件更改以通過運動來控制它。

/* SPACE RACE Game using Arduino and Nokia 5110 LCD

* Coded by: Aswinth Raj

* Input -> Joystick (A0,A1)

*/


#include //SPI librarey for Communication

#include //Graphics lib for LCD

#include //Nokia 5110 LCD librarey

//Bitmap Data for SpaceShip

static const unsigned char PROGMEM ship[] =

{

B00000000,B00000000,

B00000001,B00000000,

B00000011,B10000000,

B00000010,B10000000,

B00000010,B11000000,

B00000111,B11000000,

B00001101,B11100000,

B00011111,B11110000,

B00111111,B11111000,

B01111111,B11111100,

B01111111,B11111100,

B01111111,B11111100,

B00011111,B11110000,

B00000111,B11100000,

B00000000,B00000000,

};


//Bitmap Data for enemyship

static const unsigned char PROGMEM enemy[] =

{

B00000101,B11000000,

B00001011,B11100000,

B00000011,B11100000,

B00110011,B11111000,

B01111111,B11111100,

B10111111,B11111010,

B01110111,B11011100,

B01111110,B11111100,

B00111111,B11111100,

B11101111,B11101110,

B11000001,B00000110,

B10000001,B00000010,

B10000000,B00000010,

B00000000,B00000000,

};


Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); //Specifiy the pins to which the LCD is connected


int enemy_0_pos, enemy_1_pos, enemy_phase;

int Joy_X;

int game_speed = 0;

int score = 0;

char POS=2;

boolean enemy_dead = true;

boolean control = true;


void setup() {

Serial.begin(9600); //Serial Monitor for Debugging


display.begin(); //Begin the LCD communication

display.setContrast(30); //Set the contrast of the display

display.clearDisplay(); // clears the screen and start new

}


void loop() {

display.clearDisplay(); // clears the screen and start new


gamescreen(); //Displays the box, score and speed values


//Get input from user

Joy_X = analogRead(A1); //Read the X vaue from Joystick

if (Joy_X < 312 && POS!=1 && control==true) //If joy stick moves right?

{ POS--; control = false;} //Decrement position of spaceship

else if (Joy_X > 712 && POS!=3 && control==true) //If joy stick moves right

{ POS++; control = false;} //Increment position of spaceship

else if (Joy_X >502 && Joy_X<522) //If joystick back to initial position?

control = true; //Preare it for next move

//Input from user received




player_car(POS); //Place the Space ship based on the input from user


if (enemy_dead) //Check of enemy ships are dead

{ //If they are dead

enemy_0_pos = POS; //create first enemy above the space ship

enemy_1_pos = random(0,4); //create secound enemy at some other random place

enemy_phase = 0; //Bring the enemy form the top

enemy_dead = false; //Enemy is created so they are not dead anymore

}


enemy_ship (enemy_0_pos,enemy_phase); enemy_phase++; //Place the first enemy on screen and drive him down

enemy_ship (enemy_1_pos,enemy_phase); enemy_phase++; //Place the secound enemy on screen and drive him down


if (enemy_phase>22 && ((enemy_0_pos == POS) || (enemy_1_pos == POS)) ) //If the Spaceship touches any one of the enemy

game_over(); //Display game over



if (enemy_phase>40) //If thespace ship escapes the enemys

{enemy_dead = true; score++;} //Increase the score and kill the enemys


Level_Controller(); //BAsed on score increase the speed of game




display.display(); //Update the display with all the changes made so far

}


void Level_Controller() //Increase the speed of game based on the score.

{

if (score>=0 && score<=10) //If score 0-10 ?

{

game_speed = 0; delay(80); //slow the game by 80ms

}

if (score>10 && score<=20) //If score 10-40 ?

{

game_speed = 1; delay(70); //slow the game by 70ms

}

if (score>20 && score<=30) //If score 20-40 ?

{

game_speed = 2; delay(60); //slow the game by 60ms

}

if (score>30 && score<=40) //If score 30-40 ?

{

game_speed = 3; delay(50); //slow the game by 50ms

}

}


void enemy_ship(int place, int phase) //Place the enemy_ship in the new place and phase

{

if (place==1)

display.drawBitmap(2, phase, enemy, 15, 15, BLACK);


if (place==2)

display.drawBitmap(18, phase, enemy, 15, 15, BLACK);


if (place==3)

display.drawBitmap(34, phase, enemy, 15, 15, BLACK);

}


void game_over() //Display game over screen

{

while(1) //The program will be stuck here for ever

{

delay(100);

display.clearDisplay();

display.setCursor(20,2);

display.println("GAME OVER");



display.display();

}

}


void gamescreen()

{

//Draw the Border for Screen

display.drawLine(0, 0, 0, 47, BLACK);

display.drawLine(50, 0, 50, 47, BLACK);

display.drawLine(0, 47, 50, 47, BLACK);


//Enter Default Texts

display.setTextSize(1);

display.setTextColor(BLACK);

display.setCursor(52,2);

display.println("Speed");

display.setCursor(54,12);

display.println(game_speed);

display.setCursor(52,25);

display.println("Score");

display.setCursor(54,35);

display.println(score);

}


void player_car(char pos) //Place the spaceship based on the user selected position

{

if (pos==1)

display.drawBitmap(2, 32, ship, 15, 15, BLACK);


if (pos==2)

display.drawBitmap(18, 32, ship, 15, 15, BLACK);


if (pos==3)

display.drawBitmap(34, 32, ship, 15, 15, BLACK);

}

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • lcd
    lcd
    +關(guān)注

    關(guān)注

    34

    文章

    4363

    瀏覽量

    166195
  • Arduino
    +關(guān)注

    關(guān)注

    187

    文章

    6453

    瀏覽量

    185927
收藏 人收藏

    評論

    相關(guān)推薦

    請問怎么實現(xiàn)arduino圖形界面編程?

    arduino圖形界面編程,比如很簡單的例子,我用c++編程個程序界面,然后通過點擊圖形界面的按鈕實現(xiàn)arduino控制相關(guān)動作,比如說led燈亮,電機旋轉(zhuǎn)! 求大神指教,或推薦相
    發(fā)表于 05-22 03:58

    使用arduino pro micro制作一個游戲控制器

    描述基于 Arduino 的 DIY 游戲控制器 | Arduino PS2 游戲控制器大家好,玩游戲總是很有趣,但是用自己的 DIY 自定
    發(fā)表于 09-01 06:38

    圖形點陣LCD液晶模塊顯示界面的可視化編程方案與實踐

    圖形點陣LCD液晶模塊顯示界面的可視化編程方案與實踐 隨著圖形點陣LCD液晶顯示模塊在各行各業(yè)的逐步使用,使得人機界面變得越來越直觀,尤其
    發(fā)表于 11-05 09:16 ?1045次閱讀
    <b class='flag-5'>圖形</b>點陣<b class='flag-5'>LCD</b>液晶模塊顯示界<b class='flag-5'>面的</b>可視化編程方案與實踐

    Arduino教程_Arduino圖形化編程教程_ArduBlock

    Arduino教程_Arduino圖形化編程軟件_ArduBlock
    發(fā)表于 09-25 09:22 ?0次下載
    <b class='flag-5'>Arduino</b>教程_<b class='flag-5'>Arduino</b><b class='flag-5'>圖形</b>化編程教程_ArduBlock

    LCD圖形生成工具

    LCD圖形生成工具
    發(fā)表于 12-01 16:44 ?13次下載

    ARDUINO LCD

    ARDUINO LCD
    發(fā)表于 01-22 17:33 ?13次下載

    如何使用Arduino制作Buzz Wire游戲

    Arduino 在構(gòu)建愛好項目和游戲方面非常受歡迎,我們之前使用 Arduino 構(gòu)建過貪吃蛇游戲、乒乓球游戲、太空競賽
    的頭像 發(fā)表于 08-17 16:50 ?2104次閱讀
    如何使用<b class='flag-5'>Arduino</b>制作Buzz Wire<b class='flag-5'>游戲</b>

    使用Arduino創(chuàng)建

    電子發(fā)燒友網(wǎng)站提供《使用Arduino創(chuàng)建庫.zip》資料免費下載
    發(fā)表于 11-08 14:37 ?0次下載
    使用<b class='flag-5'>Arduino</b><b class='flag-5'>創(chuàng)建</b>庫

    arduino創(chuàng)建一個游戲控制器

    電子發(fā)燒友網(wǎng)站提供《用arduino創(chuàng)建一個游戲控制器.zip》資料免費下載
    發(fā)表于 11-10 11:21 ?1次下載
    用<b class='flag-5'>arduino</b><b class='flag-5'>創(chuàng)建</b>一個<b class='flag-5'>游戲</b>控制器

    TinkerCad電路上的Arduino LCD游戲

    電子發(fā)燒友網(wǎng)站提供《TinkerCad電路上的Arduino LCD游戲.zip》資料免費下載
    發(fā)表于 11-11 11:21 ?4次下載
    TinkerCad電路上的<b class='flag-5'>Arduino</b> <b class='flag-5'>LCD</b><b class='flag-5'>游戲</b>

    Arduino Esplora LCD屏幕實施的生命游戲交互式實施

    電子發(fā)燒友網(wǎng)站提供《為Arduino Esplora LCD屏幕實施的生命游戲交互式實施.zip》資料免費下載
    發(fā)表于 11-16 10:08 ?0次下載
    為<b class='flag-5'>Arduino</b> Esplora <b class='flag-5'>LCD</b>屏幕實施的生命<b class='flag-5'>游戲</b>交互式實施

    Arduino微控制器使用而創(chuàng)建的Connect 4游戲

    電子發(fā)燒友網(wǎng)站提供《與Arduino微控制器使用而創(chuàng)建的Connect 4游戲.zip》資料免費下載
    發(fā)表于 11-24 14:41 ?0次下載
    與<b class='flag-5'>Arduino</b>微控制器使用而<b class='flag-5'>創(chuàng)建</b>的Connect 4<b class='flag-5'>游戲</b>

    基于ArduinoLCD上的小游戲

    方案介紹所需的部件如上圖所示。從沒有電源的Arduino開始。請勿插入USB電纜。這將在以后的步驟中進行編程和嘗試游戲。連接 使用長連接線將Arduino上的5V信號連接到面包板頂部紅色行的最左
    發(fā)表于 12-30 14:31 ?1次下載

    創(chuàng)建Arduino字時鐘

    電子發(fā)燒友網(wǎng)站提供《創(chuàng)建Arduino字時鐘.zip》資料免費下載
    發(fā)表于 02-03 11:00 ?2次下載
    <b class='flag-5'>創(chuàng)建</b><b class='flag-5'>Arduino</b>字時鐘

    使用Arduino驅(qū)動LCD的DIY指南

    利用Arduino驅(qū)動LCD顯示屏?目的本教程描述了如何使用Arduino驅(qū)動LCD顯示屏。
    的頭像 發(fā)表于 02-24 09:51 ?4602次閱讀
    使用<b class='flag-5'>Arduino</b>驅(qū)動<b class='flag-5'>LCD</b>的DIY指南