ST7565 | Làm game hứng trứng

21/06/2019
st7565-lam-game-hung-trung

Chuẩn bị phần cứng

  • Arduino chip atm328 trở lên, mình sử dụng arduino uno r3
  • Lcd st7565  128x64 homephone spi
  • Nút bấm 6 nút up/down/right/left/ và fight/select.

Nối mạch:

Bạn hãy tham khảo cách nối mạch và nút bấm tại bài viết giới thiệu lcd nhé:

ST7565 | Hướng dẫn sử dụng glcd ST7565 homephone và chia sẻ thư viện

2

Ý tưởng nhanh.

Trong game này, những quả trứng từ trên cao rơi xuống một cách ngẫu nhiên, người chơi điều khiển rỏ di chuyển qua trái qua phải, nếu hứng trúng một quả trứng người chơi sẽ được cộng thêm điểm, nếu để rơi, thì bị trừ điểm, trò chơi kết thúc khi số điểm bằng 0.

Nội dung chi tiết

Chiếc rổ được hai nhân vật Cả mẹo và Dần béo cầm chung, di chuyển trái phải nhờ điều khiển bằng nút bấm. Các quả trứng được tạo ra một cách radom với hoành độ và khoảng cách xuất hiện khác nhau.

Tạo một class Object cơ sở có chứa các thuộc tính về tọa độ, kích thước ảnh, sự tồn tại của trứng, biên, hướng.

Hàm set/get –ghi/đọc dữ liệu, hàm ve/xoa thực hiện vẽ và xóa ảnh bitmap

2 class egg và contruot (con trượt) kế thừa thuộc tính và phương thức từ Object.

3

B1: Test con trượt

