一板网电子技术论坛

风筝
发表于: 2018-5-22 14:56:58 | 显示全部楼层

编程一直是一项非常有趣的工作,使用像Arduino这样的开发平台会更加有趣。几乎所有的程序员都会尝试使用他们学习/练习的语言来开发某种游戏。这有助于他们以有趣而富有成效的方式调整自己的编程技巧。自从我认识它之后,一直是Arduino的忠实拥趸,并且一直想要尝试一些酷酷的东西,当我发现一起使用像诺基亚5110这样的图形液晶显示器和Arduino开发板是那么酷的事情时,开发游戏的想法开始实施。这是一个有趣的方式来调整一些编程技巧,同时玩得开心,同样你们也可以对开发你的游戏感兴趣。因此,在本教程中,我们将学习如何使用Arduino和图形LCD创建平面游戏。


我们已经使用Arduino开发板制作了老式的Snake游戏,所以这次我们尝试了一些新的东西,并且将此游戏命名为太空竞赛,您需要使用操纵杆使您的船舶免受敌方船只的伤害。


游戏设计

在我们开始之前,设计你的游戏如何实际工作是非常重要的。我选择了诺基亚5110图形液晶显示器和操纵杆作为硬件。由于诺基亚5110没有很大的空间,我们已经在显示器的84×48像素分辨率内规划了整个游戏。

nokia-5110-graphical-lcd-display.jpg


在这个游戏中,我们必须使用游戏区域,以及在比分板区域显示比分等。了解像素放置位置的位置非常重要,以便跟踪像素位置并在屏幕上更新它们。


一旦游戏画面出现,我们必须决定游戏中的角色。对于我的比赛,我们只有两名球员角色,一名太空飞船和一名敌人角色,应该看起来像一艘外星飞船。诺基亚LCD可以显示位图图像,所以我决定使用该选项来显示我的太空飞船和敌人。


因此,我们将有一艘太空飞船通过外星人太空船进行比赛,为了避免与外星人撞击,这艘太空船将有三条航道改变。在任何时候,外星人只能占据两条赛道,玩家应该可以驾驶自由赛道。一旦这些想法得出结论,我们可以继续进行硬件和编程。


电路原理图

这款Arduino游戏的电路非常简单,我们只需要将诺基亚5110液晶显示模块和操纵杆与Arduino连接起来。完整的电路图如下所示

Space-Race-Game-Circuit-diagram-using-Arduino-and-Nokia-5110-Graphical-Display.jpg


诺基亚5110液晶显示器可以在3.3V电压下工作,操纵杆模块可以工作在5V电压下,因此请确保只连接3.3V的LCD,因为5V会永久损坏。 LCD通过SPI协议与Arduino通信,操纵杆只读取ADC读取电压变化。连接设置将如下所示

Space-Race-Game-Circuit-hardware.jpg


编程Arduino太空竞赛游戏

游戏的完整程序可以在本页末尾找到;您可以直接在您的Arduino IDE上使用它并将其上传到您的开发板。


和往常一样,我们通过添加我们的库头文件来开始我们的程序,我们需要三个用于此项目的库,其中SPI库默认添加到您的IDE中。另外两个库必须从Adafruit Github页面下载。如果您不确定如何添加库,请按照前提条件部分中提到的LCD接口教程进行操作。

  1. #include <SPI.h> //SPI librarey for Communication
  2. #include <Adafruit_GFX.h> //Graphics lib for LCD
  3. #include <Adafruit_PCD8544.h> //Nokia 5110 LCD library
复制代码