Ảnh bitmap hai nhân vật cầm rổ: 

 
  1. #include "ST7565_homephone.h"
  2.  
  3. #ifdef __AVR__
  4. #include <avr/io.h>
  5. #include <avr/pgmspace.h>
  6. #endif
  7.  
  8. ST7565 lcd(3, 4, 5, 6);
  9.  
  10. // cài đặt chân input
  11. #define fight_b A5
  12. #define select_b A4
  13. #define right_b A3
  14. #define up_b A2
  15. #define left_b A1
  16. #define down_b A0
  17. unsigned int timedelay;
  18. /* Qủa trứng (7x7) pixel
  19. * */
  20.  
  21. const static unsigned char __attribute__((progmem)) trung_7x7[] = {
  22. 0x1C, 0x22, 0x41, 0x41, 0x22, 0x1C,
  23. };
  24. /* Cả hai nhân vật 37x19
  25. *
  26. */
  27.  
  28. const static unsigned char __attribute__((progmem)) ca_hai_37x19[] = {
  29.  
  30. /* page 0 (lines 0-7) */
  31. 0x80, 0x70, 0x88, 0x4, 0x4, 0x4, 0x98, 0xa4, 0xa4, 0x2c, 0x38, 0x20, 0xc0,
  32. 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x40, 0xb0, 0x50, 0x5c,
  33. 0xa6, 0xa2, 0x5c, 0x44, 0x86, 0xf, 0xb2, 0x43, 0x80, 0x0,
  34. /* page 1 (lines 8-15) */
  35. 0x1, 0x2, 0x5, 0x4, 0x8, 0x93, 0xfc, 0xf8, 0xf8, 0xf9, 0xf1, 0x31, 0x39,
  36. 0x18, 0x3f, 0x43, 0xa5, 0x89, 0x91, 0xa5, 0x43, 0x3f, 0x18, 0x30, 0x70,
  37. 0x64, 0x68, 0x68, 0xf8, 0x78, 0x78, 0xf7, 0xf0, 0xfa, 0xf4, 0xe3, 0xc0,
  38. /* page 2 (lines 16-23) */
  39. 0x0, 0x0, 0x0, 0x0, 0x6, 0x5, 0x5, 0x5, 0x5, 0x1, 0x7, 0x0, 0x0, 0x0, 0x0,
  40. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7,
  41. 0x4, 0x0, 0x3, 0x7, 0x7, 0x7, 0x7,
  42. };
  43.  
  44. /*LỚP CƠ SỎ-OBJECT)*/
  45. class object {
  46. public: // biến toàn cục
  47. byte Xmin = 0, Xmax = 127, Ymin = 0, Ymax = 63; // biên
  48. byte x_ro = 60, y_ro = 40, width_ro = 30,
  49. high_ro = 10; // tọa độ rỏ và kích thước rỏ
  50. public:
  51. // tập hàm ghi thông tin
  52. void set_ton_tai(boolean value) { ton_tai = value; }
  53. void set_x(byte value) { x = value; }
  54. void set_y(byte value) { y = value; }
  55. void set_huong(byte value) { huong = value; }
  56. // tập hàm lấy thông tin
  57. boolean get_ton_tai() { return ton_tai; }
  58. byte get_x() { return x; }
  59. byte get_y() { return y; }
  60. byte get_huong() { return huong; }
  61.  
  62. private:
  63. // chỉ 2 tập hàm thành viên viên trên mới sử đụng được 4 tham số này:
  64. boolean ton_tai;
  65. byte x;
  66. byte y;
  67. byte huong;
  68. };
  69.  
  70. void setup() {
  71. pinMode(left_b, INPUT_PULLUP);
  72. pinMode(down_b, INPUT_PULLUP);
  73. pinMode(right_b, INPUT_PULLUP);
  74. pinMode(up_b, INPUT_PULLUP);
  75. pinMode(fight_b, INPUT_PULLUP);
  76. pinMode(select_b, INPUT_PULLUP);
  77. Serial.begin(9600);
  78. lcd.ON();
  79. lcd.SET(20, 0, 0, 0, 4);
  80. /*
  81. Serial.begin(9600);
  82. */
  83. // delay
  84. timedelay = 50;
  85. // tọa độ rỏ và kích thước rỏ mặc định để test
  86. // sẽ thay tọa độ rỏ là tọa độ con trượt ở phần sau
  87. }
  88.  
  89. //=============================================
  90. class contruot : public object {
  91. public:
  92. void xoa_con_truot(byte x, byte y) {
  93. // vẽ một hình chữ nhật màu trắng có kích thước bằng ảnh bitmap
  94. lcd.fillrect(x, y, 37, 19, DELETE);
  95. lcd.display();
  96. }
  97. void ve_con_truot(byte x, byte y) {
  98. // VẼ bitmap cho con trượt
  99. lcd.bitmap(x, y, 37, 19, ca_hai_37x19, BLACK);
  100. lcd.display();
  101. }
  102. contruot() {
  103. // hàm tạo constructer
  104.  
  105. // đặt x, y, con trượt một giá trị cho trước
  106. set_x((Xmax - Xmin) / 2);
  107. set_y(Ymax - 18);
  108. }
  109. void di_con_truot() {
  110. // lấy thông tin
  111. byte x_moi, x_cu, y_cu; // mới và cũ
  112.  
  113. x_cu = get_x();
  114. y_cu = get_y();
  115. // vẽ
  116. ve_con_truot(x_cu, y_cu);
  117. //đọc giá trị 4 button
  118. if (lcd.pullup_4(right_b, up_b, left_b, down_b) == 1) { // nút right
  119.  
  120. xoa_con_truot(x_cu, y_cu); // xóa ảnh cũ trên màn hình
  121.  
  122. if (x_cu <= (Xmax - 10)) { // trong biên
  123. x_moi = x_cu + 5; // cộng hoành độ lên 5 đơn vị
  124. } else {
  125. x_moi = x_cu;
  126. }
  127. // vẽ ảnh con trượt
  128. ve_con_truot(x_moi, y_cu);
  129. set_x(x_moi); // ghi lại thông tin hoành độ
  130. }
  131.  
  132. if (lcd.pullup_4(right_b, up_b, left_b, down_b) == 3) { // nút left
  133.  
  134. xoa_con_truot(x_cu, y_cu); // xóa ảnh cũ trên màn hình
  135. if (x_cu >= (Xmin + 10)) { // trong biên
  136. x_moi = x_cu - 5; // trừ hoành độ xuống 5 đơn vị
  137. } else {
  138. x_moi = x_cu;
  139. }
  140. // vẽ ảnh con trượt
  141.  
  142. ve_con_truot(x_moi, y_cu);
  143. set_x(x_moi); // ghi lại thông tin hoành độ
  144. }
  145.  
  146. } // di chuyển con chạy
  147. }; // class
  148. contruot Dan_va_Ca; // tạo 1 con trượt là Dần và Cả= constructor
  149. void loop() {
  150. // bước 1:
  151.  
  152. Dan_va_Ca.di_con_truot();
  153. Serial.print(Dan_va_Ca.get_x());
  154. Serial.println(Dan_va_Ca.get_y());
  155. delay(50);
  156. }

 

4

B2: Tạo trứng random

 
  1. #include "ST7565_homephone.h"
  2. #ifdef __AVR__
  3. #include <avr/io.h>
  4. #include <avr/pgmspace.h>
  5. #endif
  6.  
  7. ST7565 lcd(3, 4, 5, 6);
  8.  
  9. unsigned int timedelay;
  10. /* Qủa trứng (7x7) pixel
  11. * */
  12.  
  13. const static unsigned char __attribute__((progmem)) trung_7x7[] = {
  14. 0x1C, 0x22, 0x41, 0x41, 0x22, 0x1C,
  15. };
  16. /*LỚP CƠ SỎ-OBJECT)*/
  17. class object {
  18. public: // biến toàn cục
  19. byte Xmin = 0, Xmax = 127, Ymin = 0, Ymax = 63; // biên
  20. byte x_ro = 60, y_ro = 40, width_ro = 30,
  21. high_ro = 10; // tọa độ rỏ và kích thước rỏ
  22. // tọa độ rỏ và kích thước rỏ mặc định để test
  23. // sẽ thay tọa độ rỏ là tọa độ con trượt ở phần sau
  24. public:
  25. // tập hàm ghi thông tin
  26. void set_ton_tai(byte value) { ton_tai = value; }
  27. void set_x(byte value) { x = value; }
  28. void set_y(byte value) { y = value; }
  29. void set_huong(byte value) { huong = value; }
  30.  
  31. // tập hàm lấy thông tin
  32. boolean get_ton_tai() { return ton_tai; }
  33. byte get_x() { return x; }
  34. byte get_y() { return y; }
  35. byte get_huong() { return huong; }
  36.  
  37. private:
  38. // chỉ 2 tập hàm trên mới sử đụng được 4 tham số này
  39. boolean ton_tai;
  40. byte x;
  41. byte y;
  42. byte huong;
  43. };
  44. class egg : public object {
  45. public:
  46. egg() {
  47. // gán các thuộc tính khi tạo mới 1 quả trứng
  48. unsigned int seed;
  49. seed = millis();
  50. randomSeed(seed % 100);
  51. // tạo sinh số randomSeed bằng đồng hồ hệ thống
  52. byte x;
  53. byte y;
  54. x = random(Xmin + 10, Xmax - 10);
  55. y = random(Ymin + 1, Ymin + 15);
  56. // lưu thông tin vào
  57. set_x(x);
  58. set_y(y);
  59. // vẽ
  60. ve_trung(x, y);
  61. }
  62. void ve_trung(byte x, byte y) {
  63. // vẽ trứng
  64. lcd.bitmap(x, y, 7, 7, trung_7x7, BLACK);
  65. lcd.display();
  66. }
  67.  
  68. void xoa_trung(byte x, byte y) {
  69. // xóa trứng bằng 1 hình chữ nhật màu trắng kích thước bằng quả trứng
  70. lcd.fillrect(x, y, 7, 7, DELETE);
  71. lcd.display();
  72. }
  73. };
  74. void setup() {
  75. Serial.begin(9600);
  76. lcd.ON();
  77. lcd.SET(20, 0, 0, 0, 4);
  78. /*
  79. Serial.begin(9600);
  80. */
  81. timedelay = 500;
  82. lcd.clear();
  83. }
  84. egg qua_trung[3]; // chúng ta cần tạo mới 3 quả trứng
  85. // khi vừa tạo mới thì nó đã mang 2 thuộc tính x, y
  86. void loop() {
  87. // delay
  88. for (byte i = 0; i < 3; i++) { // duyệt 0,1,2
  89. Serial.print("(");
  90. Serial.print(qua_trung[i].get_x());
  91. Serial.print(",");
  92. Serial.print(qua_trung[i].get_y());
  93. Serial.print(")");
  94. }
  95. Serial.println("");
  96. delay(timedelay);
  97. lcd.clear();
  98. }

5