如果您已经按照教程,您应该知道可以在LCD中显示位图图像。因此,我们必须使用教程中提到的软件将所需的图像转换为位图代码,您可以从互联网上选择任何图像,并通过将其转换为位图代码来使用它。确保图像足够简单,可以显示在我们的液晶显示屏上,在实际尝试液晶显示屏之前检查预览。在我们的程序中,我们使用了两个位图字符,一个是太空船,另一个是敌方船,两者的位图代码被添加到我们的代码中,如下所示。

  1. //Bitmap Data for SpaceShip
  2. static const unsigned char PROGMEM ship[] =
  3. {
  4. B00000000,B00000000,
  5. B00000001,B00000000,
  6. B00000011,B10000000,
  7. B00000010,B10000000,
  8. B00000010,B11000000,
  9. B00000111,B11000000,
  10. B00001101,B11100000,
  11. B00011111,B11110000,
  12. B00111111,B11111000,
  13. B01111111,B11111100,
  14. B01111111,B11111100,
  15. B01111111,B11111100,
  16. B00011111,B11110000,
  17. B00000111,B11100000,
  18. B00000000,B00000000,
  19. };

  20. //Bitmap Data for enemyship
  21. static const unsigned char PROGMEM enemy[] =
  22. {
  23. B00000101,B11000000,
  24. B00001011,B11100000,
  25. B00000011,B11100000,
  26. B00110011,B11111000,
  27. B01111111,B11111100,
  28. B10111111,B11111010,
  29. B01110111,B11011100,
  30. B01111110,B11111100,
  31. B00111111,B11111100,
  32. B11101111,B11101110,
  33. B11000001,B00000110,
  34. B10000001,B00000010,
  35. B10000000,B00000010,
  36. B00000000,B00000000,
  37. };
复制代码

我们必须指定诺基亚LCD 5110显示器所连接的引脚。如果按照上面的电路图进行显示,则使用SPI通信进行通信,LCD初始化代码如下所示,不需要更改。

  1. Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); //Specifiy the pins to which the LCD is connected
复制代码

setup函数中,我们只需以9600波特率启动串行监视器,以便我们可以调试内容并初始化LCD显示。我们还必须设置LCD显示屏的对比度,每个显示屏在不同的对比度下都能发挥最佳效果,所以请使用该值来检查哪种最适合您。最后,我们还清除显示屏幕以重新开始。

  1. void setup()   {
  2.   Serial.begin(9600); //Serial Monitor for Debugging
  3.   display.begin(); //Begin the LCD communication
  4.   display.setContrast(30); //Set the contrast of the display
  5.   display.clearDisplay();   // clears the screen and start new
  6. }
复制代码

一旦屏幕被清除,我们跳进loop函数,在那里我们显示游戏屏幕。游戏画面不过是显示游戏的基本框架以及分数和速度等级。我们已经使用线条功能绘制三条线作为边界,右边我们显示文本得分和速度,就像旧复古手持游戏设备一样。

  1. void gamescreen()
  2. {

  3. //Draw the Border for Screen
  4.   display.drawLine(0, 0, 0, 47, BLACK);
  5.   display.drawLine(50, 0, 50, 47, BLACK);
  6.   display.drawLine(0, 47, 50, 47, BLACK);

  7. //Enter Default Texts
  8.   display.setTextSize(1);
  9.   display.setTextColor(BLACK);
  10.   display.setCursor(52,2);
  11.   display.println("Speed");
  12.   display.setCursor(54,12);
  13.   display.println(game_speed);
  14.   display.setCursor(52,25);
  15.   display.println("Score");
  16.   display.setCursor(54,35);
  17.   display.println(score);
  18. }
复制代码

接下来,我们必须从用户那里获得输入,以允许他/她控制太空船。输入将从连接到引脚A1的操纵杆模块接收。如果传感器的模拟值没有移动,则它的模拟值将为512,并且在沿着X轴移动时会增加和减少。我们使用这些值来确定用户是想要移动到左边还是右边。

  1.   //Get input from user
  2.   Joy_X = analogRead(A1); //Read the X vaue from Joystick
  3.   if (Joy_X < 312 && POS!=1 && control==true) //If joy stick moves right
  4.   { POS--; control = false;} //Decrement position of spaceship
  5.   else if (Joy_X > 712 && POS!=3 && control==true) //If joy stick moves right
  6.   { POS++; control = false;} //Increment position of spaceship
  7.   else if (Joy_X >502 && Joy_X<522) //If joystick back to initial position
  8.   control = true; //Preare it for next move
  9.   //Input from user received