B3: Xử lý trứng

 
  1. #include "ST7565_homephone.h"
  2. #ifdef __AVR__
  3. #include <avr/io.h>
  4. #include <avr/pgmspace.h>
  5. #endif
  6. ST7565 lcd(3, 4, 5, 6);
  7. unsigned int timedelay;
  8. /* Qủa trứng (7x7) pixel
  9. * */
  10. const static unsigned char __attribute__((progmem)) trung_7x7[] = {
  11. 0x1C, 0x22, 0x41, 0x41, 0x22, 0x1C,
  12. };
  13. /*LỚP CƠ SỎ-OBJECT)*/
  14. class object {
  15. public: // biến toàn cục
  16. byte Xmin = 0, Xmax = 127, Ymin = 0, Ymax = 63; // biên
  17. byte x_ro = 60, y_ro = 40, width_ro = 30,
  18. high_ro = 10; // tọa độ rỏ và kích thước rỏ
  19. // tọa độ rỏ và kích thước rỏ mặc định để test
  20. // sẽ thay tọa độ rỏ là tọa độ con trượt ở phần sau
  21. public:
  22. // tập hàm ghi thông tin
  23. void set_ton_tai(boolean value) { ton_tai = value; }
  24. void set_x(byte value) { x = value; }
  25. void set_y(byte value) { y = value; }
  26. void set_huong(byte value) { huong = value; }
  27. // tập hàm lấy thông tin
  28. boolean get_ton_tai() { return ton_tai; }
  29. byte get_x() { return x; }
  30. byte get_y() { return y; }
  31. byte get_huong() { return huong; }
  32. private:
  33. // chỉ 2 tập hàm trên mới sử đụng được 4 tham số này
  34. boolean ton_tai;
  35. byte x;
  36. byte y;
  37. byte huong;
  38. };
  39. class egg : public object {
  40. public:
  41. void tao_trung() {
  42. // dành cho (1) , cái mà nó được gọi
  43. // gán các thuộc tính khi tạo mới 1 quả trứng
  44. unsigned int seed;
  45. seed = millis();
  46. randomSeed(seed % 100);
  47. // tạo sinh số randomSeed bằng đồng hồ hệ thống
  48. byte x;
  49. byte y;
  50. x = random(Xmin + 20, Xmax - 10);
  51. y = random(Ymin + 1, Ymin + 15);
  52. // lưu thông tin vào
  53. set_x(x);
  54. set_y(y);
  55. set_ton_tai(1);
  56. // vẽ
  57. ve_trung(x, y);
  58. }
  59. void ve_trung(byte x, byte y) {
  60. // vẽ trứng
  61. lcd.bitmap(x, y, 7, 7, trung_7x7, BLACK);
  62. lcd.display();
  63. }
  64. void xoa_trung(byte x, byte y) {
  65. // xóa trứng bằng 1 hình chữ nhật màu trắng kích thước bằng quả trứng
  66. lcd.fillrect(x, y, 7, 7, DELETE);
  67. lcd.display();
  68. }
  69. void di_chuyen_trung() { // di chuyển trứng RƠI
  70. byte x_cu, y_cu, y_moi; // giá trị cũ và mới
  71. if (get_ton_tai() == 1) {
  72. // nếu trứng đó tồn tại thì cho phép tiếp tục
  73. // lấy thông tin
  74. x_cu = get_x();
  75. y_cu = get_y();
  76. // xóa vị trí cũ
  77. xoa_trung(x_cu, y_cu);
  78. y_moi = y_cu + 2; // di xuống
  79. // vẽ
  80. ve_trung(x_cu, y_moi);
  81. // lưu lại tt
  82. set_x(x_cu);
  83. set_y(y_moi);
  84. } // if
  85. }
  86. boolean kiem_tra(byte x, byte y) { // x,y tọa độ rỏ
  87. // kiểm tra xem quả trứng có rơi vào rỏ hay không
  88. // nếu hiệu tọa độ của trứng với rỏ mà DƯƠNG và NHỎ HƠN hoặc BẰNG kích..
  89. //..thước rỏ,thì trứng đã rơi vào trong rỏ
  90. //( trứng phải ở giữa rỏ)
  91. // do tọa độ của 2 vật này thuộc kiểu biến nguyên dương byte
  92. // do đó cần kiểu nguyên có phần âm (int ) để lưu hiệu
  93. int hieu_x, hieu_y;
  94. // hoành độ trứng trừ hoành độ rỏ
  95. hieu_x = (get_x() + 7) - x; // cộng 7 vì:trứng phải ở giữa rỏ)
  96. hieu_y = get_y() - y;
  97. if ((hieu_x <= (width_ro)) && (hieu_x >= 0) && (hieu_y <= high_ro) &&
  98. (hieu_y >= 0)) {
  99. // thỏa mãn điều kiện
  100. return 1; // trả về giá trị true
  101. } else {
  102. return 0; // trả về giá trị false
  103. }
  104. } // kiểm tra
  105. void xu_li_ve_trung(byte x, byte y) { // x, y là tọa độ rỏ
  106. // bước 2:
  107. if (get_ton_tai() == 0) {
  108. // nếu quả trứng không tồn tại
  109. // thì phải tạo mới
  110. tao_trung();
  111. } else
  112. if (get_ton_tai() == 1) { // trứng tồn tại
  113. if (kiem_tra(x, y) == 1) { // nếu trứng vào rỏ
  114. // b1: xóa tồn tại quả trứng đó di
  115. set_ton_tai(0);
  116. // b2: cộng điểm
  117. }
  118. if (get_y() >= Ymax) { // nếu trứng quá biên,(chạm đất, vỡ)
  119. // b1: xóa tồn tại quả trứng đó đi
  120. set_ton_tai(0);
  121. }
  122. }
  123. di_chuyen_trung();
  124. }
  125. };
  126. //=============================================
  127. void setup() {
  128. Serial.begin(9600);
  129. lcd.ON();
  130. lcd.SET(20, 0, 0, 0, 4);
  131. /*
  132. Serial.begin(9600);
  133. */
  134. // delay
  135. timedelay = 50;
  136. // tọa độ rỏ và kích thước rỏ mặc định để test
  137. // sẽ thay tọa độ rỏ là tọa độ con trượt ở phần sau
  138. }
  139. // bước 1:
  140. egg qua_trung[4]; // chúng ta cần tạo 4 quả trứng
  141. object btc; // biến toàn cục
  142. void loop() {
  143. // khi vừa tạo mới thì nó đã mang 2 thuộc tính x, y
  144. for (byte i = 0; i < 4; i++) { // duyệt 4 quả 0,1,2,3
  145. qua_trung[i].xu_li_ve_trung(btc.x_ro, btc.y_ro);
  146. }
  147. delay(200);
  148. }