复制代码

在从用户处获得太空飞船的位置之后,我们必须将太空船放置在该特定位置。我们使用下面的函数,并传递位置值作为参数,然后根据太空船的位置放置在各自的轨道上。

  1. void player_car(char pos) //Place the spaceship based on the user selected position
  2. {
  3.   if (pos==1)
  4.   display.drawBitmap(2, 32, ship, 15, 15, BLACK);

  5.   if (pos==2)
  6.   display.drawBitmap(18, 32, ship, 15, 15, BLACK);

  7.   if (pos==3)
  8.   display.drawBitmap(34, 32, ship, 15, 15, BLACK);
  9. }
复制代码

现在我们的飞船被放置在屏幕上并准备好参加比赛,我们必须介绍将与玩家一起参赛的敌方船只。每次敌舰穿越萤幕时,我们都认为他已经死了,当他死了的时候,我们必须制造一艘新的太空船。下面的功能也是一样的。它为两艘敌方船只创造了一个新的位置并将它们放置在屏幕的顶部。

  1.   if (enemy_dead) //Check of enemy ships are dead
  2.   { //If they are dead
  3.   enemy_0_pos = POS; //create first enemy above the space ship
  4.   enemy_1_pos = random(0,4); //create secound enemy at some other random place
  5.   enemy_phase = 0; //Bring the enemy form the top
  6.   enemy_dead = false; //Enemy is created so they are not dead anymore
  7.   }
复制代码

在将敌舰放在屏幕的顶部之后,我们必须把它放下来,这样它就好像我们的玩家向上飞行一样,为此我们只需要增加相位(图像显示的位置),这样它慢慢下降。如下所示,对敌方船只也是如此

  1. enemy_ship (enemy_0_pos,enemy_phase); enemy_phase++; //Place the first enemy on screen and drive him down
  2.   enemy_ship (enemy_1_pos,enemy_phase); enemy_phase++; //Place the secound enemy on screen and drive him down
复制代码

函数enemy_ship如下所示,它与player_car函数非常相似,但在这里我们有两个参数。一种是将敌人放在轨道上,另一种是将敌人移向底部。

  1. void enemy_ship(int place, int phase) //Place the enemy_ship in the new place and phase
  2. {
  3.   if (place==1)
  4.   display.drawBitmap(2, phase, enemy, 15, 15, BLACK);

  5. if (place==2)
  6.   display.drawBitmap(18, phase, enemy, 15, 15, BLACK);

  7.   if (place==3)
  8.   display.drawBitmap(34, phase, enemy, 15, 15, BLACK);
  9. }
复制代码

下一段代码应该检查太空船是否已经避开了敌舰。为了检查这一点,我们需要知道敌方船只和玩家的太空飞船的位置。因为我们知道我们只需要检查太空船的位置是否与敌舰一样。只有当敌舰靠近太空船时我们才会检查。如果玩家没有回避敌人,那就意味着游戏结束。  

  1.   if (enemy_phase>22 && ((enemy_0_pos == POS) || (enemy_1_pos == POS)) ) //If the Spaceship touches any one of the enemy
  2.   game_over(); //Display game over
复制代码

如果玩家成功避开了敌人,那么我们应该杀死敌人并给玩家一分。要做到这一点,我们只需检查敌人是否已经到达屏幕的底部,如果有,我们使用下面的代码杀死它

  1.   if (enemy_phase>40) //If thespace ship escapes the enemies
  2.   {enemy_dead = true; score++;} //Increase the score and kill the enemies
复制代码

如果我们不会因为获得高分而增加游戏难度,那将会是多么有趣。所以我们使用另一个函数来监控玩家的分数,并根据分数来提高游戏的速度。速度实际上是通过使用延迟功能来控制的,这将控制游戏的刷新间隔,从而使其变快或变慢。

  1. void   Level_Controller() //Increase the speed of game based on the score.
  2. {
  3.   if (score>=0 && score<=10) //If score 0-10
  4.   {
  5.     game_speed = 0; delay(80); //slow the game by 80ms
  6.   }
  7.     if (score>10 && score<=20) //If score 10-40
  8.   {
  9.     game_speed = 1; delay(70); //slow the game by 70ms
  10.   }
  11.     if (score>20 && score<=30) //If score 20-40
  12.   {
  13.     game_speed = 2; delay(60); //slow the game by 60ms
  14.   }
  15.     if (score>30 && score<=40) //If score 30-40
  16.   {
  17.     game_speed = 3; delay(50); //slow the game by 50ms
  18.   }
  19. }
复制代码

Arduino Space Racer游戏工作过程

在确认了硬件和程序后,只需构建电路并将代码上传到Arduino开发板即可。你应该注意到游戏开始如下所示

Space-Race-Game-using-Arduino-and-Nokia-5110-Graphical-Display.jpg


通过向左或向右移动使用操纵杆逃脱敌方飞船。 为了避免每个敌人,你会得到你的分数增加1。 当比分变高时,比赛的速度也会增加,也就是说,每得到10分,速度就会增加10毫秒。 你可以继续前进,在这个游戏的基础上引入新的关卡或者每一个硬件改动来控制它,而不是使用加速度计运动。 创造力是唯一的限制。


希望你了解这个项目并且喜欢制作它。 如果您在开展此项工作时遇到任何问题,请随时在下面进行回复!


代码

本文使用的完整代码如下: main.txt (5.36 KB, 下载次数: 68)

跳转到指定楼层
代登辉
发表于: 2019-2-27 22:59:49 | 显示全部楼层

'display' was not declared in this scope
这是怎么回事?
回复

使用道具 举报

代登辉
发表于: 2019-2-28 00:29:37 | 显示全部楼层

另外两个库找不到,请楼主分享一下链接
回复

使用道具 举报

风筝
发表于: 2019-2-28 09:58:00 | 显示全部楼层

代登辉 发表于 2019-2-28 00:29
另外两个库找不到,请楼主分享一下链接

Adafruit_GFX的下载地址链接:https://github.com/adafruit/Adafruit-GFX-Library

Adafruit_PCD8544的下载地址链接:https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library


在Github页面中选择Download ZIP进行下载,以下是两个文件:

Adafruit-GFX-Library-master.zip (310.19 KB, 下载次数: 18)

回复

使用道具 举报

代登辉
发表于: 2019-2-28 23:23:19 | 显示全部楼层

风筝 发表于 2019-2-28 09:58
Adafruit_GFX的下载地址链接:https://github.com/adafruit/Adafruit-GFX-LibraryAdafruit_PCD8544的下载 ...

谢谢
回复

使用道具 举报

qsxza
发表于: 2019-5-8 21:00:55 | 显示全部楼层

这个摇杆怎么连接的?
回复

使用道具 举报

ICCCCC
发表于: 2019-5-26 09:30:19 | 显示全部楼层

为什么代码上传成功了5110什么都不显示啊
回复

使用道具 举报

ICCCCC
发表于: 2019-5-26 10:50:40 | 显示全部楼层

WARNING: Spurious .github folder in 'Adafruit PCD8544 Nokia 5110 LCD library' library
求教这个警告怎么消除啊
回复

使用道具 举报

pufan
发表于: 2019-6-12 11:03:31 | 显示全部楼层

ICCCCC 发表于 2019-5-26 09:30
为什么代码上传成功了5110什么都不显示啊

找到问题了么?为什么不显示?我的也不显示
回复

使用道具 举报

45367111
发表于: 2019-7-3 18:31:51 | 显示全部楼层

感谢大佬分享的教程,结课作业获得了老师的赞赏
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 377 | 回复: 685



手机版|

GMT+8, 2019-10-21 22:55 , Processed in 0.171873 second(s), 32 queries . Powered by Discuz! X3.4

YiBoard一板网 © 2015-2018 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表