6

B4: Hoàn thiện

 
  1. #include "ST7565_homephone.h"
  2. #ifdef __AVR__
  3. #include <avr/io.h>
  4. #include <avr/pgmspace.h>
  5. #endif
  6. ST7565 lcd(3, 4, 5, 6);
  7. // cài đặt chân input
  8. #define fight_b A5
  9. #define select_b A4
  10. #define right_b A3
  11. #define up_b A2
  12. #define left_b A1
  13. #define down_b A0
  14. //
  15. unsigned int timedelay;
  16. /* Qủa trứng (7x7) pixel
  17. * */
  18. const static unsigned char __attribute__((progmem)) trung_7x7[] = {
  19. 0x1C, 0x22, 0x41, 0x41, 0x22, 0x1C,
  20. };
  21. /* Cả hai nhân vật 37x19
  22. *
  23. */
  24. const static unsigned char __attribute__((progmem)) ca_hai_37x19[] = {
  25. /* page 0 (lines 0-7) */
  26. 0x80, 0x70, 0x88, 0x4, 0x4, 0x4, 0x98, 0xa4, 0xa4, 0x2c, 0x38, 0x20, 0xc0,
  27. 0x0, 0x80, 0x0,
  28. 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x40, 0xb0, 0x50, 0x5c, 0xa6, 0xa2,
  29. 0x5c, 0x44, 0x86,
  30. 0xf, 0xb2, 0x43, 0x80, 0x0,
  31. /* page 1 (lines 8-15) */
  32. 0x1, 0x2, 0x5, 0x4, 0x8, 0x93, 0xfc, 0xf8, 0xf8, 0xf9, 0xf1, 0x31, 0x39,
  33. 0x18, 0x3f, 0x43,
  34. 0xa5, 0x89, 0x91, 0xa5, 0x43, 0x3f, 0x18, 0x30, 0x70, 0x64, 0x68, 0x68,
  35. 0xf8, 0x78, 0x78, 0xf7,
  36. 0xf0, 0xfa, 0xf4, 0xe3, 0xc0,
  37. /* page 2 (lines 16-23) */
  38. 0x0, 0x0, 0x0, 0x0, 0x6, 0x5, 0x5, 0x5, 0x5, 0x1, 0x7, 0x0, 0x0, 0x0, 0x0,
  39. 0x0,
  40. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7, 0x4,
  41. 0x0,
  42. 0x3, 0x7, 0x7, 0x7, 0x7,
  43. };
  44. void setup() {
  45. pinMode(select_b, INPUT_PULLUP);
  46. pinMode(down_b, INPUT_PULLUP);
  47. pinMode(up_b, INPUT_PULLUP);
  48. pinMode(left_b, INPUT_PULLUP);
  49. pinMode(right_b, INPUT_PULLUP);
  50. pinMode(fight_b, INPUT_PULLUP);
  51. lcd.ON();
  52. lcd.SET(23, 0, 0, 0, 4);
  53. /*
  54. Serial.begin(9600);
  55. */
  56. // delay
  57. timedelay = 20;
  58. }
  59. /*LỚP CƠ SỎ-OBJECT)*/
  60. class object {
  61. public: // biến toàn cục
  62. static int diem_ban_dau;
  63. static int diem;
  64. static int diem_cao;
  65. // static được hiểu nôm na là duy nhất cho dù có bao nhiêu đối tượng tạo ra..
  66. // khai báo static bên ngoài lớp
  67. byte Xmin = 0, Xmax = 127, Ymin = 0, Ymax = 63; // biên
  68. byte width_ro = 12, high_ro = 10; // tọa độ rỏ và kích thước rỏ
  69. // tập hàm ghi thông
  70. void set_ton_tai(boolean value) { ton_tai = value; }
  71. void set_x(byte value) { x = value; }
  72. void set_y(byte value) { y = value; }
  73. void set_huong(byte value) { huong = value; }
  74. // tập hàm lấy thông tin
  75. int get_diem_cao() { return diem_cao; }
  76. boolean get_ton_tai() { return ton_tai; }
  77. byte get_x() { return x; }
  78. byte get_y() { return y; }
  79. byte get_huong() { return huong; }
  80. private:
  81. // chỉ 2 tập hàm thành viên viên trên mới sử đụng được 4 tham số này:
  82. boolean ton_tai;
  83. byte x;
  84. byte y;
  85. byte huong;
  86. };
  87. int object::diem_ban_dau = 5;
  88. int object::diem = diem_ban_dau;
  89. int object::diem_cao = diem;
  90. //=============================================
  91. class contruot : public object {
  92. public:
  93. void xoa_con_truot(byte x, byte y) {
  94. // vẽ một hình chữ nhật màu trắng có kích thước bằng ảnh bitmap
  95. lcd.fillrect(x, y, 37, 19, DELETE);
  96. lcd.display();
  97. }
  98. void ve_con_truot(byte x, byte y) {
  99. // VẼ bitmap cho con trượt
  100. lcd.bitmap(x, y, 37, 19, ca_hai_37x19, BLACK);
  101. lcd.display();
  102. }
  103. contruot() {
  104. // hàm tạo constructer
  105. // đặt x, y, con trượt một giá trị cho trước
  106. set_x((Xmax - Xmin) / 2);
  107. set_y(Ymax - 18);
  108. }
  109. void di_con_truot() {
  110. // lấy thông tin
  111. byte x_moi, x_cu, y_cu; // mới và cũ
  112. x_cu = get_x();
  113. y_cu = get_y();
  114. // vẽ
  115. ve_con_truot(x_cu, y_cu);
  116. //đọc giá trị 4 button
  117. if (lcd.pullup_4(right_b, up_b, left_b, down_b) == 1) { // nút right
  118. xoa_con_truot(x_cu, y_cu); // xóa ảnh cũ trên màn hình
  119. if (x_cu <= (Xmax - 10)) { // trong biên
  120. x_moi = x_cu + 5; // cộng hoành độ lên 5 đơn vị
  121. } else {
  122. x_moi = x_cu;
  123. }
  124. // vẽ ảnh con trượt
  125. ve_con_truot(x_moi, y_cu);
  126. set_x(x_moi); // ghi lại thông tin hoành độ
  127. }
  128. if (lcd.pullup_4(right_b, up_b, left_b, down_b) == 3) { // nút left
  129. xoa_con_truot(x_cu, y_cu); // xóa ảnh cũ trên màn hình
  130. if (x_cu >= (Xmin + 10)) { // trong biên
  131. x_moi = x_cu - 5; // trừ hoành độ xuống 5 đơn vị
  132. } else {
  133. x_moi = x_cu;
  134. }
  135. // vẽ ảnh con trượt
  136. ve_con_truot(x_moi, y_cu);
  137. set_x(x_moi); // ghi lại thông tin hoành độ
  138. }
  139. } // di chuyển con chạy
  140. }; // class
  141. //===========================================================
  142. class egg : public object {
  143. public:
  144. void tao_trung() {
  145. // dành cho (1) , cái mà nó được gọi
  146. // gán các thuộc tính khi tạo mới 1 quả trứng
  147. unsigned int seed;
  148. seed = millis();
  149. randomSeed(seed % 100);
  150. // tạo sinh số randomSeed bằng đồng hồ hệ thống
  151. byte x;
  152. byte y;
  153. x = random(Xmin + 20, Xmax - 10);
  154. y = random(Ymin + 1, Ymin + 15);
  155. // lưu thông tin vào
  156. set_x(x);
  157. set_y(y);
  158. set_ton_tai(1);
  159. // vẽ
  160. ve_trung(x, y);
  161. }
  162. void ve_trung(byte x, byte y) {
  163. // vẽ trứng
  164. lcd.bitmap(x, y, 7, 7, trung_7x7, BLACK);
  165. lcd.display();
  166. }
  167. void xoa_trung(byte x, byte y) {
  168. // xóa trứng bằng 1 hình chữ nhật màu trắng kích thước bằng quả trứng
  169. lcd.fillrect(x, y, 7, 7, DELETE);
  170. lcd.display();
  171. }
  172. void di_chuyen_trung() { // di chuyển trứng RƠI
  173. byte x_cu, y_cu, y_moi; // giá trị cũ và mới
  174. if (get_ton_tai() == 1) {
  175. // nếu trứng đó tồn tại thì cho phép tiếp tục
  176. // lấy thông tin
  177. x_cu = get_x();
  178. y_cu = get_y();
  179. // xóa vị trí cũ
  180. xoa_trung(x_cu, y_cu);
  181. y_moi = y_cu + 2; // di xuống
  182. // vẽ
  183. ve_trung(x_cu, y_moi);
  184. // lưu lại tt
  185. set_x(x_cu);
  186. set_y(y_moi);
  187. } // if
  188. }
  189. boolean kiem_tra(byte x, byte y) { // x,y tọa độ rỏ
  190. // kiểm tra xem quả trứng có rơi vào rỏ hay không
  191. // nếu hiệu tọa độ của trứng với rỏ mà DƯƠNG và NHỎ HƠN hoặc BẰNG kích..
  192. //..thước rỏ,thì trứng đã rơi vào trong rỏ
  193. //( trứng phải ở giữa rỏ)
  194. // do tọa độ của 2 vật này thuộc kiểu biến nguyên dương byte
  195. // do đó cần kiểu nguyên có phần âm (int ) để lưu hiệu
  196. int hieu_x, hieu_y;
  197. // hoành độ trứng trừ hoành độ rỏ
  198. hieu_x = (get_x() + 7) - x; // cộng 7 vì:trứng phải ở giữa rỏ)
  199. hieu_y = get_y() - y;
  200. if ((hieu_x <= (width_ro)) && (hieu_x >= 0) && (hieu_y <= high_ro) &&
  201. (hieu_y >= 0)) {
  202. // thỏa mãn điều kiện
  203. return 1; // trả về giá trị true
  204. } else {
  205. return 0; // trả về giá trị false
  206. }
  207. } // kiểm tra
  208. void xu_li_ve_trung(byte x, byte y) { // x, y là tọa độ rỏ
  209. // bước 2:
  210. if (get_ton_tai() == 0) {
  211. // nếu quả trứng không tồn tại
  212. // thì phải tạo mới
  213. tao_trung();
  214. } else
  215. if (get_ton_tai() == 1) { // trứng tồn tại
  216. if (kiem_tra(x, y) == 1) { // nếu trứng vào rỏ
  217. // xóa tồn tại quả trứng đó di
  218. set_ton_tai(0);
  219. diem++;
  220. }
  221. if (get_y() >= Ymax) { // nếu trứng quá biên,(chạm đất, vỡ)
  222. // xóa tồn tại quả trứng đó đi
  223. set_ton_tai(0);
  224. diem--;
  225. }
  226. }
  227. di_chuyen_trung();
  228. }
  229. };
  230. //====================================================
  231. class computer : public object {
  232. public:
  233. void lap_vo_han() {
  234. // dừng dòng chảy chính bằng vòng lặp vô hạn
  235. // thoát lặp khi nút Fight được nhấn
  236. lcd.asc_string(10, 54, asc("Fight!"), BLACK);
  237. while (digitalRead(fight_b) != 0) {
  238. lcd.rect(8, 53, 40, 10, BLACK);
  239. lcd.display();
  240. if (digitalRead(fight_b) == 0) {
  241. break; // thoát ngay
  242. }
  243. delay(250);
  244. lcd.rect(8, 53, 40, 10, DELETE);
  245. lcd.display();
  246. if (digitalRead(fight_b) == 0) {
  247. break; // thoát ngay
  248. }
  249. delay(250);
  250. }
  251. } //đóng lặp vô hạn
  252. void in_diem() {
  253. if (diem >= diem_cao) {
  254. diem_cao = diem;
  255. }
  256. if (diem <= 0) {
  257. reset();
  258. } // thua cuộc
  259. lcd.fillrect(Xmin + 5, Ymin, Xmax - Xmin, 8, DELETE); // xóa ảnh cũ
  260. lcd.number_long(Xmin + 5, 0, diem, ASCII_NUMBER, BLACK);
  261. lcd.number_long(Xmax - 15, 0, diem_cao, ASCII_NUMBER, BLACK);
  262. lcd.display();
  263. }
  264. //=============================================
  265. void reset() {
  266. diem = diem_ban_dau; // đặt lại điểm ban dau
  267. lap_vo_han(); // chờ nhấn nút fight
  268. lcd.clear(); // làm sạch màn hình
  269. }
  270. }; // class
  271. //====================================================
  272. contruot Dan_va_Ca; // tạo 1 con trượt là Dần và Cả= constructor
  273. egg qua_trung[4]; // chúng ta cần tạo 4 quả trứng
  274. computer c;
  275. void loop() {
  276. byte x_ro, y_ro;
  277. // lấy tọa độ rổ-rổ là con trượt
  278. Dan_va_Ca.di_con_truot();
  279. x_ro =
  280. Dan_va_Ca.get_x() + 13; // cộng 13 vì rổ cách gốc tọa độ bitmap từng đó
  281. y_ro =
  282. (Dan_va_Ca.get_y() + 5); // cộng 5 vì rổ cách gốc tọa độ bitmap từng đó
  283. c.in_diem(); // in điểm
  284. for (byte i = 0; i < 4; i++) { // duyệt 4 quả 0,1,2,3
  285. qua_trung[i].xu_li_ve_trung(x_ro, y_ro);
  286. }
  287. // nhấn fight để tăng tốc
  288. if (digitalRead(fight_b) == 1) { // ko nhấn
  289. delay(timedelay);
  290. } else {
  291. delay(timedelay / 5);
  292. }
  293. }

 

7

Tạm kết

Vì tất cả code được đặt trong một file duy nhất nên nó hơi dài  nhỉ frown. Code này mình nghĩ sao thì viết đó, miễn nó chạy là mình đã cảm thấy ok rồi, còn tối ưu hóa thì tạm nghỉ. Mời pà con Copy về chơi thử.

Tăng tốc game: nhấn nút FIGHT.

Thua cuộc nhấn FIGHT để chơi tiếp nhé.

Vẫn còn nhiều cái hay lắm, hãy đón đọc nhélaughcheeky...Hi vọng bạn thấy thích bài viết này. yesheart

Hẹn gặp mọi người ở bài tiếp theo.

 

Bình luận
Nội dung này chưa có bình luận, hãy gửi bình luận đầu tiên của bạn.
VIẾT BÌNH LUẬN CỦA BẠN